macro-agent 0.0.17 → 0.1.1
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/.claude/settings.local.json +3 -1
- package/.sudocode/specs.jsonl +4 -0
- package/CLAUDE.md +16 -14
- package/README.md +11 -29
- package/dist/acp/macro-agent.d.ts +17 -0
- package/dist/acp/macro-agent.d.ts.map +1 -1
- package/dist/acp/macro-agent.js +183 -55
- package/dist/acp/macro-agent.js.map +1 -1
- package/dist/acp/types.d.ts +32 -1
- package/dist/acp/types.d.ts.map +1 -1
- package/dist/acp/types.js.map +1 -1
- package/dist/agent/agent-manager.d.ts +65 -1
- package/dist/agent/agent-manager.d.ts.map +1 -1
- package/dist/agent/agent-manager.js +464 -183
- package/dist/agent/agent-manager.js.map +1 -1
- package/dist/agent/types.d.ts +1 -1
- package/dist/agent/types.d.ts.map +1 -1
- package/dist/api/server.d.ts +3 -0
- package/dist/api/server.d.ts.map +1 -1
- package/dist/api/server.js +37 -6
- package/dist/api/server.js.map +1 -1
- package/dist/auth/index.d.ts +2 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +2 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/token.d.ts +41 -0
- package/dist/auth/token.d.ts.map +1 -0
- package/dist/auth/token.js +73 -0
- package/dist/auth/token.js.map +1 -0
- package/dist/cli/acp.d.ts +2 -23
- package/dist/cli/acp.d.ts.map +1 -1
- package/dist/cli/acp.js +127 -61
- package/dist/cli/acp.js.map +1 -1
- package/dist/cli/index.js +147 -15
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/mcp.d.ts +6 -0
- package/dist/cli/mcp.d.ts.map +1 -1
- package/dist/cli/mcp.js +268 -181
- package/dist/cli/mcp.js.map +1 -1
- package/dist/cli/parse-args.d.ts +20 -0
- package/dist/cli/parse-args.d.ts.map +1 -0
- package/dist/cli/parse-args.js +43 -0
- package/dist/cli/parse-args.js.map +1 -0
- package/dist/cli/stable-instance-id.d.ts +8 -0
- package/dist/cli/stable-instance-id.d.ts.map +1 -0
- package/dist/cli/stable-instance-id.js +14 -0
- package/dist/cli/stable-instance-id.js.map +1 -0
- package/dist/config/project-config.d.ts +74 -7
- package/dist/config/project-config.d.ts.map +1 -1
- package/dist/config/project-config.js +123 -20
- package/dist/config/project-config.js.map +1 -1
- package/dist/map/adapter/acp-over-map.d.ts +23 -0
- package/dist/map/adapter/acp-over-map.d.ts.map +1 -1
- package/dist/map/adapter/acp-over-map.js +482 -55
- package/dist/map/adapter/acp-over-map.js.map +1 -1
- package/dist/map/adapter/connection-manager.d.ts.map +1 -1
- package/dist/map/adapter/connection-manager.js +3 -0
- package/dist/map/adapter/connection-manager.js.map +1 -1
- package/dist/map/adapter/event-log.d.ts +87 -0
- package/dist/map/adapter/event-log.d.ts.map +1 -0
- package/dist/map/adapter/event-log.js +122 -0
- package/dist/map/adapter/event-log.js.map +1 -0
- package/dist/map/adapter/event-translator.js +6 -6
- package/dist/map/adapter/event-translator.js.map +1 -1
- package/dist/map/adapter/extensions/agent-lifecycle.d.ts +82 -0
- package/dist/map/adapter/extensions/agent-lifecycle.d.ts.map +1 -0
- package/dist/map/adapter/extensions/agent-lifecycle.js +164 -0
- package/dist/map/adapter/extensions/agent-lifecycle.js.map +1 -0
- package/dist/map/adapter/extensions/index.d.ts +10 -1
- package/dist/map/adapter/extensions/index.d.ts.map +1 -1
- package/dist/map/adapter/extensions/index.js +34 -0
- package/dist/map/adapter/extensions/index.js.map +1 -1
- package/dist/map/adapter/extensions/mcp-bridge.d.ts +57 -0
- package/dist/map/adapter/extensions/mcp-bridge.d.ts.map +1 -0
- package/dist/map/adapter/extensions/mcp-bridge.js +745 -0
- package/dist/map/adapter/extensions/mcp-bridge.js.map +1 -0
- package/dist/map/adapter/extensions/rename.d.ts +29 -0
- package/dist/map/adapter/extensions/rename.d.ts.map +1 -0
- package/dist/map/adapter/extensions/rename.js +49 -0
- package/dist/map/adapter/extensions/rename.js.map +1 -0
- package/dist/map/adapter/extensions/task.d.ts.map +1 -1
- package/dist/map/adapter/extensions/task.js +10 -0
- package/dist/map/adapter/extensions/task.js.map +1 -1
- package/dist/map/adapter/extensions/update-metadata.d.ts +29 -0
- package/dist/map/adapter/extensions/update-metadata.d.ts.map +1 -0
- package/dist/map/adapter/extensions/update-metadata.js +67 -0
- package/dist/map/adapter/extensions/update-metadata.js.map +1 -0
- package/dist/map/adapter/index.d.ts +2 -1
- package/dist/map/adapter/index.d.ts.map +1 -1
- package/dist/map/adapter/index.js +8 -2
- package/dist/map/adapter/index.js.map +1 -1
- package/dist/map/adapter/interface.d.ts +2 -0
- package/dist/map/adapter/interface.d.ts.map +1 -1
- package/dist/map/adapter/map-adapter.d.ts +4 -0
- package/dist/map/adapter/map-adapter.d.ts.map +1 -1
- package/dist/map/adapter/map-adapter.js +302 -30
- package/dist/map/adapter/map-adapter.js.map +1 -1
- package/dist/map/adapter/subscription-manager.d.ts.map +1 -1
- package/dist/map/adapter/subscription-manager.js +5 -1
- package/dist/map/adapter/subscription-manager.js.map +1 -1
- package/dist/map/adapter/types.d.ts +2 -0
- package/dist/map/adapter/types.d.ts.map +1 -1
- package/dist/mcp/map-client.d.ts +39 -0
- package/dist/mcp/map-client.d.ts.map +1 -0
- package/dist/mcp/map-client.js +129 -0
- package/dist/mcp/map-client.js.map +1 -0
- package/dist/mcp/mcp-server.d.ts +14 -0
- package/dist/mcp/mcp-server.d.ts.map +1 -1
- package/dist/mcp/mcp-server.js +113 -85
- package/dist/mcp/mcp-server.js.map +1 -1
- package/dist/mcp/types.d.ts +9 -1
- package/dist/mcp/types.d.ts.map +1 -1
- package/dist/mcp/types.js.map +1 -1
- package/dist/metrics/metrics.js +1 -1
- package/dist/metrics/metrics.js.map +1 -1
- package/dist/roles/capabilities.d.ts +3 -1
- package/dist/roles/capabilities.d.ts.map +1 -1
- package/dist/roles/capabilities.js +17 -7
- package/dist/roles/capabilities.js.map +1 -1
- package/dist/roles/config-loader.d.ts +6 -6
- package/dist/roles/config-loader.d.ts.map +1 -1
- package/dist/roles/config-loader.js +6 -6
- package/dist/roles/config-loader.js.map +1 -1
- package/dist/roles/registry.d.ts +2 -2
- package/dist/roles/registry.js +2 -2
- package/dist/server/combined-server.d.ts +20 -0
- package/dist/server/combined-server.d.ts.map +1 -1
- package/dist/server/combined-server.js +107 -8
- package/dist/server/combined-server.js.map +1 -1
- package/dist/store/event-store.d.ts +7 -1
- package/dist/store/event-store.d.ts.map +1 -1
- package/dist/store/event-store.js +91 -8
- package/dist/store/event-store.js.map +1 -1
- package/dist/store/types/agents.d.ts +23 -0
- package/dist/store/types/agents.d.ts.map +1 -1
- package/dist/store/types/events.d.ts +1 -1
- package/dist/store/types/events.d.ts.map +1 -1
- package/dist/task/backend/index.d.ts +47 -29
- package/dist/task/backend/index.d.ts.map +1 -1
- package/dist/task/backend/index.js +109 -71
- package/dist/task/backend/index.js.map +1 -1
- package/dist/task/backend/memory.d.ts +1 -0
- package/dist/task/backend/memory.d.ts.map +1 -1
- package/dist/task/backend/memory.js +3 -0
- package/dist/task/backend/memory.js.map +1 -1
- package/dist/task/backend/opentasks/backend.d.ts +140 -0
- package/dist/task/backend/opentasks/backend.d.ts.map +1 -0
- package/dist/task/backend/opentasks/backend.js +1023 -0
- package/dist/task/backend/opentasks/backend.js.map +1 -0
- package/dist/task/backend/opentasks/client.d.ts +337 -0
- package/dist/task/backend/opentasks/client.d.ts.map +1 -0
- package/dist/task/backend/opentasks/client.js +225 -0
- package/dist/task/backend/opentasks/client.js.map +1 -0
- package/dist/task/backend/opentasks/daemon-manager.d.ts +89 -0
- package/dist/task/backend/opentasks/daemon-manager.d.ts.map +1 -0
- package/dist/task/backend/opentasks/daemon-manager.js +195 -0
- package/dist/task/backend/opentasks/daemon-manager.js.map +1 -0
- package/dist/task/backend/opentasks/index.d.ts +21 -0
- package/dist/task/backend/opentasks/index.d.ts.map +1 -0
- package/dist/task/backend/opentasks/index.js +21 -0
- package/dist/task/backend/opentasks/index.js.map +1 -0
- package/dist/task/backend/opentasks/mapping.d.ts +48 -0
- package/dist/task/backend/opentasks/mapping.d.ts.map +1 -0
- package/dist/task/backend/opentasks/mapping.js +77 -0
- package/dist/task/backend/opentasks/mapping.js.map +1 -0
- package/dist/task/backend/types.d.ts +33 -53
- package/dist/task/backend/types.d.ts.map +1 -1
- package/dist/task/backend/types.js +7 -11
- package/dist/task/backend/types.js.map +1 -1
- package/dist/task/backend/unified-tool-provider.d.ts +57 -0
- package/dist/task/backend/unified-tool-provider.d.ts.map +1 -0
- package/dist/task/backend/unified-tool-provider.js +623 -0
- package/dist/task/backend/unified-tool-provider.js.map +1 -0
- package/dist/teams/team-loader.d.ts +2 -2
- package/dist/teams/team-loader.js +3 -3
- package/dist/teams/team-loader.js.map +1 -1
- package/dist/teams/team-runtime.d.ts.map +1 -1
- package/dist/teams/team-runtime.js +2 -0
- package/dist/teams/team-runtime.js.map +1 -1
- package/docs/architecture.md +7 -6
- package/docs/configuration.md +26 -62
- package/docs/implementation-details.md +5 -5
- package/docs/implementation-summary.md +17 -17
- package/docs/plan-self-driving-support.md +4 -4
- package/docs/spec-self-driving-support.md +10 -10
- package/docs/team-templates.md +2 -2
- package/docs/teams.md +3 -3
- package/docs/troubleshooting.md +10 -11
- package/package.json +6 -4
- package/src/__tests__/e2e/agent-spawn-visibility.e2e.test.ts +761 -0
- package/src/__tests__/e2e/full-agent-conflict-resolution.e2e.test.ts +2 -2
- package/src/__tests__/e2e/mcp-thin-client-bridge.e2e.test.ts +304 -0
- package/src/__tests__/e2e/mcp-tools-available.e2e.test.ts +324 -0
- package/src/__tests__/e2e/multi-agent.e2e.test.ts +5 -5
- package/src/__tests__/e2e/spawn-session-streaming.e2e.test.ts +563 -0
- package/src/acp/__tests__/history.test.ts +8 -4
- package/src/acp/__tests__/integration.test.ts +56 -31
- package/src/acp/__tests__/macro-agent.test.ts +16 -7
- package/src/acp/macro-agent.ts +230 -62
- package/src/acp/types.ts +46 -1
- package/src/agent/__tests__/agent-manager.test.ts +228 -2
- package/src/agent/agent-manager.ts +714 -261
- package/src/agent/types.ts +3 -1
- package/src/api/server.ts +41 -7
- package/src/auth/__tests__/token.test.ts +100 -0
- package/src/auth/index.ts +1 -0
- package/src/auth/token.ts +82 -0
- package/src/cli/__tests__/acp.test.ts +1 -1
- package/src/cli/__tests__/stable-instance-id.test.ts +1 -1
- package/src/cli/acp.ts +130 -72
- package/src/cli/index.ts +120 -14
- package/src/cli/mcp.ts +311 -207
- package/src/cli/parse-args.ts +54 -0
- package/src/cli/stable-instance-id.ts +14 -0
- package/src/config/project-config.ts +190 -27
- package/src/lifecycle/__tests__/cascade-termination.test.ts +1 -1
- package/src/map/adapter/__tests__/acp-over-map-cancel.test.ts +820 -0
- package/src/map/adapter/__tests__/acp-over-map-getmodels.test.ts +355 -0
- package/src/map/adapter/__tests__/acp-over-map-history.test.ts +724 -2
- package/src/map/adapter/__tests__/acp-over-map-persistence.e2e.test.ts +1 -1
- package/src/map/adapter/__tests__/event-broadcast.test.ts +420 -0
- package/src/map/adapter/__tests__/event-log.test.ts +527 -0
- package/src/map/adapter/__tests__/event-translator.test.ts +3 -3
- package/src/map/adapter/__tests__/extensions.test.ts +408 -0
- package/src/map/adapter/__tests__/map-adapter.test.ts +99 -0
- package/src/map/adapter/__tests__/mcp-bridge.test.ts +1187 -0
- package/src/map/adapter/__tests__/multi-client-broadcast.test.ts +711 -0
- package/src/map/adapter/__tests__/websocket-integration.test.ts +218 -0
- package/src/map/adapter/acp-over-map.ts +777 -92
- package/src/map/adapter/connection-manager.ts +3 -0
- package/src/map/adapter/event-log.ts +208 -0
- package/src/map/adapter/event-translator.ts +6 -6
- package/src/map/adapter/extensions/agent-lifecycle.ts +267 -0
- package/src/map/adapter/extensions/index.ts +60 -0
- package/src/map/adapter/extensions/mcp-bridge.ts +995 -0
- package/src/map/adapter/extensions/task.ts +11 -0
- package/src/map/adapter/extensions/update-metadata.ts +126 -0
- package/src/map/adapter/index.ts +28 -0
- package/src/map/adapter/interface.ts +2 -0
- package/src/map/adapter/map-adapter.ts +373 -38
- package/src/map/adapter/subscription-manager.ts +5 -1
- package/src/map/adapter/types.ts +2 -0
- package/src/mcp/__tests__/map-client.test.ts +386 -0
- package/src/mcp/__tests__/mcp-server-thin-client.test.ts +368 -0
- package/src/mcp/__tests__/mcp-server.test.ts +100 -1
- package/src/mcp/map-client.ts +177 -0
- package/src/mcp/mcp-server.ts +191 -100
- package/src/mcp/types.ts +6 -1
- package/src/metrics/metrics.ts +1 -1
- package/src/monitor/__tests__/stale-agent-flow.integration.test.ts +1 -1
- package/src/roles/__tests__/config-loader.test.ts +7 -7
- package/src/roles/capabilities.ts +17 -7
- package/src/roles/config-loader.ts +6 -6
- package/src/roles/registry.ts +2 -2
- package/src/server/__tests__/combined-server.test.ts +94 -21
- package/src/server/combined-server.ts +189 -33
- package/src/steering/__tests__/steering-integration.test.ts +1 -1
- package/src/store/__tests__/event-store.test.ts +236 -1
- package/src/store/__tests__/instance.test.ts +3 -3
- package/src/store/event-store.ts +109 -8
- package/src/store/types/agents.ts +16 -0
- package/src/store/types/events.ts +1 -1
- package/src/task/backend/__tests__/create-task-backend.test.ts +225 -0
- package/src/task/backend/__tests__/e2e/unified-tool-provider-opentasks.e2e.test.ts +524 -0
- package/src/task/backend/__tests__/unified-tool-provider.test.ts +579 -0
- package/src/task/backend/index.ts +156 -106
- package/src/task/backend/memory.ts +4 -0
- package/src/task/backend/opentasks/__tests__/backend.test.ts +968 -0
- package/src/task/backend/opentasks/__tests__/daemon-manager.test.ts +406 -0
- package/src/task/backend/opentasks/__tests__/mapping.test.ts +84 -0
- package/src/task/backend/opentasks/__tests__/opentasks-backend.e2e.test.ts +1338 -0
- package/src/task/backend/opentasks/backend.ts +1323 -0
- package/src/task/backend/opentasks/client.ts +652 -0
- package/src/task/backend/opentasks/daemon-manager.ts +253 -0
- package/src/task/backend/opentasks/index.ts +69 -0
- package/src/task/backend/opentasks/mapping.ts +94 -0
- package/src/task/backend/types.ts +42 -66
- package/src/task/backend/unified-tool-provider.ts +779 -0
- package/src/teams/__tests__/cross-subsystem.integration.test.ts +1 -1
- package/src/teams/team-loader.ts +3 -3
- package/src/teams/team-runtime.ts +2 -0
- package/test_fixtures/README.md +2 -3
- package/test_fixtures/fixtures/index.ts +0 -3
- package/test_fixtures/fixtures/projects/project-with-specs.ts +7 -149
- package/test_fixtures/fixtures/repos/index.ts +1 -3
- package/test_fixtures/fixtures/repos/temp-repo-factory.ts +0 -116
- package/test_fixtures/fixtures/repos/types.ts +0 -11
- package/test_fixtures/harness/__tests__/fixtures.test.ts +10 -102
- package/test_fixtures/harness/__tests__/temp-repo-and-simulator.test.ts +0 -33
- package/test_fixtures/harness/simulator/agent-simulator.ts +4 -4
- package/vitest.config.ts +1 -1
- package/vitest.e2e.config.ts +1 -1
- package/vitest.setup.ts +1 -30
- package/.macro-agent/teams/self-driving/prompts/grinder.md +0 -27
- package/.macro-agent/teams/self-driving/prompts/judge.md +0 -27
- package/.macro-agent/teams/self-driving/prompts/planner.md +0 -33
- package/.macro-agent/teams/self-driving/roles/grinder.yaml +0 -17
- package/.macro-agent/teams/self-driving/roles/judge.yaml +0 -24
- package/.macro-agent/teams/self-driving/roles/planner.yaml +0 -18
- package/.macro-agent/teams/self-driving/team.yaml +0 -103
- package/.macro-agent/teams/structured/prompts/developer.md +0 -26
- package/.macro-agent/teams/structured/prompts/lead.md +0 -25
- package/.macro-agent/teams/structured/prompts/reviewer.md +0 -24
- package/.macro-agent/teams/structured/roles/developer.yaml +0 -12
- package/.macro-agent/teams/structured/roles/lead.yaml +0 -11
- package/.macro-agent/teams/structured/roles/reviewer.yaml +0 -19
- package/.macro-agent/teams/structured/team.yaml +0 -89
- package/docs/sudocode-integration.md +0 -383
- package/src/task/backend/__tests__/backend-parity.test.ts +0 -451
- package/src/task/backend/__tests__/tool-provider-edge-cases.test.ts +0 -430
- package/src/task/backend/__tests__/tool-provider.test.ts +0 -983
- package/src/task/backend/sudocode/__tests__/backend-edge-cases.test.ts +0 -575
- package/src/task/backend/sudocode/__tests__/backend.test.ts +0 -1194
- package/src/task/backend/sudocode/__tests__/client-integration.test.ts +0 -418
- package/src/task/backend/sudocode/__tests__/client.test.ts +0 -345
- package/src/task/backend/sudocode/__tests__/e2e/backend.e2e.test.ts +0 -753
- package/src/task/backend/sudocode/__tests__/e2e/server-client.e2e.test.ts +0 -680
- package/src/task/backend/sudocode/__tests__/e2e-workflow.test.ts +0 -666
- package/src/task/backend/sudocode/__tests__/integration/standalone-client.integration.test.ts +0 -396
- package/src/task/backend/sudocode/__tests__/integration/sudocode-cli.integration.test.ts +0 -328
- package/src/task/backend/sudocode/__tests__/integration/test-utils.ts +0 -175
- package/src/task/backend/sudocode/__tests__/mapping-edge-cases.test.ts +0 -265
- package/src/task/backend/sudocode/__tests__/server-client.test.ts +0 -675
- package/src/task/backend/sudocode/__tests__/sync-policy-edge-cases.test.ts +0 -521
- package/src/task/backend/sudocode/__tests__/sync-policy.test.ts +0 -519
- package/src/task/backend/sudocode/__tests__/tools.test.ts +0 -471
- package/src/task/backend/sudocode/backend.ts +0 -1237
- package/src/task/backend/sudocode/client.ts +0 -515
- package/src/task/backend/sudocode/index.ts +0 -120
- package/src/task/backend/sudocode/mapping.ts +0 -93
- package/src/task/backend/sudocode/server-client.ts +0 -522
- package/src/task/backend/sudocode/standalone-client.ts +0 -623
- package/src/task/backend/sudocode/sync-policy.ts +0 -387
- package/src/task/backend/sudocode/tools.ts +0 -896
- package/src/task/backend/tool-provider.ts +0 -506
- package/test_fixtures/fixtures/sudocode/index.ts +0 -29
- package/test_fixtures/fixtures/sudocode/issues.ts +0 -185
- package/test_fixtures/fixtures/sudocode/specs.ts +0 -159
package/src/task/backend/sudocode/__tests__/integration/standalone-client.integration.test.ts
DELETED
|
@@ -1,396 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Integration tests for StandaloneClient
|
|
3
|
-
*
|
|
4
|
-
* These tests use the real @sudocode-ai/cli package with a temp SQLite database
|
|
5
|
-
* to verify that the StandaloneClient implementation works correctly.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { describe, it, expect, beforeEach, afterEach } from "vitest";
|
|
9
|
-
import { mkdtempSync, rmSync } from "fs";
|
|
10
|
-
import { tmpdir } from "os";
|
|
11
|
-
import { join } from "path";
|
|
12
|
-
import {
|
|
13
|
-
StandaloneClient,
|
|
14
|
-
createStandaloneClient,
|
|
15
|
-
} from "../../standalone-client.js";
|
|
16
|
-
import {
|
|
17
|
-
createTestContext,
|
|
18
|
-
createTestIssue,
|
|
19
|
-
createTestSpec,
|
|
20
|
-
createBlockingRelationship,
|
|
21
|
-
createImplementsRelationship,
|
|
22
|
-
type TestContext,
|
|
23
|
-
} from "./test-utils.js";
|
|
24
|
-
|
|
25
|
-
describe("StandaloneClient Integration", () => {
|
|
26
|
-
let tmpDir: string;
|
|
27
|
-
let client: StandaloneClient;
|
|
28
|
-
|
|
29
|
-
beforeEach(async () => {
|
|
30
|
-
// Create a fresh temp directory for each test
|
|
31
|
-
tmpDir = mkdtempSync(join(tmpdir(), "sudocode-client-test-"));
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
afterEach(() => {
|
|
35
|
-
// Clean up temp directory (client cleanup is handled per-describe block)
|
|
36
|
-
if (tmpDir) {
|
|
37
|
-
rmSync(tmpDir, { recursive: true, force: true });
|
|
38
|
-
}
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
describe("Initialization", () => {
|
|
42
|
-
it("should initialize with a new project directory", async () => {
|
|
43
|
-
client = await createStandaloneClient({ projectPath: tmpDir });
|
|
44
|
-
expect(client.isReady()).toBe(true);
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
it("should create .sudocode directory if it doesn't exist", async () => {
|
|
48
|
-
const { existsSync } = await import("fs");
|
|
49
|
-
expect(existsSync(join(tmpDir, ".sudocode"))).toBe(false);
|
|
50
|
-
|
|
51
|
-
client = await createStandaloneClient({ projectPath: tmpDir });
|
|
52
|
-
|
|
53
|
-
expect(existsSync(join(tmpDir, ".sudocode"))).toBe(true);
|
|
54
|
-
expect(existsSync(join(tmpDir, ".sudocode", "cache.db"))).toBe(true);
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
it("should close cleanly", async () => {
|
|
58
|
-
client = await createStandaloneClient({ projectPath: tmpDir });
|
|
59
|
-
expect(client.isReady()).toBe(true);
|
|
60
|
-
|
|
61
|
-
client.close();
|
|
62
|
-
|
|
63
|
-
expect(client.isReady()).toBe(false);
|
|
64
|
-
});
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
describe("Issue Operations", () => {
|
|
68
|
-
let ctx: TestContext;
|
|
69
|
-
|
|
70
|
-
beforeEach(async () => {
|
|
71
|
-
// Create a test context and use its directory for the client
|
|
72
|
-
ctx = createTestContext();
|
|
73
|
-
tmpDir = ctx.tmpDir;
|
|
74
|
-
client = await createStandaloneClient({ projectPath: tmpDir });
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
afterEach(() => {
|
|
78
|
-
if (client) client.close();
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
it("should retrieve an issue created via CLI", async () => {
|
|
82
|
-
// Create issue directly via CLI
|
|
83
|
-
const createdIssue = createTestIssue(ctx, {
|
|
84
|
-
title: "Test Issue",
|
|
85
|
-
content: "Test content",
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
// Retrieve via client
|
|
89
|
-
const issue = await client.getIssue(createdIssue.id);
|
|
90
|
-
|
|
91
|
-
expect(issue).not.toBeNull();
|
|
92
|
-
expect(issue!.id).toBe(createdIssue.id);
|
|
93
|
-
expect(issue!.title).toBe("Test Issue");
|
|
94
|
-
expect(issue!.content).toBe("Test content");
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
it("should return null for non-existent issue", async () => {
|
|
98
|
-
const issue = await client.getIssue("i-nonexistent");
|
|
99
|
-
expect(issue).toBeNull();
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
it("should list issues", async () => {
|
|
103
|
-
createTestIssue(ctx, { title: "Issue 1", status: "open" });
|
|
104
|
-
createTestIssue(ctx, { title: "Issue 2", status: "in_progress" });
|
|
105
|
-
createTestIssue(ctx, { title: "Issue 3", status: "closed" });
|
|
106
|
-
|
|
107
|
-
const issues = await client.listIssues();
|
|
108
|
-
expect(issues).toHaveLength(3);
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
it("should filter issues by status", async () => {
|
|
112
|
-
createTestIssue(ctx, { title: "Open Issue", status: "open" });
|
|
113
|
-
createTestIssue(ctx, { title: "Closed Issue", status: "closed" });
|
|
114
|
-
|
|
115
|
-
const openIssues = await client.listIssues({ status: "open" });
|
|
116
|
-
expect(openIssues).toHaveLength(1);
|
|
117
|
-
expect(openIssues[0].title).toBe("Open Issue");
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
it("should search issues by text", async () => {
|
|
121
|
-
createTestIssue(ctx, { title: "Fix the bug", content: "A bug fix" });
|
|
122
|
-
createTestIssue(ctx, { title: "Add feature", content: "New feature" });
|
|
123
|
-
|
|
124
|
-
const bugIssues = await client.listIssues({ search: "bug" });
|
|
125
|
-
expect(bugIssues).toHaveLength(1);
|
|
126
|
-
expect(bugIssues[0].title).toBe("Fix the bug");
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
it("should get ready issues (no blockers)", async () => {
|
|
130
|
-
const ready1 = createTestIssue(ctx, { title: "Ready 1", status: "open" });
|
|
131
|
-
const blocker = createTestIssue(ctx, {
|
|
132
|
-
title: "Blocker",
|
|
133
|
-
status: "open",
|
|
134
|
-
});
|
|
135
|
-
const blocked = createTestIssue(ctx, {
|
|
136
|
-
title: "Blocked",
|
|
137
|
-
status: "open",
|
|
138
|
-
});
|
|
139
|
-
|
|
140
|
-
createBlockingRelationship(ctx.db, blocker.id, blocked.id);
|
|
141
|
-
|
|
142
|
-
const readyIssues = await client.getReadyIssues();
|
|
143
|
-
const readyIds = readyIssues.map((i) => i.id);
|
|
144
|
-
|
|
145
|
-
expect(readyIds).toContain(ready1.id);
|
|
146
|
-
expect(readyIds).toContain(blocker.id);
|
|
147
|
-
expect(readyIds).not.toContain(blocked.id);
|
|
148
|
-
});
|
|
149
|
-
|
|
150
|
-
it("should update an issue", async () => {
|
|
151
|
-
const issue = createTestIssue(ctx, {
|
|
152
|
-
title: "Original",
|
|
153
|
-
status: "open",
|
|
154
|
-
});
|
|
155
|
-
|
|
156
|
-
const updated = await client.updateIssue(issue.id, {
|
|
157
|
-
title: "Updated",
|
|
158
|
-
status: "in_progress",
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
expect(updated.title).toBe("Updated");
|
|
162
|
-
expect(updated.status).toBe("in_progress");
|
|
163
|
-
|
|
164
|
-
// Verify persistence
|
|
165
|
-
const retrieved = await client.getIssue(issue.id);
|
|
166
|
-
expect(retrieved!.title).toBe("Updated");
|
|
167
|
-
expect(retrieved!.status).toBe("in_progress");
|
|
168
|
-
});
|
|
169
|
-
});
|
|
170
|
-
|
|
171
|
-
describe("Relationship Operations", () => {
|
|
172
|
-
let ctx: TestContext;
|
|
173
|
-
|
|
174
|
-
beforeEach(async () => {
|
|
175
|
-
ctx = createTestContext();
|
|
176
|
-
tmpDir = ctx.tmpDir;
|
|
177
|
-
client = await createStandaloneClient({ projectPath: tmpDir });
|
|
178
|
-
});
|
|
179
|
-
|
|
180
|
-
afterEach(() => {
|
|
181
|
-
if (client) client.close();
|
|
182
|
-
});
|
|
183
|
-
|
|
184
|
-
it("should create a blocks relationship", async () => {
|
|
185
|
-
const blocker = createTestIssue(ctx, { title: "Blocker" });
|
|
186
|
-
const blocked = createTestIssue(ctx, { title: "Blocked" });
|
|
187
|
-
|
|
188
|
-
await client.createLink(blocker.id, blocked.id, "blocks");
|
|
189
|
-
|
|
190
|
-
// Verify the relationship was created
|
|
191
|
-
const blockers = await client.getBlockers(blocked.id);
|
|
192
|
-
expect(blockers).toHaveLength(1);
|
|
193
|
-
expect(blockers[0].id).toBe(blocker.id);
|
|
194
|
-
});
|
|
195
|
-
|
|
196
|
-
it("should get blockers for an issue", async () => {
|
|
197
|
-
const blocker1 = createTestIssue(ctx, { title: "Blocker 1" });
|
|
198
|
-
const blocker2 = createTestIssue(ctx, { title: "Blocker 2" });
|
|
199
|
-
const blocked = createTestIssue(ctx, { title: "Blocked" });
|
|
200
|
-
|
|
201
|
-
createBlockingRelationship(ctx.db, blocker1.id, blocked.id);
|
|
202
|
-
createBlockingRelationship(ctx.db, blocker2.id, blocked.id);
|
|
203
|
-
|
|
204
|
-
const blockers = await client.getBlockers(blocked.id);
|
|
205
|
-
expect(blockers).toHaveLength(2);
|
|
206
|
-
|
|
207
|
-
const blockerIds = blockers.map((b) => b.id);
|
|
208
|
-
expect(blockerIds).toContain(blocker1.id);
|
|
209
|
-
expect(blockerIds).toContain(blocker2.id);
|
|
210
|
-
});
|
|
211
|
-
|
|
212
|
-
it("should get issues that a given issue blocks", async () => {
|
|
213
|
-
const blocker = createTestIssue(ctx, { title: "Blocker" });
|
|
214
|
-
const blocked1 = createTestIssue(ctx, { title: "Blocked 1" });
|
|
215
|
-
const blocked2 = createTestIssue(ctx, { title: "Blocked 2" });
|
|
216
|
-
|
|
217
|
-
createBlockingRelationship(ctx.db, blocker.id, blocked1.id);
|
|
218
|
-
createBlockingRelationship(ctx.db, blocker.id, blocked2.id);
|
|
219
|
-
|
|
220
|
-
const blocking = await client.getBlocking(blocker.id);
|
|
221
|
-
expect(blocking).toHaveLength(2);
|
|
222
|
-
|
|
223
|
-
const blockedIds = blocking.map((b) => b.id);
|
|
224
|
-
expect(blockedIds).toContain(blocked1.id);
|
|
225
|
-
expect(blockedIds).toContain(blocked2.id);
|
|
226
|
-
});
|
|
227
|
-
|
|
228
|
-
it("should remove a blocks relationship", async () => {
|
|
229
|
-
const blocker = createTestIssue(ctx, { title: "Blocker" });
|
|
230
|
-
const blocked = createTestIssue(ctx, { title: "Blocked" });
|
|
231
|
-
|
|
232
|
-
createBlockingRelationship(ctx.db, blocker.id, blocked.id);
|
|
233
|
-
|
|
234
|
-
// Verify relationship exists
|
|
235
|
-
let blockers = await client.getBlockers(blocked.id);
|
|
236
|
-
expect(blockers).toHaveLength(1);
|
|
237
|
-
|
|
238
|
-
// Remove via client
|
|
239
|
-
await client.removeLink(blocker.id, blocked.id, "blocks");
|
|
240
|
-
|
|
241
|
-
// Verify relationship is gone
|
|
242
|
-
blockers = await client.getBlockers(blocked.id);
|
|
243
|
-
expect(blockers).toHaveLength(0);
|
|
244
|
-
});
|
|
245
|
-
});
|
|
246
|
-
|
|
247
|
-
describe("Spec Operations", () => {
|
|
248
|
-
let ctx: TestContext;
|
|
249
|
-
|
|
250
|
-
beforeEach(async () => {
|
|
251
|
-
ctx = createTestContext();
|
|
252
|
-
tmpDir = ctx.tmpDir;
|
|
253
|
-
client = await createStandaloneClient({ projectPath: tmpDir });
|
|
254
|
-
});
|
|
255
|
-
|
|
256
|
-
afterEach(() => {
|
|
257
|
-
if (client) client.close();
|
|
258
|
-
});
|
|
259
|
-
|
|
260
|
-
it("should retrieve a spec created via CLI", async () => {
|
|
261
|
-
const createdSpec = createTestSpec(ctx, {
|
|
262
|
-
title: "Test Spec",
|
|
263
|
-
content: "Spec content",
|
|
264
|
-
});
|
|
265
|
-
|
|
266
|
-
const spec = await client.getSpec(createdSpec.id);
|
|
267
|
-
|
|
268
|
-
expect(spec).not.toBeNull();
|
|
269
|
-
expect(spec!.id).toBe(createdSpec.id);
|
|
270
|
-
expect(spec!.title).toBe("Test Spec");
|
|
271
|
-
expect(spec!.content).toBe("Spec content");
|
|
272
|
-
});
|
|
273
|
-
|
|
274
|
-
it("should return null for non-existent spec", async () => {
|
|
275
|
-
const spec = await client.getSpec("s-nonexistent");
|
|
276
|
-
expect(spec).toBeNull();
|
|
277
|
-
});
|
|
278
|
-
|
|
279
|
-
it("should list specs", async () => {
|
|
280
|
-
createTestSpec(ctx, { title: "Spec 1" });
|
|
281
|
-
createTestSpec(ctx, { title: "Spec 2" });
|
|
282
|
-
createTestSpec(ctx, { title: "Spec 3" });
|
|
283
|
-
|
|
284
|
-
const specs = await client.listSpecs();
|
|
285
|
-
expect(specs).toHaveLength(3);
|
|
286
|
-
});
|
|
287
|
-
|
|
288
|
-
it("should search specs by text", async () => {
|
|
289
|
-
createTestSpec(ctx, { title: "Auth Spec", content: "Authentication" });
|
|
290
|
-
createTestSpec(ctx, { title: "Database Spec", content: "Database design" });
|
|
291
|
-
|
|
292
|
-
const authSpecs = await client.listSpecs({ search: "Auth" });
|
|
293
|
-
expect(authSpecs).toHaveLength(1);
|
|
294
|
-
expect(authSpecs[0].title).toBe("Auth Spec");
|
|
295
|
-
});
|
|
296
|
-
});
|
|
297
|
-
|
|
298
|
-
describe("Issue-Spec Relationships", () => {
|
|
299
|
-
let ctx: TestContext;
|
|
300
|
-
|
|
301
|
-
beforeEach(async () => {
|
|
302
|
-
ctx = createTestContext();
|
|
303
|
-
tmpDir = ctx.tmpDir;
|
|
304
|
-
client = await createStandaloneClient({ projectPath: tmpDir });
|
|
305
|
-
});
|
|
306
|
-
|
|
307
|
-
afterEach(() => {
|
|
308
|
-
if (client) client.close();
|
|
309
|
-
});
|
|
310
|
-
|
|
311
|
-
it("should create an implements relationship via client", async () => {
|
|
312
|
-
const spec = createTestSpec(ctx, { title: "Feature Spec" });
|
|
313
|
-
const issue = createTestIssue(ctx, { title: "Implement Feature" });
|
|
314
|
-
|
|
315
|
-
await client.createLink(issue.id, spec.id, "implements");
|
|
316
|
-
|
|
317
|
-
// Note: We can't easily verify this without exposing relationship queries
|
|
318
|
-
// but the operation should complete without error
|
|
319
|
-
});
|
|
320
|
-
});
|
|
321
|
-
|
|
322
|
-
describe("Event Subscriptions", () => {
|
|
323
|
-
let ctx: TestContext;
|
|
324
|
-
|
|
325
|
-
beforeEach(async () => {
|
|
326
|
-
ctx = createTestContext();
|
|
327
|
-
tmpDir = ctx.tmpDir;
|
|
328
|
-
client = await createStandaloneClient({
|
|
329
|
-
projectPath: tmpDir,
|
|
330
|
-
pollInterval: 100, // Fast polling for tests
|
|
331
|
-
});
|
|
332
|
-
});
|
|
333
|
-
|
|
334
|
-
afterEach(() => {
|
|
335
|
-
if (client) client.close();
|
|
336
|
-
});
|
|
337
|
-
|
|
338
|
-
it("should emit events when updating an issue", async () => {
|
|
339
|
-
const issue = createTestIssue(ctx, { title: "Test", status: "open" });
|
|
340
|
-
|
|
341
|
-
const events: Array<{ type: string; issueId: string }> = [];
|
|
342
|
-
const unsubscribe = client.onIssueChange((event) => {
|
|
343
|
-
events.push({ type: event.type, issueId: event.issueId });
|
|
344
|
-
});
|
|
345
|
-
|
|
346
|
-
// Update via client
|
|
347
|
-
await client.updateIssue(issue.id, { status: "in_progress" });
|
|
348
|
-
|
|
349
|
-
expect(events).toHaveLength(1);
|
|
350
|
-
expect(events[0].type).toBe("status_changed");
|
|
351
|
-
expect(events[0].issueId).toBe(issue.id);
|
|
352
|
-
|
|
353
|
-
unsubscribe();
|
|
354
|
-
});
|
|
355
|
-
|
|
356
|
-
it("should filter events by issue ID", async () => {
|
|
357
|
-
const issue1 = createTestIssue(ctx, { title: "Issue 1" });
|
|
358
|
-
const issue2 = createTestIssue(ctx, { title: "Issue 2" });
|
|
359
|
-
|
|
360
|
-
const events: string[] = [];
|
|
361
|
-
const unsubscribe = client.onIssueChange(issue1.id, (event) => {
|
|
362
|
-
events.push(event.issueId);
|
|
363
|
-
});
|
|
364
|
-
|
|
365
|
-
// Update both issues
|
|
366
|
-
await client.updateIssue(issue1.id, { title: "Updated 1" });
|
|
367
|
-
await client.updateIssue(issue2.id, { title: "Updated 2" });
|
|
368
|
-
|
|
369
|
-
// Should only see events for issue1
|
|
370
|
-
expect(events).toHaveLength(1);
|
|
371
|
-
expect(events[0]).toBe(issue1.id);
|
|
372
|
-
|
|
373
|
-
unsubscribe();
|
|
374
|
-
});
|
|
375
|
-
|
|
376
|
-
it("should unsubscribe correctly", async () => {
|
|
377
|
-
const issue = createTestIssue(ctx, { title: "Test" });
|
|
378
|
-
|
|
379
|
-
const events: string[] = [];
|
|
380
|
-
const unsubscribe = client.onIssueChange((event) => {
|
|
381
|
-
events.push(event.issueId);
|
|
382
|
-
});
|
|
383
|
-
|
|
384
|
-
// First update should be captured
|
|
385
|
-
await client.updateIssue(issue.id, { title: "Update 1" });
|
|
386
|
-
expect(events).toHaveLength(1);
|
|
387
|
-
|
|
388
|
-
// Unsubscribe
|
|
389
|
-
unsubscribe();
|
|
390
|
-
|
|
391
|
-
// Second update should not be captured
|
|
392
|
-
await client.updateIssue(issue.id, { title: "Update 2" });
|
|
393
|
-
expect(events).toHaveLength(1);
|
|
394
|
-
});
|
|
395
|
-
});
|
|
396
|
-
});
|