sudocode 1.1.17 → 1.1.18-dev.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.
- package/node_modules/@sudocode-ai/cli/README.md +330 -0
- package/node_modules/@sudocode-ai/cli/dist/cli/feedback-commands.d.ts +53 -0
- package/node_modules/@sudocode-ai/cli/dist/cli/feedback-commands.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/cli/feedback-commands.js +339 -0
- package/node_modules/@sudocode-ai/cli/dist/cli/feedback-commands.js.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/cli/init-commands.d.ts +20 -0
- package/node_modules/@sudocode-ai/cli/dist/cli/init-commands.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/cli/init-commands.js +145 -0
- package/node_modules/@sudocode-ai/cli/dist/cli/init-commands.js.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/cli/issue-commands.d.ts +46 -0
- package/node_modules/@sudocode-ai/cli/dist/cli/issue-commands.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/cli/issue-commands.js +353 -0
- package/node_modules/@sudocode-ai/cli/dist/cli/issue-commands.js.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/cli/merge-commands.d.ts +42 -0
- package/node_modules/@sudocode-ai/cli/dist/cli/merge-commands.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/cli/merge-commands.js +405 -0
- package/node_modules/@sudocode-ai/cli/dist/cli/merge-commands.js.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/cli/plugin-commands.d.ts +62 -0
- package/node_modules/@sudocode-ai/cli/dist/cli/plugin-commands.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/cli/plugin-commands.js +595 -0
- package/node_modules/@sudocode-ai/cli/dist/cli/plugin-commands.js.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/cli/query-commands.d.ts +18 -0
- package/node_modules/@sudocode-ai/cli/dist/cli/query-commands.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/cli/query-commands.js +61 -0
- package/node_modules/@sudocode-ai/cli/dist/cli/query-commands.js.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/cli/reference-commands.d.ts +22 -0
- package/node_modules/@sudocode-ai/cli/dist/cli/reference-commands.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/cli/reference-commands.js +136 -0
- package/node_modules/@sudocode-ai/cli/dist/cli/reference-commands.js.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/cli/relationship-commands.d.ts +14 -0
- package/node_modules/@sudocode-ai/cli/dist/cli/relationship-commands.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/cli/relationship-commands.js +83 -0
- package/node_modules/@sudocode-ai/cli/dist/cli/relationship-commands.js.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/cli/server-commands.d.ts +17 -0
- package/node_modules/@sudocode-ai/cli/dist/cli/server-commands.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/cli/server-commands.js +123 -0
- package/node_modules/@sudocode-ai/cli/dist/cli/server-commands.js.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/cli/spec-commands.d.ts +38 -0
- package/node_modules/@sudocode-ai/cli/dist/cli/spec-commands.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/cli/spec-commands.js +326 -0
- package/node_modules/@sudocode-ai/cli/dist/cli/spec-commands.js.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/cli/status-commands.d.ts +17 -0
- package/node_modules/@sudocode-ai/cli/dist/cli/status-commands.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/cli/status-commands.js +131 -0
- package/node_modules/@sudocode-ai/cli/dist/cli/status-commands.js.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/cli/sync-commands.d.ts +24 -0
- package/node_modules/@sudocode-ai/cli/dist/cli/sync-commands.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/cli/sync-commands.js +429 -0
- package/node_modules/@sudocode-ai/cli/dist/cli/sync-commands.js.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/cli/update-commands.d.ts +16 -0
- package/node_modules/@sudocode-ai/cli/dist/cli/update-commands.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/cli/update-commands.js +160 -0
- package/node_modules/@sudocode-ai/cli/dist/cli/update-commands.js.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/cli.d.ts +6 -0
- package/node_modules/@sudocode-ai/cli/dist/cli.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/cli.js +543 -0
- package/node_modules/@sudocode-ai/cli/dist/cli.js.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/config.d.ts +50 -0
- package/node_modules/@sudocode-ai/cli/dist/config.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/config.js +76 -0
- package/node_modules/@sudocode-ai/cli/dist/config.js.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/db.d.ts +21 -0
- package/node_modules/@sudocode-ai/cli/dist/db.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/db.js +55 -0
- package/node_modules/@sudocode-ai/cli/dist/db.js.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/export.d.ts +84 -0
- package/node_modules/@sudocode-ai/cli/dist/export.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/export.js +265 -0
- package/node_modules/@sudocode-ai/cli/dist/export.js.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/filename-generator.d.ts +31 -0
- package/node_modules/@sudocode-ai/cli/dist/filename-generator.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/filename-generator.js +103 -0
- package/node_modules/@sudocode-ai/cli/dist/filename-generator.js.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/id-generator.d.ts +63 -0
- package/node_modules/@sudocode-ai/cli/dist/id-generator.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/id-generator.js +196 -0
- package/node_modules/@sudocode-ai/cli/dist/id-generator.js.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/import.d.ts +134 -0
- package/node_modules/@sudocode-ai/cli/dist/import.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/import.js +751 -0
- package/node_modules/@sudocode-ai/cli/dist/import.js.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/index.d.ts +15 -0
- package/node_modules/@sudocode-ai/cli/dist/index.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/index.js +15 -0
- package/node_modules/@sudocode-ai/cli/dist/index.js.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/integrations/base-provider.d.ts +108 -0
- package/node_modules/@sudocode-ai/cli/dist/integrations/base-provider.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/integrations/base-provider.js +80 -0
- package/node_modules/@sudocode-ai/cli/dist/integrations/base-provider.js.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/integrations/config-resolver.d.ts +62 -0
- package/node_modules/@sudocode-ai/cli/dist/integrations/config-resolver.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/integrations/config-resolver.js +69 -0
- package/node_modules/@sudocode-ai/cli/dist/integrations/config-resolver.js.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/integrations/config-validator.d.ts +75 -0
- package/node_modules/@sudocode-ai/cli/dist/integrations/config-validator.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/integrations/config-validator.js +129 -0
- package/node_modules/@sudocode-ai/cli/dist/integrations/config-validator.js.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/integrations/index.d.ts +14 -0
- package/node_modules/@sudocode-ai/cli/dist/integrations/index.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/integrations/index.js +20 -0
- package/node_modules/@sudocode-ai/cli/dist/integrations/index.js.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/integrations/plugin-loader.d.ts +77 -0
- package/node_modules/@sudocode-ai/cli/dist/integrations/plugin-loader.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/integrations/plugin-loader.js +265 -0
- package/node_modules/@sudocode-ai/cli/dist/integrations/plugin-loader.js.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/integrations/registry.d.ts +67 -0
- package/node_modules/@sudocode-ai/cli/dist/integrations/registry.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/integrations/registry.js +77 -0
- package/node_modules/@sudocode-ai/cli/dist/integrations/registry.js.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/integrations/sync-coordinator.d.ts +191 -0
- package/node_modules/@sudocode-ai/cli/dist/integrations/sync-coordinator.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/integrations/sync-coordinator.js +798 -0
- package/node_modules/@sudocode-ai/cli/dist/integrations/sync-coordinator.js.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/integrations/types.d.ts +142 -0
- package/node_modules/@sudocode-ai/cli/dist/integrations/types.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/integrations/types.js +6 -0
- package/node_modules/@sudocode-ai/cli/dist/integrations/types.js.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/integrations/utils/conflict-resolver.d.ts +79 -0
- package/node_modules/@sudocode-ai/cli/dist/integrations/utils/conflict-resolver.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/integrations/utils/conflict-resolver.js +106 -0
- package/node_modules/@sudocode-ai/cli/dist/integrations/utils/conflict-resolver.js.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/jsonl.d.ts +69 -0
- package/node_modules/@sudocode-ai/cli/dist/jsonl.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/jsonl.js +333 -0
- package/node_modules/@sudocode-ai/cli/dist/jsonl.js.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/markdown.d.ts +146 -0
- package/node_modules/@sudocode-ai/cli/dist/markdown.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/markdown.js +329 -0
- package/node_modules/@sudocode-ai/cli/dist/markdown.js.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/merge-resolver.d.ts +85 -0
- package/node_modules/@sudocode-ai/cli/dist/merge-resolver.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/merge-resolver.js +301 -0
- package/node_modules/@sudocode-ai/cli/dist/merge-resolver.js.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/operations/events.d.ts +53 -0
- package/node_modules/@sudocode-ai/cli/dist/operations/events.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/operations/events.js +108 -0
- package/node_modules/@sudocode-ai/cli/dist/operations/events.js.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/operations/external-links.d.ts +147 -0
- package/node_modules/@sudocode-ai/cli/dist/operations/external-links.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/operations/external-links.js +411 -0
- package/node_modules/@sudocode-ai/cli/dist/operations/external-links.js.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/operations/feedback-anchors.d.ts +92 -0
- package/node_modules/@sudocode-ai/cli/dist/operations/feedback-anchors.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/operations/feedback-anchors.js +444 -0
- package/node_modules/@sudocode-ai/cli/dist/operations/feedback-anchors.js.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/operations/feedback.d.ts +94 -0
- package/node_modules/@sudocode-ai/cli/dist/operations/feedback.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/operations/feedback.js +278 -0
- package/node_modules/@sudocode-ai/cli/dist/operations/feedback.js.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/operations/index.d.ts +11 -0
- package/node_modules/@sudocode-ai/cli/dist/operations/index.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/operations/index.js +11 -0
- package/node_modules/@sudocode-ai/cli/dist/operations/index.js.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/operations/issues.d.ts +88 -0
- package/node_modules/@sudocode-ai/cli/dist/operations/issues.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/operations/issues.js +474 -0
- package/node_modules/@sudocode-ai/cli/dist/operations/issues.js.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/operations/references.d.ts +34 -0
- package/node_modules/@sudocode-ai/cli/dist/operations/references.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/operations/references.js +117 -0
- package/node_modules/@sudocode-ai/cli/dist/operations/references.js.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/operations/relationships.d.ts +64 -0
- package/node_modules/@sudocode-ai/cli/dist/operations/relationships.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/operations/relationships.js +281 -0
- package/node_modules/@sudocode-ai/cli/dist/operations/relationships.js.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/operations/specs.d.ts +69 -0
- package/node_modules/@sudocode-ai/cli/dist/operations/specs.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/operations/specs.js +330 -0
- package/node_modules/@sudocode-ai/cli/dist/operations/specs.js.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/operations/tags.d.ts +42 -0
- package/node_modules/@sudocode-ai/cli/dist/operations/tags.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/operations/tags.js +127 -0
- package/node_modules/@sudocode-ai/cli/dist/operations/tags.js.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/operations/transactions.d.ts +41 -0
- package/node_modules/@sudocode-ai/cli/dist/operations/transactions.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/operations/transactions.js +111 -0
- package/node_modules/@sudocode-ai/cli/dist/operations/transactions.js.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/sync.d.ts +47 -0
- package/node_modules/@sudocode-ai/cli/dist/sync.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/sync.js +464 -0
- package/node_modules/@sudocode-ai/cli/dist/sync.js.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/test-schema.d.ts +5 -0
- package/node_modules/@sudocode-ai/cli/dist/test-schema.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/test-schema.js +46 -0
- package/node_modules/@sudocode-ai/cli/dist/test-schema.js.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/types.d.ts +7 -0
- package/node_modules/@sudocode-ai/cli/dist/types.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/types.js +7 -0
- package/node_modules/@sudocode-ai/cli/dist/types.js.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/update-checker.d.ts +33 -0
- package/node_modules/@sudocode-ai/cli/dist/update-checker.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/update-checker.js +193 -0
- package/node_modules/@sudocode-ai/cli/dist/update-checker.js.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/validation.d.ts +11 -0
- package/node_modules/@sudocode-ai/cli/dist/validation.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/validation.js +58 -0
- package/node_modules/@sudocode-ai/cli/dist/validation.js.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/version.d.ts +12 -0
- package/node_modules/@sudocode-ai/cli/dist/version.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/version.js +23 -0
- package/node_modules/@sudocode-ai/cli/dist/version.js.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/watcher.d.ts +69 -0
- package/node_modules/@sudocode-ai/cli/dist/watcher.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/cli/dist/watcher.js +783 -0
- package/node_modules/@sudocode-ai/cli/dist/watcher.js.map +1 -0
- package/node_modules/@sudocode-ai/cli/package.json +73 -0
- package/node_modules/@sudocode-ai/integration-beads/package.json +44 -0
- package/node_modules/@sudocode-ai/integration-github/package.json +41 -0
- package/node_modules/@sudocode-ai/integration-openspec/package.json +43 -0
- package/node_modules/@sudocode-ai/integration-speckit/package.json +42 -0
- package/node_modules/@sudocode-ai/local-server/README.md +25 -0
- package/node_modules/@sudocode-ai/local-server/dist/cli.d.ts +7 -0
- package/node_modules/@sudocode-ai/local-server/dist/cli.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/cli.js +7 -0
- package/node_modules/@sudocode-ai/local-server/dist/cli.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/errors/agent-errors.d.ts +43 -0
- package/node_modules/@sudocode-ai/local-server/dist/errors/agent-errors.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/errors/agent-errors.js +69 -0
- package/node_modules/@sudocode-ai/local-server/dist/errors/agent-errors.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/adapters/claude-adapter.d.ts +63 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/adapters/claude-adapter.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/adapters/claude-adapter.js +83 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/adapters/claude-adapter.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/adapters/codex-adapter.d.ts +67 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/adapters/codex-adapter.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/adapters/codex-adapter.js +183 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/adapters/codex-adapter.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/adapters/codex-config-builder.d.ts +30 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/adapters/codex-config-builder.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/adapters/codex-config-builder.js +110 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/adapters/codex-config-builder.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/adapters/copilot-adapter.d.ts +94 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/adapters/copilot-adapter.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/adapters/copilot-adapter.js +163 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/adapters/copilot-adapter.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/adapters/copilot-config-builder.d.ts +48 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/adapters/copilot-config-builder.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/adapters/copilot-config-builder.js +125 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/adapters/copilot-config-builder.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/adapters/cursor-adapter.d.ts +66 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/adapters/cursor-adapter.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/adapters/cursor-adapter.js +121 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/adapters/cursor-adapter.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/adapters/cursor-config-builder.d.ts +29 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/adapters/cursor-config-builder.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/adapters/cursor-config-builder.js +49 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/adapters/cursor-config-builder.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/adapters/shared/config-presets.d.ts +102 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/adapters/shared/config-presets.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/adapters/shared/config-presets.js +205 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/adapters/shared/config-presets.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/adapters/shared/config-utils.d.ts +95 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/adapters/shared/config-utils.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/adapters/shared/config-utils.js +163 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/adapters/shared/config-utils.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/adapters/shared/index.d.ts +8 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/adapters/shared/index.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/adapters/shared/index.js +8 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/adapters/shared/index.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/executors/agent-executor-wrapper.d.ts +154 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/executors/agent-executor-wrapper.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/executors/agent-executor-wrapper.js +725 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/executors/agent-executor-wrapper.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/executors/executor-factory.d.ts +95 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/executors/executor-factory.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/executors/executor-factory.js +128 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/executors/executor-factory.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/output/ag-ui-adapter.d.ts +174 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/output/ag-ui-adapter.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/output/ag-ui-adapter.js +436 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/output/ag-ui-adapter.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/output/claude-to-ag-ui.d.ts +90 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/output/claude-to-ag-ui.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/output/claude-to-ag-ui.js +153 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/output/claude-to-ag-ui.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/output/index.d.ts +15 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/output/index.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/output/index.js +13 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/output/index.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/output/normalized-to-ag-ui-adapter.d.ts +108 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/output/normalized-to-ag-ui-adapter.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/output/normalized-to-ag-ui-adapter.js +321 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/output/normalized-to-ag-ui-adapter.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/output/types.d.ts +421 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/output/types.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/output/types.js +22 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/output/types.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/process/builders/claude.d.ts +53 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/process/builders/claude.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/process/builders/claude.js +225 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/process/builders/claude.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/transport/event-buffer.d.ts +119 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/transport/event-buffer.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/transport/event-buffer.js +208 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/transport/event-buffer.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/transport/index.d.ts +10 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/transport/index.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/transport/index.js +10 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/transport/index.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/transport/ipc-transport-manager.d.ts +74 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/transport/ipc-transport-manager.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/transport/ipc-transport-manager.js +104 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/transport/ipc-transport-manager.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/transport/sse-transport.d.ts +146 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/transport/sse-transport.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/transport/sse-transport.js +282 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/transport/sse-transport.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/transport/transport-manager.d.ts +176 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/transport/transport-manager.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/transport/transport-manager.js +234 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/transport/transport-manager.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/worktree/config.d.ts +74 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/worktree/config.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/worktree/config.js +280 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/worktree/config.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/worktree/conflict-detector.d.ts +85 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/worktree/conflict-detector.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/worktree/conflict-detector.js +129 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/worktree/conflict-detector.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/worktree/git-cli.d.ts +208 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/worktree/git-cli.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/worktree/git-cli.js +280 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/worktree/git-cli.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/worktree/git-sync-cli.d.ts +225 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/worktree/git-sync-cli.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/worktree/git-sync-cli.js +464 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/worktree/git-sync-cli.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/worktree/index.d.ts +16 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/worktree/index.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/worktree/index.js +15 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/worktree/index.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/worktree/manager.d.ts +221 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/worktree/manager.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/worktree/manager.js +508 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/worktree/manager.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/worktree/types.d.ts +90 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/worktree/types.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/worktree/types.js +42 -0
- package/node_modules/@sudocode-ai/local-server/dist/execution/worktree/types.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/index.d.ts +6 -0
- package/node_modules/@sudocode-ai/local-server/dist/index.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/index.js +371 -0
- package/node_modules/@sudocode-ai/local-server/dist/index.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/middleware/project-context.d.ts +37 -0
- package/node_modules/@sudocode-ai/local-server/dist/middleware/project-context.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/middleware/project-context.js +91 -0
- package/node_modules/@sudocode-ai/local-server/dist/middleware/project-context.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/public/assets/index-D4AKx6EO.css +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/public/assets/index-DorQqwGV.js +927 -0
- package/node_modules/@sudocode-ai/local-server/dist/public/assets/index-DorQqwGV.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/public/assets/react-vendor-DoNwlLhy.js +60 -0
- package/node_modules/@sudocode-ai/local-server/dist/public/assets/react-vendor-DoNwlLhy.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/public/assets/ui-vendor-DlxvBun1.js +54 -0
- package/node_modules/@sudocode-ai/local-server/dist/public/assets/ui-vendor-DlxvBun1.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/public/favicon.ico +0 -0
- package/node_modules/@sudocode-ai/local-server/dist/public/index.html +16 -0
- package/node_modules/@sudocode-ai/local-server/dist/public/logo.png +0 -0
- package/node_modules/@sudocode-ai/local-server/dist/routes/agents.d.ts +3 -0
- package/node_modules/@sudocode-ai/local-server/dist/routes/agents.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/routes/agents.js +62 -0
- package/node_modules/@sudocode-ai/local-server/dist/routes/agents.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/routes/config.d.ts +3 -0
- package/node_modules/@sudocode-ai/local-server/dist/routes/config.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/routes/config.js +116 -0
- package/node_modules/@sudocode-ai/local-server/dist/routes/config.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/routes/editors.d.ts +15 -0
- package/node_modules/@sudocode-ai/local-server/dist/routes/editors.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/routes/editors.js +98 -0
- package/node_modules/@sudocode-ai/local-server/dist/routes/editors.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/routes/executions-stream.d.ts +27 -0
- package/node_modules/@sudocode-ai/local-server/dist/routes/executions-stream.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/routes/executions-stream.js +59 -0
- package/node_modules/@sudocode-ai/local-server/dist/routes/executions-stream.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/routes/executions.d.ts +18 -0
- package/node_modules/@sudocode-ai/local-server/dist/routes/executions.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/routes/executions.js +1169 -0
- package/node_modules/@sudocode-ai/local-server/dist/routes/executions.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/routes/feedback.d.ts +8 -0
- package/node_modules/@sudocode-ai/local-server/dist/routes/feedback.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/routes/feedback.js +340 -0
- package/node_modules/@sudocode-ai/local-server/dist/routes/feedback.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/routes/files.d.ts +18 -0
- package/node_modules/@sudocode-ai/local-server/dist/routes/files.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/routes/files.js +89 -0
- package/node_modules/@sudocode-ai/local-server/dist/routes/files.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/routes/import.d.ts +142 -0
- package/node_modules/@sudocode-ai/local-server/dist/routes/import.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/routes/import.js +896 -0
- package/node_modules/@sudocode-ai/local-server/dist/routes/import.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/routes/issues.d.ts +8 -0
- package/node_modules/@sudocode-ai/local-server/dist/routes/issues.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/routes/issues.js +419 -0
- package/node_modules/@sudocode-ai/local-server/dist/routes/issues.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/routes/plugins.d.ts +34 -0
- package/node_modules/@sudocode-ai/local-server/dist/routes/plugins.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/routes/plugins.js +602 -0
- package/node_modules/@sudocode-ai/local-server/dist/routes/plugins.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/routes/projects.d.ts +11 -0
- package/node_modules/@sudocode-ai/local-server/dist/routes/projects.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/routes/projects.js +536 -0
- package/node_modules/@sudocode-ai/local-server/dist/routes/projects.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/routes/relationships.d.ts +8 -0
- package/node_modules/@sudocode-ai/local-server/dist/routes/relationships.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/routes/relationships.js +310 -0
- package/node_modules/@sudocode-ai/local-server/dist/routes/relationships.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/routes/repo-info.d.ts +3 -0
- package/node_modules/@sudocode-ai/local-server/dist/routes/repo-info.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/routes/repo-info.js +203 -0
- package/node_modules/@sudocode-ai/local-server/dist/routes/repo-info.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/routes/specs.d.ts +8 -0
- package/node_modules/@sudocode-ai/local-server/dist/routes/specs.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/routes/specs.js +414 -0
- package/node_modules/@sudocode-ai/local-server/dist/routes/specs.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/routes/update.d.ts +7 -0
- package/node_modules/@sudocode-ai/local-server/dist/routes/update.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/routes/update.js +194 -0
- package/node_modules/@sudocode-ai/local-server/dist/routes/update.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/routes/version.d.ts +3 -0
- package/node_modules/@sudocode-ai/local-server/dist/routes/version.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/routes/version.js +25 -0
- package/node_modules/@sudocode-ai/local-server/dist/routes/version.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/routes/workflows.d.ts +8 -0
- package/node_modules/@sudocode-ai/local-server/dist/routes/workflows.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/routes/workflows.js +1729 -0
- package/node_modules/@sudocode-ai/local-server/dist/routes/workflows.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/agent-registry.d.ts +140 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/agent-registry.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/agent-registry.js +272 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/agent-registry.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/db.d.ts +33 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/db.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/db.js +90 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/db.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/editor-service.d.ts +57 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/editor-service.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/editor-service.js +204 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/editor-service.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/execution-changes-service.d.ts +110 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/execution-changes-service.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/execution-changes-service.js +710 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/execution-changes-service.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/execution-event-callbacks.d.ts +73 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/execution-event-callbacks.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/execution-event-callbacks.js +82 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/execution-event-callbacks.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/execution-lifecycle.d.ts +145 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/execution-lifecycle.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/execution-lifecycle.js +392 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/execution-lifecycle.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/execution-logs-cleanup.d.ts +88 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/execution-logs-cleanup.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/execution-logs-cleanup.js +137 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/execution-logs-cleanup.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/execution-logs-store.d.ts +252 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/execution-logs-store.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/execution-logs-store.js +379 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/execution-logs-store.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/execution-service.d.ts +280 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/execution-service.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/execution-service.js +1240 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/execution-service.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/execution-worker-pool.d.ts +116 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/execution-worker-pool.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/execution-worker-pool.js +326 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/execution-worker-pool.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/executions.d.ts +63 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/executions.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/executions.js +177 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/executions.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/export.d.ts +32 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/export.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/export.js +114 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/export.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/external-refresh-service.d.ts +104 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/external-refresh-service.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/external-refresh-service.js +520 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/external-refresh-service.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/feedback.d.ts +56 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/feedback.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/feedback.js +78 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/feedback.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/file-search/git-ls-files-strategy.d.ts +72 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/file-search/git-ls-files-strategy.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/file-search/git-ls-files-strategy.js +176 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/file-search/git-ls-files-strategy.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/file-search/index.d.ts +9 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/file-search/index.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/file-search/index.js +10 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/file-search/index.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/file-search/registry.d.ts +97 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/file-search/registry.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/file-search/registry.js +140 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/file-search/registry.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/file-search/strategy.d.ts +58 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/file-search/strategy.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/file-search/strategy.js +8 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/file-search/strategy.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/integration-sync-service.d.ts +185 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/integration-sync-service.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/integration-sync-service.js +428 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/integration-sync-service.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/issues.d.ts +27 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/issues.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/issues.js +35 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/issues.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/project-context.d.ts +97 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/project-context.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/project-context.js +170 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/project-context.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/project-manager.d.ts +102 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/project-manager.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/project-manager.js +502 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/project-manager.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/project-registry.d.ts +98 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/project-registry.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/project-registry.js +289 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/project-registry.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/prompt-resolver.d.ts +97 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/prompt-resolver.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/prompt-resolver.js +377 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/prompt-resolver.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/prompt-template-engine.d.ts +108 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/prompt-template-engine.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/prompt-template-engine.js +212 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/prompt-template-engine.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/prompt-templates.d.ts +97 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/prompt-templates.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/prompt-templates.js +236 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/prompt-templates.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/relationships.d.ts +35 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/relationships.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/relationships.js +42 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/relationships.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/repo-info.d.ts +33 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/repo-info.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/repo-info.js +136 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/repo-info.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/specs.d.ts +27 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/specs.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/specs.js +35 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/specs.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/version-service.d.ts +14 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/version-service.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/version-service.js +57 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/version-service.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/watcher.d.ts +49 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/watcher.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/watcher.js +52 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/watcher.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/websocket.d.ts +179 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/websocket.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/websocket.js +543 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/websocket.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/workflow-broadcast-service.d.ts +43 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/workflow-broadcast-service.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/workflow-broadcast-service.js +155 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/workflow-broadcast-service.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/worktree-sync-service.d.ts +437 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/worktree-sync-service.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/worktree-sync-service.js +1505 -0
- package/node_modules/@sudocode-ai/local-server/dist/services/worktree-sync-service.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/types/editor.d.ts +49 -0
- package/node_modules/@sudocode-ai/local-server/dist/types/editor.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/types/editor.js +50 -0
- package/node_modules/@sudocode-ai/local-server/dist/types/editor.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/types/project.d.ts +58 -0
- package/node_modules/@sudocode-ai/local-server/dist/types/project.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/types/project.js +10 -0
- package/node_modules/@sudocode-ai/local-server/dist/types/project.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/utils/execFileNoThrow.d.ts +43 -0
- package/node_modules/@sudocode-ai/local-server/dist/utils/execFileNoThrow.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/utils/execFileNoThrow.js +53 -0
- package/node_modules/@sudocode-ai/local-server/dist/utils/execFileNoThrow.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/utils/executable-check.d.ts +36 -0
- package/node_modules/@sudocode-ai/local-server/dist/utils/executable-check.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/utils/executable-check.js +79 -0
- package/node_modules/@sudocode-ai/local-server/dist/utils/executable-check.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/utils/sudocode-dir.d.ts +6 -0
- package/node_modules/@sudocode-ai/local-server/dist/utils/sudocode-dir.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/utils/sudocode-dir.js +9 -0
- package/node_modules/@sudocode-ai/local-server/dist/utils/sudocode-dir.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/workers/execution-worker.d.ts +18 -0
- package/node_modules/@sudocode-ai/local-server/dist/workers/execution-worker.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/workers/execution-worker.js +340 -0
- package/node_modules/@sudocode-ai/local-server/dist/workers/execution-worker.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/workers/worker-ipc.d.ts +84 -0
- package/node_modules/@sudocode-ai/local-server/dist/workers/worker-ipc.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/workers/worker-ipc.js +29 -0
- package/node_modules/@sudocode-ai/local-server/dist/workers/worker-ipc.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/workflow/base-workflow-engine.d.ts +186 -0
- package/node_modules/@sudocode-ai/local-server/dist/workflow/base-workflow-engine.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/workflow/base-workflow-engine.js +557 -0
- package/node_modules/@sudocode-ai/local-server/dist/workflow/base-workflow-engine.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/workflow/dependency-analyzer.d.ts +78 -0
- package/node_modules/@sudocode-ai/local-server/dist/workflow/dependency-analyzer.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/workflow/dependency-analyzer.js +264 -0
- package/node_modules/@sudocode-ai/local-server/dist/workflow/dependency-analyzer.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/workflow/engines/orchestrator-engine.d.ts +237 -0
- package/node_modules/@sudocode-ai/local-server/dist/workflow/engines/orchestrator-engine.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/workflow/engines/orchestrator-engine.js +749 -0
- package/node_modules/@sudocode-ai/local-server/dist/workflow/engines/orchestrator-engine.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/workflow/engines/sequential-engine.d.ts +276 -0
- package/node_modules/@sudocode-ai/local-server/dist/workflow/engines/sequential-engine.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/workflow/engines/sequential-engine.js +1110 -0
- package/node_modules/@sudocode-ai/local-server/dist/workflow/engines/sequential-engine.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/workflow/index.d.ts +15 -0
- package/node_modules/@sudocode-ai/local-server/dist/workflow/index.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/workflow/index.js +22 -0
- package/node_modules/@sudocode-ai/local-server/dist/workflow/index.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/workflow/mcp/api-client.d.ts +103 -0
- package/node_modules/@sudocode-ai/local-server/dist/workflow/mcp/api-client.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/workflow/mcp/api-client.js +193 -0
- package/node_modules/@sudocode-ai/local-server/dist/workflow/mcp/api-client.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/workflow/mcp/index.d.ts +16 -0
- package/node_modules/@sudocode-ai/local-server/dist/workflow/mcp/index.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/workflow/mcp/index.js +114 -0
- package/node_modules/@sudocode-ai/local-server/dist/workflow/mcp/index.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/workflow/mcp/server.d.ts +85 -0
- package/node_modules/@sudocode-ai/local-server/dist/workflow/mcp/server.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/workflow/mcp/server.js +520 -0
- package/node_modules/@sudocode-ai/local-server/dist/workflow/mcp/server.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/workflow/mcp/tools/escalation.d.ts +36 -0
- package/node_modules/@sudocode-ai/local-server/dist/workflow/mcp/tools/escalation.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/workflow/mcp/tools/escalation.js +47 -0
- package/node_modules/@sudocode-ai/local-server/dist/workflow/mcp/tools/escalation.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/workflow/mcp/tools/execution.d.ts +59 -0
- package/node_modules/@sudocode-ai/local-server/dist/workflow/mcp/tools/execution.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/workflow/mcp/tools/execution.js +67 -0
- package/node_modules/@sudocode-ai/local-server/dist/workflow/mcp/tools/execution.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/workflow/mcp/tools/inspection.d.ts +82 -0
- package/node_modules/@sudocode-ai/local-server/dist/workflow/mcp/tools/inspection.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/workflow/mcp/tools/inspection.js +57 -0
- package/node_modules/@sudocode-ai/local-server/dist/workflow/mcp/tools/inspection.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/workflow/mcp/tools/workflow.d.ts +59 -0
- package/node_modules/@sudocode-ai/local-server/dist/workflow/mcp/tools/workflow.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/workflow/mcp/tools/workflow.js +40 -0
- package/node_modules/@sudocode-ai/local-server/dist/workflow/mcp/tools/workflow.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/workflow/mcp/types.d.ts +345 -0
- package/node_modules/@sudocode-ai/local-server/dist/workflow/mcp/types.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/workflow/mcp/types.js +7 -0
- package/node_modules/@sudocode-ai/local-server/dist/workflow/mcp/types.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/workflow/services/prompt-builder.d.ts +36 -0
- package/node_modules/@sudocode-ai/local-server/dist/workflow/services/prompt-builder.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/workflow/services/prompt-builder.js +329 -0
- package/node_modules/@sudocode-ai/local-server/dist/workflow/services/prompt-builder.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/workflow/services/wakeup-service.d.ts +262 -0
- package/node_modules/@sudocode-ai/local-server/dist/workflow/services/wakeup-service.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/workflow/services/wakeup-service.js +809 -0
- package/node_modules/@sudocode-ai/local-server/dist/workflow/services/wakeup-service.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/workflow/workflow-engine.d.ts +221 -0
- package/node_modules/@sudocode-ai/local-server/dist/workflow/workflow-engine.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/workflow/workflow-engine.js +94 -0
- package/node_modules/@sudocode-ai/local-server/dist/workflow/workflow-engine.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/workflow/workflow-event-emitter.d.ts +278 -0
- package/node_modules/@sudocode-ai/local-server/dist/workflow/workflow-event-emitter.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/local-server/dist/workflow/workflow-event-emitter.js +259 -0
- package/node_modules/@sudocode-ai/local-server/dist/workflow/workflow-event-emitter.js.map +1 -0
- package/node_modules/@sudocode-ai/local-server/package.json +78 -0
- package/node_modules/@sudocode-ai/mcp/README.md +226 -0
- package/node_modules/@sudocode-ai/mcp/dist/client.d.ts +33 -0
- package/node_modules/@sudocode-ai/mcp/dist/client.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/mcp/dist/client.js +166 -0
- package/node_modules/@sudocode-ai/mcp/dist/client.js.map +1 -0
- package/node_modules/@sudocode-ai/mcp/dist/index.d.ts +6 -0
- package/node_modules/@sudocode-ai/mcp/dist/index.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/mcp/dist/index.js +64 -0
- package/node_modules/@sudocode-ai/mcp/dist/index.js.map +1 -0
- package/node_modules/@sudocode-ai/mcp/dist/server.d.ts +26 -0
- package/node_modules/@sudocode-ai/mcp/dist/server.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/mcp/dist/server.js +577 -0
- package/node_modules/@sudocode-ai/mcp/dist/server.js.map +1 -0
- package/node_modules/@sudocode-ai/mcp/dist/tools/analytics.d.ts +41 -0
- package/node_modules/@sudocode-ai/mcp/dist/tools/analytics.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/mcp/dist/tools/analytics.js +21 -0
- package/node_modules/@sudocode-ai/mcp/dist/tools/analytics.js.map +1 -0
- package/node_modules/@sudocode-ai/mcp/dist/tools/feedback.d.ts +21 -0
- package/node_modules/@sudocode-ai/mcp/dist/tools/feedback.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/mcp/dist/tools/feedback.js +30 -0
- package/node_modules/@sudocode-ai/mcp/dist/tools/feedback.js.map +1 -0
- package/node_modules/@sudocode-ai/mcp/dist/tools/init.d.ts +17 -0
- package/node_modules/@sudocode-ai/mcp/dist/tools/init.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/mcp/dist/tools/init.js +15 -0
- package/node_modules/@sudocode-ai/mcp/dist/tools/init.js.map +1 -0
- package/node_modules/@sudocode-ai/mcp/dist/tools/issues.d.ts +44 -0
- package/node_modules/@sudocode-ai/mcp/dist/tools/issues.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/mcp/dist/tools/issues.js +109 -0
- package/node_modules/@sudocode-ai/mcp/dist/tools/issues.js.map +1 -0
- package/node_modules/@sudocode-ai/mcp/dist/tools/references.d.ts +21 -0
- package/node_modules/@sudocode-ai/mcp/dist/tools/references.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/mcp/dist/tools/references.js +49 -0
- package/node_modules/@sudocode-ai/mcp/dist/tools/references.js.map +1 -0
- package/node_modules/@sudocode-ai/mcp/dist/tools/relationships.d.ts +15 -0
- package/node_modules/@sudocode-ai/mcp/dist/tools/relationships.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/mcp/dist/tools/relationships.js +18 -0
- package/node_modules/@sudocode-ai/mcp/dist/tools/relationships.js.map +1 -0
- package/node_modules/@sudocode-ai/mcp/dist/tools/specs.d.ts +35 -0
- package/node_modules/@sudocode-ai/mcp/dist/tools/specs.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/mcp/dist/tools/specs.js +85 -0
- package/node_modules/@sudocode-ai/mcp/dist/tools/specs.js.map +1 -0
- package/node_modules/@sudocode-ai/mcp/dist/types.d.ts +35 -0
- package/node_modules/@sudocode-ai/mcp/dist/types.d.ts.map +1 -0
- package/node_modules/@sudocode-ai/mcp/dist/types.js +21 -0
- package/node_modules/@sudocode-ai/mcp/dist/types.js.map +1 -0
- package/node_modules/@sudocode-ai/mcp/package.json +67 -0
- package/node_modules/@sudocode-ai/types/README.md +7 -0
- package/node_modules/@sudocode-ai/types/package.json +76 -0
- package/node_modules/@sudocode-ai/types/src/agents.d.ts +278 -0
- package/node_modules/@sudocode-ai/types/src/artifacts.d.ts +66 -0
- package/node_modules/@sudocode-ai/types/src/events.d.ts +70 -0
- package/node_modules/@sudocode-ai/types/src/index.d.ts +452 -0
- package/node_modules/@sudocode-ai/types/src/integrations.d.ts +454 -0
- package/node_modules/@sudocode-ai/types/src/workflows.d.ts +501 -0
- package/node_modules/commander/LICENSE +22 -0
- package/node_modules/commander/Readme.md +1149 -0
- package/node_modules/commander/esm.mjs +16 -0
- package/node_modules/commander/index.js +24 -0
- package/node_modules/commander/lib/argument.js +149 -0
- package/node_modules/commander/lib/command.js +2662 -0
- package/node_modules/commander/lib/error.js +39 -0
- package/node_modules/commander/lib/help.js +709 -0
- package/node_modules/commander/lib/option.js +367 -0
- package/node_modules/commander/lib/suggestSimilar.js +101 -0
- package/node_modules/commander/package-support.json +16 -0
- package/node_modules/commander/package.json +82 -0
- package/node_modules/commander/typings/esm.d.mts +3 -0
- package/node_modules/commander/typings/index.d.ts +1045 -0
- package/node_modules/glob/LICENSE +15 -0
- package/node_modules/glob/README.md +1265 -0
- package/node_modules/glob/package.json +99 -0
- package/node_modules/isexe/LICENSE +15 -0
- package/node_modules/isexe/README.md +74 -0
- package/node_modules/isexe/package.json +96 -0
- package/node_modules/which/LICENSE +15 -0
- package/node_modules/which/README.md +51 -0
- package/node_modules/which/bin/which.js +52 -0
- package/node_modules/which/lib/index.js +111 -0
- package/node_modules/which/package.json +52 -0
- package/package.json +9 -9
|
@@ -0,0 +1,1505 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Worktree Sync Service
|
|
3
|
+
*
|
|
4
|
+
* Orchestrates worktree sync operations including conflict detection,
|
|
5
|
+
* JSONL resolution, git operations, and database updates.
|
|
6
|
+
*
|
|
7
|
+
* @module services/worktree-sync-service
|
|
8
|
+
*/
|
|
9
|
+
import * as fs from "fs";
|
|
10
|
+
import * as path from "path";
|
|
11
|
+
import { execSync } from "child_process";
|
|
12
|
+
import { GitSyncCli, } from "../execution/worktree/git-sync-cli.js";
|
|
13
|
+
import { ConflictDetector, } from "../execution/worktree/conflict-detector.js";
|
|
14
|
+
import { mergeThreeWay, hasGitConflictMarkers, parseMergeConflictFile, resolveEntities, } from "@sudocode-ai/cli/dist/merge-resolver.js";
|
|
15
|
+
import { writeJSONL, readJSONLSync, } from "@sudocode-ai/cli/dist/jsonl.js";
|
|
16
|
+
import * as os from "os";
|
|
17
|
+
/**
|
|
18
|
+
* Worktree sync error codes
|
|
19
|
+
*/
|
|
20
|
+
export var WorktreeSyncErrorCode;
|
|
21
|
+
(function (WorktreeSyncErrorCode) {
|
|
22
|
+
WorktreeSyncErrorCode["NO_WORKTREE"] = "NO_WORKTREE";
|
|
23
|
+
WorktreeSyncErrorCode["WORKTREE_MISSING"] = "WORKTREE_MISSING";
|
|
24
|
+
WorktreeSyncErrorCode["BRANCH_MISSING"] = "BRANCH_MISSING";
|
|
25
|
+
WorktreeSyncErrorCode["DIRTY_WORKING_TREE"] = "DIRTY_WORKING_TREE";
|
|
26
|
+
WorktreeSyncErrorCode["TARGET_BRANCH_MISSING"] = "TARGET_BRANCH_MISSING";
|
|
27
|
+
WorktreeSyncErrorCode["NO_COMMON_BASE"] = "NO_COMMON_BASE";
|
|
28
|
+
WorktreeSyncErrorCode["CODE_CONFLICTS"] = "CODE_CONFLICTS";
|
|
29
|
+
WorktreeSyncErrorCode["MERGE_FAILED"] = "MERGE_FAILED";
|
|
30
|
+
WorktreeSyncErrorCode["JSONL_RESOLUTION_FAILED"] = "JSONL_RESOLUTION_FAILED";
|
|
31
|
+
WorktreeSyncErrorCode["DATABASE_SYNC_FAILED"] = "DATABASE_SYNC_FAILED";
|
|
32
|
+
WorktreeSyncErrorCode["EXECUTION_NOT_FOUND"] = "EXECUTION_NOT_FOUND";
|
|
33
|
+
})(WorktreeSyncErrorCode || (WorktreeSyncErrorCode = {}));
|
|
34
|
+
/**
|
|
35
|
+
* Worktree sync error class
|
|
36
|
+
*/
|
|
37
|
+
export class WorktreeSyncError extends Error {
|
|
38
|
+
code;
|
|
39
|
+
cause;
|
|
40
|
+
constructor(message, code, cause) {
|
|
41
|
+
super(message);
|
|
42
|
+
this.code = code;
|
|
43
|
+
this.cause = cause;
|
|
44
|
+
this.name = "WorktreeSyncError";
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* WorktreeSyncService
|
|
49
|
+
*
|
|
50
|
+
* Main service class for orchestrating worktree sync operations
|
|
51
|
+
*/
|
|
52
|
+
export class WorktreeSyncService {
|
|
53
|
+
db;
|
|
54
|
+
repoPath;
|
|
55
|
+
gitSync;
|
|
56
|
+
constructor(db, repoPath) {
|
|
57
|
+
this.db = db;
|
|
58
|
+
this.repoPath = repoPath;
|
|
59
|
+
this.gitSync = new GitSyncCli(repoPath);
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Preview sync without making changes
|
|
63
|
+
*
|
|
64
|
+
* @param executionId - Execution ID to preview sync for
|
|
65
|
+
* @returns Preview result with conflicts, diff, and warnings
|
|
66
|
+
*/
|
|
67
|
+
async previewSync(executionId) {
|
|
68
|
+
// 1. Load execution and validate
|
|
69
|
+
const execution = await this._loadAndValidateExecution(executionId);
|
|
70
|
+
// 2. Validate critical preconditions (ones that prevent us from getting any info)
|
|
71
|
+
// These are "hard" failures - we can't get diff/commits if these fail
|
|
72
|
+
const criticalPreconditionError = await this._validateCriticalPreconditions(execution);
|
|
73
|
+
if (criticalPreconditionError) {
|
|
74
|
+
return {
|
|
75
|
+
canSync: false,
|
|
76
|
+
conflicts: {
|
|
77
|
+
hasConflicts: false,
|
|
78
|
+
codeConflicts: [],
|
|
79
|
+
jsonlConflicts: [],
|
|
80
|
+
totalFiles: 0,
|
|
81
|
+
summary: "",
|
|
82
|
+
},
|
|
83
|
+
diff: { files: [], additions: 0, deletions: 0 },
|
|
84
|
+
commits: [],
|
|
85
|
+
mergeBase: "",
|
|
86
|
+
uncommittedJSONLChanges: [],
|
|
87
|
+
uncommittedChanges: { files: [], additions: 0, deletions: 0 },
|
|
88
|
+
executionStatus: execution.status,
|
|
89
|
+
warnings: [criticalPreconditionError],
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
// 3. Create ConflictDetector instance for worktree context
|
|
93
|
+
const worktreeConflictDetector = new ConflictDetector(execution.worktree_path);
|
|
94
|
+
// 4. Find merge base (use main repo since it has both branches)
|
|
95
|
+
const mergeBase = this.gitSync.getMergeBase(execution.branch_name, execution.target_branch);
|
|
96
|
+
// 4. Get commit list
|
|
97
|
+
const commits = this.gitSync.getCommitList(mergeBase, execution.branch_name);
|
|
98
|
+
// 6. Get diff summary (use main repo to see all changes)
|
|
99
|
+
const diff = this.gitSync.getDiff(mergeBase, execution.branch_name);
|
|
100
|
+
// 7. Detect conflicts (use worktree for conflict detection)
|
|
101
|
+
const conflicts = worktreeConflictDetector.detectConflicts(execution.branch_name, execution.target_branch);
|
|
102
|
+
// 7. Check for uncommitted changes in worktree (not included by default)
|
|
103
|
+
const uncommittedFiles = this._getUncommittedFiles(execution.worktree_path);
|
|
104
|
+
const uncommittedJSONL = uncommittedFiles.filter((file) => file.endsWith(".jsonl") &&
|
|
105
|
+
(file.includes(".sudocode/") || file.startsWith(".sudocode/")));
|
|
106
|
+
const uncommittedChanges = this._getUncommittedFileStats(execution.worktree_path);
|
|
107
|
+
// 8. Generate warnings and check "soft" preconditions
|
|
108
|
+
const warnings = [];
|
|
109
|
+
let canSync = true;
|
|
110
|
+
// Check local working tree status (categorizes JSONL vs other uncommitted changes)
|
|
111
|
+
const localWorkingTreeStatus = this.gitSync.getWorkingTreeStatus();
|
|
112
|
+
let localUncommittedJsonl;
|
|
113
|
+
if (!localWorkingTreeStatus.isClean) {
|
|
114
|
+
if (localWorkingTreeStatus.hasOnlyJsonlChanges) {
|
|
115
|
+
// Only JSONL files uncommitted - can still sync, will auto-merge
|
|
116
|
+
localUncommittedJsonl = {
|
|
117
|
+
files: localWorkingTreeStatus.uncommittedJsonlFiles,
|
|
118
|
+
willAutoMerge: true,
|
|
119
|
+
};
|
|
120
|
+
// Don't add warning - info will be shown in UI
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
// Non-JSONL files are uncommitted - block sync
|
|
124
|
+
warnings.push("Local working tree has uncommitted changes. Stash or commit them first.");
|
|
125
|
+
canSync = false;
|
|
126
|
+
// Still include JSONL info for context
|
|
127
|
+
if (localWorkingTreeStatus.uncommittedJsonlFiles.length > 0) {
|
|
128
|
+
localUncommittedJsonl = {
|
|
129
|
+
files: localWorkingTreeStatus.uncommittedJsonlFiles,
|
|
130
|
+
willAutoMerge: false, // Can't auto-merge if there are other uncommitted files
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
// Warn if execution is running/paused
|
|
136
|
+
if (execution.status === "running" || execution.status === "paused") {
|
|
137
|
+
warnings.push("Execution is currently active. Synced state may not reflect final execution result.");
|
|
138
|
+
}
|
|
139
|
+
// Warn about code conflicts
|
|
140
|
+
if (conflicts.codeConflicts.length > 0) {
|
|
141
|
+
warnings.push(`${conflicts.codeConflicts.length} code conflict(s) detected. Manual resolution may be required.`);
|
|
142
|
+
}
|
|
143
|
+
// Note about uncommitted files (not included by default)
|
|
144
|
+
// if (uncommittedChanges && uncommittedChanges.files.length > 0) {
|
|
145
|
+
// warnings.push(
|
|
146
|
+
// `${uncommittedChanges.files.length} uncommitted file(s) in worktree will NOT be included (only committed changes are synced).`
|
|
147
|
+
// );
|
|
148
|
+
// }
|
|
149
|
+
// 9. Detect potential local conflicts for uncommitted files
|
|
150
|
+
// These are files in worktree that also have local changes or are untracked locally
|
|
151
|
+
const potentialLocalConflicts = this._detectPotentialLocalConflicts(uncommittedChanges?.files || []);
|
|
152
|
+
return {
|
|
153
|
+
canSync,
|
|
154
|
+
conflicts,
|
|
155
|
+
diff,
|
|
156
|
+
commits,
|
|
157
|
+
mergeBase,
|
|
158
|
+
uncommittedJSONLChanges: uncommittedJSONL,
|
|
159
|
+
uncommittedChanges,
|
|
160
|
+
potentialLocalConflicts,
|
|
161
|
+
localUncommittedJsonl,
|
|
162
|
+
executionStatus: execution.status,
|
|
163
|
+
warnings,
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Validate critical preconditions that prevent us from getting any sync info
|
|
168
|
+
*
|
|
169
|
+
* These are "hard" failures - if these fail, we can't get diff/commits info.
|
|
170
|
+
* Returns an error message if validation fails, null if validation passes.
|
|
171
|
+
*
|
|
172
|
+
* @param execution - Execution to validate
|
|
173
|
+
* @returns Error message if validation fails, null if validation passes
|
|
174
|
+
*/
|
|
175
|
+
async _validateCriticalPreconditions(execution) {
|
|
176
|
+
// 1. Check worktree path exists
|
|
177
|
+
if (!execution.worktree_path) {
|
|
178
|
+
return "No worktree path for execution";
|
|
179
|
+
}
|
|
180
|
+
// 2. Check worktree still exists on filesystem
|
|
181
|
+
if (!fs.existsSync(execution.worktree_path)) {
|
|
182
|
+
return "Worktree no longer exists";
|
|
183
|
+
}
|
|
184
|
+
// 3. Get list of branches
|
|
185
|
+
const branches = this._getBranches();
|
|
186
|
+
// 4. Check worktree branch exists
|
|
187
|
+
if (!branches.includes(execution.branch_name)) {
|
|
188
|
+
return `Worktree branch '${execution.branch_name}' not found`;
|
|
189
|
+
}
|
|
190
|
+
// 5. Check target branch exists
|
|
191
|
+
if (!branches.includes(execution.target_branch)) {
|
|
192
|
+
return `Target branch '${execution.target_branch}' not found`;
|
|
193
|
+
}
|
|
194
|
+
// 6. Verify branches have common base
|
|
195
|
+
try {
|
|
196
|
+
this.gitSync.getMergeBase(execution.branch_name, execution.target_branch);
|
|
197
|
+
}
|
|
198
|
+
catch (error) {
|
|
199
|
+
return "Worktree and target branch have diverged without common history";
|
|
200
|
+
}
|
|
201
|
+
return null;
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Load execution from database and validate it exists
|
|
205
|
+
*
|
|
206
|
+
* Used by previewSync() and will be used in i-9gz4 (squash sync)
|
|
207
|
+
*
|
|
208
|
+
* @param executionId - Execution ID to load
|
|
209
|
+
* @returns Execution record
|
|
210
|
+
* @throws WorktreeSyncError if execution not found
|
|
211
|
+
*/
|
|
212
|
+
async _loadAndValidateExecution(executionId) {
|
|
213
|
+
const stmt = this.db.prepare("SELECT * FROM executions WHERE id = ?");
|
|
214
|
+
const execution = stmt.get(executionId);
|
|
215
|
+
if (!execution) {
|
|
216
|
+
throw new WorktreeSyncError(`Execution ${executionId} not found`, WorktreeSyncErrorCode.EXECUTION_NOT_FOUND);
|
|
217
|
+
}
|
|
218
|
+
return execution;
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Validate preconditions for sync
|
|
222
|
+
*
|
|
223
|
+
* Used by previewSync() and will be used in i-9gz4 (squash sync)
|
|
224
|
+
*
|
|
225
|
+
* Checks:
|
|
226
|
+
* - Worktree exists
|
|
227
|
+
* - Worktree branch exists
|
|
228
|
+
* - Local working tree is clean (or only has JSONL changes which can be auto-merged)
|
|
229
|
+
* - Target branch exists
|
|
230
|
+
* - Branches have common base
|
|
231
|
+
*
|
|
232
|
+
* @param execution - Execution to validate
|
|
233
|
+
* @param options - Options to control validation behavior
|
|
234
|
+
* @param options.skipDirtyWorkingTreeCheck - Skip the dirty working tree check entirely
|
|
235
|
+
* @param options.allowJsonlOnlyChanges - Allow sync if only JSONL files are uncommitted (they'll be auto-merged)
|
|
236
|
+
* @throws WorktreeSyncError if any precondition fails
|
|
237
|
+
*/
|
|
238
|
+
async _validateSyncPreconditions(execution, options) {
|
|
239
|
+
const { skipDirtyWorkingTreeCheck = false, allowJsonlOnlyChanges = false } = options || {};
|
|
240
|
+
// 1. Check worktree path exists
|
|
241
|
+
if (!execution.worktree_path) {
|
|
242
|
+
throw new WorktreeSyncError("No worktree path for execution", WorktreeSyncErrorCode.NO_WORKTREE);
|
|
243
|
+
}
|
|
244
|
+
// 2. Check worktree still exists on filesystem
|
|
245
|
+
if (!fs.existsSync(execution.worktree_path)) {
|
|
246
|
+
throw new WorktreeSyncError("Worktree no longer exists", WorktreeSyncErrorCode.WORKTREE_MISSING);
|
|
247
|
+
}
|
|
248
|
+
// 3. Get list of branches
|
|
249
|
+
const branches = this._getBranches();
|
|
250
|
+
// 4. Check worktree branch exists
|
|
251
|
+
if (!branches.includes(execution.branch_name)) {
|
|
252
|
+
throw new WorktreeSyncError(`Worktree branch '${execution.branch_name}' not found`, WorktreeSyncErrorCode.BRANCH_MISSING);
|
|
253
|
+
}
|
|
254
|
+
// 5. Check target branch exists
|
|
255
|
+
if (!branches.includes(execution.target_branch)) {
|
|
256
|
+
throw new WorktreeSyncError(`Target branch '${execution.target_branch}' not found`, WorktreeSyncErrorCode.TARGET_BRANCH_MISSING);
|
|
257
|
+
}
|
|
258
|
+
// 6. Check local working tree is clean (skip for stage mode since it doesn't commit)
|
|
259
|
+
if (!skipDirtyWorkingTreeCheck) {
|
|
260
|
+
const workingTreeStatus = this.gitSync.getWorkingTreeStatus();
|
|
261
|
+
if (!workingTreeStatus.isClean) {
|
|
262
|
+
// If only JSONL files are uncommitted and allowJsonlOnlyChanges is true, allow sync
|
|
263
|
+
if (allowJsonlOnlyChanges && workingTreeStatus.hasOnlyJsonlChanges) {
|
|
264
|
+
// This is OK - JSONL files will be auto-merged
|
|
265
|
+
}
|
|
266
|
+
else if (workingTreeStatus.uncommittedOtherFiles.length > 0) {
|
|
267
|
+
// Non-JSONL files are uncommitted - block sync
|
|
268
|
+
throw new WorktreeSyncError("Local working tree has uncommitted changes. Stash or commit them first.", WorktreeSyncErrorCode.DIRTY_WORKING_TREE);
|
|
269
|
+
}
|
|
270
|
+
else {
|
|
271
|
+
// Only JSONL files but allowJsonlOnlyChanges is false - block sync
|
|
272
|
+
throw new WorktreeSyncError("Local working tree has uncommitted changes. Stash or commit them first.", WorktreeSyncErrorCode.DIRTY_WORKING_TREE);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
// 7. Verify branches have common base
|
|
277
|
+
try {
|
|
278
|
+
this.gitSync.getMergeBase(execution.branch_name, execution.target_branch);
|
|
279
|
+
}
|
|
280
|
+
catch (error) {
|
|
281
|
+
throw new WorktreeSyncError("Worktree and target branch have diverged without common history", WorktreeSyncErrorCode.NO_COMMON_BASE, error);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* Saved state of uncommitted JSONL files for restoration after merge
|
|
286
|
+
*/
|
|
287
|
+
_savedUncommittedJsonl = null;
|
|
288
|
+
/**
|
|
289
|
+
* Save uncommitted JSONL files before merge operation
|
|
290
|
+
*
|
|
291
|
+
* Reads both the uncommitted (working tree) and committed (HEAD) versions
|
|
292
|
+
* of each JSONL file, then resets the working tree copy to HEAD.
|
|
293
|
+
* The saved versions can be restored with _restoreUncommittedJsonl().
|
|
294
|
+
*
|
|
295
|
+
* @returns Map of file paths to their uncommitted and pre-committed content
|
|
296
|
+
*/
|
|
297
|
+
async _saveUncommittedJsonl() {
|
|
298
|
+
const status = this.gitSync.getWorkingTreeStatus();
|
|
299
|
+
const savedFiles = new Map();
|
|
300
|
+
for (const filePath of status.uncommittedJsonlFiles) {
|
|
301
|
+
const fullPath = path.join(this.repoPath, filePath);
|
|
302
|
+
// Read current uncommitted content from working tree
|
|
303
|
+
let uncommittedContent = "";
|
|
304
|
+
if (fs.existsSync(fullPath)) {
|
|
305
|
+
uncommittedContent = fs.readFileSync(fullPath, "utf8");
|
|
306
|
+
}
|
|
307
|
+
// Read committed version from HEAD
|
|
308
|
+
let preCommittedContent = "";
|
|
309
|
+
try {
|
|
310
|
+
preCommittedContent = execSync(`git show HEAD:${this._escapeShellArg(filePath)}`, {
|
|
311
|
+
cwd: this.repoPath,
|
|
312
|
+
encoding: "utf8",
|
|
313
|
+
stdio: "pipe",
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
catch {
|
|
317
|
+
// File might not exist at HEAD (new file), use empty content
|
|
318
|
+
preCommittedContent = "";
|
|
319
|
+
}
|
|
320
|
+
savedFiles.set(filePath, { uncommittedContent, preCommittedContent });
|
|
321
|
+
// Reset the file to HEAD so it doesn't interfere with merge
|
|
322
|
+
try {
|
|
323
|
+
execSync(`git checkout HEAD -- ${this._escapeShellArg(filePath)}`, {
|
|
324
|
+
cwd: this.repoPath,
|
|
325
|
+
stdio: "pipe",
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
catch {
|
|
329
|
+
// If file doesn't exist at HEAD, remove it from working tree
|
|
330
|
+
if (fs.existsSync(fullPath)) {
|
|
331
|
+
fs.unlinkSync(fullPath);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
this._savedUncommittedJsonl = savedFiles;
|
|
336
|
+
return savedFiles;
|
|
337
|
+
}
|
|
338
|
+
/**
|
|
339
|
+
* Restore uncommitted JSONL files after merge operation
|
|
340
|
+
*
|
|
341
|
+
* Performs a three-way merge:
|
|
342
|
+
* - base: pre-merge committed version (from HEAD before merge)
|
|
343
|
+
* - ours: saved uncommitted local changes
|
|
344
|
+
* - theirs: post-merge result
|
|
345
|
+
*
|
|
346
|
+
* The merged result is written back to the working tree.
|
|
347
|
+
*/
|
|
348
|
+
async _restoreUncommittedJsonl() {
|
|
349
|
+
if (!this._savedUncommittedJsonl || this._savedUncommittedJsonl.size === 0) {
|
|
350
|
+
return;
|
|
351
|
+
}
|
|
352
|
+
for (const [filePath, saved] of this._savedUncommittedJsonl) {
|
|
353
|
+
const fullPath = path.join(this.repoPath, filePath);
|
|
354
|
+
// Read post-merge version from working tree
|
|
355
|
+
let postMergeContent = "";
|
|
356
|
+
if (fs.existsSync(fullPath)) {
|
|
357
|
+
postMergeContent = fs.readFileSync(fullPath, "utf8");
|
|
358
|
+
}
|
|
359
|
+
// Parse all three versions as JSONL entities
|
|
360
|
+
const parseJsonl = (content) => {
|
|
361
|
+
if (!content.trim())
|
|
362
|
+
return [];
|
|
363
|
+
return content
|
|
364
|
+
.split("\n")
|
|
365
|
+
.filter((line) => line.trim())
|
|
366
|
+
.map((line) => {
|
|
367
|
+
try {
|
|
368
|
+
return JSON.parse(line);
|
|
369
|
+
}
|
|
370
|
+
catch {
|
|
371
|
+
return null;
|
|
372
|
+
}
|
|
373
|
+
})
|
|
374
|
+
.filter((entity) => entity !== null);
|
|
375
|
+
};
|
|
376
|
+
const baseEntities = parseJsonl(saved.preCommittedContent);
|
|
377
|
+
const oursEntities = parseJsonl(saved.uncommittedContent);
|
|
378
|
+
const theirsEntities = parseJsonl(postMergeContent);
|
|
379
|
+
// Perform three-way merge using the merge resolver
|
|
380
|
+
const { entities: merged } = mergeThreeWay(baseEntities, oursEntities, theirsEntities);
|
|
381
|
+
// Write merged result back to working tree
|
|
382
|
+
await writeJSONL(fullPath, merged);
|
|
383
|
+
}
|
|
384
|
+
// Clear saved state
|
|
385
|
+
this._savedUncommittedJsonl = null;
|
|
386
|
+
}
|
|
387
|
+
/**
|
|
388
|
+
* Create safety snapshot before sync
|
|
389
|
+
*
|
|
390
|
+
* Creates a git tag pointing to current target branch HEAD
|
|
391
|
+
* for rollback capability
|
|
392
|
+
*
|
|
393
|
+
* @param executionId - Execution ID
|
|
394
|
+
* @param targetBranch - Target branch name
|
|
395
|
+
* @returns Tag name created
|
|
396
|
+
*/
|
|
397
|
+
async _createSafetySnapshot(executionId, targetBranch) {
|
|
398
|
+
const tagName = `sudocode-sync-before-${executionId}`;
|
|
399
|
+
// Get current commit of target branch
|
|
400
|
+
const currentCommit = this._getCurrentCommit(targetBranch);
|
|
401
|
+
// Create annotated tag
|
|
402
|
+
this.gitSync.createSafetyTag(tagName, currentCommit);
|
|
403
|
+
return tagName;
|
|
404
|
+
}
|
|
405
|
+
/**
|
|
406
|
+
* Get all uncommitted files from worktree
|
|
407
|
+
*
|
|
408
|
+
* @param worktreePath - Path to worktree
|
|
409
|
+
* @returns Array of all uncommitted file paths
|
|
410
|
+
*/
|
|
411
|
+
_getUncommittedFiles(worktreePath) {
|
|
412
|
+
const gitSyncWorktree = new GitSyncCli(worktreePath);
|
|
413
|
+
return gitSyncWorktree.getUncommittedFiles();
|
|
414
|
+
}
|
|
415
|
+
/**
|
|
416
|
+
* Get uncommitted file stats from worktree
|
|
417
|
+
*
|
|
418
|
+
* Returns list of files and aggregate additions/deletions stats
|
|
419
|
+
* for uncommitted changes in the worktree.
|
|
420
|
+
*
|
|
421
|
+
* @param worktreePath - Path to worktree
|
|
422
|
+
* @returns Uncommitted file stats
|
|
423
|
+
*/
|
|
424
|
+
_getUncommittedFileStats(worktreePath) {
|
|
425
|
+
try {
|
|
426
|
+
// Get modified files
|
|
427
|
+
const modifiedOutput = execSync("git diff --numstat", {
|
|
428
|
+
cwd: worktreePath,
|
|
429
|
+
encoding: "utf8",
|
|
430
|
+
stdio: "pipe",
|
|
431
|
+
});
|
|
432
|
+
// Get untracked files
|
|
433
|
+
const untrackedFiles = execSync("git ls-files --others --exclude-standard", {
|
|
434
|
+
cwd: worktreePath,
|
|
435
|
+
encoding: "utf8",
|
|
436
|
+
stdio: "pipe",
|
|
437
|
+
})
|
|
438
|
+
.split("\n")
|
|
439
|
+
.filter((line) => line.trim().length > 0);
|
|
440
|
+
// Parse modified file stats
|
|
441
|
+
let additions = 0;
|
|
442
|
+
let deletions = 0;
|
|
443
|
+
const modifiedFiles = [];
|
|
444
|
+
for (const line of modifiedOutput.split("\n")) {
|
|
445
|
+
if (!line.trim())
|
|
446
|
+
continue;
|
|
447
|
+
const parts = line.split("\t");
|
|
448
|
+
if (parts.length >= 3) {
|
|
449
|
+
const add = parts[0] === "-" ? 0 : parseInt(parts[0], 10) || 0;
|
|
450
|
+
const del = parts[1] === "-" ? 0 : parseInt(parts[1], 10) || 0;
|
|
451
|
+
additions += add;
|
|
452
|
+
deletions += del;
|
|
453
|
+
modifiedFiles.push(parts[2]);
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
// Count lines in untracked files as additions
|
|
457
|
+
for (const filePath of untrackedFiles) {
|
|
458
|
+
try {
|
|
459
|
+
const fullPath = path.join(worktreePath, filePath);
|
|
460
|
+
if (fs.existsSync(fullPath) && fs.statSync(fullPath).isFile()) {
|
|
461
|
+
const content = fs.readFileSync(fullPath, "utf-8");
|
|
462
|
+
additions += content.split("\n").length;
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
catch (e) {
|
|
466
|
+
// Skip files we can't read
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
// Combine all files
|
|
470
|
+
const allFiles = [...new Set([...modifiedFiles, ...untrackedFiles])];
|
|
471
|
+
return {
|
|
472
|
+
files: allFiles,
|
|
473
|
+
additions,
|
|
474
|
+
deletions,
|
|
475
|
+
};
|
|
476
|
+
}
|
|
477
|
+
catch (error) {
|
|
478
|
+
// Return empty stats on error
|
|
479
|
+
return {
|
|
480
|
+
files: [],
|
|
481
|
+
additions: 0,
|
|
482
|
+
deletions: 0,
|
|
483
|
+
};
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
/**
|
|
487
|
+
* Check if local working tree is clean
|
|
488
|
+
*
|
|
489
|
+
* TODO: Will be used in i-7ya6 (sync preview)
|
|
490
|
+
*
|
|
491
|
+
* @returns true if clean, false if dirty
|
|
492
|
+
*/
|
|
493
|
+
// @ts-expect-error - Foundation method, will be used in i-7ya6
|
|
494
|
+
_isLocalTreeClean() {
|
|
495
|
+
return this.gitSync.isWorkingTreeClean();
|
|
496
|
+
}
|
|
497
|
+
/**
|
|
498
|
+
* Get list of branches in repository
|
|
499
|
+
*
|
|
500
|
+
* @returns Array of branch names
|
|
501
|
+
*/
|
|
502
|
+
_getBranches() {
|
|
503
|
+
try {
|
|
504
|
+
const output = execSync("git branch --format='%(refname:short)'", {
|
|
505
|
+
cwd: this.repoPath,
|
|
506
|
+
encoding: "utf8",
|
|
507
|
+
stdio: "pipe",
|
|
508
|
+
shell: "/bin/bash",
|
|
509
|
+
});
|
|
510
|
+
return output
|
|
511
|
+
.split("\n")
|
|
512
|
+
.map((line) => line.trim())
|
|
513
|
+
.filter((line) => line.length > 0);
|
|
514
|
+
}
|
|
515
|
+
catch (error) {
|
|
516
|
+
throw new WorktreeSyncError(`Failed to get branch list: ${error.message}`, WorktreeSyncErrorCode.BRANCH_MISSING, error);
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
/**
|
|
520
|
+
* Get current commit SHA for a branch
|
|
521
|
+
*
|
|
522
|
+
* @param branchName - Branch name
|
|
523
|
+
* @returns Commit SHA
|
|
524
|
+
*/
|
|
525
|
+
_getCurrentCommit(branchName) {
|
|
526
|
+
try {
|
|
527
|
+
const output = execSync(`git rev-parse ${this._escapeShellArg(branchName)}`, {
|
|
528
|
+
cwd: this.repoPath,
|
|
529
|
+
encoding: "utf8",
|
|
530
|
+
stdio: "pipe",
|
|
531
|
+
});
|
|
532
|
+
return output.trim();
|
|
533
|
+
}
|
|
534
|
+
catch (error) {
|
|
535
|
+
throw new WorktreeSyncError(`Failed to get commit for branch ${branchName}: ${error.message}`, WorktreeSyncErrorCode.BRANCH_MISSING, error);
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
/**
|
|
539
|
+
* Escape shell argument for safe command execution
|
|
540
|
+
*
|
|
541
|
+
* @param arg - Argument to escape
|
|
542
|
+
* @returns Escaped argument
|
|
543
|
+
*/
|
|
544
|
+
_escapeShellArg(arg) {
|
|
545
|
+
// Escape single quotes and wrap in single quotes
|
|
546
|
+
return `'${arg.replace(/'/g, "'\\''")}'`;
|
|
547
|
+
}
|
|
548
|
+
/**
|
|
549
|
+
* Resolve JSONL conflicts using three-way merge
|
|
550
|
+
*
|
|
551
|
+
* Used in squash sync to auto-resolve JSONL conflicts
|
|
552
|
+
*
|
|
553
|
+
* @param execution - Execution record
|
|
554
|
+
* @param jsonlConflicts - List of JSONL conflicts to resolve
|
|
555
|
+
* @throws WorktreeSyncError if resolution fails
|
|
556
|
+
*/
|
|
557
|
+
async resolveJSONLConflicts(execution, jsonlConflicts) {
|
|
558
|
+
if (jsonlConflicts.length === 0) {
|
|
559
|
+
return;
|
|
560
|
+
}
|
|
561
|
+
const mergeBase = this.gitSync.getMergeBase(execution.branch_name, execution.target_branch);
|
|
562
|
+
for (const conflict of jsonlConflicts) {
|
|
563
|
+
try {
|
|
564
|
+
// Read three versions of the file
|
|
565
|
+
const baseVersion = await this._readJSONLVersion(conflict.filePath, mergeBase);
|
|
566
|
+
const ourVersion = await this._readJSONLVersion(conflict.filePath, execution.target_branch);
|
|
567
|
+
const theirVersion = await this._readJSONLVersion(conflict.filePath, execution.branch_name);
|
|
568
|
+
// Perform three-way merge
|
|
569
|
+
const { entities: merged } = mergeThreeWay(baseVersion, ourVersion, theirVersion);
|
|
570
|
+
// Write resolved version to local repo
|
|
571
|
+
const resolvedPath = path.join(this.repoPath, conflict.filePath);
|
|
572
|
+
await writeJSONL(resolvedPath, merged);
|
|
573
|
+
// Stage the resolved file
|
|
574
|
+
execSync(`git add ${this._escapeShellArg(conflict.filePath)}`, {
|
|
575
|
+
cwd: this.repoPath,
|
|
576
|
+
stdio: "pipe",
|
|
577
|
+
});
|
|
578
|
+
}
|
|
579
|
+
catch (error) {
|
|
580
|
+
throw new WorktreeSyncError(`Failed to resolve JSONL conflict in ${conflict.filePath}: ${error.message}`, WorktreeSyncErrorCode.JSONL_RESOLUTION_FAILED, error);
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
/**
|
|
585
|
+
* Read JSONL file at a specific git revision
|
|
586
|
+
*
|
|
587
|
+
* @param filePath - Relative path to JSONL file
|
|
588
|
+
* @param revision - Git revision (commit SHA or branch name)
|
|
589
|
+
* @returns Array of JSONL entities
|
|
590
|
+
*/
|
|
591
|
+
async _readJSONLVersion(filePath, revision) {
|
|
592
|
+
try {
|
|
593
|
+
// Get file content at revision using git show
|
|
594
|
+
const content = execSync(`git show ${this._escapeShellArg(revision)}:${this._escapeShellArg(filePath)}`, {
|
|
595
|
+
cwd: this.repoPath,
|
|
596
|
+
encoding: "utf8",
|
|
597
|
+
stdio: "pipe",
|
|
598
|
+
});
|
|
599
|
+
// Parse JSONL content
|
|
600
|
+
const lines = content
|
|
601
|
+
.split("\n")
|
|
602
|
+
.filter((line) => line.trim().length > 0);
|
|
603
|
+
return lines.map((line) => JSON.parse(line));
|
|
604
|
+
}
|
|
605
|
+
catch (error) {
|
|
606
|
+
// File might not exist at this revision (new file)
|
|
607
|
+
if (error.status === 128) {
|
|
608
|
+
return [];
|
|
609
|
+
}
|
|
610
|
+
throw error;
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
/**
|
|
614
|
+
* Commit uncommitted JSONL files in worktree
|
|
615
|
+
*
|
|
616
|
+
* Used during sync to include uncommitted JSONL changes
|
|
617
|
+
*
|
|
618
|
+
* @param worktreePath - Path to worktree
|
|
619
|
+
* @param uncommittedFiles - List of uncommitted JSONL file paths
|
|
620
|
+
* @throws WorktreeSyncError if commit fails
|
|
621
|
+
*/
|
|
622
|
+
async commitUncommittedJSONL(worktreePath, uncommittedFiles) {
|
|
623
|
+
if (uncommittedFiles.length === 0) {
|
|
624
|
+
return;
|
|
625
|
+
}
|
|
626
|
+
try {
|
|
627
|
+
// Stage all uncommitted JSONL files
|
|
628
|
+
for (const file of uncommittedFiles) {
|
|
629
|
+
execSync(`git add ${this._escapeShellArg(file)}`, {
|
|
630
|
+
cwd: worktreePath,
|
|
631
|
+
stdio: "pipe",
|
|
632
|
+
});
|
|
633
|
+
}
|
|
634
|
+
// Create commit with descriptive message
|
|
635
|
+
const fileList = uncommittedFiles.join(", ");
|
|
636
|
+
const message = `Auto-commit uncommitted JSONL changes before sync\n\nFiles: ${fileList}`;
|
|
637
|
+
execSync(`git commit -m ${this._escapeShellArg(message)}`, {
|
|
638
|
+
cwd: worktreePath,
|
|
639
|
+
stdio: "pipe",
|
|
640
|
+
});
|
|
641
|
+
}
|
|
642
|
+
catch (error) {
|
|
643
|
+
throw new WorktreeSyncError(`Failed to commit uncommitted JSONL files: ${error.message}`, WorktreeSyncErrorCode.DATABASE_SYNC_FAILED, error);
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
/**
|
|
647
|
+
* Perform git merge --squash operation, allowing conflicts
|
|
648
|
+
*
|
|
649
|
+
* This method doesn't throw on conflicts.
|
|
650
|
+
* Instead, it returns information about whether conflicts occurred.
|
|
651
|
+
*
|
|
652
|
+
* @param sourceBranch - Branch to merge from (worktree branch)
|
|
653
|
+
* @param targetBranch - Branch to merge into
|
|
654
|
+
* @returns Object with filesChanged count and hasConflicts flag
|
|
655
|
+
*/
|
|
656
|
+
_performSquashMergeAllowConflicts(sourceBranch, targetBranch) {
|
|
657
|
+
// Checkout target branch
|
|
658
|
+
execSync(`git checkout ${this._escapeShellArg(targetBranch)}`, {
|
|
659
|
+
cwd: this.repoPath,
|
|
660
|
+
stdio: "pipe",
|
|
661
|
+
});
|
|
662
|
+
// Perform squash merge - may fail with conflicts
|
|
663
|
+
let hasConflicts = false;
|
|
664
|
+
try {
|
|
665
|
+
execSync(`git merge --squash ${this._escapeShellArg(sourceBranch)}`, {
|
|
666
|
+
cwd: this.repoPath,
|
|
667
|
+
stdio: "pipe",
|
|
668
|
+
});
|
|
669
|
+
}
|
|
670
|
+
catch (error) {
|
|
671
|
+
// Check if this is a conflict situation (exit code 1) or a real error
|
|
672
|
+
// git merge --squash returns 1 on conflicts but stages what it can
|
|
673
|
+
hasConflicts = true;
|
|
674
|
+
}
|
|
675
|
+
// Count staged files (including conflicted ones)
|
|
676
|
+
const statusOutput = execSync("git diff --cached --name-only", {
|
|
677
|
+
cwd: this.repoPath,
|
|
678
|
+
encoding: "utf8",
|
|
679
|
+
stdio: "pipe",
|
|
680
|
+
});
|
|
681
|
+
const filesChanged = statusOutput
|
|
682
|
+
.split("\n")
|
|
683
|
+
.filter((line) => line.trim().length > 0).length;
|
|
684
|
+
// Check for actual conflicts in the working tree
|
|
685
|
+
try {
|
|
686
|
+
const conflictCheck = execSync("git diff --name-only --diff-filter=U", {
|
|
687
|
+
cwd: this.repoPath,
|
|
688
|
+
encoding: "utf8",
|
|
689
|
+
stdio: "pipe",
|
|
690
|
+
});
|
|
691
|
+
hasConflicts = conflictCheck.trim().length > 0;
|
|
692
|
+
}
|
|
693
|
+
catch (e) {
|
|
694
|
+
// If this fails, assume no conflicts
|
|
695
|
+
}
|
|
696
|
+
return { filesChanged, hasConflicts };
|
|
697
|
+
}
|
|
698
|
+
/**
|
|
699
|
+
* Check if a file has local uncommitted changes compared to HEAD
|
|
700
|
+
*
|
|
701
|
+
* @param filePath - Relative path to the file
|
|
702
|
+
* @returns true if file has uncommitted changes, false otherwise
|
|
703
|
+
*/
|
|
704
|
+
_hasLocalUncommittedChanges(filePath) {
|
|
705
|
+
try {
|
|
706
|
+
// git diff --quiet exits with 1 if there are changes, 0 if clean
|
|
707
|
+
execSync(`git diff --quiet HEAD -- ${this._escapeShellArg(filePath)}`, {
|
|
708
|
+
cwd: this.repoPath,
|
|
709
|
+
stdio: "pipe",
|
|
710
|
+
});
|
|
711
|
+
return false; // Exit 0 = no changes
|
|
712
|
+
}
|
|
713
|
+
catch {
|
|
714
|
+
return true; // Exit 1 = has changes
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
/**
|
|
718
|
+
* Detect potential local conflicts for uncommitted worktree files
|
|
719
|
+
*
|
|
720
|
+
* Checks which uncommitted worktree files also exist locally with changes
|
|
721
|
+
* or are untracked locally. These files may have merge conflicts when synced.
|
|
722
|
+
*
|
|
723
|
+
* @param worktreeFiles - List of uncommitted files in worktree
|
|
724
|
+
* @returns Info about files that may have conflicts
|
|
725
|
+
*/
|
|
726
|
+
_detectPotentialLocalConflicts(worktreeFiles) {
|
|
727
|
+
const conflictFiles = [];
|
|
728
|
+
for (const filePath of worktreeFiles) {
|
|
729
|
+
const localPath = path.join(this.repoPath, filePath);
|
|
730
|
+
const localFileExists = fs.existsSync(localPath);
|
|
731
|
+
if (localFileExists) {
|
|
732
|
+
// Check if local file has uncommitted changes vs HEAD or is untracked
|
|
733
|
+
const hasChangesVsHead = this._hasLocalUncommittedChanges(filePath);
|
|
734
|
+
const isUntracked = this._isFileUntracked(filePath);
|
|
735
|
+
if (hasChangesVsHead || isUntracked) {
|
|
736
|
+
conflictFiles.push(filePath);
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
return {
|
|
741
|
+
count: conflictFiles.length,
|
|
742
|
+
files: conflictFiles,
|
|
743
|
+
};
|
|
744
|
+
}
|
|
745
|
+
/**
|
|
746
|
+
* Check if a file is untracked by git (not in the index)
|
|
747
|
+
*
|
|
748
|
+
* @param filePath - Relative path to the file
|
|
749
|
+
* @returns true if file is untracked, false if tracked
|
|
750
|
+
*/
|
|
751
|
+
_isFileUntracked(filePath) {
|
|
752
|
+
try {
|
|
753
|
+
// git ls-files returns the file path if it's tracked, empty if not
|
|
754
|
+
const result = execSync(`git ls-files -- ${this._escapeShellArg(filePath)}`, {
|
|
755
|
+
cwd: this.repoPath,
|
|
756
|
+
encoding: "utf8",
|
|
757
|
+
stdio: "pipe",
|
|
758
|
+
});
|
|
759
|
+
return result.trim().length === 0; // Empty = untracked
|
|
760
|
+
}
|
|
761
|
+
catch {
|
|
762
|
+
return true; // Assume untracked on error
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
/**
|
|
766
|
+
* Check if a file is a JSONL file in the .sudocode directory
|
|
767
|
+
*
|
|
768
|
+
* @param filePath - Relative path to the file
|
|
769
|
+
* @returns true if file is a .sudocode JSONL file
|
|
770
|
+
*/
|
|
771
|
+
_isJSONLFile(filePath) {
|
|
772
|
+
return (filePath.endsWith(".jsonl") &&
|
|
773
|
+
(filePath.startsWith(".sudocode/") || filePath.includes("/.sudocode/")));
|
|
774
|
+
}
|
|
775
|
+
/**
|
|
776
|
+
* Perform three-way merge on a file using git merge-file
|
|
777
|
+
*
|
|
778
|
+
* Uses HEAD as base, local working copy as "ours", and worktree version as "theirs".
|
|
779
|
+
* Modifies the local file in place, inserting conflict markers if needed.
|
|
780
|
+
*
|
|
781
|
+
* @param filePath - Relative path to the file in local repo
|
|
782
|
+
* @param worktreeFilePath - Absolute path to the file in worktree
|
|
783
|
+
* @returns true if there are conflicts, false if merge was clean
|
|
784
|
+
*/
|
|
785
|
+
_threeWayMergeFile(filePath, worktreeFilePath) {
|
|
786
|
+
const localFilePath = path.join(this.repoPath, filePath);
|
|
787
|
+
// Create temp file for base version from HEAD
|
|
788
|
+
const tempDir = os.tmpdir();
|
|
789
|
+
const baseTempFile = path.join(tempDir, `sudocode-merge-base-${Date.now()}-${path.basename(filePath)}`);
|
|
790
|
+
try {
|
|
791
|
+
// Get base version from HEAD
|
|
792
|
+
let baseContent = "";
|
|
793
|
+
try {
|
|
794
|
+
baseContent = execSync(`git show HEAD:${this._escapeShellArg(filePath)}`, {
|
|
795
|
+
cwd: this.repoPath,
|
|
796
|
+
encoding: "utf8",
|
|
797
|
+
stdio: "pipe",
|
|
798
|
+
});
|
|
799
|
+
}
|
|
800
|
+
catch {
|
|
801
|
+
// File might be new (not in HEAD), use empty base
|
|
802
|
+
baseContent = "";
|
|
803
|
+
}
|
|
804
|
+
fs.writeFileSync(baseTempFile, baseContent, "utf8");
|
|
805
|
+
// git merge-file modifies the first file in place
|
|
806
|
+
// Returns 0 if clean merge, >0 for number of conflicts, -1 for error
|
|
807
|
+
try {
|
|
808
|
+
execSync(`git merge-file -L "LOCAL" -L "BASE" -L "WORKTREE" ${this._escapeShellArg(localFilePath)} ${this._escapeShellArg(baseTempFile)} ${this._escapeShellArg(worktreeFilePath)}`, {
|
|
809
|
+
cwd: this.repoPath,
|
|
810
|
+
stdio: "pipe",
|
|
811
|
+
});
|
|
812
|
+
return false; // Exit 0 = clean merge, no conflicts
|
|
813
|
+
}
|
|
814
|
+
catch (error) {
|
|
815
|
+
// Exit code > 0 means conflicts (number of conflicts)
|
|
816
|
+
// Exit code < 0 means error
|
|
817
|
+
if (error.status > 0) {
|
|
818
|
+
return true; // Has conflicts
|
|
819
|
+
}
|
|
820
|
+
// Real error - rethrow
|
|
821
|
+
throw error;
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
finally {
|
|
825
|
+
// Clean up temp file
|
|
826
|
+
if (fs.existsSync(baseTempFile)) {
|
|
827
|
+
fs.unlinkSync(baseTempFile);
|
|
828
|
+
}
|
|
829
|
+
}
|
|
830
|
+
}
|
|
831
|
+
/**
|
|
832
|
+
* Merge two JSONL files using UUID-based resolution
|
|
833
|
+
*
|
|
834
|
+
* Reads both local and worktree versions, merges entities by UUID,
|
|
835
|
+
* and writes the result back to the local file.
|
|
836
|
+
*
|
|
837
|
+
* @param localFilePath - Absolute path to local JSONL file
|
|
838
|
+
* @param worktreeFilePath - Absolute path to worktree JSONL file
|
|
839
|
+
*/
|
|
840
|
+
async _mergeJSONLFiles(localFilePath, worktreeFilePath) {
|
|
841
|
+
// Read both versions
|
|
842
|
+
const localEntities = readJSONLSync(localFilePath, { skipErrors: true });
|
|
843
|
+
const worktreeEntities = readJSONLSync(worktreeFilePath, {
|
|
844
|
+
skipErrors: true,
|
|
845
|
+
});
|
|
846
|
+
// Combine and resolve using UUID-based deduplication
|
|
847
|
+
const allEntities = [...localEntities, ...worktreeEntities];
|
|
848
|
+
const { entities: merged } = resolveEntities(allEntities);
|
|
849
|
+
// Write merged result back to local file
|
|
850
|
+
await writeJSONL(localFilePath, merged);
|
|
851
|
+
}
|
|
852
|
+
/**
|
|
853
|
+
* Copy uncommitted files from worktree to local repo with safe merging
|
|
854
|
+
*
|
|
855
|
+
* For files with local uncommitted changes:
|
|
856
|
+
* - JSONL files: Uses UUID-based merge resolution
|
|
857
|
+
* - Other files: Uses git merge-file for three-way merge with conflict markers
|
|
858
|
+
*
|
|
859
|
+
* Files without local changes are copied directly.
|
|
860
|
+
*
|
|
861
|
+
* @param worktreePath - Path to the worktree
|
|
862
|
+
* @param options - Optional settings
|
|
863
|
+
* @param options.overrideLocalChanges - If true, skip merge and overwrite local changes
|
|
864
|
+
* @returns Object with filesCopied count and list of files with conflicts
|
|
865
|
+
*/
|
|
866
|
+
async _copyUncommittedFiles(worktreePath, options) {
|
|
867
|
+
const { overrideLocalChanges = false } = options || {};
|
|
868
|
+
// Get list of uncommitted/untracked files in worktree
|
|
869
|
+
const modifiedOutput = execSync("git diff --name-only", {
|
|
870
|
+
cwd: worktreePath,
|
|
871
|
+
encoding: "utf8",
|
|
872
|
+
stdio: "pipe",
|
|
873
|
+
});
|
|
874
|
+
const untrackedOutput = execSync("git ls-files --others --exclude-standard", {
|
|
875
|
+
cwd: worktreePath,
|
|
876
|
+
encoding: "utf8",
|
|
877
|
+
stdio: "pipe",
|
|
878
|
+
});
|
|
879
|
+
const modifiedFiles = modifiedOutput
|
|
880
|
+
.split("\n")
|
|
881
|
+
.filter((line) => line.trim().length > 0);
|
|
882
|
+
const untrackedFiles = untrackedOutput
|
|
883
|
+
.split("\n")
|
|
884
|
+
.filter((line) => line.trim().length > 0);
|
|
885
|
+
const allFiles = [...new Set([...modifiedFiles, ...untrackedFiles])];
|
|
886
|
+
if (allFiles.length === 0) {
|
|
887
|
+
return { filesCopied: 0, filesWithConflicts: [] };
|
|
888
|
+
}
|
|
889
|
+
// Process each file from worktree
|
|
890
|
+
let filesCopied = 0;
|
|
891
|
+
const filesWithConflicts = [];
|
|
892
|
+
for (const filePath of allFiles) {
|
|
893
|
+
const srcPath = path.join(worktreePath, filePath);
|
|
894
|
+
const destPath = path.join(this.repoPath, filePath);
|
|
895
|
+
// Check if source file exists
|
|
896
|
+
if (!fs.existsSync(srcPath)) {
|
|
897
|
+
continue;
|
|
898
|
+
}
|
|
899
|
+
// Create destination directory if needed
|
|
900
|
+
const destDir = path.dirname(destPath);
|
|
901
|
+
if (!fs.existsSync(destDir)) {
|
|
902
|
+
fs.mkdirSync(destDir, { recursive: true });
|
|
903
|
+
}
|
|
904
|
+
// Check if local file has uncommitted changes or is untracked
|
|
905
|
+
// We need to merge if: (1) file exists locally AND (2) either has changes vs HEAD or is untracked
|
|
906
|
+
const localFileExists = fs.existsSync(destPath);
|
|
907
|
+
const localHasChangesVsHead = localFileExists && this._hasLocalUncommittedChanges(filePath);
|
|
908
|
+
const localIsUntracked = localFileExists && this._isFileUntracked(filePath);
|
|
909
|
+
const needsMerge = !overrideLocalChanges && (localHasChangesVsHead || localIsUntracked);
|
|
910
|
+
let hasConflicts = false;
|
|
911
|
+
if (!needsMerge) {
|
|
912
|
+
// No local changes OR override mode - copy directly (overwrites local)
|
|
913
|
+
fs.copyFileSync(srcPath, destPath);
|
|
914
|
+
}
|
|
915
|
+
else if (this._isJSONLFile(filePath)) {
|
|
916
|
+
// JSONL file with local changes - use UUID-based merge
|
|
917
|
+
await this._mergeJSONLFiles(destPath, srcPath);
|
|
918
|
+
}
|
|
919
|
+
else {
|
|
920
|
+
// Other file with local changes - use three-way merge
|
|
921
|
+
hasConflicts = this._threeWayMergeFile(filePath, srcPath);
|
|
922
|
+
if (hasConflicts) {
|
|
923
|
+
filesWithConflicts.push(filePath);
|
|
924
|
+
}
|
|
925
|
+
}
|
|
926
|
+
// Stage the file ONLY if it doesn't have conflicts
|
|
927
|
+
// Files with conflict markers should remain unstaged so VS Code can detect them
|
|
928
|
+
if (!hasConflicts) {
|
|
929
|
+
execSync(`git add ${this._escapeShellArg(filePath)}`, {
|
|
930
|
+
cwd: this.repoPath,
|
|
931
|
+
stdio: "pipe",
|
|
932
|
+
});
|
|
933
|
+
}
|
|
934
|
+
filesCopied++;
|
|
935
|
+
}
|
|
936
|
+
return { filesCopied, filesWithConflicts };
|
|
937
|
+
}
|
|
938
|
+
/**
|
|
939
|
+
* Resolve JSONL merge conflicts in the local repository
|
|
940
|
+
*
|
|
941
|
+
* Checks for git conflict markers in issues.jsonl and specs.jsonl,
|
|
942
|
+
* and resolves them using the merge-resolver logic.
|
|
943
|
+
*
|
|
944
|
+
* @returns Number of files resolved
|
|
945
|
+
*/
|
|
946
|
+
async _resolveJSONLConflicts() {
|
|
947
|
+
const sudocodePath = path.join(this.repoPath, ".sudocode");
|
|
948
|
+
const issuesPath = path.join(sudocodePath, "issues.jsonl");
|
|
949
|
+
const specsPath = path.join(sudocodePath, "specs.jsonl");
|
|
950
|
+
let filesResolved = 0;
|
|
951
|
+
// Check and resolve issues.jsonl
|
|
952
|
+
if (fs.existsSync(issuesPath) && hasGitConflictMarkers(issuesPath)) {
|
|
953
|
+
await this._resolveJSONLFile(issuesPath);
|
|
954
|
+
filesResolved++;
|
|
955
|
+
}
|
|
956
|
+
// Check and resolve specs.jsonl
|
|
957
|
+
if (fs.existsSync(specsPath) && hasGitConflictMarkers(specsPath)) {
|
|
958
|
+
await this._resolveJSONLFile(specsPath);
|
|
959
|
+
filesResolved++;
|
|
960
|
+
}
|
|
961
|
+
return filesResolved;
|
|
962
|
+
}
|
|
963
|
+
/**
|
|
964
|
+
* Resolve conflicts in a single JSONL file
|
|
965
|
+
*
|
|
966
|
+
* @param filePath - Path to the JSONL file with conflicts
|
|
967
|
+
*/
|
|
968
|
+
async _resolveJSONLFile(filePath) {
|
|
969
|
+
// Read file with conflict markers
|
|
970
|
+
const content = fs.readFileSync(filePath, "utf8");
|
|
971
|
+
// Parse conflicts
|
|
972
|
+
const sections = parseMergeConflictFile(content);
|
|
973
|
+
// Extract all entities (from both clean and conflict sections)
|
|
974
|
+
const allEntities = [];
|
|
975
|
+
for (const section of sections) {
|
|
976
|
+
if (section.type === "clean") {
|
|
977
|
+
for (const line of section.lines) {
|
|
978
|
+
if (line.trim()) {
|
|
979
|
+
try {
|
|
980
|
+
allEntities.push(JSON.parse(line));
|
|
981
|
+
}
|
|
982
|
+
catch {
|
|
983
|
+
// Skip malformed lines
|
|
984
|
+
}
|
|
985
|
+
}
|
|
986
|
+
}
|
|
987
|
+
}
|
|
988
|
+
else {
|
|
989
|
+
// Conflict section - include both ours and theirs
|
|
990
|
+
for (const line of [
|
|
991
|
+
...(section.ours || []),
|
|
992
|
+
...(section.theirs || []),
|
|
993
|
+
]) {
|
|
994
|
+
if (line.trim()) {
|
|
995
|
+
try {
|
|
996
|
+
allEntities.push(JSON.parse(line));
|
|
997
|
+
}
|
|
998
|
+
catch {
|
|
999
|
+
// Skip malformed lines
|
|
1000
|
+
}
|
|
1001
|
+
}
|
|
1002
|
+
}
|
|
1003
|
+
}
|
|
1004
|
+
}
|
|
1005
|
+
// Resolve conflicts
|
|
1006
|
+
const { entities: resolved } = resolveEntities(allEntities, {
|
|
1007
|
+
verbose: false,
|
|
1008
|
+
});
|
|
1009
|
+
// Write back resolved entities
|
|
1010
|
+
await writeJSONL(filePath, resolved);
|
|
1011
|
+
// Stage the resolved file
|
|
1012
|
+
const relativePath = path.relative(this.repoPath, filePath);
|
|
1013
|
+
execSync(`git add ${this._escapeShellArg(relativePath)}`, {
|
|
1014
|
+
cwd: this.repoPath,
|
|
1015
|
+
stdio: "pipe",
|
|
1016
|
+
});
|
|
1017
|
+
}
|
|
1018
|
+
/**
|
|
1019
|
+
* Generate commit message for squash sync
|
|
1020
|
+
*
|
|
1021
|
+
* @param execution - Execution record
|
|
1022
|
+
* @param commitCount - Number of commits being squashed
|
|
1023
|
+
* @returns Generated commit message
|
|
1024
|
+
*/
|
|
1025
|
+
_generateCommitMessage(execution, commitCount) {
|
|
1026
|
+
const issueId = execution.issue_id || "unknown";
|
|
1027
|
+
const branchName = execution.branch_name;
|
|
1028
|
+
return `Squash merge from ${branchName} (${commitCount} commit${commitCount !== 1 ? "s" : ""})
|
|
1029
|
+
|
|
1030
|
+
Issue: ${issueId}
|
|
1031
|
+
Execution: ${execution.id}
|
|
1032
|
+
|
|
1033
|
+
Synced changes from worktree execution.`;
|
|
1034
|
+
}
|
|
1035
|
+
/**
|
|
1036
|
+
* Create commit with staged changes
|
|
1037
|
+
*
|
|
1038
|
+
* @param message - Commit message
|
|
1039
|
+
* @returns Commit SHA
|
|
1040
|
+
* @throws WorktreeSyncError if commit fails
|
|
1041
|
+
*/
|
|
1042
|
+
_createCommit(message) {
|
|
1043
|
+
try {
|
|
1044
|
+
execSync(`git commit -m ${this._escapeShellArg(message)}`, {
|
|
1045
|
+
cwd: this.repoPath,
|
|
1046
|
+
stdio: "pipe",
|
|
1047
|
+
});
|
|
1048
|
+
// Get the commit SHA
|
|
1049
|
+
const sha = execSync("git rev-parse HEAD", {
|
|
1050
|
+
cwd: this.repoPath,
|
|
1051
|
+
encoding: "utf8",
|
|
1052
|
+
stdio: "pipe",
|
|
1053
|
+
}).trim();
|
|
1054
|
+
return sha;
|
|
1055
|
+
}
|
|
1056
|
+
catch (error) {
|
|
1057
|
+
throw new WorktreeSyncError(`Failed to create commit: ${error.message}`, WorktreeSyncErrorCode.MERGE_FAILED, error);
|
|
1058
|
+
}
|
|
1059
|
+
}
|
|
1060
|
+
/**
|
|
1061
|
+
* Rollback to safety snapshot
|
|
1062
|
+
*
|
|
1063
|
+
* @param targetBranch - Target branch to reset
|
|
1064
|
+
* @param tagName - Safety tag to rollback to
|
|
1065
|
+
* @throws WorktreeSyncError if rollback fails
|
|
1066
|
+
*/
|
|
1067
|
+
async _rollbackToSnapshot(targetBranch, tagName) {
|
|
1068
|
+
try {
|
|
1069
|
+
// Checkout target branch
|
|
1070
|
+
execSync(`git checkout ${this._escapeShellArg(targetBranch)}`, {
|
|
1071
|
+
cwd: this.repoPath,
|
|
1072
|
+
stdio: "pipe",
|
|
1073
|
+
});
|
|
1074
|
+
// Reset to tag
|
|
1075
|
+
execSync(`git reset --hard ${this._escapeShellArg(tagName)}`, {
|
|
1076
|
+
cwd: this.repoPath,
|
|
1077
|
+
stdio: "pipe",
|
|
1078
|
+
});
|
|
1079
|
+
console.log(`Rolled back ${targetBranch} to ${tagName}`);
|
|
1080
|
+
}
|
|
1081
|
+
catch (error) {
|
|
1082
|
+
throw new WorktreeSyncError(`Failed to rollback to snapshot ${tagName}: ${error.message}`, WorktreeSyncErrorCode.MERGE_FAILED, error);
|
|
1083
|
+
}
|
|
1084
|
+
}
|
|
1085
|
+
/**
|
|
1086
|
+
* Perform squash sync operation
|
|
1087
|
+
*
|
|
1088
|
+
* Squashes all committed worktree changes into a single commit on the target branch.
|
|
1089
|
+
* Only includes committed changes - uncommitted changes are excluded.
|
|
1090
|
+
* If merge conflicts occur, they are left for the user to resolve manually.
|
|
1091
|
+
*
|
|
1092
|
+
* @param executionId - Execution ID to sync
|
|
1093
|
+
* @param customCommitMessage - Optional custom commit message
|
|
1094
|
+
* @returns Sync result with details
|
|
1095
|
+
* @throws WorktreeSyncError if sync fails
|
|
1096
|
+
*/
|
|
1097
|
+
async squashSync(executionId, customCommitMessage) {
|
|
1098
|
+
// 1. Load and validate execution
|
|
1099
|
+
const execution = await this._loadAndValidateExecution(executionId);
|
|
1100
|
+
// 2. Validate preconditions (allow JSONL-only changes, they'll be auto-merged)
|
|
1101
|
+
await this._validateSyncPreconditions(execution, { allowJsonlOnlyChanges: true });
|
|
1102
|
+
// 3. Save uncommitted JSONL files before merge (will be restored after)
|
|
1103
|
+
const savedJsonlFiles = await this._saveUncommittedJsonl();
|
|
1104
|
+
const hasUncommittedJsonl = savedJsonlFiles.size > 0;
|
|
1105
|
+
// 4. Preview sync to get info (we'll proceed even with conflicts)
|
|
1106
|
+
const preview = await this.previewSync(executionId);
|
|
1107
|
+
// 4. Check if there are any commits to merge
|
|
1108
|
+
if (preview.commits.length === 0) {
|
|
1109
|
+
return {
|
|
1110
|
+
success: false,
|
|
1111
|
+
filesChanged: 0,
|
|
1112
|
+
error: "No commits to merge. Only committed changes are included in sync.",
|
|
1113
|
+
};
|
|
1114
|
+
}
|
|
1115
|
+
// 5. Check if worktree branch is already merged into target
|
|
1116
|
+
if (this._isAncestor(execution.branch_name, execution.target_branch)) {
|
|
1117
|
+
return {
|
|
1118
|
+
success: false,
|
|
1119
|
+
filesChanged: 0,
|
|
1120
|
+
error: "Target branch is already up to date with worktree changes. Nothing to merge.",
|
|
1121
|
+
};
|
|
1122
|
+
}
|
|
1123
|
+
let safetyTag;
|
|
1124
|
+
try {
|
|
1125
|
+
// 6. Create safety snapshot (before any changes)
|
|
1126
|
+
safetyTag = await this._createSafetySnapshot(executionId, execution.target_branch);
|
|
1127
|
+
// 7. Perform git merge --squash (may have conflicts)
|
|
1128
|
+
const mergeResult = this._performSquashMergeAllowConflicts(execution.branch_name, execution.target_branch);
|
|
1129
|
+
// 8. Check if there are unresolved conflicts
|
|
1130
|
+
if (mergeResult.hasConflicts) {
|
|
1131
|
+
// Get list of files with conflicts
|
|
1132
|
+
let filesWithConflicts = [];
|
|
1133
|
+
try {
|
|
1134
|
+
const conflictCheck = execSync("git diff --name-only --diff-filter=U", {
|
|
1135
|
+
cwd: this.repoPath,
|
|
1136
|
+
encoding: "utf8",
|
|
1137
|
+
stdio: "pipe",
|
|
1138
|
+
});
|
|
1139
|
+
filesWithConflicts = conflictCheck
|
|
1140
|
+
.trim()
|
|
1141
|
+
.split("\n")
|
|
1142
|
+
.filter((f) => f.length > 0);
|
|
1143
|
+
}
|
|
1144
|
+
catch {
|
|
1145
|
+
// If command fails, leave empty
|
|
1146
|
+
}
|
|
1147
|
+
// Return with conflicts info - user must resolve manually
|
|
1148
|
+
return {
|
|
1149
|
+
success: false,
|
|
1150
|
+
filesChanged: mergeResult.filesChanged,
|
|
1151
|
+
hasConflicts: true,
|
|
1152
|
+
filesWithConflicts,
|
|
1153
|
+
error: "Merge conflicts detected. Please resolve them manually and commit.",
|
|
1154
|
+
cleanupOffered: false,
|
|
1155
|
+
};
|
|
1156
|
+
}
|
|
1157
|
+
// 9. Generate commit message
|
|
1158
|
+
const commitMessage = customCommitMessage ||
|
|
1159
|
+
this._generateCommitMessage(execution, preview.commits.length);
|
|
1160
|
+
// 10. Create commit
|
|
1161
|
+
const finalCommit = this._createCommit(commitMessage);
|
|
1162
|
+
// 11. Restore uncommitted JSONL files with three-way merge
|
|
1163
|
+
if (hasUncommittedJsonl) {
|
|
1164
|
+
await this._restoreUncommittedJsonl();
|
|
1165
|
+
}
|
|
1166
|
+
// 12. Return success result
|
|
1167
|
+
return {
|
|
1168
|
+
success: true,
|
|
1169
|
+
finalCommit,
|
|
1170
|
+
filesChanged: mergeResult.filesChanged,
|
|
1171
|
+
cleanupOffered: true,
|
|
1172
|
+
};
|
|
1173
|
+
}
|
|
1174
|
+
catch (error) {
|
|
1175
|
+
// Restore uncommitted JSONL files even on failure (to avoid losing user changes)
|
|
1176
|
+
if (hasUncommittedJsonl) {
|
|
1177
|
+
try {
|
|
1178
|
+
await this._restoreUncommittedJsonl();
|
|
1179
|
+
}
|
|
1180
|
+
catch (restoreError) {
|
|
1181
|
+
console.error("Failed to restore uncommitted JSONL files:", restoreError);
|
|
1182
|
+
}
|
|
1183
|
+
}
|
|
1184
|
+
// Rollback to safety snapshot on failure
|
|
1185
|
+
if (safetyTag) {
|
|
1186
|
+
try {
|
|
1187
|
+
await this._rollbackToSnapshot(execution.target_branch, safetyTag);
|
|
1188
|
+
}
|
|
1189
|
+
catch (rollbackError) {
|
|
1190
|
+
console.error(`Failed to rollback to snapshot ${safetyTag}:`, rollbackError);
|
|
1191
|
+
}
|
|
1192
|
+
}
|
|
1193
|
+
throw new WorktreeSyncError(`Squash sync failed: ${error.message}`, WorktreeSyncErrorCode.MERGE_FAILED, error);
|
|
1194
|
+
}
|
|
1195
|
+
}
|
|
1196
|
+
/**
|
|
1197
|
+
* Perform stage sync operation
|
|
1198
|
+
*
|
|
1199
|
+
* Applies committed worktree changes to the working directory without committing.
|
|
1200
|
+
* Changes are left staged, ready for the user to commit manually.
|
|
1201
|
+
* Only includes committed changes by default - uncommitted changes are excluded
|
|
1202
|
+
* unless includeUncommitted is true.
|
|
1203
|
+
*
|
|
1204
|
+
* @param executionId - Execution ID to sync
|
|
1205
|
+
* @param options - Optional settings
|
|
1206
|
+
* @param options.includeUncommitted - If true, also copy uncommitted files from worktree
|
|
1207
|
+
* @param options.overrideLocalChanges - If true, overwrite local changes instead of merging
|
|
1208
|
+
* @returns Sync result with details
|
|
1209
|
+
* @throws WorktreeSyncError if sync fails
|
|
1210
|
+
*/
|
|
1211
|
+
async stageSync(executionId, options) {
|
|
1212
|
+
const { includeUncommitted = false, overrideLocalChanges = false } = options || {};
|
|
1213
|
+
// 1. Load and validate execution
|
|
1214
|
+
const execution = await this._loadAndValidateExecution(executionId);
|
|
1215
|
+
// 2. Validate preconditions (skip dirty working tree check - stage mode doesn't commit)
|
|
1216
|
+
await this._validateSyncPreconditions(execution, {
|
|
1217
|
+
skipDirtyWorkingTreeCheck: true,
|
|
1218
|
+
});
|
|
1219
|
+
// 3. Preview sync to get info
|
|
1220
|
+
const preview = await this.previewSync(executionId);
|
|
1221
|
+
// 4. Check if there's anything to sync
|
|
1222
|
+
const hasCommits = preview.commits.length > 0;
|
|
1223
|
+
if (!hasCommits && !includeUncommitted) {
|
|
1224
|
+
return {
|
|
1225
|
+
success: false,
|
|
1226
|
+
filesChanged: 0,
|
|
1227
|
+
error: "No commits to merge. Only committed changes are included in sync.",
|
|
1228
|
+
};
|
|
1229
|
+
}
|
|
1230
|
+
let safetyTag;
|
|
1231
|
+
try {
|
|
1232
|
+
// 5. Create safety snapshot (before any changes)
|
|
1233
|
+
safetyTag = await this._createSafetySnapshot(executionId, execution.target_branch);
|
|
1234
|
+
let filesChanged = 0;
|
|
1235
|
+
let hasConflicts = false;
|
|
1236
|
+
// 6. Perform git merge --squash for committed changes (if any)
|
|
1237
|
+
if (hasCommits) {
|
|
1238
|
+
const mergeResult = this._performSquashMergeAllowConflicts(execution.branch_name, execution.target_branch);
|
|
1239
|
+
filesChanged = mergeResult.filesChanged;
|
|
1240
|
+
hasConflicts = mergeResult.hasConflicts;
|
|
1241
|
+
}
|
|
1242
|
+
// 7. Copy uncommitted files from worktree if requested (with safe merging)
|
|
1243
|
+
let uncommittedFilesCopied = 0;
|
|
1244
|
+
let filesWithConflicts = [];
|
|
1245
|
+
if (includeUncommitted && execution.worktree_path) {
|
|
1246
|
+
const copyResult = await this._copyUncommittedFiles(execution.worktree_path, { overrideLocalChanges });
|
|
1247
|
+
uncommittedFilesCopied = copyResult.filesCopied;
|
|
1248
|
+
filesWithConflicts = copyResult.filesWithConflicts;
|
|
1249
|
+
filesChanged += uncommittedFilesCopied;
|
|
1250
|
+
// If we have conflicts from uncommitted files merge, mark hasConflicts
|
|
1251
|
+
if (filesWithConflicts.length > 0) {
|
|
1252
|
+
hasConflicts = true;
|
|
1253
|
+
}
|
|
1254
|
+
}
|
|
1255
|
+
// 8. Auto-resolve JSONL conflicts if any (from git merge --squash)
|
|
1256
|
+
const jsonlFilesResolved = await this._resolveJSONLConflicts();
|
|
1257
|
+
if (jsonlFilesResolved > 0) {
|
|
1258
|
+
// Re-check for remaining conflicts after JSONL resolution
|
|
1259
|
+
try {
|
|
1260
|
+
const conflictCheck = execSync("git diff --name-only --diff-filter=U", {
|
|
1261
|
+
cwd: this.repoPath,
|
|
1262
|
+
encoding: "utf8",
|
|
1263
|
+
stdio: "pipe",
|
|
1264
|
+
});
|
|
1265
|
+
const remainingConflictFiles = conflictCheck
|
|
1266
|
+
.trim()
|
|
1267
|
+
.split("\n")
|
|
1268
|
+
.filter((f) => f.length > 0);
|
|
1269
|
+
hasConflicts = remainingConflictFiles.length > 0;
|
|
1270
|
+
// Add any remaining conflict files not already tracked
|
|
1271
|
+
for (const file of remainingConflictFiles) {
|
|
1272
|
+
if (!filesWithConflicts.includes(file)) {
|
|
1273
|
+
filesWithConflicts.push(file);
|
|
1274
|
+
}
|
|
1275
|
+
}
|
|
1276
|
+
}
|
|
1277
|
+
catch {
|
|
1278
|
+
// If command fails, assume no additional conflicts
|
|
1279
|
+
}
|
|
1280
|
+
}
|
|
1281
|
+
// 9. Check if there are unresolved (non-JSONL) conflicts
|
|
1282
|
+
if (hasConflicts) {
|
|
1283
|
+
return {
|
|
1284
|
+
success: false,
|
|
1285
|
+
filesChanged,
|
|
1286
|
+
hasConflicts: true,
|
|
1287
|
+
filesWithConflicts,
|
|
1288
|
+
uncommittedFilesIncluded: uncommittedFilesCopied,
|
|
1289
|
+
error: "Merge conflicts detected. Please resolve them manually.",
|
|
1290
|
+
cleanupOffered: false,
|
|
1291
|
+
};
|
|
1292
|
+
}
|
|
1293
|
+
// 10. Return success result WITHOUT creating a commit
|
|
1294
|
+
// Changes remain staged for user to commit manually
|
|
1295
|
+
return {
|
|
1296
|
+
success: true,
|
|
1297
|
+
filesChanged,
|
|
1298
|
+
uncommittedFilesIncluded: uncommittedFilesCopied,
|
|
1299
|
+
cleanupOffered: true,
|
|
1300
|
+
};
|
|
1301
|
+
}
|
|
1302
|
+
catch (error) {
|
|
1303
|
+
// Rollback to safety snapshot on failure
|
|
1304
|
+
if (safetyTag) {
|
|
1305
|
+
try {
|
|
1306
|
+
await this._rollbackToSnapshot(execution.target_branch, safetyTag);
|
|
1307
|
+
}
|
|
1308
|
+
catch (rollbackError) {
|
|
1309
|
+
console.error(`Failed to rollback to snapshot ${safetyTag}:`, rollbackError);
|
|
1310
|
+
}
|
|
1311
|
+
}
|
|
1312
|
+
throw new WorktreeSyncError(`Stage sync failed: ${error.message}`, WorktreeSyncErrorCode.MERGE_FAILED, error);
|
|
1313
|
+
}
|
|
1314
|
+
}
|
|
1315
|
+
/**
|
|
1316
|
+
* Check if worktree branch is an ancestor of target branch
|
|
1317
|
+
*
|
|
1318
|
+
* If the worktree branch is an ancestor, it means target already has all
|
|
1319
|
+
* the commits from the worktree (e.g., via a previous sync).
|
|
1320
|
+
*
|
|
1321
|
+
* @param worktreeBranch - Worktree branch name
|
|
1322
|
+
* @param targetBranch - Target branch name
|
|
1323
|
+
* @returns true if worktree branch is an ancestor of target branch
|
|
1324
|
+
*/
|
|
1325
|
+
_isAncestor(worktreeBranch, targetBranch) {
|
|
1326
|
+
try {
|
|
1327
|
+
execSync(`git merge-base --is-ancestor ${this._escapeShellArg(worktreeBranch)} ${this._escapeShellArg(targetBranch)}`, {
|
|
1328
|
+
cwd: this.repoPath,
|
|
1329
|
+
stdio: "pipe",
|
|
1330
|
+
});
|
|
1331
|
+
// Exit code 0 means worktreeBranch IS an ancestor of targetBranch
|
|
1332
|
+
return true;
|
|
1333
|
+
}
|
|
1334
|
+
catch {
|
|
1335
|
+
// Exit code 1 means NOT an ancestor, which is what we want for merging
|
|
1336
|
+
return false;
|
|
1337
|
+
}
|
|
1338
|
+
}
|
|
1339
|
+
/**
|
|
1340
|
+
* Perform preserve sync operation
|
|
1341
|
+
*
|
|
1342
|
+
* Merges all commits from worktree branch to target branch, preserving commit history.
|
|
1343
|
+
* Only includes committed changes - uncommitted changes are excluded.
|
|
1344
|
+
* If merge conflicts occur, they are left for the user to resolve manually.
|
|
1345
|
+
*
|
|
1346
|
+
* @param executionId - Execution ID to sync
|
|
1347
|
+
* @returns Sync result with details
|
|
1348
|
+
* @throws WorktreeSyncError if sync fails
|
|
1349
|
+
*/
|
|
1350
|
+
async preserveSync(executionId) {
|
|
1351
|
+
// 1. Load and validate execution
|
|
1352
|
+
const execution = await this._loadAndValidateExecution(executionId);
|
|
1353
|
+
// 2. Validate preconditions (allow JSONL-only changes, they'll be auto-merged)
|
|
1354
|
+
await this._validateSyncPreconditions(execution, { allowJsonlOnlyChanges: true });
|
|
1355
|
+
// 3. Save uncommitted JSONL files before merge (will be restored after)
|
|
1356
|
+
const savedJsonlFiles = await this._saveUncommittedJsonl();
|
|
1357
|
+
const hasUncommittedJsonl = savedJsonlFiles.size > 0;
|
|
1358
|
+
// 4. Preview sync to get info
|
|
1359
|
+
const preview = await this.previewSync(executionId);
|
|
1360
|
+
// 4. Check if there are any commits to merge
|
|
1361
|
+
if (preview.commits.length === 0) {
|
|
1362
|
+
return {
|
|
1363
|
+
success: false,
|
|
1364
|
+
filesChanged: 0,
|
|
1365
|
+
error: "No commits to merge. Only committed changes are included in sync.",
|
|
1366
|
+
};
|
|
1367
|
+
}
|
|
1368
|
+
// 5. Check if worktree branch is already merged into target
|
|
1369
|
+
// This happens if a previous sync (squash or preserve) already merged these commits
|
|
1370
|
+
if (this._isAncestor(execution.branch_name, execution.target_branch)) {
|
|
1371
|
+
return {
|
|
1372
|
+
success: false,
|
|
1373
|
+
filesChanged: 0,
|
|
1374
|
+
error: "Target branch is already up to date with worktree changes. Nothing to merge.",
|
|
1375
|
+
};
|
|
1376
|
+
}
|
|
1377
|
+
let safetyTag;
|
|
1378
|
+
try {
|
|
1379
|
+
// 6. Create safety snapshot (before any changes)
|
|
1380
|
+
safetyTag = await this._createSafetySnapshot(executionId, execution.target_branch);
|
|
1381
|
+
// 7. Checkout target branch
|
|
1382
|
+
execSync(`git checkout ${this._escapeShellArg(execution.target_branch)}`, {
|
|
1383
|
+
cwd: this.repoPath,
|
|
1384
|
+
stdio: "pipe",
|
|
1385
|
+
});
|
|
1386
|
+
// 8. Perform regular merge (preserves commit history)
|
|
1387
|
+
let hasConflicts = false;
|
|
1388
|
+
let filesChanged = 0;
|
|
1389
|
+
try {
|
|
1390
|
+
execSync(`git merge ${this._escapeShellArg(execution.branch_name)}`, {
|
|
1391
|
+
cwd: this.repoPath,
|
|
1392
|
+
stdio: "pipe",
|
|
1393
|
+
});
|
|
1394
|
+
}
|
|
1395
|
+
catch (error) {
|
|
1396
|
+
// Merge may have failed due to conflicts
|
|
1397
|
+
hasConflicts = true;
|
|
1398
|
+
}
|
|
1399
|
+
// 9. Count files changed
|
|
1400
|
+
try {
|
|
1401
|
+
const diffOutput = execSync(`git diff --name-only ${this._escapeShellArg(safetyTag)}..HEAD`, {
|
|
1402
|
+
cwd: this.repoPath,
|
|
1403
|
+
encoding: "utf8",
|
|
1404
|
+
stdio: "pipe",
|
|
1405
|
+
});
|
|
1406
|
+
filesChanged = diffOutput
|
|
1407
|
+
.split("\n")
|
|
1408
|
+
.filter((line) => line.trim().length > 0).length;
|
|
1409
|
+
}
|
|
1410
|
+
catch {
|
|
1411
|
+
// If merge is in progress, count staged/conflicted files
|
|
1412
|
+
const statusOutput = execSync("git diff --name-only --cached", {
|
|
1413
|
+
cwd: this.repoPath,
|
|
1414
|
+
encoding: "utf8",
|
|
1415
|
+
stdio: "pipe",
|
|
1416
|
+
});
|
|
1417
|
+
filesChanged = statusOutput
|
|
1418
|
+
.split("\n")
|
|
1419
|
+
.filter((line) => line.trim().length > 0).length;
|
|
1420
|
+
}
|
|
1421
|
+
// 10. Auto-resolve JSONL conflicts if any
|
|
1422
|
+
const jsonlFilesResolved = await this._resolveJSONLConflicts();
|
|
1423
|
+
if (jsonlFilesResolved > 0) {
|
|
1424
|
+
// Re-check for remaining conflicts
|
|
1425
|
+
try {
|
|
1426
|
+
const conflictCheck = execSync("git diff --name-only --diff-filter=U", {
|
|
1427
|
+
cwd: this.repoPath,
|
|
1428
|
+
encoding: "utf8",
|
|
1429
|
+
stdio: "pipe",
|
|
1430
|
+
});
|
|
1431
|
+
hasConflicts = conflictCheck.trim().length > 0;
|
|
1432
|
+
}
|
|
1433
|
+
catch {
|
|
1434
|
+
hasConflicts = false;
|
|
1435
|
+
}
|
|
1436
|
+
}
|
|
1437
|
+
// 11. Check if there are unresolved conflicts
|
|
1438
|
+
if (hasConflicts) {
|
|
1439
|
+
// Get list of files with conflicts
|
|
1440
|
+
let filesWithConflicts = [];
|
|
1441
|
+
try {
|
|
1442
|
+
const conflictCheck = execSync("git diff --name-only --diff-filter=U", {
|
|
1443
|
+
cwd: this.repoPath,
|
|
1444
|
+
encoding: "utf8",
|
|
1445
|
+
stdio: "pipe",
|
|
1446
|
+
});
|
|
1447
|
+
filesWithConflicts = conflictCheck
|
|
1448
|
+
.trim()
|
|
1449
|
+
.split("\n")
|
|
1450
|
+
.filter((f) => f.length > 0);
|
|
1451
|
+
}
|
|
1452
|
+
catch {
|
|
1453
|
+
// If command fails, leave empty
|
|
1454
|
+
}
|
|
1455
|
+
return {
|
|
1456
|
+
success: false,
|
|
1457
|
+
filesChanged,
|
|
1458
|
+
hasConflicts: true,
|
|
1459
|
+
filesWithConflicts,
|
|
1460
|
+
error: "Merge conflicts detected. Please resolve them manually and commit.",
|
|
1461
|
+
cleanupOffered: false,
|
|
1462
|
+
};
|
|
1463
|
+
}
|
|
1464
|
+
// 12. Get the final commit SHA
|
|
1465
|
+
const finalCommit = execSync("git rev-parse HEAD", {
|
|
1466
|
+
cwd: this.repoPath,
|
|
1467
|
+
encoding: "utf8",
|
|
1468
|
+
stdio: "pipe",
|
|
1469
|
+
}).trim();
|
|
1470
|
+
// 13. Restore uncommitted JSONL files with three-way merge
|
|
1471
|
+
if (hasUncommittedJsonl) {
|
|
1472
|
+
await this._restoreUncommittedJsonl();
|
|
1473
|
+
}
|
|
1474
|
+
// 14. Return success result
|
|
1475
|
+
return {
|
|
1476
|
+
success: true,
|
|
1477
|
+
finalCommit,
|
|
1478
|
+
filesChanged,
|
|
1479
|
+
cleanupOffered: true,
|
|
1480
|
+
};
|
|
1481
|
+
}
|
|
1482
|
+
catch (error) {
|
|
1483
|
+
// Restore uncommitted JSONL files even on failure (to avoid losing user changes)
|
|
1484
|
+
if (hasUncommittedJsonl) {
|
|
1485
|
+
try {
|
|
1486
|
+
await this._restoreUncommittedJsonl();
|
|
1487
|
+
}
|
|
1488
|
+
catch (restoreError) {
|
|
1489
|
+
console.error("Failed to restore uncommitted JSONL files:", restoreError);
|
|
1490
|
+
}
|
|
1491
|
+
}
|
|
1492
|
+
// Rollback to safety snapshot on failure
|
|
1493
|
+
if (safetyTag) {
|
|
1494
|
+
try {
|
|
1495
|
+
await this._rollbackToSnapshot(execution.target_branch, safetyTag);
|
|
1496
|
+
}
|
|
1497
|
+
catch (rollbackError) {
|
|
1498
|
+
console.error(`Failed to rollback to snapshot ${safetyTag}:`, rollbackError);
|
|
1499
|
+
}
|
|
1500
|
+
}
|
|
1501
|
+
throw new WorktreeSyncError(`Preserve sync failed: ${error.message}`, WorktreeSyncErrorCode.MERGE_FAILED, error);
|
|
1502
|
+
}
|
|
1503
|
+
}
|
|
1504
|
+
}
|
|
1505
|
+
//# sourceMappingURL=worktree-sync-service.js.map
|