macro-agent 0.1.0 → 0.1.2
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/issues.jsonl +28 -0
- package/.sudocode/specs.jsonl +8 -0
- package/CLAUDE.md +25 -17
- 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 +544 -200
- package/dist/agent/agent-manager.js.map +1 -1
- package/dist/agent/types.d.ts +8 -1
- package/dist/agent/types.d.ts.map +1 -1
- package/dist/agent/types.js.map +1 -1
- package/dist/api/server.d.ts +8 -1
- package/dist/api/server.d.ts.map +1 -1
- package/dist/api/server.js +136 -8
- package/dist/api/server.js.map +1 -1
- package/dist/api/types.d.ts +1 -1
- package/dist/api/types.d.ts.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 +197 -61
- package/dist/cli/acp.js.map +1 -1
- package/dist/cli/index.js +152 -16
- 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 +279 -173
- 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 +85 -7
- package/dist/config/project-config.d.ts.map +1 -1
- package/dist/config/project-config.js +133 -20
- package/dist/config/project-config.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/lifecycle/handlers/index.d.ts +7 -3
- package/dist/lifecycle/handlers/index.d.ts.map +1 -1
- package/dist/lifecycle/handlers/index.js +25 -8
- package/dist/lifecycle/handlers/index.js.map +1 -1
- package/dist/lifecycle/types.d.ts +2 -0
- package/dist/lifecycle/types.d.ts.map +1 -1
- package/dist/lifecycle/types.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 +13 -1
- package/dist/map/adapter/extensions/index.d.ts.map +1 -1
- package/dist/map/adapter/extensions/index.js +61 -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/streams.d.ts +95 -0
- package/dist/map/adapter/extensions/streams.d.ts.map +1 -0
- package/dist/map/adapter/extensions/streams.js +515 -0
- package/dist/map/adapter/extensions/streams.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 +10 -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 +3 -1
- 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 +16 -0
- package/dist/mcp/mcp-server.d.ts.map +1 -1
- package/dist/mcp/mcp-server.js +125 -88
- package/dist/mcp/mcp-server.js.map +1 -1
- package/dist/mcp/tools/done.d.ts.map +1 -1
- package/dist/mcp/tools/done.js +18 -0
- package/dist/mcp/tools/done.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/builtin/coordinator.d.ts.map +1 -1
- package/dist/roles/builtin/coordinator.js +2 -1
- package/dist/roles/builtin/coordinator.js.map +1 -1
- package/dist/roles/builtin/integrator.d.ts.map +1 -1
- package/dist/roles/builtin/integrator.js +2 -1
- package/dist/roles/builtin/integrator.js.map +1 -1
- package/dist/roles/builtin/worker.d.ts.map +1 -1
- package/dist/roles/builtin/worker.js +3 -1
- package/dist/roles/builtin/worker.js.map +1 -1
- package/dist/roles/capabilities.d.ts +9 -1
- package/dist/roles/capabilities.d.ts.map +1 -1
- package/dist/roles/capabilities.js +27 -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 +8 -7
- 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/roles/types.d.ts +3 -1
- package/dist/roles/types.d.ts.map +1 -1
- package/dist/server/combined-server.d.ts +28 -1
- package/dist/server/combined-server.d.ts.map +1 -1
- package/dist/server/combined-server.js +111 -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 +80 -24
- package/dist/store/event-store.js.map +1 -1
- package/dist/store/instance.d.ts +1 -1
- package/dist/store/instance.d.ts.map +1 -1
- package/dist/store/instance.js +2 -2
- package/dist/store/instance.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/index.d.ts +3 -1
- package/dist/teams/index.d.ts.map +1 -1
- package/dist/teams/index.js +2 -0
- package/dist/teams/index.js.map +1 -1
- package/dist/teams/seed-defaults.d.ts +20 -0
- package/dist/teams/seed-defaults.d.ts.map +1 -0
- package/dist/teams/seed-defaults.js +71 -0
- package/dist/teams/seed-defaults.js.map +1 -0
- package/dist/teams/team-loader.d.ts +7 -3
- package/dist/teams/team-loader.d.ts.map +1 -1
- package/dist/teams/team-loader.js +156 -164
- package/dist/teams/team-loader.js.map +1 -1
- package/dist/teams/team-manager.d.ts +112 -0
- package/dist/teams/team-manager.d.ts.map +1 -0
- package/dist/teams/team-manager.js +305 -0
- package/dist/teams/team-manager.js.map +1 -0
- package/dist/teams/team-runtime.d.ts +125 -19
- package/dist/teams/team-runtime.d.ts.map +1 -1
- package/dist/teams/team-runtime.js +529 -119
- package/dist/teams/team-runtime.js.map +1 -1
- package/dist/teams/types.d.ts +41 -151
- package/dist/teams/types.d.ts.map +1 -1
- package/dist/teams/types.js +2 -3
- package/dist/teams/types.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 +76 -3
- package/docs/troubleshooting.md +10 -11
- package/package.json +7 -4
- package/references/minimem/.claude/settings.json +7 -0
- package/references/minimem/.sudocode/issues.jsonl +18 -0
- package/references/minimem/.sudocode/specs.jsonl +1 -0
- package/references/minimem/CLAUDE.md +310 -0
- package/references/minimem/README.md +562 -0
- package/references/minimem/claude-plugin/.claude-plugin/plugin.json +10 -0
- package/references/minimem/claude-plugin/.mcp.json +7 -0
- package/references/minimem/claude-plugin/README.md +158 -0
- package/references/minimem/claude-plugin/commands/recall.md +47 -0
- package/references/minimem/claude-plugin/commands/remember.md +41 -0
- package/references/minimem/claude-plugin/hooks/__tests__/hooks.test.ts +272 -0
- package/references/minimem/claude-plugin/hooks/hooks.json +27 -0
- package/references/minimem/claude-plugin/hooks/session-end.sh +86 -0
- package/references/minimem/claude-plugin/hooks/session-start.sh +85 -0
- package/references/minimem/claude-plugin/skills/memory/SKILL.md +108 -0
- package/references/minimem/media/banner.png +0 -0
- package/references/minimem/package-lock.json +5373 -0
- package/references/minimem/package.json +72 -0
- package/references/minimem/scripts/postbuild.js +35 -0
- package/references/minimem/src/__tests__/edge-cases.test.ts +371 -0
- package/references/minimem/src/__tests__/errors.test.ts +265 -0
- package/references/minimem/src/__tests__/helpers.ts +199 -0
- package/references/minimem/src/__tests__/internal.test.ts +407 -0
- package/references/minimem/src/__tests__/knowledge.test.ts +287 -0
- package/references/minimem/src/__tests__/minimem.integration.test.ts +1127 -0
- package/references/minimem/src/__tests__/session.test.ts +190 -0
- package/references/minimem/src/cli/__tests__/commands.test.ts +759 -0
- package/references/minimem/src/cli/commands/__tests__/conflicts.test.ts +141 -0
- package/references/minimem/src/cli/commands/append.ts +76 -0
- package/references/minimem/src/cli/commands/config.ts +262 -0
- package/references/minimem/src/cli/commands/conflicts.ts +413 -0
- package/references/minimem/src/cli/commands/daemon.ts +169 -0
- package/references/minimem/src/cli/commands/index.ts +12 -0
- package/references/minimem/src/cli/commands/init.ts +88 -0
- package/references/minimem/src/cli/commands/mcp.ts +177 -0
- package/references/minimem/src/cli/commands/push-pull.ts +213 -0
- package/references/minimem/src/cli/commands/search.ts +158 -0
- package/references/minimem/src/cli/commands/status.ts +84 -0
- package/references/minimem/src/cli/commands/sync-init.ts +290 -0
- package/references/minimem/src/cli/commands/sync.ts +70 -0
- package/references/minimem/src/cli/commands/upsert.ts +197 -0
- package/references/minimem/src/cli/config.ts +584 -0
- package/references/minimem/src/cli/index.ts +264 -0
- package/references/minimem/src/cli/shared.ts +161 -0
- package/references/minimem/src/cli/sync/__tests__/central.test.ts +152 -0
- package/references/minimem/src/cli/sync/__tests__/conflicts.test.ts +209 -0
- package/references/minimem/src/cli/sync/__tests__/daemon.test.ts +118 -0
- package/references/minimem/src/cli/sync/__tests__/detection.test.ts +207 -0
- package/references/minimem/src/cli/sync/__tests__/integration.test.ts +476 -0
- package/references/minimem/src/cli/sync/__tests__/registry.test.ts +363 -0
- package/references/minimem/src/cli/sync/__tests__/state.test.ts +255 -0
- package/references/minimem/src/cli/sync/__tests__/validation.test.ts +193 -0
- package/references/minimem/src/cli/sync/__tests__/watcher.test.ts +178 -0
- package/references/minimem/src/cli/sync/central.ts +292 -0
- package/references/minimem/src/cli/sync/conflicts.ts +204 -0
- package/references/minimem/src/cli/sync/daemon.ts +407 -0
- package/references/minimem/src/cli/sync/detection.ts +138 -0
- package/references/minimem/src/cli/sync/index.ts +107 -0
- package/references/minimem/src/cli/sync/operations.ts +373 -0
- package/references/minimem/src/cli/sync/registry.ts +279 -0
- package/references/minimem/src/cli/sync/state.ts +355 -0
- package/references/minimem/src/cli/sync/validation.ts +206 -0
- package/references/minimem/src/cli/sync/watcher.ts +234 -0
- package/references/minimem/src/cli/version.ts +34 -0
- package/references/minimem/src/core/index.ts +9 -0
- package/references/minimem/src/core/indexer.ts +628 -0
- package/references/minimem/src/core/searcher.ts +221 -0
- package/references/minimem/src/db/schema.ts +183 -0
- package/references/minimem/src/db/sqlite-vec.ts +24 -0
- package/references/minimem/src/embeddings/__tests__/embeddings.test.ts +431 -0
- package/references/minimem/src/embeddings/batch-gemini.ts +392 -0
- package/references/minimem/src/embeddings/batch-openai.ts +409 -0
- package/references/minimem/src/embeddings/embeddings.ts +434 -0
- package/references/minimem/src/index.ts +109 -0
- package/references/minimem/src/internal.ts +299 -0
- package/references/minimem/src/minimem.ts +1276 -0
- package/references/minimem/src/search/__tests__/hybrid.test.ts +247 -0
- package/references/minimem/src/search/graph.ts +234 -0
- package/references/minimem/src/search/hybrid.ts +151 -0
- package/references/minimem/src/search/search.ts +256 -0
- package/references/minimem/src/server/__tests__/mcp.test.ts +341 -0
- package/references/minimem/src/server/__tests__/tools.test.ts +364 -0
- package/references/minimem/src/server/mcp.ts +326 -0
- package/references/minimem/src/server/tools.ts +720 -0
- package/references/minimem/src/session.ts +460 -0
- package/references/minimem/tsconfig.json +19 -0
- package/references/minimem/tsup.config.ts +26 -0
- package/references/minimem/vitest.config.ts +24 -0
- package/references/openteams/.claude/settings.json +6 -0
- package/references/openteams/README.md +1 -0
- package/references/openteams/SKILL.md +341 -0
- package/references/openteams/design.md +411 -0
- package/references/openteams/examples/bmad-method/prompts/analyst/ROLE.md +16 -0
- package/references/openteams/examples/bmad-method/prompts/analyst/SOUL.md +5 -0
- package/references/openteams/examples/bmad-method/prompts/architect/ROLE.md +24 -0
- package/references/openteams/examples/bmad-method/prompts/architect/SOUL.md +5 -0
- package/references/openteams/examples/bmad-method/prompts/developer/ROLE.md +25 -0
- package/references/openteams/examples/bmad-method/prompts/developer/SOUL.md +5 -0
- package/references/openteams/examples/bmad-method/prompts/master/ROLE.md +21 -0
- package/references/openteams/examples/bmad-method/prompts/master/SOUL.md +5 -0
- package/references/openteams/examples/bmad-method/prompts/pm/ROLE.md +20 -0
- package/references/openteams/examples/bmad-method/prompts/pm/SOUL.md +5 -0
- package/references/openteams/examples/bmad-method/prompts/qa/ROLE.md +17 -0
- package/references/openteams/examples/bmad-method/prompts/qa/SOUL.md +5 -0
- package/references/openteams/examples/bmad-method/prompts/quick-flow-dev/ROLE.md +23 -0
- package/references/openteams/examples/bmad-method/prompts/quick-flow-dev/SOUL.md +5 -0
- package/references/openteams/examples/bmad-method/prompts/scrum-master/ROLE.md +27 -0
- package/references/openteams/examples/bmad-method/prompts/scrum-master/SOUL.md +5 -0
- package/references/openteams/examples/bmad-method/prompts/tech-writer/ROLE.md +21 -0
- package/references/openteams/examples/bmad-method/prompts/tech-writer/SOUL.md +5 -0
- package/references/openteams/examples/bmad-method/prompts/ux-designer/ROLE.md +16 -0
- package/references/openteams/examples/bmad-method/prompts/ux-designer/SOUL.md +5 -0
- package/references/openteams/examples/bmad-method/roles/analyst.yaml +9 -0
- package/references/openteams/examples/bmad-method/roles/architect.yaml +9 -0
- package/references/openteams/examples/bmad-method/roles/developer.yaml +8 -0
- package/references/openteams/examples/bmad-method/roles/master.yaml +8 -0
- package/references/openteams/examples/bmad-method/roles/pm.yaml +9 -0
- package/references/openteams/examples/bmad-method/roles/qa.yaml +8 -0
- package/references/openteams/examples/bmad-method/roles/quick-flow-dev.yaml +8 -0
- package/references/openteams/examples/bmad-method/roles/scrum-master.yaml +9 -0
- package/references/openteams/examples/bmad-method/roles/tech-writer.yaml +8 -0
- package/references/openteams/examples/bmad-method/roles/ux-designer.yaml +8 -0
- package/references/openteams/examples/bmad-method/team.yaml +161 -0
- package/references/openteams/examples/get-shit-done/prompts/codebase-mapper/ROLE.md +17 -0
- package/references/openteams/examples/get-shit-done/prompts/codebase-mapper/SOUL.md +5 -0
- package/references/openteams/examples/get-shit-done/prompts/debugger/ROLE.md +25 -0
- package/references/openteams/examples/get-shit-done/prompts/debugger/SOUL.md +5 -0
- package/references/openteams/examples/get-shit-done/prompts/executor/ROLE.md +34 -0
- package/references/openteams/examples/get-shit-done/prompts/executor/SOUL.md +5 -0
- package/references/openteams/examples/get-shit-done/prompts/integration-checker/ROLE.md +18 -0
- package/references/openteams/examples/get-shit-done/prompts/integration-checker/SOUL.md +3 -0
- package/references/openteams/examples/get-shit-done/prompts/orchestrator/ROLE.md +42 -0
- package/references/openteams/examples/get-shit-done/prompts/orchestrator/SOUL.md +5 -0
- package/references/openteams/examples/get-shit-done/prompts/phase-researcher/ROLE.md +15 -0
- package/references/openteams/examples/get-shit-done/prompts/phase-researcher/SOUL.md +3 -0
- package/references/openteams/examples/get-shit-done/prompts/plan-checker/ROLE.md +17 -0
- package/references/openteams/examples/get-shit-done/prompts/plan-checker/SOUL.md +3 -0
- package/references/openteams/examples/get-shit-done/prompts/planner/ROLE.md +28 -0
- package/references/openteams/examples/get-shit-done/prompts/planner/SOUL.md +5 -0
- package/references/openteams/examples/get-shit-done/prompts/project-researcher/ROLE.md +16 -0
- package/references/openteams/examples/get-shit-done/prompts/project-researcher/SOUL.md +3 -0
- package/references/openteams/examples/get-shit-done/prompts/research-synthesizer/ROLE.md +13 -0
- package/references/openteams/examples/get-shit-done/prompts/research-synthesizer/SOUL.md +3 -0
- package/references/openteams/examples/get-shit-done/prompts/roadmapper/ROLE.md +14 -0
- package/references/openteams/examples/get-shit-done/prompts/roadmapper/SOUL.md +3 -0
- package/references/openteams/examples/get-shit-done/prompts/verifier/ROLE.md +19 -0
- package/references/openteams/examples/get-shit-done/prompts/verifier/SOUL.md +5 -0
- package/references/openteams/examples/get-shit-done/roles/codebase-mapper.yaml +8 -0
- package/references/openteams/examples/get-shit-done/roles/debugger.yaml +8 -0
- package/references/openteams/examples/get-shit-done/roles/executor.yaml +8 -0
- package/references/openteams/examples/get-shit-done/roles/integration-checker.yaml +8 -0
- package/references/openteams/examples/get-shit-done/roles/orchestrator.yaml +9 -0
- package/references/openteams/examples/get-shit-done/roles/phase-researcher.yaml +7 -0
- package/references/openteams/examples/get-shit-done/roles/plan-checker.yaml +8 -0
- package/references/openteams/examples/get-shit-done/roles/planner.yaml +8 -0
- package/references/openteams/examples/get-shit-done/roles/project-researcher.yaml +8 -0
- package/references/openteams/examples/get-shit-done/roles/research-synthesizer.yaml +7 -0
- package/references/openteams/examples/get-shit-done/roles/roadmapper.yaml +7 -0
- package/references/openteams/examples/get-shit-done/roles/verifier.yaml +8 -0
- package/references/openteams/examples/get-shit-done/team.yaml +154 -0
- package/references/openteams/package-lock.json +2181 -0
- package/references/openteams/package.json +48 -0
- package/references/openteams/schema/role.schema.json +125 -0
- package/references/openteams/schema/team.schema.json +284 -0
- package/references/openteams/src/cli/agent.ts +104 -0
- package/references/openteams/src/cli/cli.test.ts +381 -0
- package/references/openteams/src/cli/generate.ts +220 -0
- package/references/openteams/src/cli/message.ts +241 -0
- package/references/openteams/src/cli/task.ts +154 -0
- package/references/openteams/src/cli/team.ts +104 -0
- package/references/openteams/src/cli/template.ts +207 -0
- package/references/openteams/src/cli.ts +45 -0
- package/references/openteams/src/db/database.test.ts +185 -0
- package/references/openteams/src/db/database.ts +240 -0
- package/references/openteams/src/generators/agent-prompt-generator.test.ts +332 -0
- package/references/openteams/src/generators/agent-prompt-generator.ts +521 -0
- package/references/openteams/src/generators/package-generator.test.ts +129 -0
- package/references/openteams/src/generators/package-generator.ts +102 -0
- package/references/openteams/src/generators/skill-generator.test.ts +246 -0
- package/references/openteams/src/generators/skill-generator.ts +374 -0
- package/references/openteams/src/index.ts +104 -0
- package/references/openteams/src/services/agent-service.test.ts +158 -0
- package/references/openteams/src/services/agent-service.ts +84 -0
- package/references/openteams/src/services/communication-service.test.ts +455 -0
- package/references/openteams/src/services/communication-service.ts +371 -0
- package/references/openteams/src/services/message-service.test.ts +342 -0
- package/references/openteams/src/services/message-service.ts +203 -0
- package/references/openteams/src/services/task-service.test.ts +434 -0
- package/references/openteams/src/services/task-service.ts +239 -0
- package/references/openteams/src/services/team-service.test.ts +181 -0
- package/references/openteams/src/services/team-service.ts +139 -0
- package/references/openteams/src/services/template-service.test.ts +306 -0
- package/references/openteams/src/services/template-service.ts +182 -0
- package/references/openteams/src/spawner/acp-factory.ts +96 -0
- package/references/openteams/src/spawner/interface.ts +31 -0
- package/references/openteams/src/spawner/mock.test.ts +93 -0
- package/references/openteams/src/spawner/mock.ts +59 -0
- package/references/openteams/src/template/loader.test.ts +1319 -0
- package/references/openteams/src/template/loader.ts +698 -0
- package/references/openteams/src/template/types.ts +200 -0
- package/references/openteams/src/types.ts +205 -0
- package/references/openteams/tsconfig.json +18 -0
- package/references/openteams/vitest.config.ts +9 -0
- package/references/skill-tree/.claude/settings.json +6 -0
- package/references/skill-tree/.sudocode/issues.jsonl +11 -0
- package/references/skill-tree/.sudocode/specs.jsonl +1 -0
- package/references/skill-tree/CLAUDE.md +150 -0
- package/references/skill-tree/README.md +324 -0
- package/references/skill-tree/docs/GAPS_v1.md +221 -0
- package/references/skill-tree/docs/INTEGRATION_PLAN.md +467 -0
- package/references/skill-tree/docs/TODOS.md +91 -0
- package/references/skill-tree/docs/anthropic_skill_guide.md +1364 -0
- package/references/skill-tree/docs/design/federated-skill-trees.md +524 -0
- package/references/skill-tree/docs/design/multi-agent-sync.md +759 -0
- package/references/skill-tree/docs/scraper/BRAINSTORM.md +583 -0
- package/references/skill-tree/docs/scraper/POC_PLAN.md +420 -0
- package/references/skill-tree/docs/scraper/README.md +170 -0
- package/references/skill-tree/examples/basic-usage.ts +190 -0
- package/references/skill-tree/package-lock.json +1509 -0
- package/references/skill-tree/package.json +66 -0
- package/references/skill-tree/scraper/README.md +123 -0
- package/references/skill-tree/scraper/docs/DESIGN.md +683 -0
- package/references/skill-tree/scraper/docs/PLAN.md +336 -0
- package/references/skill-tree/scraper/drizzle.config.ts +10 -0
- package/references/skill-tree/scraper/package-lock.json +6329 -0
- package/references/skill-tree/scraper/package.json +68 -0
- package/references/skill-tree/scraper/test/fixtures/invalid-skill/missing-description.md +7 -0
- package/references/skill-tree/scraper/test/fixtures/invalid-skill/missing-name.md +7 -0
- package/references/skill-tree/scraper/test/fixtures/minimal-skill/SKILL.md +27 -0
- package/references/skill-tree/scraper/test/fixtures/skill-json/SKILL.json +21 -0
- package/references/skill-tree/scraper/test/fixtures/skill-with-meta/SKILL.md +54 -0
- package/references/skill-tree/scraper/test/fixtures/skill-with-meta/_meta.json +24 -0
- package/references/skill-tree/scraper/test/fixtures/valid-skill/SKILL.md +93 -0
- package/references/skill-tree/scraper/test/fixtures/valid-skill/_meta.json +22 -0
- package/references/skill-tree/scraper/tsup.config.ts +14 -0
- package/references/skill-tree/scraper/vitest.config.ts +17 -0
- package/references/skill-tree/scripts/convert-to-vitest.ts +166 -0
- package/references/skill-tree/skills/skill-writer/SKILL.md +339 -0
- package/references/skill-tree/skills/skill-writer/references/examples.md +326 -0
- package/references/skill-tree/skills/skill-writer/references/patterns.md +210 -0
- package/references/skill-tree/skills/skill-writer/references/quality-checklist.md +123 -0
- package/references/skill-tree/test/run-all.ts +106 -0
- package/references/skill-tree/test/utils.ts +128 -0
- package/references/skill-tree/vitest.config.ts +16 -0
- 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 +809 -285
- package/src/agent/types.ts +12 -1
- package/src/api/__tests__/server.test.ts +203 -4
- package/src/api/server.ts +169 -10
- package/src/api/types.ts +3 -1
- 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 +197 -72
- package/src/cli/index.ts +125 -15
- package/src/cli/mcp.ts +315 -197
- package/src/cli/parse-args.ts +54 -0
- package/src/cli/stable-instance-id.ts +14 -0
- package/src/config/project-config.ts +214 -27
- package/src/index.ts +3 -0
- package/src/lifecycle/__tests__/cascade-termination.test.ts +1 -1
- package/src/lifecycle/__tests__/handlers.test.ts +53 -0
- package/src/lifecycle/handlers/index.ts +25 -8
- package/src/lifecycle/types.ts +3 -0
- 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__/stream-extensions.test.ts +494 -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 +96 -0
- package/src/map/adapter/extensions/mcp-bridge.ts +995 -0
- package/src/map/adapter/extensions/streams.ts +839 -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 +33 -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 +10 -1
- 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 +205 -103
- package/src/mcp/tools/done.ts +19 -0
- 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/builtin/coordinator.ts +2 -0
- package/src/roles/builtin/integrator.ts +2 -0
- package/src/roles/builtin/worker.ts +3 -0
- package/src/roles/capabilities.ts +28 -7
- package/src/roles/config-loader.ts +8 -7
- package/src/roles/registry.ts +2 -2
- package/src/roles/types.ts +7 -0
- package/src/server/__tests__/combined-server.test.ts +94 -21
- package/src/server/combined-server.ts +203 -33
- package/src/steering/__tests__/steering-integration.test.ts +1 -1
- package/src/store/__tests__/event-store-oob.test.ts +109 -0
- 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 +92 -23
- package/src/store/instance.ts +2 -2
- package/src/store/types/agents.ts +20 -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__/memory-pull-mode.test.ts +153 -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 +256 -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/CLAUDE.md +180 -0
- package/src/teams/__tests__/cross-subsystem.integration.test.ts +1 -1
- package/src/teams/__tests__/e2e/workspace-isolation.e2e.test.ts +1263 -0
- package/src/teams/__tests__/team-manager.test.ts +814 -0
- package/src/teams/__tests__/team-system.test.ts +1291 -8
- package/src/teams/index.ts +21 -3
- package/src/teams/seed-defaults.ts +79 -0
- package/src/teams/team-loader.ts +202 -236
- package/src/teams/team-manager.ts +387 -0
- package/src/teams/team-runtime.ts +592 -121
- package/src/teams/types.ts +99 -200
- 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,753 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* E2E Tests for SudocodeTaskBackend
|
|
3
|
-
*
|
|
4
|
-
* Tests the full task lifecycle integration with sudocode issues,
|
|
5
|
-
* including blocker workflows, multiple tasks per issue, and sync policies.
|
|
6
|
-
*
|
|
7
|
-
* Run with:
|
|
8
|
-
* npm run test:e2e:sudocode
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
import { describe, it, expect, beforeAll, afterAll, beforeEach, afterEach } from "vitest";
|
|
12
|
-
import { spawn, execSync, ChildProcess } from "child_process";
|
|
13
|
-
import { mkdtempSync, rmSync, existsSync } from "fs";
|
|
14
|
-
import { tmpdir } from "os";
|
|
15
|
-
import { join } from "path";
|
|
16
|
-
import { ServerClient } from "../../server-client.js";
|
|
17
|
-
import { SudocodeTaskBackend } from "../../backend.js";
|
|
18
|
-
import { createEventStore } from "../../../../../store/event-store.js";
|
|
19
|
-
import type { EventStore } from "../../../../../store/event-store.js";
|
|
20
|
-
import type { Issue } from "../../client.js";
|
|
21
|
-
import type { TaskChangeEvent } from "../../../types.js";
|
|
22
|
-
|
|
23
|
-
// Configuration
|
|
24
|
-
const TEST_PORT = 13580; // Different port from server-client tests
|
|
25
|
-
const SERVER_URL = `http://localhost:${TEST_PORT}`;
|
|
26
|
-
const WS_URL = `ws://localhost:${TEST_PORT}/ws`;
|
|
27
|
-
const TEST_TIMEOUT = 20000;
|
|
28
|
-
const SERVER_STARTUP_TIMEOUT = 15000;
|
|
29
|
-
|
|
30
|
-
// Global state
|
|
31
|
-
let serverProcess: ChildProcess | null = null;
|
|
32
|
-
let projectDir: string | null = null;
|
|
33
|
-
let projectId: string | null = null;
|
|
34
|
-
let eventStore: EventStore;
|
|
35
|
-
let client: ServerClient;
|
|
36
|
-
let backend: SudocodeTaskBackend;
|
|
37
|
-
|
|
38
|
-
// Track created issues for cleanup
|
|
39
|
-
const createdIssueIds: string[] = [];
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Normalize path to handle macOS symlinks (/var -> /private/var)
|
|
43
|
-
*/
|
|
44
|
-
function normalizePath(p: string): string {
|
|
45
|
-
if (p.startsWith("/private/")) {
|
|
46
|
-
return p.substring("/private".length);
|
|
47
|
-
}
|
|
48
|
-
return p;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Wait for the server to be ready
|
|
53
|
-
*/
|
|
54
|
-
async function waitForServer(
|
|
55
|
-
url: string,
|
|
56
|
-
timeout: number = SERVER_STARTUP_TIMEOUT
|
|
57
|
-
): Promise<boolean> {
|
|
58
|
-
const startTime = Date.now();
|
|
59
|
-
|
|
60
|
-
while (Date.now() - startTime < timeout) {
|
|
61
|
-
try {
|
|
62
|
-
const controller = new AbortController();
|
|
63
|
-
const timeoutId = setTimeout(() => controller.abort(), 1000);
|
|
64
|
-
|
|
65
|
-
const response = await fetch(`${url}/health`, {
|
|
66
|
-
signal: controller.signal,
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
clearTimeout(timeoutId);
|
|
70
|
-
|
|
71
|
-
if (response.ok) {
|
|
72
|
-
return true;
|
|
73
|
-
}
|
|
74
|
-
} catch {
|
|
75
|
-
// Server not ready yet
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
await new Promise((r) => setTimeout(r, 200));
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
return false;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* Get the project ID for our test project from the server (with retry)
|
|
86
|
-
*/
|
|
87
|
-
async function getProjectId(
|
|
88
|
-
serverUrl: string,
|
|
89
|
-
projectPath: string,
|
|
90
|
-
maxRetries: number = 10
|
|
91
|
-
): Promise<string> {
|
|
92
|
-
const normalizedPath = normalizePath(projectPath);
|
|
93
|
-
|
|
94
|
-
for (let attempt = 0; attempt < maxRetries; attempt++) {
|
|
95
|
-
try {
|
|
96
|
-
const response = await fetch(`${serverUrl}/api/projects`);
|
|
97
|
-
const result = await response.json();
|
|
98
|
-
|
|
99
|
-
if (!result.success || !Array.isArray(result.data)) {
|
|
100
|
-
await new Promise((r) => setTimeout(r, 500));
|
|
101
|
-
continue;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
const project = result.data.find((p: { path: string; id: string }) => {
|
|
105
|
-
const normalizedProjectPath = normalizePath(p.path);
|
|
106
|
-
return normalizedProjectPath === normalizedPath;
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
if (project) {
|
|
110
|
-
return project.id;
|
|
111
|
-
}
|
|
112
|
-
} catch {
|
|
113
|
-
// Retry
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
await new Promise((r) => setTimeout(r, 500));
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
throw new Error(`Project not found for path: ${projectPath} after ${maxRetries} retries`);
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* Start the sudocode server
|
|
124
|
-
*/
|
|
125
|
-
async function startServer(): Promise<void> {
|
|
126
|
-
// Kill any stale processes on the test port
|
|
127
|
-
try {
|
|
128
|
-
execSync(`lsof -t -i :${TEST_PORT} | xargs kill -9 2>/dev/null || true`, {
|
|
129
|
-
stdio: "ignore",
|
|
130
|
-
});
|
|
131
|
-
} catch {
|
|
132
|
-
// Ignore
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
// Create temporary project directory
|
|
136
|
-
projectDir = mkdtempSync(join(tmpdir(), "sudocode-backend-e2e-"));
|
|
137
|
-
|
|
138
|
-
// Initialize sudocode
|
|
139
|
-
await new Promise<void>((resolve, reject) => {
|
|
140
|
-
const initProcess = spawn("npx", ["sudocode", "init"], {
|
|
141
|
-
cwd: projectDir!,
|
|
142
|
-
stdio: "pipe",
|
|
143
|
-
});
|
|
144
|
-
|
|
145
|
-
initProcess.on("close", (code) => {
|
|
146
|
-
if (code === 0) {
|
|
147
|
-
resolve();
|
|
148
|
-
} else {
|
|
149
|
-
reject(new Error(`sudocode init failed with code ${code}`));
|
|
150
|
-
}
|
|
151
|
-
});
|
|
152
|
-
|
|
153
|
-
initProcess.on("error", reject);
|
|
154
|
-
});
|
|
155
|
-
|
|
156
|
-
// Start the server
|
|
157
|
-
serverProcess = spawn(
|
|
158
|
-
"npx",
|
|
159
|
-
["sudocode", "server", "-p", String(TEST_PORT)],
|
|
160
|
-
{
|
|
161
|
-
cwd: projectDir,
|
|
162
|
-
stdio: "pipe",
|
|
163
|
-
env: { ...process.env, FORCE_COLOR: "0" },
|
|
164
|
-
}
|
|
165
|
-
);
|
|
166
|
-
|
|
167
|
-
serverProcess.stdout?.on("data", (data) => {
|
|
168
|
-
if (process.env.DEBUG_E2E) {
|
|
169
|
-
console.log(`[server stdout] ${data}`);
|
|
170
|
-
}
|
|
171
|
-
});
|
|
172
|
-
|
|
173
|
-
serverProcess.stderr?.on("data", (data) => {
|
|
174
|
-
if (process.env.DEBUG_E2E) {
|
|
175
|
-
console.error(`[server stderr] ${data}`);
|
|
176
|
-
}
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
// Wait for server to be ready
|
|
180
|
-
const ready = await waitForServer(SERVER_URL);
|
|
181
|
-
if (!ready) {
|
|
182
|
-
throw new Error(`Server failed to start within ${SERVER_STARTUP_TIMEOUT}ms`);
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
// Get project ID
|
|
186
|
-
projectId = await getProjectId(SERVER_URL, projectDir);
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
/**
|
|
190
|
-
* Stop the sudocode server
|
|
191
|
-
*/
|
|
192
|
-
async function stopServer(): Promise<void> {
|
|
193
|
-
if (serverProcess) {
|
|
194
|
-
serverProcess.kill("SIGTERM");
|
|
195
|
-
|
|
196
|
-
await new Promise<void>((resolve) => {
|
|
197
|
-
const timeout = setTimeout(() => {
|
|
198
|
-
serverProcess?.kill("SIGKILL");
|
|
199
|
-
resolve();
|
|
200
|
-
}, 5000);
|
|
201
|
-
|
|
202
|
-
serverProcess!.on("close", () => {
|
|
203
|
-
clearTimeout(timeout);
|
|
204
|
-
resolve();
|
|
205
|
-
});
|
|
206
|
-
});
|
|
207
|
-
|
|
208
|
-
serverProcess = null;
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
if (projectDir && existsSync(projectDir)) {
|
|
212
|
-
rmSync(projectDir, { recursive: true, force: true });
|
|
213
|
-
projectDir = null;
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
/**
|
|
218
|
-
* Create a test issue via the API
|
|
219
|
-
*/
|
|
220
|
-
async function createTestIssue(
|
|
221
|
-
title: string,
|
|
222
|
-
content?: string
|
|
223
|
-
): Promise<Issue> {
|
|
224
|
-
const response = await fetch(`${SERVER_URL}/api/issues`, {
|
|
225
|
-
method: "POST",
|
|
226
|
-
headers: {
|
|
227
|
-
"Content-Type": "application/json",
|
|
228
|
-
"X-Project-ID": projectId!,
|
|
229
|
-
},
|
|
230
|
-
body: JSON.stringify({
|
|
231
|
-
title,
|
|
232
|
-
content: content ?? `Test content for ${title}`,
|
|
233
|
-
status: "open",
|
|
234
|
-
priority: 2,
|
|
235
|
-
}),
|
|
236
|
-
});
|
|
237
|
-
|
|
238
|
-
const result = await response.json();
|
|
239
|
-
if (!result.success) {
|
|
240
|
-
throw new Error(`Failed to create issue: ${result.message}`);
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
createdIssueIds.push(result.data.id);
|
|
244
|
-
return result.data;
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
/**
|
|
248
|
-
* Wait for condition with timeout
|
|
249
|
-
*/
|
|
250
|
-
async function waitFor(
|
|
251
|
-
condition: () => boolean | Promise<boolean>,
|
|
252
|
-
timeout: number = 5000
|
|
253
|
-
): Promise<void> {
|
|
254
|
-
const startTime = Date.now();
|
|
255
|
-
while (Date.now() - startTime < timeout) {
|
|
256
|
-
if (await condition()) {
|
|
257
|
-
return;
|
|
258
|
-
}
|
|
259
|
-
await new Promise((r) => setTimeout(r, 100));
|
|
260
|
-
}
|
|
261
|
-
throw new Error(`Condition not met within ${timeout}ms`);
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
describe("SudocodeTaskBackend E2E", () => {
|
|
265
|
-
beforeAll(async () => {
|
|
266
|
-
console.log("\n🚀 Starting sudocode server for Backend E2E tests...");
|
|
267
|
-
await startServer();
|
|
268
|
-
console.log(`✅ Server ready at ${SERVER_URL}\n`);
|
|
269
|
-
}, SERVER_STARTUP_TIMEOUT + 10000);
|
|
270
|
-
|
|
271
|
-
afterAll(async () => {
|
|
272
|
-
console.log("\n🛑 Shutting down sudocode server...");
|
|
273
|
-
await stopServer();
|
|
274
|
-
console.log("✅ Cleanup complete\n");
|
|
275
|
-
}, 15000);
|
|
276
|
-
|
|
277
|
-
beforeEach(async () => {
|
|
278
|
-
// Create a fresh EventStore for each test with a unique instance ID
|
|
279
|
-
const instanceId = `e2e-test-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
280
|
-
eventStore = await createEventStore({
|
|
281
|
-
instanceId,
|
|
282
|
-
inMemory: true, // Use in-memory for tests
|
|
283
|
-
});
|
|
284
|
-
|
|
285
|
-
// Create ServerClient
|
|
286
|
-
client = new ServerClient({
|
|
287
|
-
serverUrl: SERVER_URL,
|
|
288
|
-
wsUrl: WS_URL,
|
|
289
|
-
projectId: projectId!,
|
|
290
|
-
});
|
|
291
|
-
|
|
292
|
-
// Wait for WebSocket connection
|
|
293
|
-
await new Promise<void>((resolve, reject) => {
|
|
294
|
-
const timeout = setTimeout(() => {
|
|
295
|
-
reject(new Error("WebSocket connection timeout"));
|
|
296
|
-
}, 5000);
|
|
297
|
-
|
|
298
|
-
const checkReady = () => {
|
|
299
|
-
if (client.isReady()) {
|
|
300
|
-
clearTimeout(timeout);
|
|
301
|
-
resolve();
|
|
302
|
-
} else {
|
|
303
|
-
setTimeout(checkReady, 50);
|
|
304
|
-
}
|
|
305
|
-
};
|
|
306
|
-
checkReady();
|
|
307
|
-
});
|
|
308
|
-
|
|
309
|
-
// Create SudocodeTaskBackend
|
|
310
|
-
backend = new SudocodeTaskBackend(eventStore, client, {
|
|
311
|
-
syncStatus: true,
|
|
312
|
-
autoCloseIssues: false,
|
|
313
|
-
});
|
|
314
|
-
});
|
|
315
|
-
|
|
316
|
-
afterEach(() => {
|
|
317
|
-
if (client) {
|
|
318
|
-
client.close();
|
|
319
|
-
}
|
|
320
|
-
});
|
|
321
|
-
|
|
322
|
-
describe("Basic Workflow", () => {
|
|
323
|
-
it(
|
|
324
|
-
"should complete full task lifecycle bound to issue",
|
|
325
|
-
{ timeout: TEST_TIMEOUT },
|
|
326
|
-
async () => {
|
|
327
|
-
// Create sudocode issue
|
|
328
|
-
const issue = await createTestIssue("E2E Backend Task Lifecycle");
|
|
329
|
-
|
|
330
|
-
// 1. Create task bound to issue
|
|
331
|
-
const task = await backend.create({
|
|
332
|
-
description: "Implement test feature",
|
|
333
|
-
created_by: "test-agent",
|
|
334
|
-
external_id: issue.id,
|
|
335
|
-
});
|
|
336
|
-
|
|
337
|
-
expect(task.external_id).toBe(issue.id);
|
|
338
|
-
expect(task.status).toBe("pending");
|
|
339
|
-
|
|
340
|
-
// 2. Assign task
|
|
341
|
-
await backend.assign(task.id, "worker-1");
|
|
342
|
-
const assignedTask = await backend.get(task.id);
|
|
343
|
-
expect(assignedTask?.assigned_agent).toBe("worker-1");
|
|
344
|
-
expect(assignedTask?.status).toBe("assigned");
|
|
345
|
-
|
|
346
|
-
// 3. Start task
|
|
347
|
-
await backend.start(task.id);
|
|
348
|
-
const inProgressTask = await backend.get(task.id);
|
|
349
|
-
expect(inProgressTask?.status).toBe("in_progress");
|
|
350
|
-
|
|
351
|
-
// Verify issue status was updated (if syncStatus is true)
|
|
352
|
-
await new Promise((r) => setTimeout(r, 200));
|
|
353
|
-
const updatedIssue = await client.getIssue(issue.id);
|
|
354
|
-
expect(updatedIssue?.status).toBe("in_progress");
|
|
355
|
-
|
|
356
|
-
// 4. Complete task
|
|
357
|
-
await backend.complete(task.id, { summary: "Feature implemented" });
|
|
358
|
-
const completedTask = await backend.get(task.id);
|
|
359
|
-
expect(completedTask?.status).toBe("completed");
|
|
360
|
-
}
|
|
361
|
-
);
|
|
362
|
-
|
|
363
|
-
it(
|
|
364
|
-
"should create task without external binding",
|
|
365
|
-
{ timeout: TEST_TIMEOUT },
|
|
366
|
-
async () => {
|
|
367
|
-
const task = await backend.create({
|
|
368
|
-
description: "Internal task without issue binding",
|
|
369
|
-
created_by: "test-agent",
|
|
370
|
-
});
|
|
371
|
-
|
|
372
|
-
expect(task.external_id).toBeUndefined();
|
|
373
|
-
expect(task.status).toBe("pending");
|
|
374
|
-
|
|
375
|
-
// Should still work through full lifecycle
|
|
376
|
-
await backend.assign(task.id, "worker-1");
|
|
377
|
-
await backend.start(task.id);
|
|
378
|
-
await backend.complete(task.id);
|
|
379
|
-
|
|
380
|
-
const completedTask = await backend.get(task.id);
|
|
381
|
-
expect(completedTask?.status).toBe("completed");
|
|
382
|
-
}
|
|
383
|
-
);
|
|
384
|
-
});
|
|
385
|
-
|
|
386
|
-
describe("Multiple Tasks Per Issue", () => {
|
|
387
|
-
it(
|
|
388
|
-
"should support multiple tasks bound to same issue",
|
|
389
|
-
{ timeout: TEST_TIMEOUT },
|
|
390
|
-
async () => {
|
|
391
|
-
const issue = await createTestIssue("E2E Multi-Task Issue");
|
|
392
|
-
|
|
393
|
-
// Create two tasks for same issue (parallel workers)
|
|
394
|
-
const task1 = await backend.create({
|
|
395
|
-
description: "Worker 1 attempt",
|
|
396
|
-
created_by: "coordinator",
|
|
397
|
-
external_id: issue.id,
|
|
398
|
-
});
|
|
399
|
-
|
|
400
|
-
const task2 = await backend.create({
|
|
401
|
-
description: "Worker 2 attempt",
|
|
402
|
-
created_by: "coordinator",
|
|
403
|
-
external_id: issue.id,
|
|
404
|
-
});
|
|
405
|
-
|
|
406
|
-
// Both bound to same issue
|
|
407
|
-
expect(task1.external_id).toBe(issue.id);
|
|
408
|
-
expect(task2.external_id).toBe(issue.id);
|
|
409
|
-
|
|
410
|
-
// Start both
|
|
411
|
-
await backend.assign(task1.id, "worker-1");
|
|
412
|
-
await backend.assign(task2.id, "worker-2");
|
|
413
|
-
await backend.start(task1.id);
|
|
414
|
-
await backend.start(task2.id);
|
|
415
|
-
|
|
416
|
-
// Complete one, fail other
|
|
417
|
-
await backend.complete(task1.id, { summary: "success" });
|
|
418
|
-
await backend.fail(task2.id, { code: "TIMEOUT", message: "Timed out" });
|
|
419
|
-
|
|
420
|
-
// Verify statuses
|
|
421
|
-
const completedTask = await backend.get(task1.id);
|
|
422
|
-
const failedTask = await backend.get(task2.id);
|
|
423
|
-
expect(completedTask?.status).toBe("completed");
|
|
424
|
-
expect(failedTask?.status).toBe("failed");
|
|
425
|
-
|
|
426
|
-
// Issue should still be open (coordinator decides when to close)
|
|
427
|
-
const finalIssue = await client.getIssue(issue.id);
|
|
428
|
-
expect(finalIssue?.status).toBe("in_progress");
|
|
429
|
-
}
|
|
430
|
-
);
|
|
431
|
-
});
|
|
432
|
-
|
|
433
|
-
describe("Blocker Workflow", () => {
|
|
434
|
-
it(
|
|
435
|
-
"should handle blockers via sudocode relationships",
|
|
436
|
-
{ timeout: TEST_TIMEOUT },
|
|
437
|
-
async () => {
|
|
438
|
-
// Create two issues with blocking relationship
|
|
439
|
-
const blockerIssue = await createTestIssue("E2E Blocker Task");
|
|
440
|
-
const blockedIssue = await createTestIssue("E2E Blocked Task");
|
|
441
|
-
|
|
442
|
-
// Create blocking relationship
|
|
443
|
-
await client.createLink(blockerIssue.id, blockedIssue.id, "blocks");
|
|
444
|
-
|
|
445
|
-
// Create tasks bound to these issues
|
|
446
|
-
const blockerTask = await backend.create({
|
|
447
|
-
description: "Blocker task",
|
|
448
|
-
created_by: "coordinator",
|
|
449
|
-
external_id: blockerIssue.id,
|
|
450
|
-
});
|
|
451
|
-
|
|
452
|
-
const blockedTask = await backend.create({
|
|
453
|
-
description: "Blocked task",
|
|
454
|
-
created_by: "coordinator",
|
|
455
|
-
external_id: blockedIssue.id,
|
|
456
|
-
});
|
|
457
|
-
|
|
458
|
-
// Verify the blocking relationship exists via backend.getBlockers
|
|
459
|
-
// (This doesn't depend on toExtendedTask's isBlocked computation)
|
|
460
|
-
const blockers = await backend.getBlockers(blockedTask.id);
|
|
461
|
-
expect(blockers.length).toBeGreaterThan(0);
|
|
462
|
-
expect(blockers[0].id).toBe(blockerTask.id);
|
|
463
|
-
|
|
464
|
-
// Blocked task should have isBlocked (via toExtendedTask computation)
|
|
465
|
-
const enrichedBlocked = await backend.get(blockedTask.id);
|
|
466
|
-
expect(enrichedBlocked?.isBlocked).toBe(true);
|
|
467
|
-
|
|
468
|
-
// Blocker task should not be blocked
|
|
469
|
-
const enrichedBlocker = await backend.get(blockerTask.id);
|
|
470
|
-
expect(enrichedBlocker?.isBlocked).toBe(false);
|
|
471
|
-
|
|
472
|
-
// listReady should exclude blocked task
|
|
473
|
-
const ready = await backend.listReady();
|
|
474
|
-
const readyIds = ready.map((t) => t.id);
|
|
475
|
-
expect(readyIds).toContain(blockerTask.id);
|
|
476
|
-
expect(readyIds).not.toContain(blockedTask.id);
|
|
477
|
-
|
|
478
|
-
// Complete blocker task and close blocker issue
|
|
479
|
-
await backend.assign(blockerTask.id, "worker-1");
|
|
480
|
-
await backend.start(blockerTask.id);
|
|
481
|
-
await backend.complete(blockerTask.id, { summary: "done" });
|
|
482
|
-
await client.updateIssue(blockerIssue.id, { status: "closed" });
|
|
483
|
-
|
|
484
|
-
// Wait for status to propagate
|
|
485
|
-
await new Promise((r) => setTimeout(r, 500));
|
|
486
|
-
|
|
487
|
-
// Now blocked task should be ready
|
|
488
|
-
const readyAfter = await backend.listReady();
|
|
489
|
-
const readyIdsAfter = readyAfter.map((t) => t.id);
|
|
490
|
-
expect(readyIdsAfter).toContain(blockedTask.id);
|
|
491
|
-
|
|
492
|
-
// isBlocked should now be false
|
|
493
|
-
const unblockedTask = await backend.get(blockedTask.id);
|
|
494
|
-
expect(unblockedTask?.isBlocked).toBe(false);
|
|
495
|
-
}
|
|
496
|
-
);
|
|
497
|
-
|
|
498
|
-
it(
|
|
499
|
-
"should use getBlockers and getBlocking methods",
|
|
500
|
-
{ timeout: TEST_TIMEOUT },
|
|
501
|
-
async () => {
|
|
502
|
-
const blockerIssue = await createTestIssue("E2E Blocker For Methods");
|
|
503
|
-
const blockedIssue = await createTestIssue("E2E Blocked For Methods");
|
|
504
|
-
|
|
505
|
-
await client.createLink(blockerIssue.id, blockedIssue.id, "blocks");
|
|
506
|
-
|
|
507
|
-
const blockerTask = await backend.create({
|
|
508
|
-
description: "Blocker",
|
|
509
|
-
created_by: "test",
|
|
510
|
-
external_id: blockerIssue.id,
|
|
511
|
-
});
|
|
512
|
-
|
|
513
|
-
const blockedTask = await backend.create({
|
|
514
|
-
description: "Blocked",
|
|
515
|
-
created_by: "test",
|
|
516
|
-
external_id: blockedIssue.id,
|
|
517
|
-
});
|
|
518
|
-
|
|
519
|
-
// Wait for relationship to propagate
|
|
520
|
-
await new Promise((r) => setTimeout(r, 300));
|
|
521
|
-
|
|
522
|
-
// Test getBlockers
|
|
523
|
-
const blockers = await backend.getBlockers(blockedTask.id);
|
|
524
|
-
expect(blockers.map((t) => t.id)).toContain(blockerTask.id);
|
|
525
|
-
|
|
526
|
-
// Test getBlocking
|
|
527
|
-
const blocking = await backend.getBlocking(blockerTask.id);
|
|
528
|
-
expect(blocking.map((t) => t.id)).toContain(blockedTask.id);
|
|
529
|
-
}
|
|
530
|
-
);
|
|
531
|
-
});
|
|
532
|
-
|
|
533
|
-
describe("Task Filtering", () => {
|
|
534
|
-
it(
|
|
535
|
-
"should filter tasks by status",
|
|
536
|
-
{ timeout: TEST_TIMEOUT },
|
|
537
|
-
async () => {
|
|
538
|
-
const issue1 = await createTestIssue("E2E Filter Issue 1");
|
|
539
|
-
const issue2 = await createTestIssue("E2E Filter Issue 2");
|
|
540
|
-
|
|
541
|
-
const task1 = await backend.create({
|
|
542
|
-
description: "Task 1",
|
|
543
|
-
created_by: "test",
|
|
544
|
-
external_id: issue1.id,
|
|
545
|
-
});
|
|
546
|
-
|
|
547
|
-
const task2 = await backend.create({
|
|
548
|
-
description: "Task 2",
|
|
549
|
-
created_by: "test",
|
|
550
|
-
external_id: issue2.id,
|
|
551
|
-
});
|
|
552
|
-
|
|
553
|
-
// Start task1
|
|
554
|
-
await backend.assign(task1.id, "worker-1");
|
|
555
|
-
await backend.start(task1.id);
|
|
556
|
-
|
|
557
|
-
// Filter by status
|
|
558
|
-
const pendingTasks = await backend.list({ status: "pending" });
|
|
559
|
-
expect(pendingTasks.some((t) => t.id === task2.id)).toBe(true);
|
|
560
|
-
expect(pendingTasks.some((t) => t.id === task1.id)).toBe(false);
|
|
561
|
-
|
|
562
|
-
const inProgressTasks = await backend.list({ status: "in_progress" });
|
|
563
|
-
expect(inProgressTasks.some((t) => t.id === task1.id)).toBe(true);
|
|
564
|
-
expect(inProgressTasks.some((t) => t.id === task2.id)).toBe(false);
|
|
565
|
-
}
|
|
566
|
-
);
|
|
567
|
-
|
|
568
|
-
it(
|
|
569
|
-
"should filter tasks by assigned agent",
|
|
570
|
-
{ timeout: TEST_TIMEOUT },
|
|
571
|
-
async () => {
|
|
572
|
-
const task1 = await backend.create({
|
|
573
|
-
description: "Task for Worker 1",
|
|
574
|
-
created_by: "test",
|
|
575
|
-
});
|
|
576
|
-
|
|
577
|
-
const task2 = await backend.create({
|
|
578
|
-
description: "Task for Worker 2",
|
|
579
|
-
created_by: "test",
|
|
580
|
-
});
|
|
581
|
-
|
|
582
|
-
await backend.assign(task1.id, "worker-1");
|
|
583
|
-
await backend.assign(task2.id, "worker-2");
|
|
584
|
-
|
|
585
|
-
const worker1Tasks = await backend.list({ assigned_agent: "worker-1" });
|
|
586
|
-
expect(worker1Tasks.length).toBe(1);
|
|
587
|
-
expect(worker1Tasks[0].id).toBe(task1.id);
|
|
588
|
-
|
|
589
|
-
const worker2Tasks = await backend.list({ assigned_agent: "worker-2" });
|
|
590
|
-
expect(worker2Tasks.length).toBe(1);
|
|
591
|
-
expect(worker2Tasks[0].id).toBe(task2.id);
|
|
592
|
-
}
|
|
593
|
-
);
|
|
594
|
-
});
|
|
595
|
-
|
|
596
|
-
describe("Subtask Hierarchy", () => {
|
|
597
|
-
it(
|
|
598
|
-
"should create and manage subtasks",
|
|
599
|
-
{ timeout: TEST_TIMEOUT },
|
|
600
|
-
async () => {
|
|
601
|
-
const parentIssue = await createTestIssue("E2E Parent Task Issue");
|
|
602
|
-
|
|
603
|
-
const parentTask = await backend.create({
|
|
604
|
-
description: "Parent task",
|
|
605
|
-
created_by: "coordinator",
|
|
606
|
-
external_id: parentIssue.id,
|
|
607
|
-
});
|
|
608
|
-
|
|
609
|
-
// Create subtasks
|
|
610
|
-
const subtask1 = await backend.createSubtask(parentTask.id, {
|
|
611
|
-
description: "Subtask 1",
|
|
612
|
-
created_by: "coordinator",
|
|
613
|
-
});
|
|
614
|
-
|
|
615
|
-
const subtask2 = await backend.createSubtask(parentTask.id, {
|
|
616
|
-
description: "Subtask 2",
|
|
617
|
-
created_by: "coordinator",
|
|
618
|
-
});
|
|
619
|
-
|
|
620
|
-
expect(subtask1.parent_task).toBe(parentTask.id);
|
|
621
|
-
expect(subtask2.parent_task).toBe(parentTask.id);
|
|
622
|
-
|
|
623
|
-
// Get children
|
|
624
|
-
const children = await backend.getChildren(parentTask.id);
|
|
625
|
-
expect(children.length).toBe(2);
|
|
626
|
-
expect(children.map((c) => c.id)).toContain(subtask1.id);
|
|
627
|
-
expect(children.map((c) => c.id)).toContain(subtask2.id);
|
|
628
|
-
|
|
629
|
-
// Get subtask status
|
|
630
|
-
const status = await backend.getSubtaskStatus(parentTask.id);
|
|
631
|
-
expect(status.total).toBe(2);
|
|
632
|
-
expect(status.pending).toBe(2);
|
|
633
|
-
expect(status.completed).toBe(0);
|
|
634
|
-
expect(status.allCompleted).toBe(false);
|
|
635
|
-
|
|
636
|
-
// Complete subtasks
|
|
637
|
-
await backend.assign(subtask1.id, "worker-1");
|
|
638
|
-
await backend.start(subtask1.id);
|
|
639
|
-
await backend.complete(subtask1.id);
|
|
640
|
-
|
|
641
|
-
await backend.assign(subtask2.id, "worker-2");
|
|
642
|
-
await backend.start(subtask2.id);
|
|
643
|
-
await backend.complete(subtask2.id);
|
|
644
|
-
|
|
645
|
-
const finalStatus = await backend.getSubtaskStatus(parentTask.id);
|
|
646
|
-
expect(finalStatus.completed).toBe(2);
|
|
647
|
-
expect(finalStatus.allCompleted).toBe(true);
|
|
648
|
-
}
|
|
649
|
-
);
|
|
650
|
-
});
|
|
651
|
-
|
|
652
|
-
describe("Agent History", () => {
|
|
653
|
-
it(
|
|
654
|
-
"should track agent assignment history",
|
|
655
|
-
{ timeout: TEST_TIMEOUT },
|
|
656
|
-
async () => {
|
|
657
|
-
const task = await backend.create({
|
|
658
|
-
description: "Task with history",
|
|
659
|
-
created_by: "coordinator",
|
|
660
|
-
});
|
|
661
|
-
|
|
662
|
-
// First assignment
|
|
663
|
-
await backend.assign(task.id, "worker-1");
|
|
664
|
-
await backend.start(task.id);
|
|
665
|
-
|
|
666
|
-
// Unassign and reassign
|
|
667
|
-
await backend.unassign(task.id);
|
|
668
|
-
await backend.assign(task.id, "worker-2");
|
|
669
|
-
await backend.start(task.id);
|
|
670
|
-
await backend.complete(task.id);
|
|
671
|
-
|
|
672
|
-
// Check history
|
|
673
|
-
const history = await backend.getAgentHistory(task.id);
|
|
674
|
-
expect(history.length).toBeGreaterThanOrEqual(2);
|
|
675
|
-
expect(history.some((h) => h.agent_id === "worker-1")).toBe(true);
|
|
676
|
-
expect(history.some((h) => h.agent_id === "worker-2")).toBe(true);
|
|
677
|
-
}
|
|
678
|
-
);
|
|
679
|
-
});
|
|
680
|
-
|
|
681
|
-
describe("Event Subscriptions", () => {
|
|
682
|
-
it(
|
|
683
|
-
"should emit events on task changes",
|
|
684
|
-
{ timeout: TEST_TIMEOUT },
|
|
685
|
-
async () => {
|
|
686
|
-
const events: TaskChangeEvent[] = [];
|
|
687
|
-
|
|
688
|
-
const unsubscribe = backend.onTaskChange((event) => {
|
|
689
|
-
events.push(event);
|
|
690
|
-
});
|
|
691
|
-
|
|
692
|
-
try {
|
|
693
|
-
const task = await backend.create({
|
|
694
|
-
description: "Event test task",
|
|
695
|
-
created_by: "test",
|
|
696
|
-
});
|
|
697
|
-
|
|
698
|
-
await backend.assign(task.id, "worker-1");
|
|
699
|
-
await backend.start(task.id);
|
|
700
|
-
await backend.complete(task.id);
|
|
701
|
-
|
|
702
|
-
// Wait for events
|
|
703
|
-
await new Promise((r) => setTimeout(r, 200));
|
|
704
|
-
|
|
705
|
-
// Should have received events for create, assign, start, complete
|
|
706
|
-
// Backend currently emits "updated" for all changes
|
|
707
|
-
expect(events.length).toBeGreaterThanOrEqual(3);
|
|
708
|
-
|
|
709
|
-
const eventTypes = events.map((e) => e.type);
|
|
710
|
-
expect(eventTypes).toContain("updated");
|
|
711
|
-
} finally {
|
|
712
|
-
unsubscribe();
|
|
713
|
-
}
|
|
714
|
-
}
|
|
715
|
-
);
|
|
716
|
-
|
|
717
|
-
it(
|
|
718
|
-
"should filter events by task ID",
|
|
719
|
-
{ timeout: TEST_TIMEOUT },
|
|
720
|
-
async () => {
|
|
721
|
-
const task1Events: TaskChangeEvent[] = [];
|
|
722
|
-
|
|
723
|
-
const task1 = await backend.create({
|
|
724
|
-
description: "Task 1 for events",
|
|
725
|
-
created_by: "test",
|
|
726
|
-
});
|
|
727
|
-
|
|
728
|
-
const task2 = await backend.create({
|
|
729
|
-
description: "Task 2 for events",
|
|
730
|
-
created_by: "test",
|
|
731
|
-
});
|
|
732
|
-
|
|
733
|
-
const unsubscribe = backend.onTaskChange(task1.id, (event) => {
|
|
734
|
-
task1Events.push(event);
|
|
735
|
-
});
|
|
736
|
-
|
|
737
|
-
try {
|
|
738
|
-
await backend.assign(task1.id, "worker-1");
|
|
739
|
-
await backend.assign(task2.id, "worker-2");
|
|
740
|
-
await backend.start(task1.id);
|
|
741
|
-
await backend.start(task2.id);
|
|
742
|
-
|
|
743
|
-
await new Promise((r) => setTimeout(r, 200));
|
|
744
|
-
|
|
745
|
-
// Should only have events for task1
|
|
746
|
-
expect(task1Events.every((e) => e.taskId === task1.id)).toBe(true);
|
|
747
|
-
} finally {
|
|
748
|
-
unsubscribe();
|
|
749
|
-
}
|
|
750
|
-
}
|
|
751
|
-
);
|
|
752
|
-
});
|
|
753
|
-
});
|