macro-agent 0.1.0 → 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 +15 -0
- package/dist/acp/macro-agent.d.ts.map +1 -1
- package/dist/acp/macro-agent.js +131 -35
- 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 +17 -0
- package/dist/map/adapter/acp-over-map.d.ts.map +1 -1
- package/dist/map/adapter/acp-over-map.js +384 -23
- 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 +3 -0
- package/dist/map/adapter/map-adapter.d.ts.map +1 -1
- package/dist/map/adapter/map-adapter.js +258 -35
- 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 +2 -1
- package/dist/store/event-store.d.ts.map +1 -1
- package/dist/store/event-store.js +69 -20
- package/dist/store/event-store.js.map +1 -1
- package/dist/store/types/agents.d.ts +18 -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__/integration.test.ts +56 -31
- package/src/acp/__tests__/macro-agent.test.ts +16 -7
- package/src/acp/macro-agent.ts +170 -36
- 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 +22 -4
- package/src/map/adapter/__tests__/acp-over-map-getmodels.test.ts +355 -0
- package/src/map/adapter/__tests__/acp-over-map-history.test.ts +263 -0
- 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 +678 -66
- 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 +312 -47
- 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 +196 -1
- package/src/store/__tests__/instance.test.ts +3 -3
- package/src/store/event-store.ts +80 -21
- package/src/store/types/agents.ts +15 -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
|
@@ -1,328 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Integration tests for Sudocode CLI operations
|
|
3
|
-
*
|
|
4
|
-
* These tests use the real @sudocode-ai/cli package with a temp SQLite database
|
|
5
|
-
* to verify that our integration with sudocode works correctly.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { describe, it, expect, beforeEach, afterEach } from "vitest";
|
|
9
|
-
import {
|
|
10
|
-
createTestContext,
|
|
11
|
-
createTestIssue,
|
|
12
|
-
createTestSpec,
|
|
13
|
-
createBlockingRelationship,
|
|
14
|
-
createImplementsRelationship,
|
|
15
|
-
getIssue,
|
|
16
|
-
listIssues,
|
|
17
|
-
updateIssue,
|
|
18
|
-
getSpec,
|
|
19
|
-
listSpecs,
|
|
20
|
-
getOutgoingRelationships,
|
|
21
|
-
getIncomingRelationships,
|
|
22
|
-
getReadyIssues,
|
|
23
|
-
type TestContext,
|
|
24
|
-
} from "./test-utils.js";
|
|
25
|
-
|
|
26
|
-
describe("Sudocode CLI Integration", () => {
|
|
27
|
-
let ctx: TestContext;
|
|
28
|
-
|
|
29
|
-
beforeEach(() => {
|
|
30
|
-
ctx = createTestContext();
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
afterEach(() => {
|
|
34
|
-
ctx.cleanup();
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
describe("Issue Operations", () => {
|
|
38
|
-
it("should create and retrieve an issue", () => {
|
|
39
|
-
const issue = createTestIssue(ctx, {
|
|
40
|
-
title: "Test Issue",
|
|
41
|
-
content: "Test content",
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
expect(issue.id).toMatch(/^i-/);
|
|
45
|
-
expect(issue.title).toBe("Test Issue");
|
|
46
|
-
expect(issue.content).toBe("Test content");
|
|
47
|
-
expect(issue.status).toBe("open");
|
|
48
|
-
expect(issue.priority).toBe(2);
|
|
49
|
-
|
|
50
|
-
const retrieved = getIssue(ctx.db, issue.id);
|
|
51
|
-
expect(retrieved).toEqual(issue);
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
it("should list issues with filters", () => {
|
|
55
|
-
const issue1 = createTestIssue(ctx, { title: "Issue 1", status: "open" });
|
|
56
|
-
const issue2 = createTestIssue(ctx, {
|
|
57
|
-
title: "Issue 2",
|
|
58
|
-
status: "in_progress",
|
|
59
|
-
});
|
|
60
|
-
const issue3 = createTestIssue(ctx, {
|
|
61
|
-
title: "Issue 3",
|
|
62
|
-
status: "closed",
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
const allIssues = listIssues(ctx.db);
|
|
66
|
-
expect(allIssues).toHaveLength(3);
|
|
67
|
-
|
|
68
|
-
const openIssues = listIssues(ctx.db, { status: "open" });
|
|
69
|
-
expect(openIssues).toHaveLength(1);
|
|
70
|
-
expect(openIssues[0].id).toBe(issue1.id);
|
|
71
|
-
|
|
72
|
-
const inProgressIssues = listIssues(ctx.db, { status: "in_progress" });
|
|
73
|
-
expect(inProgressIssues).toHaveLength(1);
|
|
74
|
-
expect(inProgressIssues[0].id).toBe(issue2.id);
|
|
75
|
-
|
|
76
|
-
const closedIssues = listIssues(ctx.db, { status: "closed" });
|
|
77
|
-
expect(closedIssues).toHaveLength(1);
|
|
78
|
-
expect(closedIssues[0].id).toBe(issue3.id);
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
it("should update an issue", () => {
|
|
82
|
-
const issue = createTestIssue(ctx, { title: "Original Title" });
|
|
83
|
-
|
|
84
|
-
const updated = updateIssue(ctx.db, issue.id, {
|
|
85
|
-
title: "Updated Title",
|
|
86
|
-
status: "in_progress",
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
expect(updated.title).toBe("Updated Title");
|
|
90
|
-
expect(updated.status).toBe("in_progress");
|
|
91
|
-
|
|
92
|
-
const retrieved = getIssue(ctx.db, issue.id);
|
|
93
|
-
expect(retrieved?.title).toBe("Updated Title");
|
|
94
|
-
expect(retrieved?.status).toBe("in_progress");
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
it("should support issue hierarchy (parent/child)", () => {
|
|
98
|
-
const parent = createTestIssue(ctx, { title: "Parent Issue" });
|
|
99
|
-
const child = createTestIssue(ctx, {
|
|
100
|
-
title: "Child Issue",
|
|
101
|
-
parent_id: parent.id,
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
expect(child.parent_id).toBe(parent.id);
|
|
105
|
-
|
|
106
|
-
const children = listIssues(ctx.db, { parent_id: parent.id });
|
|
107
|
-
expect(children).toHaveLength(1);
|
|
108
|
-
expect(children[0].id).toBe(child.id);
|
|
109
|
-
});
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
describe("Spec Operations", () => {
|
|
113
|
-
it("should create and retrieve a spec", () => {
|
|
114
|
-
const spec = createTestSpec(ctx, {
|
|
115
|
-
title: "Test Spec",
|
|
116
|
-
content: "Spec content",
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
expect(spec.id).toMatch(/^s-/);
|
|
120
|
-
expect(spec.title).toBe("Test Spec");
|
|
121
|
-
expect(spec.content).toBe("Spec content");
|
|
122
|
-
expect(spec.priority).toBe(2);
|
|
123
|
-
|
|
124
|
-
const retrieved = getSpec(ctx.db, spec.id);
|
|
125
|
-
expect(retrieved).toEqual(spec);
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
it("should list specs", () => {
|
|
129
|
-
createTestSpec(ctx, { title: "Spec 1" });
|
|
130
|
-
createTestSpec(ctx, { title: "Spec 2" });
|
|
131
|
-
createTestSpec(ctx, { title: "Spec 3" });
|
|
132
|
-
|
|
133
|
-
const specs = listSpecs(ctx.db);
|
|
134
|
-
expect(specs).toHaveLength(3);
|
|
135
|
-
});
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
describe("Relationship Operations", () => {
|
|
139
|
-
it("should create a blocking relationship between issues", () => {
|
|
140
|
-
const blocker = createTestIssue(ctx, { title: "Blocker Issue" });
|
|
141
|
-
const blocked = createTestIssue(ctx, { title: "Blocked Issue" });
|
|
142
|
-
|
|
143
|
-
createBlockingRelationship(ctx.db, blocker.id, blocked.id);
|
|
144
|
-
|
|
145
|
-
// Check outgoing relationships from blocker
|
|
146
|
-
const outgoing = getOutgoingRelationships(ctx.db, blocker.id, "issue");
|
|
147
|
-
expect(outgoing).toHaveLength(1);
|
|
148
|
-
expect(outgoing[0].to_id).toBe(blocked.id);
|
|
149
|
-
expect(outgoing[0].relationship_type).toBe("blocks");
|
|
150
|
-
|
|
151
|
-
// Check incoming relationships to blocked
|
|
152
|
-
const incoming = getIncomingRelationships(ctx.db, blocked.id, "issue");
|
|
153
|
-
expect(incoming).toHaveLength(1);
|
|
154
|
-
expect(incoming[0].from_id).toBe(blocker.id);
|
|
155
|
-
expect(incoming[0].relationship_type).toBe("blocks");
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
it("should create an implements relationship between issue and spec", () => {
|
|
159
|
-
const spec = createTestSpec(ctx, { title: "Feature Spec" });
|
|
160
|
-
const issue = createTestIssue(ctx, { title: "Implement Feature" });
|
|
161
|
-
|
|
162
|
-
createImplementsRelationship(ctx.db, issue.id, spec.id);
|
|
163
|
-
|
|
164
|
-
// Check outgoing from issue
|
|
165
|
-
const outgoing = getOutgoingRelationships(ctx.db, issue.id, "issue");
|
|
166
|
-
expect(outgoing).toHaveLength(1);
|
|
167
|
-
expect(outgoing[0].to_id).toBe(spec.id);
|
|
168
|
-
expect(outgoing[0].relationship_type).toBe("implements");
|
|
169
|
-
|
|
170
|
-
// Check incoming to spec
|
|
171
|
-
const incoming = getIncomingRelationships(ctx.db, spec.id, "spec");
|
|
172
|
-
expect(incoming).toHaveLength(1);
|
|
173
|
-
expect(incoming[0].from_id).toBe(issue.id);
|
|
174
|
-
});
|
|
175
|
-
|
|
176
|
-
it("should auto-update blocked status when adding a blocks relationship", () => {
|
|
177
|
-
const blocker = createTestIssue(ctx, { title: "Blocker", status: "open" });
|
|
178
|
-
const blocked = createTestIssue(ctx, { title: "Blocked", status: "open" });
|
|
179
|
-
|
|
180
|
-
// Adding a blocks relationship should set the blocked issue to 'blocked' status
|
|
181
|
-
createBlockingRelationship(ctx.db, blocker.id, blocked.id);
|
|
182
|
-
|
|
183
|
-
const updatedBlocked = getIssue(ctx.db, blocked.id);
|
|
184
|
-
expect(updatedBlocked?.status).toBe("blocked");
|
|
185
|
-
});
|
|
186
|
-
|
|
187
|
-
it("should auto-unblock when blocker is closed", () => {
|
|
188
|
-
const blocker = createTestIssue(ctx, { title: "Blocker", status: "open" });
|
|
189
|
-
const blocked = createTestIssue(ctx, { title: "Blocked", status: "open" });
|
|
190
|
-
|
|
191
|
-
createBlockingRelationship(ctx.db, blocker.id, blocked.id);
|
|
192
|
-
|
|
193
|
-
// Verify blocked is now 'blocked'
|
|
194
|
-
let blockedIssue = getIssue(ctx.db, blocked.id);
|
|
195
|
-
expect(blockedIssue?.status).toBe("blocked");
|
|
196
|
-
|
|
197
|
-
// Close the blocker
|
|
198
|
-
updateIssue(ctx.db, blocker.id, { status: "closed" });
|
|
199
|
-
|
|
200
|
-
// Blocked issue should now be 'open' again
|
|
201
|
-
blockedIssue = getIssue(ctx.db, blocked.id);
|
|
202
|
-
expect(blockedIssue?.status).toBe("open");
|
|
203
|
-
});
|
|
204
|
-
});
|
|
205
|
-
|
|
206
|
-
describe("Ready Issues", () => {
|
|
207
|
-
it("should return issues without blockers", () => {
|
|
208
|
-
const ready1 = createTestIssue(ctx, { title: "Ready 1", status: "open" });
|
|
209
|
-
const ready2 = createTestIssue(ctx, { title: "Ready 2", status: "open" });
|
|
210
|
-
const blocker = createTestIssue(ctx, {
|
|
211
|
-
title: "Blocker",
|
|
212
|
-
status: "open",
|
|
213
|
-
});
|
|
214
|
-
const blocked = createTestIssue(ctx, {
|
|
215
|
-
title: "Blocked",
|
|
216
|
-
status: "open",
|
|
217
|
-
});
|
|
218
|
-
|
|
219
|
-
createBlockingRelationship(ctx.db, blocker.id, blocked.id);
|
|
220
|
-
|
|
221
|
-
const readyIssues = getReadyIssues(ctx.db);
|
|
222
|
-
|
|
223
|
-
// ready1, ready2, and blocker should be ready (not blocked)
|
|
224
|
-
// blocked should NOT be in ready list
|
|
225
|
-
const readyIds = readyIssues.map((i) => i.id);
|
|
226
|
-
expect(readyIds).toContain(ready1.id);
|
|
227
|
-
expect(readyIds).toContain(ready2.id);
|
|
228
|
-
expect(readyIds).toContain(blocker.id);
|
|
229
|
-
expect(readyIds).not.toContain(blocked.id);
|
|
230
|
-
});
|
|
231
|
-
|
|
232
|
-
it("should include previously blocked issues after blocker is closed", () => {
|
|
233
|
-
const blocker = createTestIssue(ctx, { title: "Blocker", status: "open" });
|
|
234
|
-
const blocked = createTestIssue(ctx, { title: "Blocked", status: "open" });
|
|
235
|
-
|
|
236
|
-
createBlockingRelationship(ctx.db, blocker.id, blocked.id);
|
|
237
|
-
|
|
238
|
-
// Initially blocked is not ready
|
|
239
|
-
let readyIssues = getReadyIssues(ctx.db);
|
|
240
|
-
let readyIds = readyIssues.map((i) => i.id);
|
|
241
|
-
expect(readyIds).not.toContain(blocked.id);
|
|
242
|
-
|
|
243
|
-
// Close the blocker
|
|
244
|
-
updateIssue(ctx.db, blocker.id, { status: "closed" });
|
|
245
|
-
|
|
246
|
-
// Now blocked should be ready
|
|
247
|
-
readyIssues = getReadyIssues(ctx.db);
|
|
248
|
-
readyIds = readyIssues.map((i) => i.id);
|
|
249
|
-
expect(readyIds).toContain(blocked.id);
|
|
250
|
-
});
|
|
251
|
-
});
|
|
252
|
-
|
|
253
|
-
describe("Complex Scenarios", () => {
|
|
254
|
-
it("should handle a chain of blockers", () => {
|
|
255
|
-
// Create a chain: A blocks B blocks C
|
|
256
|
-
const issueA = createTestIssue(ctx, { title: "Issue A", status: "open" });
|
|
257
|
-
const issueB = createTestIssue(ctx, { title: "Issue B", status: "open" });
|
|
258
|
-
const issueC = createTestIssue(ctx, { title: "Issue C", status: "open" });
|
|
259
|
-
|
|
260
|
-
createBlockingRelationship(ctx.db, issueA.id, issueB.id);
|
|
261
|
-
createBlockingRelationship(ctx.db, issueB.id, issueC.id);
|
|
262
|
-
|
|
263
|
-
// Only A should be ready
|
|
264
|
-
let readyIssues = getReadyIssues(ctx.db);
|
|
265
|
-
let readyIds = readyIssues.map((i) => i.id);
|
|
266
|
-
expect(readyIds).toContain(issueA.id);
|
|
267
|
-
expect(readyIds).not.toContain(issueB.id);
|
|
268
|
-
expect(readyIds).not.toContain(issueC.id);
|
|
269
|
-
|
|
270
|
-
// Close A - B should become ready, C still blocked
|
|
271
|
-
updateIssue(ctx.db, issueA.id, { status: "closed" });
|
|
272
|
-
readyIssues = getReadyIssues(ctx.db);
|
|
273
|
-
readyIds = readyIssues.map((i) => i.id);
|
|
274
|
-
expect(readyIds).toContain(issueB.id);
|
|
275
|
-
expect(readyIds).not.toContain(issueC.id);
|
|
276
|
-
|
|
277
|
-
// Close B - C should become ready
|
|
278
|
-
updateIssue(ctx.db, issueB.id, { status: "closed" });
|
|
279
|
-
readyIssues = getReadyIssues(ctx.db);
|
|
280
|
-
readyIds = readyIssues.map((i) => i.id);
|
|
281
|
-
expect(readyIds).toContain(issueC.id);
|
|
282
|
-
});
|
|
283
|
-
|
|
284
|
-
it("should handle multiple blockers", () => {
|
|
285
|
-
// C is blocked by both A and B
|
|
286
|
-
const issueA = createTestIssue(ctx, { title: "Issue A", status: "open" });
|
|
287
|
-
const issueB = createTestIssue(ctx, { title: "Issue B", status: "open" });
|
|
288
|
-
const issueC = createTestIssue(ctx, { title: "Issue C", status: "open" });
|
|
289
|
-
|
|
290
|
-
createBlockingRelationship(ctx.db, issueA.id, issueC.id);
|
|
291
|
-
createBlockingRelationship(ctx.db, issueB.id, issueC.id);
|
|
292
|
-
|
|
293
|
-
// C should be blocked
|
|
294
|
-
let issueC_status = getIssue(ctx.db, issueC.id);
|
|
295
|
-
expect(issueC_status?.status).toBe("blocked");
|
|
296
|
-
|
|
297
|
-
// Close A - C should still be blocked by B
|
|
298
|
-
updateIssue(ctx.db, issueA.id, { status: "closed" });
|
|
299
|
-
issueC_status = getIssue(ctx.db, issueC.id);
|
|
300
|
-
expect(issueC_status?.status).toBe("blocked");
|
|
301
|
-
|
|
302
|
-
// Close B - C should now be unblocked
|
|
303
|
-
updateIssue(ctx.db, issueB.id, { status: "closed" });
|
|
304
|
-
issueC_status = getIssue(ctx.db, issueC.id);
|
|
305
|
-
expect(issueC_status?.status).toBe("open");
|
|
306
|
-
});
|
|
307
|
-
|
|
308
|
-
it("should handle spec with multiple implementing issues", () => {
|
|
309
|
-
const spec = createTestSpec(ctx, { title: "Feature Spec" });
|
|
310
|
-
const issue1 = createTestIssue(ctx, { title: "Part 1" });
|
|
311
|
-
const issue2 = createTestIssue(ctx, { title: "Part 2" });
|
|
312
|
-
const issue3 = createTestIssue(ctx, { title: "Part 3" });
|
|
313
|
-
|
|
314
|
-
createImplementsRelationship(ctx.db, issue1.id, spec.id);
|
|
315
|
-
createImplementsRelationship(ctx.db, issue2.id, spec.id);
|
|
316
|
-
createImplementsRelationship(ctx.db, issue3.id, spec.id);
|
|
317
|
-
|
|
318
|
-
// All issues should reference the spec
|
|
319
|
-
const incoming = getIncomingRelationships(ctx.db, spec.id, "spec");
|
|
320
|
-
expect(incoming).toHaveLength(3);
|
|
321
|
-
|
|
322
|
-
const implementerIds = incoming.map((r) => r.from_id);
|
|
323
|
-
expect(implementerIds).toContain(issue1.id);
|
|
324
|
-
expect(implementerIds).toContain(issue2.id);
|
|
325
|
-
expect(implementerIds).toContain(issue3.id);
|
|
326
|
-
});
|
|
327
|
-
});
|
|
328
|
-
});
|
|
@@ -1,175 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Integration Test Utilities for Sudocode
|
|
3
|
-
*
|
|
4
|
-
* Provides helpers for creating real sudocode databases and test fixtures.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { mkdtempSync, mkdirSync, rmSync } from "fs";
|
|
8
|
-
import { tmpdir } from "os";
|
|
9
|
-
import { join } from "path";
|
|
10
|
-
import {
|
|
11
|
-
initDatabase,
|
|
12
|
-
createIssue,
|
|
13
|
-
getIssue,
|
|
14
|
-
listIssues,
|
|
15
|
-
updateIssue,
|
|
16
|
-
createSpec,
|
|
17
|
-
getSpec,
|
|
18
|
-
listSpecs,
|
|
19
|
-
addRelationship,
|
|
20
|
-
getOutgoingRelationships,
|
|
21
|
-
getIncomingRelationships,
|
|
22
|
-
generateIssueId,
|
|
23
|
-
generateSpecId,
|
|
24
|
-
getReadyIssues,
|
|
25
|
-
} from "@sudocode-ai/cli";
|
|
26
|
-
import type { Issue, Spec, IssueStatus } from "@sudocode-ai/types";
|
|
27
|
-
import type { Database } from "better-sqlite3";
|
|
28
|
-
|
|
29
|
-
// =============================================================================
|
|
30
|
-
// Test Database Setup
|
|
31
|
-
// =============================================================================
|
|
32
|
-
|
|
33
|
-
export interface TestContext {
|
|
34
|
-
/** Temporary directory for test files */
|
|
35
|
-
tmpDir: string;
|
|
36
|
-
/** SQLite database instance */
|
|
37
|
-
db: Database;
|
|
38
|
-
/** Cleanup function to call after tests */
|
|
39
|
-
cleanup: () => void;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Create a test context with a real sudocode database
|
|
44
|
-
*
|
|
45
|
-
* Creates the database in {tmpDir}/.sudocode/cache.db to match
|
|
46
|
-
* the structure expected by StandaloneClient.
|
|
47
|
-
*/
|
|
48
|
-
export function createTestContext(): TestContext {
|
|
49
|
-
const tmpDir = mkdtempSync(join(tmpdir(), "sudocode-test-"));
|
|
50
|
-
const sudocodeDir = join(tmpDir, ".sudocode");
|
|
51
|
-
mkdirSync(sudocodeDir, { recursive: true });
|
|
52
|
-
const dbPath = join(sudocodeDir, "cache.db");
|
|
53
|
-
const db = initDatabase({ path: dbPath });
|
|
54
|
-
|
|
55
|
-
return {
|
|
56
|
-
tmpDir,
|
|
57
|
-
db,
|
|
58
|
-
cleanup: () => {
|
|
59
|
-
db.close();
|
|
60
|
-
rmSync(tmpDir, { recursive: true, force: true });
|
|
61
|
-
},
|
|
62
|
-
};
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// =============================================================================
|
|
66
|
-
// Test Fixture Helpers
|
|
67
|
-
// =============================================================================
|
|
68
|
-
|
|
69
|
-
export interface CreateTestIssueOptions {
|
|
70
|
-
title: string;
|
|
71
|
-
content?: string;
|
|
72
|
-
status?: IssueStatus;
|
|
73
|
-
priority?: number;
|
|
74
|
-
parent_id?: string;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* Create a test issue with sensible defaults
|
|
79
|
-
*/
|
|
80
|
-
export function createTestIssue(
|
|
81
|
-
ctx: TestContext,
|
|
82
|
-
options: CreateTestIssueOptions
|
|
83
|
-
): Issue {
|
|
84
|
-
const { id, uuid } = generateIssueId(ctx.db, ctx.tmpDir);
|
|
85
|
-
return createIssue(ctx.db, {
|
|
86
|
-
id,
|
|
87
|
-
uuid,
|
|
88
|
-
title: options.title,
|
|
89
|
-
content: options.content ?? `Content for ${options.title}`,
|
|
90
|
-
status: options.status ?? "open",
|
|
91
|
-
priority: options.priority ?? 2,
|
|
92
|
-
parent_id: options.parent_id,
|
|
93
|
-
});
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
export interface CreateTestSpecOptions {
|
|
97
|
-
title: string;
|
|
98
|
-
content?: string;
|
|
99
|
-
priority?: number;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
/**
|
|
103
|
-
* Create a test spec with sensible defaults
|
|
104
|
-
*/
|
|
105
|
-
export function createTestSpec(
|
|
106
|
-
ctx: TestContext,
|
|
107
|
-
options: CreateTestSpecOptions
|
|
108
|
-
): Spec {
|
|
109
|
-
const { id, uuid } = generateSpecId(ctx.db, ctx.tmpDir);
|
|
110
|
-
return createSpec(ctx.db, {
|
|
111
|
-
id,
|
|
112
|
-
uuid,
|
|
113
|
-
title: options.title,
|
|
114
|
-
file_path: `${ctx.tmpDir}/${id}.md`,
|
|
115
|
-
content: options.content ?? `Specification for ${options.title}`,
|
|
116
|
-
priority: options.priority ?? 2,
|
|
117
|
-
});
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* Create a blocking relationship between two issues
|
|
122
|
-
*/
|
|
123
|
-
export function createBlockingRelationship(
|
|
124
|
-
db: Database,
|
|
125
|
-
blockerId: string,
|
|
126
|
-
blockedId: string
|
|
127
|
-
): void {
|
|
128
|
-
addRelationship(db, {
|
|
129
|
-
from_id: blockerId,
|
|
130
|
-
from_type: "issue",
|
|
131
|
-
to_id: blockedId,
|
|
132
|
-
to_type: "issue",
|
|
133
|
-
relationship_type: "blocks",
|
|
134
|
-
});
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
/**
|
|
138
|
-
* Create an implements relationship between an issue and a spec
|
|
139
|
-
*/
|
|
140
|
-
export function createImplementsRelationship(
|
|
141
|
-
db: Database,
|
|
142
|
-
issueId: string,
|
|
143
|
-
specId: string
|
|
144
|
-
): void {
|
|
145
|
-
addRelationship(db, {
|
|
146
|
-
from_id: issueId,
|
|
147
|
-
from_type: "issue",
|
|
148
|
-
to_id: specId,
|
|
149
|
-
to_type: "spec",
|
|
150
|
-
relationship_type: "implements",
|
|
151
|
-
});
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
// =============================================================================
|
|
155
|
-
// Re-export commonly used functions
|
|
156
|
-
// =============================================================================
|
|
157
|
-
|
|
158
|
-
export {
|
|
159
|
-
initDatabase,
|
|
160
|
-
createIssue,
|
|
161
|
-
getIssue,
|
|
162
|
-
listIssues,
|
|
163
|
-
updateIssue,
|
|
164
|
-
createSpec,
|
|
165
|
-
getSpec,
|
|
166
|
-
listSpecs,
|
|
167
|
-
addRelationship,
|
|
168
|
-
getOutgoingRelationships,
|
|
169
|
-
getIncomingRelationships,
|
|
170
|
-
generateIssueId,
|
|
171
|
-
generateSpecId,
|
|
172
|
-
getReadyIssues,
|
|
173
|
-
};
|
|
174
|
-
|
|
175
|
-
export type { Issue, Spec, IssueStatus, Database };
|