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,23 +1,67 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Team Runtime
|
|
3
3
|
*
|
|
4
|
-
* Wires a loaded
|
|
4
|
+
* Wires a loaded team template into the running system: registers roles,
|
|
5
5
|
* sets up integration strategy, configures communication topology,
|
|
6
6
|
* and manages the team lifecycle.
|
|
7
7
|
*
|
|
8
8
|
* @module teams/team-runtime
|
|
9
9
|
*/
|
|
10
|
+
import { WORKSPACE_CAPABILITIES } from "../roles/capabilities.js";
|
|
11
|
+
// =============================================================================
|
|
12
|
+
// Conversion: TeamManifest → MacroResolvedTemplate
|
|
13
|
+
// =============================================================================
|
|
14
|
+
/**
|
|
15
|
+
* Convert a legacy TeamManifest (with _ prefixed fields) to MacroResolvedTemplate.
|
|
16
|
+
* Used for backward compatibility when TeamRuntime receives a TeamManifest.
|
|
17
|
+
*/
|
|
18
|
+
function manifestToResolved(manifest) {
|
|
19
|
+
return {
|
|
20
|
+
template: {
|
|
21
|
+
manifest: {
|
|
22
|
+
name: manifest.name,
|
|
23
|
+
description: manifest.description,
|
|
24
|
+
version: manifest.version,
|
|
25
|
+
roles: manifest.roles,
|
|
26
|
+
topology: manifest.topology,
|
|
27
|
+
communication: manifest.communication,
|
|
28
|
+
},
|
|
29
|
+
roles: new Map(), // Not used — macro-agent uses resolvedRoles
|
|
30
|
+
prompts: new Map(), // Prompts are in _loadedPrompts
|
|
31
|
+
mcpServers: manifest._mcpServers,
|
|
32
|
+
sourcePath: "",
|
|
33
|
+
},
|
|
34
|
+
resolvedRoles: manifest._resolvedRoles,
|
|
35
|
+
macroAgent: manifest.macro_agent,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Check if input is a MacroResolvedTemplate (has `template` field)
|
|
40
|
+
* vs a legacy TeamManifest (has `_resolvedRoles` field).
|
|
41
|
+
*/
|
|
42
|
+
function isMacroResolvedTemplate(input) {
|
|
43
|
+
return "template" in input && "resolvedRoles" in input;
|
|
44
|
+
}
|
|
10
45
|
// =============================================================================
|
|
11
46
|
// TeamRuntime
|
|
12
47
|
// =============================================================================
|
|
13
48
|
export class TeamRuntime {
|
|
14
|
-
manifest;
|
|
15
49
|
services;
|
|
16
50
|
rootAgentId;
|
|
17
51
|
companionAgentIds = [];
|
|
18
52
|
roleRegistry;
|
|
19
53
|
lifecycleUnsubscribe;
|
|
20
54
|
integrationStrategy;
|
|
55
|
+
scalingTimer;
|
|
56
|
+
lastScaleUpTime = 0;
|
|
57
|
+
teamStreamId;
|
|
58
|
+
mergeQueueUnsub;
|
|
59
|
+
mergeRequestPollTimer;
|
|
60
|
+
lastMergeRequestSeen = 0;
|
|
61
|
+
/** The resolved template (canonical internal representation) */
|
|
62
|
+
resolved;
|
|
63
|
+
/** Legacy loaded prompts map (path → content) for backward compat */
|
|
64
|
+
loadedPrompts;
|
|
21
65
|
/** Role name → spawned agent ID mapping (populated during bootstrap) */
|
|
22
66
|
roleAgentMap = new Map();
|
|
23
67
|
/** Peer connections that couldn't be wired at bootstrap (target role not yet spawned) */
|
|
@@ -26,13 +70,34 @@ export class TeamRuntime {
|
|
|
26
70
|
peerSignalFilters = new Map();
|
|
27
71
|
/** Reverse mapping: agent ID → role name (for signal filter lookups) */
|
|
28
72
|
agentRoleMap = new Map();
|
|
73
|
+
/** Pre-computed per-role allowed signals from channel subscriptions */
|
|
74
|
+
roleAllowedSignals = new Map();
|
|
29
75
|
/** Lifecycle unsubscribe for deferred peer wiring */
|
|
30
76
|
peerWiringUnsubscribe;
|
|
31
|
-
|
|
32
|
-
|
|
77
|
+
/**
|
|
78
|
+
* Create a TeamRuntime.
|
|
79
|
+
*
|
|
80
|
+
* Accepts either a MacroResolvedTemplate (new) or a TeamManifest (legacy).
|
|
81
|
+
* Internally always uses MacroResolvedTemplate.
|
|
82
|
+
*/
|
|
83
|
+
constructor(input, services) {
|
|
33
84
|
this.services = services;
|
|
85
|
+
this.resolved = isMacroResolvedTemplate(input)
|
|
86
|
+
? input
|
|
87
|
+
: manifestToResolved(input);
|
|
88
|
+
// Extract loaded prompts from legacy manifest if available
|
|
89
|
+
this.loadedPrompts = !isMacroResolvedTemplate(input)
|
|
90
|
+
? input._loadedPrompts
|
|
91
|
+
: new Map();
|
|
34
92
|
this.roleRegistry = services.agentManager.getRoleRegistry();
|
|
35
93
|
}
|
|
94
|
+
// Convenience accessors
|
|
95
|
+
get manifest() {
|
|
96
|
+
return this.resolved.template.manifest;
|
|
97
|
+
}
|
|
98
|
+
get communication() {
|
|
99
|
+
return (this.manifest.communication ?? {});
|
|
100
|
+
}
|
|
36
101
|
// ─────────────────────────────────────────────────────────────
|
|
37
102
|
// Initialization
|
|
38
103
|
// ─────────────────────────────────────────────────────────────
|
|
@@ -41,22 +106,36 @@ export class TeamRuntime {
|
|
|
41
106
|
*
|
|
42
107
|
* 1. Register team roles into RoleRegistry
|
|
43
108
|
* 2. Store team_config event in EventStore (for MCP subprocess discovery)
|
|
44
|
-
* 3.
|
|
109
|
+
* 3. Instantiate integration strategy
|
|
110
|
+
*
|
|
111
|
+
* Note: Does NOT install spawn interceptor, signal filter, or emission
|
|
112
|
+
* validator on services. Call installOnServices() for standalone use,
|
|
113
|
+
* or let TeamManager handle composite installation.
|
|
45
114
|
*/
|
|
46
|
-
async initialize() {
|
|
47
|
-
const {
|
|
115
|
+
async initialize(options) {
|
|
116
|
+
const { eventStore } = this.services;
|
|
48
117
|
// 1. Register team roles into RoleRegistry (custom layer, highest priority)
|
|
49
|
-
for (const [, resolved] of this.
|
|
50
|
-
|
|
118
|
+
for (const [, resolved] of this.resolved.resolvedRoles) {
|
|
119
|
+
const rd = resolved.roleDefinition;
|
|
120
|
+
const existing = this.roleRegistry.getRole(rd.name);
|
|
121
|
+
if (existing) {
|
|
122
|
+
const existingCaps = [...existing.capabilities].sort();
|
|
123
|
+
const newCaps = [...rd.capabilities].sort();
|
|
124
|
+
if (existingCaps.length !== newCaps.length || existingCaps.some((c, i) => c !== newCaps[i])) {
|
|
125
|
+
console.warn(`[TeamRuntime] Role '${rd.name}' conflict: team '${this.manifest.name}' re-registers with different capabilities. ` +
|
|
126
|
+
`Existing: [${existingCaps.join(", ")}], New: [${newCaps.join(", ")}]`);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
this.roleRegistry.registerRole(rd);
|
|
51
130
|
}
|
|
52
131
|
// 2. Store team config in EventStore for cross-process access (RD2)
|
|
53
|
-
const taskMode = this.
|
|
54
|
-
const strategyName = this.
|
|
55
|
-
const strategyConfig = this.
|
|
56
|
-
const enforcement = this.
|
|
132
|
+
const taskMode = this.resolved.macroAgent.task_assignment?.mode ?? "push";
|
|
133
|
+
const strategyName = this.resolved.macroAgent.integration?.strategy ?? "queue";
|
|
134
|
+
const strategyConfig = this.resolved.macroAgent.integration?.config ?? {};
|
|
135
|
+
const enforcement = this.communication.enforcement ?? "permissive";
|
|
57
136
|
// Serialize resolved roles for MCP subprocess capability checks
|
|
58
137
|
const serializedRoles = {};
|
|
59
|
-
for (const [name, resolved] of this.
|
|
138
|
+
for (const [name, resolved] of this.resolved.resolvedRoles) {
|
|
60
139
|
const rd = resolved.roleDefinition;
|
|
61
140
|
serializedRoles[name] = {
|
|
62
141
|
name: rd.name,
|
|
@@ -74,39 +153,49 @@ export class TeamRuntime {
|
|
|
74
153
|
summary: `Team '${this.manifest.name}' initialized`,
|
|
75
154
|
team_config: {
|
|
76
155
|
teamName: this.manifest.name,
|
|
156
|
+
...(options?.teamInstanceId && { team_instance: options.teamInstanceId }),
|
|
77
157
|
strategy: strategyName,
|
|
78
158
|
strategyConfig,
|
|
79
159
|
taskMode,
|
|
80
160
|
enforcement,
|
|
81
161
|
roles: serializedRoles,
|
|
82
|
-
peerRoutes: this.
|
|
83
|
-
emissions: this.
|
|
162
|
+
peerRoutes: this.communication.routing?.peers ?? [],
|
|
163
|
+
emissions: this.communication.emissions ?? {},
|
|
84
164
|
},
|
|
85
165
|
},
|
|
86
166
|
});
|
|
87
167
|
await eventStore.persist();
|
|
88
|
-
//
|
|
168
|
+
// 3. Instantiate integration strategy and call lifecycle hook
|
|
89
169
|
try {
|
|
90
170
|
const { defaultStrategyRegistry } = await import("../workspace/strategies/registry.js");
|
|
91
171
|
this.integrationStrategy = defaultStrategyRegistry.get(strategyName, strategyConfig);
|
|
92
172
|
if (this.integrationStrategy.initialize) {
|
|
93
173
|
await this.integrationStrategy.initialize();
|
|
94
174
|
}
|
|
175
|
+
// Wire merge queue to queue strategy if workspace manager is available
|
|
176
|
+
if (this.services.workspaceManager &&
|
|
177
|
+
strategyName === "queue" &&
|
|
178
|
+
"setMergeQueue" in this.integrationStrategy) {
|
|
179
|
+
const mergeQueue = this.services.workspaceManager.getMergeQueue();
|
|
180
|
+
this.integrationStrategy.setMergeQueue(mergeQueue);
|
|
181
|
+
}
|
|
95
182
|
}
|
|
96
183
|
catch {
|
|
97
184
|
// Strategy instantiation is best-effort — queue strategy needs merge queue set later
|
|
98
185
|
}
|
|
99
|
-
// 3. Register spawn interceptor
|
|
100
|
-
agentManager.setSpawnInterceptor(this.createSpawnInterceptor());
|
|
101
186
|
}
|
|
102
187
|
// ─────────────────────────────────────────────────────────────
|
|
103
188
|
// Bootstrap
|
|
104
189
|
// ─────────────────────────────────────────────────────────────
|
|
105
190
|
/**
|
|
106
191
|
* Spawn root and companion agents per the team topology.
|
|
192
|
+
*
|
|
193
|
+
* Populates internal state (agentRoleMap, peerSignalFilters) used by
|
|
194
|
+
* createSignalFilter() and createEmissionValidator(). Call installOnServices()
|
|
195
|
+
* after bootstrap for standalone use, or let TeamManager handle installation.
|
|
107
196
|
*/
|
|
108
197
|
async bootstrap() {
|
|
109
|
-
const { agentManager
|
|
198
|
+
const { agentManager } = this.services;
|
|
110
199
|
const { topology } = this.manifest;
|
|
111
200
|
// 1. Spawn root agent
|
|
112
201
|
const rootPrompt = this.getPromptForTopologyNode(topology.root);
|
|
@@ -123,6 +212,9 @@ export class TeamRuntime {
|
|
|
123
212
|
interactionPatterns: this.getInteractionPatterns(),
|
|
124
213
|
});
|
|
125
214
|
this.rootAgentId = root.id;
|
|
215
|
+
// 1b. Set up workspace integration BEFORE companions spawn,
|
|
216
|
+
// so the spawn interceptor has teamStreamId for workspace injection
|
|
217
|
+
this.setupWorkspaceIntegration(root.id);
|
|
126
218
|
// 2. Spawn companions (peers, not children)
|
|
127
219
|
const companionIds = [];
|
|
128
220
|
for (const companion of topology.companions ?? []) {
|
|
@@ -148,12 +240,12 @@ export class TeamRuntime {
|
|
|
148
240
|
this.agentRoleMap.set(companionIds[i], topology.companions[i].role);
|
|
149
241
|
}
|
|
150
242
|
this.wirePeerRoutes();
|
|
151
|
-
// 4.
|
|
152
|
-
this.
|
|
153
|
-
// 5.
|
|
154
|
-
this.installEmissionValidator();
|
|
155
|
-
// 6. Set up continuation monitoring for daemon agents (P4.2)
|
|
243
|
+
// 4. Pre-compute role allowed signals (used by createSignalFilter)
|
|
244
|
+
this.computeRoleAllowedSignals();
|
|
245
|
+
// 5. Set up continuation monitoring for daemon agents (P4.2)
|
|
156
246
|
this.monitorContinuations();
|
|
247
|
+
// 6. Set up auto-scaling monitoring
|
|
248
|
+
this.monitorScaling();
|
|
157
249
|
return {
|
|
158
250
|
rootId: root.id,
|
|
159
251
|
companionIds,
|
|
@@ -163,10 +255,13 @@ export class TeamRuntime {
|
|
|
163
255
|
// Teardown
|
|
164
256
|
// ─────────────────────────────────────────────────────────────
|
|
165
257
|
/**
|
|
166
|
-
* Tear down team:
|
|
258
|
+
* Tear down team: stop continuation monitoring, clean up strategy.
|
|
259
|
+
*
|
|
260
|
+
* Note: Does NOT clear spawn interceptor or filters on services.
|
|
261
|
+
* The caller (TeamManager or standalone code) is responsible for
|
|
262
|
+
* removing the interceptor/filters from shared services.
|
|
167
263
|
*/
|
|
168
264
|
async teardown() {
|
|
169
|
-
this.services.agentManager.setSpawnInterceptor(null);
|
|
170
265
|
if (this.lifecycleUnsubscribe) {
|
|
171
266
|
this.lifecycleUnsubscribe();
|
|
172
267
|
this.lifecycleUnsubscribe = undefined;
|
|
@@ -175,6 +270,18 @@ export class TeamRuntime {
|
|
|
175
270
|
this.peerWiringUnsubscribe();
|
|
176
271
|
this.peerWiringUnsubscribe = undefined;
|
|
177
272
|
}
|
|
273
|
+
if (this.scalingTimer) {
|
|
274
|
+
clearInterval(this.scalingTimer);
|
|
275
|
+
this.scalingTimer = undefined;
|
|
276
|
+
}
|
|
277
|
+
if (this.mergeQueueUnsub) {
|
|
278
|
+
this.mergeQueueUnsub();
|
|
279
|
+
this.mergeQueueUnsub = undefined;
|
|
280
|
+
}
|
|
281
|
+
if (this.mergeRequestPollTimer) {
|
|
282
|
+
clearInterval(this.mergeRequestPollTimer);
|
|
283
|
+
this.mergeRequestPollTimer = undefined;
|
|
284
|
+
}
|
|
178
285
|
// Call strategy lifecycle close hook
|
|
179
286
|
if (this.integrationStrategy?.close) {
|
|
180
287
|
try {
|
|
@@ -190,15 +297,28 @@ export class TeamRuntime {
|
|
|
190
297
|
// ─────────────────────────────────────────────────────────────
|
|
191
298
|
/** Get task assignment mode */
|
|
192
299
|
getTaskMode() {
|
|
193
|
-
return this.
|
|
300
|
+
return this.resolved.macroAgent.task_assignment?.mode ?? "push";
|
|
194
301
|
}
|
|
195
302
|
/** Get integration strategy name */
|
|
196
303
|
getStrategyName() {
|
|
197
|
-
return this.
|
|
304
|
+
return this.resolved.macroAgent.integration?.strategy ?? "queue";
|
|
198
305
|
}
|
|
199
306
|
/** Get the active manifest (for API) */
|
|
200
307
|
getManifest() {
|
|
201
|
-
|
|
308
|
+
// Build a backward-compatible TeamManifest from the resolved template
|
|
309
|
+
return {
|
|
310
|
+
...this.manifest,
|
|
311
|
+
description: this.manifest.description ?? "",
|
|
312
|
+
communication: this.communication,
|
|
313
|
+
macro_agent: this.resolved.macroAgent,
|
|
314
|
+
_resolvedRoles: this.resolved.resolvedRoles,
|
|
315
|
+
_loadedPrompts: this.loadedPrompts,
|
|
316
|
+
_mcpServers: this.resolved.template.mcpServers,
|
|
317
|
+
};
|
|
318
|
+
}
|
|
319
|
+
/** Get the resolved template */
|
|
320
|
+
getResolvedTemplate() {
|
|
321
|
+
return this.resolved;
|
|
202
322
|
}
|
|
203
323
|
/** Get root agent ID (after bootstrap) */
|
|
204
324
|
getRootAgentId() {
|
|
@@ -212,10 +332,27 @@ export class TeamRuntime {
|
|
|
212
332
|
getIntegrationStrategy() {
|
|
213
333
|
return this.integrationStrategy;
|
|
214
334
|
}
|
|
335
|
+
/** Get team-wide integration stream ID (after bootstrap) */
|
|
336
|
+
getTeamStreamId() {
|
|
337
|
+
return this.teamStreamId;
|
|
338
|
+
}
|
|
215
339
|
/** Get signal filters for peer connections (for use by signal filtering - i-3o8g) */
|
|
216
340
|
getPeerSignalFilters() {
|
|
217
341
|
return this.peerSignalFilters;
|
|
218
342
|
}
|
|
343
|
+
/** Get the agent → role mapping (for TeamManager agent-team lookups) */
|
|
344
|
+
getAgentRoleMap() {
|
|
345
|
+
return this.agentRoleMap;
|
|
346
|
+
}
|
|
347
|
+
/** Register an agent's role mapping (for TeamManager to track dynamically spawned agents) */
|
|
348
|
+
registerAgent(agentId, roleName) {
|
|
349
|
+
this.agentRoleMap.set(agentId, roleName);
|
|
350
|
+
this.roleAgentMap.set(roleName, agentId);
|
|
351
|
+
}
|
|
352
|
+
/** Check if this team owns a given agent */
|
|
353
|
+
hasAgent(agentId) {
|
|
354
|
+
return this.agentRoleMap.has(agentId);
|
|
355
|
+
}
|
|
219
356
|
// ─────────────────────────────────────────────────────────────
|
|
220
357
|
// Continuation Monitoring (P4.2)
|
|
221
358
|
// ─────────────────────────────────────────────────────────────
|
|
@@ -226,7 +363,7 @@ export class TeamRuntime {
|
|
|
226
363
|
* lifecycle config enables continuations, automatically spawn a continuation.
|
|
227
364
|
*/
|
|
228
365
|
monitorContinuations() {
|
|
229
|
-
const lifecycleConfig = this.
|
|
366
|
+
const lifecycleConfig = this.resolved.macroAgent.lifecycle;
|
|
230
367
|
if (!lifecycleConfig?.continuations?.enabled)
|
|
231
368
|
return;
|
|
232
369
|
const { agentManager } = this.services;
|
|
@@ -267,17 +404,229 @@ export class TeamRuntime {
|
|
|
267
404
|
});
|
|
268
405
|
}
|
|
269
406
|
// ─────────────────────────────────────────────────────────────
|
|
407
|
+
// Auto-Scaling
|
|
408
|
+
// ─────────────────────────────────────────────────────────────
|
|
409
|
+
/** Minimum interval between scale-up actions (ms) */
|
|
410
|
+
static SCALE_COOLDOWN_MS = 10_000;
|
|
411
|
+
/** Default scaling check interval (ms) */
|
|
412
|
+
static SCALE_CHECK_INTERVAL_MS = 5_000;
|
|
413
|
+
/**
|
|
414
|
+
* Monitor task queue depth and auto-scale workers.
|
|
415
|
+
*
|
|
416
|
+
* Follows the same lifecycle pattern as monitorContinuations().
|
|
417
|
+
* Only active when `scaling.scale_on === "task_queue_depth"` and
|
|
418
|
+
* a task backend is available.
|
|
419
|
+
*/
|
|
420
|
+
monitorScaling() {
|
|
421
|
+
const scalingConfig = this.resolved.macroAgent.lifecycle?.scaling;
|
|
422
|
+
if (!scalingConfig || scalingConfig.scale_on !== "task_queue_depth")
|
|
423
|
+
return;
|
|
424
|
+
const { taskBackend } = this.services;
|
|
425
|
+
if (!taskBackend?.listClaimable)
|
|
426
|
+
return; // Need claimable task counting
|
|
427
|
+
const maxWorkers = scalingConfig.max_workers ?? Infinity;
|
|
428
|
+
const minWorkers = scalingConfig.min_workers ?? 0;
|
|
429
|
+
// Determine which role names are worker-derived (for counting active workers)
|
|
430
|
+
const workerRoleNames = new Set();
|
|
431
|
+
for (const [name, resolved] of this.resolved.resolvedRoles) {
|
|
432
|
+
if (resolved.baseRole === "worker") {
|
|
433
|
+
workerRoleNames.add(name);
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
if (workerRoleNames.size === 0)
|
|
437
|
+
return; // No worker roles to scale
|
|
438
|
+
// Pick the first worker role for spawning (most common pattern: single worker role)
|
|
439
|
+
const spawnRole = [...workerRoleNames][0];
|
|
440
|
+
this.scalingTimer = setInterval(async () => {
|
|
441
|
+
try {
|
|
442
|
+
// Count claimable tasks
|
|
443
|
+
const claimable = await taskBackend.listClaimable();
|
|
444
|
+
const pendingCount = claimable.length;
|
|
445
|
+
// Count active workers in this team
|
|
446
|
+
const allAgents = this.services.agentManager.list({ state: "running" });
|
|
447
|
+
let activeWorkers = 0;
|
|
448
|
+
for (const agent of allAgents) {
|
|
449
|
+
if (agent.role && workerRoleNames.has(agent.role) && this.agentRoleMap.has(agent.id)) {
|
|
450
|
+
activeWorkers++;
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
// Scale up: more pending tasks than active workers, under max cap
|
|
454
|
+
if (pendingCount > activeWorkers && activeWorkers < maxWorkers) {
|
|
455
|
+
const now = Date.now();
|
|
456
|
+
if (now - this.lastScaleUpTime < TeamRuntime.SCALE_COOLDOWN_MS) {
|
|
457
|
+
return; // Cooldown not elapsed
|
|
458
|
+
}
|
|
459
|
+
if (!this.rootAgentId)
|
|
460
|
+
return; // No root to spawn from
|
|
461
|
+
try {
|
|
462
|
+
await this.services.agentManager.spawn({
|
|
463
|
+
task: `[${this.manifest.name}] auto-scaled ${spawnRole}`,
|
|
464
|
+
role: spawnRole,
|
|
465
|
+
parent: this.rootAgentId,
|
|
466
|
+
});
|
|
467
|
+
this.lastScaleUpTime = now;
|
|
468
|
+
// Emit scaling event for observability
|
|
469
|
+
this.services.eventStore.emit({
|
|
470
|
+
type: "status",
|
|
471
|
+
source: { agent_id: "system" },
|
|
472
|
+
payload: {
|
|
473
|
+
status_type: "scaling",
|
|
474
|
+
summary: `Auto-scaled: spawned ${spawnRole} (pending=${pendingCount}, active=${activeWorkers}, max=${maxWorkers})`,
|
|
475
|
+
},
|
|
476
|
+
});
|
|
477
|
+
}
|
|
478
|
+
catch {
|
|
479
|
+
// Spawn failed — will retry on next tick
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
// Scale down is handled by idle_drain: workers self-terminate after idle_timeout_s
|
|
483
|
+
// No active termination needed from the scaling monitor
|
|
484
|
+
}
|
|
485
|
+
catch {
|
|
486
|
+
// Best-effort — don't crash the scaling loop
|
|
487
|
+
}
|
|
488
|
+
}, TeamRuntime.SCALE_CHECK_INTERVAL_MS);
|
|
489
|
+
// Ensure timer doesn't prevent process exit
|
|
490
|
+
if (this.scalingTimer.unref) {
|
|
491
|
+
this.scalingTimer.unref();
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
// ─────────────────────────────────────────────────────────────
|
|
495
|
+
// Workspace Integration
|
|
496
|
+
// ─────────────────────────────────────────────────────────────
|
|
497
|
+
/**
|
|
498
|
+
* Create the team-wide integration stream and subscribe to merge queue events.
|
|
499
|
+
*
|
|
500
|
+
* When a worker submits to the merge queue, the integrator agent is
|
|
501
|
+
* automatically prompted to process it.
|
|
502
|
+
*/
|
|
503
|
+
setupWorkspaceIntegration(rootAgentId) {
|
|
504
|
+
const { workspaceManager } = this.services;
|
|
505
|
+
if (!workspaceManager || !this.integrationStrategy)
|
|
506
|
+
return;
|
|
507
|
+
// Create integration stream owned by root agent
|
|
508
|
+
try {
|
|
509
|
+
this.teamStreamId = workspaceManager.createIntegrationStream(rootAgentId, { name: this.manifest.name, forkFrom: "main" });
|
|
510
|
+
}
|
|
511
|
+
catch {
|
|
512
|
+
// Workspace isolation unavailable (e.g., not a git repo)
|
|
513
|
+
return;
|
|
514
|
+
}
|
|
515
|
+
// Subscribe to merge queue events — wake integrator on mr:submitted
|
|
516
|
+
try {
|
|
517
|
+
const mergeQueue = workspaceManager.getMergeQueue();
|
|
518
|
+
if (mergeQueue?.onEvent) {
|
|
519
|
+
this.mergeQueueUnsub = mergeQueue.onEvent((event) => {
|
|
520
|
+
if (event.type !== "mr:submitted")
|
|
521
|
+
return;
|
|
522
|
+
// Find agent with workspace.integrate capability in this team
|
|
523
|
+
for (const [agentId, roleName] of this.agentRoleMap) {
|
|
524
|
+
const resolved = this.resolved.resolvedRoles.get(roleName);
|
|
525
|
+
const caps = resolved?.capabilities ?? [];
|
|
526
|
+
if (caps.includes(WORKSPACE_CAPABILITIES.INTEGRATE)) {
|
|
527
|
+
try {
|
|
528
|
+
this.services.agentManager.prompt(agentId, `Merge request ${event.data?.mrId} submitted ` +
|
|
529
|
+
`by worker ${event.data?.workerAgentId} ` +
|
|
530
|
+
`for branch ${event.data?.workerBranch}. ` +
|
|
531
|
+
`Process the merge queue.`);
|
|
532
|
+
}
|
|
533
|
+
catch {
|
|
534
|
+
// Best-effort wake
|
|
535
|
+
}
|
|
536
|
+
break;
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
});
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
catch {
|
|
543
|
+
// Merge queue not available — workspace isolation without merge queue
|
|
544
|
+
}
|
|
545
|
+
// Poll EventStore for MERGE_REQUEST signals from worker subprocesses.
|
|
546
|
+
// Workers in MCP subprocess emit to shared SQLite; main process must reload to see them.
|
|
547
|
+
this.startMergeRequestPolling();
|
|
548
|
+
}
|
|
549
|
+
/**
|
|
550
|
+
* Poll EventStore for MERGE_REQUEST signals emitted by worker subprocesses.
|
|
551
|
+
*
|
|
552
|
+
* Workers call done() in their MCP subprocess, which emits MERGE_REQUEST to
|
|
553
|
+
* the shared EventStore. This polling picks up those signals and submits to
|
|
554
|
+
* the merge queue on the main server.
|
|
555
|
+
*/
|
|
556
|
+
startMergeRequestPolling() {
|
|
557
|
+
const { workspaceManager, eventStore } = this.services;
|
|
558
|
+
if (!workspaceManager || !this.teamStreamId)
|
|
559
|
+
return;
|
|
560
|
+
const mergeQueue = workspaceManager.getMergeQueue();
|
|
561
|
+
if (!mergeQueue)
|
|
562
|
+
return;
|
|
563
|
+
this.mergeRequestPollTimer = setInterval(async () => {
|
|
564
|
+
try {
|
|
565
|
+
// Reload to see events written by subprocesses
|
|
566
|
+
if (eventStore.reload) {
|
|
567
|
+
await eventStore.reload();
|
|
568
|
+
}
|
|
569
|
+
const events = eventStore.query({ type: "status", limit: 100 });
|
|
570
|
+
for (const event of events) {
|
|
571
|
+
// Skip already-processed events
|
|
572
|
+
if (event.timestamp <= this.lastMergeRequestSeen)
|
|
573
|
+
continue;
|
|
574
|
+
const details = event.payload?.details;
|
|
575
|
+
if (details?.signal !== "MERGE_REQUEST")
|
|
576
|
+
continue;
|
|
577
|
+
// Check this agent belongs to our team
|
|
578
|
+
const sourceAgentId = event.source?.agent_id;
|
|
579
|
+
if (!sourceAgentId)
|
|
580
|
+
continue;
|
|
581
|
+
// Check if agent is a team member OR a child of a team member
|
|
582
|
+
const isTeamMember = this.agentRoleMap.has(sourceAgentId);
|
|
583
|
+
const parentAgent = eventStore.getAgent(sourceAgentId);
|
|
584
|
+
const isChildOfTeamMember = parentAgent?.parent
|
|
585
|
+
? this.agentRoleMap.has(parentAgent.parent)
|
|
586
|
+
: false;
|
|
587
|
+
if (!isTeamMember && !isChildOfTeamMember)
|
|
588
|
+
continue;
|
|
589
|
+
this.lastMergeRequestSeen = event.timestamp;
|
|
590
|
+
// Extract merge request details
|
|
591
|
+
const sourceBranch = details.sourceBranch;
|
|
592
|
+
const taskId = details.taskId;
|
|
593
|
+
const workerId = details.workerId;
|
|
594
|
+
if (!sourceBranch || !workerId)
|
|
595
|
+
continue;
|
|
596
|
+
// Submit to merge queue
|
|
597
|
+
try {
|
|
598
|
+
mergeQueue.submit({
|
|
599
|
+
streamId: this.teamStreamId,
|
|
600
|
+
taskId: taskId ?? `task-${workerId}`,
|
|
601
|
+
workerBranch: sourceBranch,
|
|
602
|
+
workerAgentId: workerId,
|
|
603
|
+
});
|
|
604
|
+
}
|
|
605
|
+
catch {
|
|
606
|
+
// Already submitted or other error — best-effort
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
catch {
|
|
611
|
+
// Best-effort polling
|
|
612
|
+
}
|
|
613
|
+
}, 2000);
|
|
614
|
+
if (this.mergeRequestPollTimer.unref) {
|
|
615
|
+
this.mergeRequestPollTimer.unref();
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
// ─────────────────────────────────────────────────────────────
|
|
270
619
|
// Spawn Interceptor
|
|
271
620
|
// ─────────────────────────────────────────────────────────────
|
|
272
621
|
/**
|
|
273
|
-
* Create the spawn interceptor that injects team context into spawn options.
|
|
622
|
+
* Internal: Create the spawn interceptor that injects team context into spawn options.
|
|
274
623
|
*/
|
|
275
|
-
|
|
624
|
+
_createSpawnInterceptor() {
|
|
276
625
|
return (options) => {
|
|
277
626
|
const roleName = options.role;
|
|
278
627
|
if (!roleName)
|
|
279
628
|
return options;
|
|
280
|
-
const resolved = this.
|
|
629
|
+
const resolved = this.resolved.resolvedRoles.get(roleName);
|
|
281
630
|
if (!resolved)
|
|
282
631
|
return options; // Unknown role — pass through
|
|
283
632
|
// Compute topics from communication topology
|
|
@@ -295,8 +644,32 @@ export class TeamRuntime {
|
|
|
295
644
|
if (strategyName) {
|
|
296
645
|
teamEnv.MACRO_INTEGRATION_STRATEGY = strategyName;
|
|
297
646
|
}
|
|
647
|
+
// Task backend config is propagated by AgentManager.buildMacroAgentMcp()
|
|
648
|
+
// from its taskBackend/openTasksSocketPath config options.
|
|
649
|
+
// Inject workspace fields based on capabilities (never overwrite explicit values)
|
|
650
|
+
const capabilities = resolved.capabilities;
|
|
651
|
+
let streamId = options.streamId;
|
|
652
|
+
let streamConfig = options.streamConfig;
|
|
653
|
+
let dataplaneTaskId = options.dataplaneTaskId;
|
|
654
|
+
if (this.teamStreamId && capabilities) {
|
|
655
|
+
if (capabilities.includes(WORKSPACE_CAPABILITIES.WORKTREE)) {
|
|
656
|
+
streamId = streamId ?? this.teamStreamId;
|
|
657
|
+
// Pull-mode workers use agentId as workspace identifier (one worktree per lifetime)
|
|
658
|
+
dataplaneTaskId = dataplaneTaskId ?? `worker-${Date.now()}`;
|
|
659
|
+
}
|
|
660
|
+
else if (capabilities.includes(WORKSPACE_CAPABILITIES.INTEGRATE)) {
|
|
661
|
+
streamId = streamId ?? this.teamStreamId;
|
|
662
|
+
}
|
|
663
|
+
// workspace.stream: stream creation is managed by TeamRuntime.setupWorkspaceIntegration(),
|
|
664
|
+
// not auto-injected. Coordinators that need sub-streams pass explicit streamConfig.
|
|
665
|
+
}
|
|
298
666
|
return {
|
|
299
667
|
...options,
|
|
668
|
+
// Workspace fields
|
|
669
|
+
streamId,
|
|
670
|
+
streamConfig,
|
|
671
|
+
dataplaneTaskId,
|
|
672
|
+
capabilities: capabilities ?? options.capabilities,
|
|
300
673
|
// Merge topics
|
|
301
674
|
topics: [
|
|
302
675
|
...(options.topics ?? []),
|
|
@@ -334,7 +707,7 @@ export class TeamRuntime {
|
|
|
334
707
|
*/
|
|
335
708
|
getTopicsForRole(roleName) {
|
|
336
709
|
const topics = [];
|
|
337
|
-
const subs = this.
|
|
710
|
+
const subs = this.communication.subscriptions?.[roleName] ?? [];
|
|
338
711
|
for (const sub of subs) {
|
|
339
712
|
// Channel name becomes the topic name
|
|
340
713
|
if (!topics.includes(sub.channel)) {
|
|
@@ -347,16 +720,16 @@ export class TeamRuntime {
|
|
|
347
720
|
* Get MCP servers configured for a role.
|
|
348
721
|
*/
|
|
349
722
|
getMcpServersForRole(roleName) {
|
|
350
|
-
return this.
|
|
723
|
+
return this.resolved.template.mcpServers.get(roleName) ?? [];
|
|
351
724
|
}
|
|
352
725
|
/**
|
|
353
726
|
* Get the loaded prompt content for a role.
|
|
354
727
|
*/
|
|
355
728
|
getPromptForRole(roleName) {
|
|
356
|
-
const resolved = this.
|
|
729
|
+
const resolved = this.resolved.resolvedRoles.get(roleName);
|
|
357
730
|
if (!resolved?.prompt)
|
|
358
731
|
return undefined;
|
|
359
|
-
return this.
|
|
732
|
+
return this.loadedPrompts.get(resolved.prompt);
|
|
360
733
|
}
|
|
361
734
|
/**
|
|
362
735
|
* Get the prompt for a topology node (root or companion).
|
|
@@ -364,7 +737,7 @@ export class TeamRuntime {
|
|
|
364
737
|
getPromptForTopologyNode(node) {
|
|
365
738
|
// Prefer topology-level prompt reference
|
|
366
739
|
if (node.prompt) {
|
|
367
|
-
return this.
|
|
740
|
+
return this.loadedPrompts.get(node.prompt);
|
|
368
741
|
}
|
|
369
742
|
// Fall back to role-level prompt
|
|
370
743
|
return this.getPromptForRole(node.role);
|
|
@@ -376,7 +749,7 @@ export class TeamRuntime {
|
|
|
376
749
|
const patterns = [];
|
|
377
750
|
const taskMode = this.getTaskMode();
|
|
378
751
|
if (taskMode === "pull") {
|
|
379
|
-
const pullConfig = this.
|
|
752
|
+
const pullConfig = this.resolved.macroAgent.task_assignment?.pull;
|
|
380
753
|
const idleTimeout = pullConfig?.idle_timeout_s ?? 300;
|
|
381
754
|
patterns.push(`## Task Claiming
|
|
382
755
|
|
|
@@ -407,24 +780,126 @@ Focus on correctness — your changes go live immediately.`);
|
|
|
407
780
|
return patterns;
|
|
408
781
|
}
|
|
409
782
|
// ─────────────────────────────────────────────────────────────
|
|
410
|
-
//
|
|
783
|
+
// Exposed Interceptor / Filter / Validator Factories
|
|
411
784
|
// ─────────────────────────────────────────────────────────────
|
|
412
785
|
/**
|
|
413
|
-
*
|
|
786
|
+
* Create the spawn interceptor for this team.
|
|
787
|
+
*
|
|
788
|
+
* Returns a function that injects team context (topics, MCP servers,
|
|
789
|
+
* env vars, prompt, interaction patterns) into spawn options.
|
|
790
|
+
* The caller (TeamManager or installOnServices) is responsible for
|
|
791
|
+
* installing it on AgentManager.
|
|
792
|
+
*/
|
|
793
|
+
createSpawnInterceptor() {
|
|
794
|
+
return this._createSpawnInterceptor();
|
|
795
|
+
}
|
|
796
|
+
/**
|
|
797
|
+
* Create the signal filter for this team.
|
|
414
798
|
*
|
|
415
799
|
* Combines two filter sources:
|
|
416
|
-
* 1. Channel subscription filters (per-role, per-topic)
|
|
417
|
-
* 2. Peer connection filters (per-agent-pair)
|
|
800
|
+
* 1. Channel subscription filters (per-role, per-topic)
|
|
801
|
+
* 2. Peer connection filters (per-agent-pair)
|
|
418
802
|
*
|
|
419
|
-
*
|
|
803
|
+
* Must be called after bootstrap() so that agentRoleMap and
|
|
804
|
+
* peerSignalFilters are populated. Returns null if no filtering needed.
|
|
420
805
|
*/
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
806
|
+
createSignalFilter() {
|
|
807
|
+
return (from, to, signal) => {
|
|
808
|
+
// Untagged status events always pass through
|
|
809
|
+
if (!signal)
|
|
810
|
+
return true;
|
|
811
|
+
// Check peer connection filter (directional: from→to)
|
|
812
|
+
const peerFilter = this.peerSignalFilters.get(`${from}→${to}`);
|
|
813
|
+
if (peerFilter) {
|
|
814
|
+
return peerFilter.includes(signal);
|
|
815
|
+
}
|
|
816
|
+
// Check channel subscription filter for recipient's role
|
|
817
|
+
const recipientRole = this.agentRoleMap.get(to);
|
|
818
|
+
if (recipientRole) {
|
|
819
|
+
const allowed = this.roleAllowedSignals.get(recipientRole);
|
|
820
|
+
if (allowed && allowed !== "all") {
|
|
821
|
+
return allowed.has(signal);
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
// No filter configured — allow delivery
|
|
825
|
+
return true;
|
|
826
|
+
};
|
|
827
|
+
}
|
|
828
|
+
/**
|
|
829
|
+
* Create the emission validator for this team.
|
|
830
|
+
*
|
|
831
|
+
* Checks whether an agent's emitted signal is in its role's allowed
|
|
832
|
+
* emissions list. Behavior depends on enforcement mode.
|
|
833
|
+
* Returns null if no emissions config exists.
|
|
834
|
+
*/
|
|
835
|
+
createEmissionValidator() {
|
|
836
|
+
const emissions = this.communication.emissions;
|
|
837
|
+
const enforcement = this.communication.enforcement ?? "permissive";
|
|
838
|
+
// No emissions config — nothing to enforce
|
|
839
|
+
if (!emissions || Object.keys(emissions).length === 0)
|
|
840
|
+
return null;
|
|
841
|
+
return (agentId, signal) => {
|
|
842
|
+
// Untagged status events are always allowed
|
|
843
|
+
if (!signal)
|
|
844
|
+
return { action: "allow" };
|
|
845
|
+
const role = this.agentRoleMap.get(agentId);
|
|
846
|
+
if (!role)
|
|
847
|
+
return { action: "allow" };
|
|
848
|
+
const allowedSignals = emissions[role];
|
|
849
|
+
if (!allowedSignals)
|
|
850
|
+
return { action: "allow" };
|
|
851
|
+
if (allowedSignals.includes(signal)) {
|
|
852
|
+
return { action: "allow" };
|
|
853
|
+
}
|
|
854
|
+
// Signal not in allowed list — enforce
|
|
855
|
+
const message = `Agent '${agentId}' (role: ${role}) emitted disallowed signal '${signal}'. Allowed: [${allowedSignals.join(", ")}]`;
|
|
856
|
+
switch (enforcement) {
|
|
857
|
+
case "strict":
|
|
858
|
+
return { action: "reject", message };
|
|
859
|
+
case "audit":
|
|
860
|
+
return { action: "audit", message };
|
|
861
|
+
case "permissive":
|
|
862
|
+
default:
|
|
863
|
+
return { action: "warn", message };
|
|
864
|
+
}
|
|
865
|
+
};
|
|
866
|
+
}
|
|
867
|
+
/**
|
|
868
|
+
* Convenience method: install interceptor, signal filter, and emission
|
|
869
|
+
* validator directly on the shared services.
|
|
870
|
+
*
|
|
871
|
+
* Use this for standalone operation (without TeamManager).
|
|
872
|
+
* TeamManager uses the individual create* methods for composite dispatch.
|
|
873
|
+
*/
|
|
874
|
+
installOnServices() {
|
|
875
|
+
const { agentManager, messageRouter } = this.services;
|
|
876
|
+
agentManager.setSpawnInterceptor(this.createSpawnInterceptor());
|
|
877
|
+
const signalFilter = this.createSignalFilter();
|
|
878
|
+
if (signalFilter && messageRouter.setSignalFilter) {
|
|
879
|
+
messageRouter.setSignalFilter(signalFilter);
|
|
880
|
+
}
|
|
881
|
+
const emissionValidator = this.createEmissionValidator();
|
|
882
|
+
if (emissionValidator && messageRouter.setEmissionValidator) {
|
|
883
|
+
messageRouter.setEmissionValidator(emissionValidator);
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
/**
|
|
887
|
+
* Convenience method: uninstall interceptor and filters from services.
|
|
888
|
+
* Use on teardown for standalone operation.
|
|
889
|
+
*/
|
|
890
|
+
uninstallFromServices() {
|
|
891
|
+
this.services.agentManager.setSpawnInterceptor(null);
|
|
892
|
+
}
|
|
893
|
+
// ─────────────────────────────────────────────────────────────
|
|
894
|
+
// Internal: Pre-compute role allowed signals
|
|
895
|
+
// ─────────────────────────────────────────────────────────────
|
|
896
|
+
/**
|
|
897
|
+
* Pre-compute per-role allowed signals from channel subscriptions.
|
|
898
|
+
* Called during bootstrap() so createSignalFilter() can use the result.
|
|
899
|
+
*/
|
|
900
|
+
computeRoleAllowedSignals() {
|
|
901
|
+
this.roleAllowedSignals.clear();
|
|
902
|
+
for (const [roleName, subs] of Object.entries(this.communication.subscriptions ?? {})) {
|
|
428
903
|
let allowed = new Set();
|
|
429
904
|
for (const sub of subs) {
|
|
430
905
|
if (!sub.signals || sub.signals.length === 0) {
|
|
@@ -436,72 +911,7 @@ Focus on correctness — your changes go live immediately.`);
|
|
|
436
911
|
allowed.add(sig);
|
|
437
912
|
}
|
|
438
913
|
}
|
|
439
|
-
roleAllowedSignals.set(roleName, allowed);
|
|
440
|
-
}
|
|
441
|
-
if (messageRouter.setSignalFilter) {
|
|
442
|
-
messageRouter.setSignalFilter((from, to, signal) => {
|
|
443
|
-
// Untagged status events always pass through
|
|
444
|
-
if (!signal)
|
|
445
|
-
return true;
|
|
446
|
-
// Check peer connection filter (directional: from→to)
|
|
447
|
-
const peerFilter = this.peerSignalFilters.get(`${from}→${to}`);
|
|
448
|
-
if (peerFilter) {
|
|
449
|
-
return peerFilter.includes(signal);
|
|
450
|
-
}
|
|
451
|
-
// Check channel subscription filter for recipient's role
|
|
452
|
-
const recipientRole = this.agentRoleMap.get(to);
|
|
453
|
-
if (recipientRole) {
|
|
454
|
-
const allowed = roleAllowedSignals.get(recipientRole);
|
|
455
|
-
if (allowed && allowed !== "all") {
|
|
456
|
-
return allowed.has(signal);
|
|
457
|
-
}
|
|
458
|
-
}
|
|
459
|
-
// No filter configured — allow delivery
|
|
460
|
-
return true;
|
|
461
|
-
});
|
|
462
|
-
}
|
|
463
|
-
}
|
|
464
|
-
// ─────────────────────────────────────────────────────────────
|
|
465
|
-
// Emission Validation
|
|
466
|
-
// ─────────────────────────────────────────────────────────────
|
|
467
|
-
/**
|
|
468
|
-
* Install emission validator on the message router.
|
|
469
|
-
* Checks whether an agent's emitted signal is in its role's allowed emissions list.
|
|
470
|
-
* Behavior depends on enforcement mode: strict (reject), permissive (warn), audit (record).
|
|
471
|
-
*/
|
|
472
|
-
installEmissionValidator() {
|
|
473
|
-
const { messageRouter } = this.services;
|
|
474
|
-
const emissions = this.manifest.communication.emissions;
|
|
475
|
-
const enforcement = this.manifest.communication.enforcement ?? "permissive";
|
|
476
|
-
// No emissions config — nothing to enforce
|
|
477
|
-
if (!emissions || Object.keys(emissions).length === 0)
|
|
478
|
-
return;
|
|
479
|
-
if (messageRouter.setEmissionValidator) {
|
|
480
|
-
messageRouter.setEmissionValidator((agentId, signal) => {
|
|
481
|
-
// Untagged status events are always allowed
|
|
482
|
-
if (!signal)
|
|
483
|
-
return { action: "allow" };
|
|
484
|
-
const role = this.agentRoleMap.get(agentId);
|
|
485
|
-
if (!role)
|
|
486
|
-
return { action: "allow" };
|
|
487
|
-
const allowedSignals = emissions[role];
|
|
488
|
-
if (!allowedSignals)
|
|
489
|
-
return { action: "allow" };
|
|
490
|
-
if (allowedSignals.includes(signal)) {
|
|
491
|
-
return { action: "allow" };
|
|
492
|
-
}
|
|
493
|
-
// Signal not in allowed list — enforce
|
|
494
|
-
const message = `Agent '${agentId}' (role: ${role}) emitted disallowed signal '${signal}'. Allowed: [${allowedSignals.join(", ")}]`;
|
|
495
|
-
switch (enforcement) {
|
|
496
|
-
case "strict":
|
|
497
|
-
return { action: "reject", message };
|
|
498
|
-
case "audit":
|
|
499
|
-
return { action: "audit", message };
|
|
500
|
-
case "permissive":
|
|
501
|
-
default:
|
|
502
|
-
return { action: "warn", message };
|
|
503
|
-
}
|
|
504
|
-
});
|
|
914
|
+
this.roleAllowedSignals.set(roleName, allowed);
|
|
505
915
|
}
|
|
506
916
|
}
|
|
507
917
|
// ─────────────────────────────────────────────────────────────
|
|
@@ -512,7 +922,7 @@ Focus on correctness — your changes go live immediately.`);
|
|
|
512
922
|
* Falls back to legacy bidirectional subtree subs when no peers config exists.
|
|
513
923
|
*/
|
|
514
924
|
wirePeerRoutes() {
|
|
515
|
-
const peers = this.
|
|
925
|
+
const peers = this.communication.routing?.peers;
|
|
516
926
|
if (!peers || peers.length === 0) {
|
|
517
927
|
// Fallback: hardcoded mutual subtree subscriptions (backwards compat)
|
|
518
928
|
this.setupLegacyPeerSubscriptions();
|