macro-agent 0.0.17 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/settings.local.json +3 -1
- package/.sudocode/specs.jsonl +4 -0
- package/CLAUDE.md +16 -14
- package/README.md +11 -29
- package/dist/acp/macro-agent.d.ts +17 -0
- package/dist/acp/macro-agent.d.ts.map +1 -1
- package/dist/acp/macro-agent.js +183 -55
- package/dist/acp/macro-agent.js.map +1 -1
- package/dist/acp/types.d.ts +32 -1
- package/dist/acp/types.d.ts.map +1 -1
- package/dist/acp/types.js.map +1 -1
- package/dist/agent/agent-manager.d.ts +65 -1
- package/dist/agent/agent-manager.d.ts.map +1 -1
- package/dist/agent/agent-manager.js +464 -183
- package/dist/agent/agent-manager.js.map +1 -1
- package/dist/agent/types.d.ts +1 -1
- package/dist/agent/types.d.ts.map +1 -1
- package/dist/api/server.d.ts +3 -0
- package/dist/api/server.d.ts.map +1 -1
- package/dist/api/server.js +37 -6
- package/dist/api/server.js.map +1 -1
- package/dist/auth/index.d.ts +2 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +2 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/token.d.ts +41 -0
- package/dist/auth/token.d.ts.map +1 -0
- package/dist/auth/token.js +73 -0
- package/dist/auth/token.js.map +1 -0
- package/dist/cli/acp.d.ts +2 -23
- package/dist/cli/acp.d.ts.map +1 -1
- package/dist/cli/acp.js +127 -61
- package/dist/cli/acp.js.map +1 -1
- package/dist/cli/index.js +147 -15
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/mcp.d.ts +6 -0
- package/dist/cli/mcp.d.ts.map +1 -1
- package/dist/cli/mcp.js +268 -181
- package/dist/cli/mcp.js.map +1 -1
- package/dist/cli/parse-args.d.ts +20 -0
- package/dist/cli/parse-args.d.ts.map +1 -0
- package/dist/cli/parse-args.js +43 -0
- package/dist/cli/parse-args.js.map +1 -0
- package/dist/cli/stable-instance-id.d.ts +8 -0
- package/dist/cli/stable-instance-id.d.ts.map +1 -0
- package/dist/cli/stable-instance-id.js +14 -0
- package/dist/cli/stable-instance-id.js.map +1 -0
- package/dist/config/project-config.d.ts +74 -7
- package/dist/config/project-config.d.ts.map +1 -1
- package/dist/config/project-config.js +123 -20
- package/dist/config/project-config.js.map +1 -1
- package/dist/map/adapter/acp-over-map.d.ts +23 -0
- package/dist/map/adapter/acp-over-map.d.ts.map +1 -1
- package/dist/map/adapter/acp-over-map.js +482 -55
- package/dist/map/adapter/acp-over-map.js.map +1 -1
- package/dist/map/adapter/connection-manager.d.ts.map +1 -1
- package/dist/map/adapter/connection-manager.js +3 -0
- package/dist/map/adapter/connection-manager.js.map +1 -1
- package/dist/map/adapter/event-log.d.ts +87 -0
- package/dist/map/adapter/event-log.d.ts.map +1 -0
- package/dist/map/adapter/event-log.js +122 -0
- package/dist/map/adapter/event-log.js.map +1 -0
- package/dist/map/adapter/event-translator.js +6 -6
- package/dist/map/adapter/event-translator.js.map +1 -1
- package/dist/map/adapter/extensions/agent-lifecycle.d.ts +82 -0
- package/dist/map/adapter/extensions/agent-lifecycle.d.ts.map +1 -0
- package/dist/map/adapter/extensions/agent-lifecycle.js +164 -0
- package/dist/map/adapter/extensions/agent-lifecycle.js.map +1 -0
- package/dist/map/adapter/extensions/index.d.ts +10 -1
- package/dist/map/adapter/extensions/index.d.ts.map +1 -1
- package/dist/map/adapter/extensions/index.js +34 -0
- package/dist/map/adapter/extensions/index.js.map +1 -1
- package/dist/map/adapter/extensions/mcp-bridge.d.ts +57 -0
- package/dist/map/adapter/extensions/mcp-bridge.d.ts.map +1 -0
- package/dist/map/adapter/extensions/mcp-bridge.js +745 -0
- package/dist/map/adapter/extensions/mcp-bridge.js.map +1 -0
- package/dist/map/adapter/extensions/rename.d.ts +29 -0
- package/dist/map/adapter/extensions/rename.d.ts.map +1 -0
- package/dist/map/adapter/extensions/rename.js +49 -0
- package/dist/map/adapter/extensions/rename.js.map +1 -0
- package/dist/map/adapter/extensions/task.d.ts.map +1 -1
- package/dist/map/adapter/extensions/task.js +10 -0
- package/dist/map/adapter/extensions/task.js.map +1 -1
- package/dist/map/adapter/extensions/update-metadata.d.ts +29 -0
- package/dist/map/adapter/extensions/update-metadata.d.ts.map +1 -0
- package/dist/map/adapter/extensions/update-metadata.js +67 -0
- package/dist/map/adapter/extensions/update-metadata.js.map +1 -0
- package/dist/map/adapter/index.d.ts +2 -1
- package/dist/map/adapter/index.d.ts.map +1 -1
- package/dist/map/adapter/index.js +8 -2
- package/dist/map/adapter/index.js.map +1 -1
- package/dist/map/adapter/interface.d.ts +2 -0
- package/dist/map/adapter/interface.d.ts.map +1 -1
- package/dist/map/adapter/map-adapter.d.ts +4 -0
- package/dist/map/adapter/map-adapter.d.ts.map +1 -1
- package/dist/map/adapter/map-adapter.js +302 -30
- package/dist/map/adapter/map-adapter.js.map +1 -1
- package/dist/map/adapter/subscription-manager.d.ts.map +1 -1
- package/dist/map/adapter/subscription-manager.js +5 -1
- package/dist/map/adapter/subscription-manager.js.map +1 -1
- package/dist/map/adapter/types.d.ts +2 -0
- package/dist/map/adapter/types.d.ts.map +1 -1
- package/dist/mcp/map-client.d.ts +39 -0
- package/dist/mcp/map-client.d.ts.map +1 -0
- package/dist/mcp/map-client.js +129 -0
- package/dist/mcp/map-client.js.map +1 -0
- package/dist/mcp/mcp-server.d.ts +14 -0
- package/dist/mcp/mcp-server.d.ts.map +1 -1
- package/dist/mcp/mcp-server.js +113 -85
- package/dist/mcp/mcp-server.js.map +1 -1
- package/dist/mcp/types.d.ts +9 -1
- package/dist/mcp/types.d.ts.map +1 -1
- package/dist/mcp/types.js.map +1 -1
- package/dist/metrics/metrics.js +1 -1
- package/dist/metrics/metrics.js.map +1 -1
- package/dist/roles/capabilities.d.ts +3 -1
- package/dist/roles/capabilities.d.ts.map +1 -1
- package/dist/roles/capabilities.js +17 -7
- package/dist/roles/capabilities.js.map +1 -1
- package/dist/roles/config-loader.d.ts +6 -6
- package/dist/roles/config-loader.d.ts.map +1 -1
- package/dist/roles/config-loader.js +6 -6
- package/dist/roles/config-loader.js.map +1 -1
- package/dist/roles/registry.d.ts +2 -2
- package/dist/roles/registry.js +2 -2
- package/dist/server/combined-server.d.ts +20 -0
- package/dist/server/combined-server.d.ts.map +1 -1
- package/dist/server/combined-server.js +107 -8
- package/dist/server/combined-server.js.map +1 -1
- package/dist/store/event-store.d.ts +7 -1
- package/dist/store/event-store.d.ts.map +1 -1
- package/dist/store/event-store.js +91 -8
- package/dist/store/event-store.js.map +1 -1
- package/dist/store/types/agents.d.ts +23 -0
- package/dist/store/types/agents.d.ts.map +1 -1
- package/dist/store/types/events.d.ts +1 -1
- package/dist/store/types/events.d.ts.map +1 -1
- package/dist/task/backend/index.d.ts +47 -29
- package/dist/task/backend/index.d.ts.map +1 -1
- package/dist/task/backend/index.js +109 -71
- package/dist/task/backend/index.js.map +1 -1
- package/dist/task/backend/memory.d.ts +1 -0
- package/dist/task/backend/memory.d.ts.map +1 -1
- package/dist/task/backend/memory.js +3 -0
- package/dist/task/backend/memory.js.map +1 -1
- package/dist/task/backend/opentasks/backend.d.ts +140 -0
- package/dist/task/backend/opentasks/backend.d.ts.map +1 -0
- package/dist/task/backend/opentasks/backend.js +1023 -0
- package/dist/task/backend/opentasks/backend.js.map +1 -0
- package/dist/task/backend/opentasks/client.d.ts +337 -0
- package/dist/task/backend/opentasks/client.d.ts.map +1 -0
- package/dist/task/backend/opentasks/client.js +225 -0
- package/dist/task/backend/opentasks/client.js.map +1 -0
- package/dist/task/backend/opentasks/daemon-manager.d.ts +89 -0
- package/dist/task/backend/opentasks/daemon-manager.d.ts.map +1 -0
- package/dist/task/backend/opentasks/daemon-manager.js +195 -0
- package/dist/task/backend/opentasks/daemon-manager.js.map +1 -0
- package/dist/task/backend/opentasks/index.d.ts +21 -0
- package/dist/task/backend/opentasks/index.d.ts.map +1 -0
- package/dist/task/backend/opentasks/index.js +21 -0
- package/dist/task/backend/opentasks/index.js.map +1 -0
- package/dist/task/backend/opentasks/mapping.d.ts +48 -0
- package/dist/task/backend/opentasks/mapping.d.ts.map +1 -0
- package/dist/task/backend/opentasks/mapping.js +77 -0
- package/dist/task/backend/opentasks/mapping.js.map +1 -0
- package/dist/task/backend/types.d.ts +33 -53
- package/dist/task/backend/types.d.ts.map +1 -1
- package/dist/task/backend/types.js +7 -11
- package/dist/task/backend/types.js.map +1 -1
- package/dist/task/backend/unified-tool-provider.d.ts +57 -0
- package/dist/task/backend/unified-tool-provider.d.ts.map +1 -0
- package/dist/task/backend/unified-tool-provider.js +623 -0
- package/dist/task/backend/unified-tool-provider.js.map +1 -0
- package/dist/teams/team-loader.d.ts +2 -2
- package/dist/teams/team-loader.js +3 -3
- package/dist/teams/team-loader.js.map +1 -1
- package/dist/teams/team-runtime.d.ts.map +1 -1
- package/dist/teams/team-runtime.js +2 -0
- package/dist/teams/team-runtime.js.map +1 -1
- package/docs/architecture.md +7 -6
- package/docs/configuration.md +26 -62
- package/docs/implementation-details.md +5 -5
- package/docs/implementation-summary.md +17 -17
- package/docs/plan-self-driving-support.md +4 -4
- package/docs/spec-self-driving-support.md +10 -10
- package/docs/team-templates.md +2 -2
- package/docs/teams.md +3 -3
- package/docs/troubleshooting.md +10 -11
- package/package.json +6 -4
- package/src/__tests__/e2e/agent-spawn-visibility.e2e.test.ts +761 -0
- package/src/__tests__/e2e/full-agent-conflict-resolution.e2e.test.ts +2 -2
- package/src/__tests__/e2e/mcp-thin-client-bridge.e2e.test.ts +304 -0
- package/src/__tests__/e2e/mcp-tools-available.e2e.test.ts +324 -0
- package/src/__tests__/e2e/multi-agent.e2e.test.ts +5 -5
- package/src/__tests__/e2e/spawn-session-streaming.e2e.test.ts +563 -0
- package/src/acp/__tests__/history.test.ts +8 -4
- package/src/acp/__tests__/integration.test.ts +56 -31
- package/src/acp/__tests__/macro-agent.test.ts +16 -7
- package/src/acp/macro-agent.ts +230 -62
- package/src/acp/types.ts +46 -1
- package/src/agent/__tests__/agent-manager.test.ts +228 -2
- package/src/agent/agent-manager.ts +714 -261
- package/src/agent/types.ts +3 -1
- package/src/api/server.ts +41 -7
- package/src/auth/__tests__/token.test.ts +100 -0
- package/src/auth/index.ts +1 -0
- package/src/auth/token.ts +82 -0
- package/src/cli/__tests__/acp.test.ts +1 -1
- package/src/cli/__tests__/stable-instance-id.test.ts +1 -1
- package/src/cli/acp.ts +130 -72
- package/src/cli/index.ts +120 -14
- package/src/cli/mcp.ts +311 -207
- package/src/cli/parse-args.ts +54 -0
- package/src/cli/stable-instance-id.ts +14 -0
- package/src/config/project-config.ts +190 -27
- package/src/lifecycle/__tests__/cascade-termination.test.ts +1 -1
- package/src/map/adapter/__tests__/acp-over-map-cancel.test.ts +820 -0
- package/src/map/adapter/__tests__/acp-over-map-getmodels.test.ts +355 -0
- package/src/map/adapter/__tests__/acp-over-map-history.test.ts +724 -2
- package/src/map/adapter/__tests__/acp-over-map-persistence.e2e.test.ts +1 -1
- package/src/map/adapter/__tests__/event-broadcast.test.ts +420 -0
- package/src/map/adapter/__tests__/event-log.test.ts +527 -0
- package/src/map/adapter/__tests__/event-translator.test.ts +3 -3
- package/src/map/adapter/__tests__/extensions.test.ts +408 -0
- package/src/map/adapter/__tests__/map-adapter.test.ts +99 -0
- package/src/map/adapter/__tests__/mcp-bridge.test.ts +1187 -0
- package/src/map/adapter/__tests__/multi-client-broadcast.test.ts +711 -0
- package/src/map/adapter/__tests__/websocket-integration.test.ts +218 -0
- package/src/map/adapter/acp-over-map.ts +777 -92
- package/src/map/adapter/connection-manager.ts +3 -0
- package/src/map/adapter/event-log.ts +208 -0
- package/src/map/adapter/event-translator.ts +6 -6
- package/src/map/adapter/extensions/agent-lifecycle.ts +267 -0
- package/src/map/adapter/extensions/index.ts +60 -0
- package/src/map/adapter/extensions/mcp-bridge.ts +995 -0
- package/src/map/adapter/extensions/task.ts +11 -0
- package/src/map/adapter/extensions/update-metadata.ts +126 -0
- package/src/map/adapter/index.ts +28 -0
- package/src/map/adapter/interface.ts +2 -0
- package/src/map/adapter/map-adapter.ts +373 -38
- package/src/map/adapter/subscription-manager.ts +5 -1
- package/src/map/adapter/types.ts +2 -0
- package/src/mcp/__tests__/map-client.test.ts +386 -0
- package/src/mcp/__tests__/mcp-server-thin-client.test.ts +368 -0
- package/src/mcp/__tests__/mcp-server.test.ts +100 -1
- package/src/mcp/map-client.ts +177 -0
- package/src/mcp/mcp-server.ts +191 -100
- package/src/mcp/types.ts +6 -1
- package/src/metrics/metrics.ts +1 -1
- package/src/monitor/__tests__/stale-agent-flow.integration.test.ts +1 -1
- package/src/roles/__tests__/config-loader.test.ts +7 -7
- package/src/roles/capabilities.ts +17 -7
- package/src/roles/config-loader.ts +6 -6
- package/src/roles/registry.ts +2 -2
- package/src/server/__tests__/combined-server.test.ts +94 -21
- package/src/server/combined-server.ts +189 -33
- package/src/steering/__tests__/steering-integration.test.ts +1 -1
- package/src/store/__tests__/event-store.test.ts +236 -1
- package/src/store/__tests__/instance.test.ts +3 -3
- package/src/store/event-store.ts +109 -8
- package/src/store/types/agents.ts +16 -0
- package/src/store/types/events.ts +1 -1
- package/src/task/backend/__tests__/create-task-backend.test.ts +225 -0
- package/src/task/backend/__tests__/e2e/unified-tool-provider-opentasks.e2e.test.ts +524 -0
- package/src/task/backend/__tests__/unified-tool-provider.test.ts +579 -0
- package/src/task/backend/index.ts +156 -106
- package/src/task/backend/memory.ts +4 -0
- package/src/task/backend/opentasks/__tests__/backend.test.ts +968 -0
- package/src/task/backend/opentasks/__tests__/daemon-manager.test.ts +406 -0
- package/src/task/backend/opentasks/__tests__/mapping.test.ts +84 -0
- package/src/task/backend/opentasks/__tests__/opentasks-backend.e2e.test.ts +1338 -0
- package/src/task/backend/opentasks/backend.ts +1323 -0
- package/src/task/backend/opentasks/client.ts +652 -0
- package/src/task/backend/opentasks/daemon-manager.ts +253 -0
- package/src/task/backend/opentasks/index.ts +69 -0
- package/src/task/backend/opentasks/mapping.ts +94 -0
- package/src/task/backend/types.ts +42 -66
- package/src/task/backend/unified-tool-provider.ts +779 -0
- package/src/teams/__tests__/cross-subsystem.integration.test.ts +1 -1
- package/src/teams/team-loader.ts +3 -3
- package/src/teams/team-runtime.ts +2 -0
- package/test_fixtures/README.md +2 -3
- package/test_fixtures/fixtures/index.ts +0 -3
- package/test_fixtures/fixtures/projects/project-with-specs.ts +7 -149
- package/test_fixtures/fixtures/repos/index.ts +1 -3
- package/test_fixtures/fixtures/repos/temp-repo-factory.ts +0 -116
- package/test_fixtures/fixtures/repos/types.ts +0 -11
- package/test_fixtures/harness/__tests__/fixtures.test.ts +10 -102
- package/test_fixtures/harness/__tests__/temp-repo-and-simulator.test.ts +0 -33
- package/test_fixtures/harness/simulator/agent-simulator.ts +4 -4
- package/vitest.config.ts +1 -1
- package/vitest.e2e.config.ts +1 -1
- package/vitest.setup.ts +1 -30
- package/.macro-agent/teams/self-driving/prompts/grinder.md +0 -27
- package/.macro-agent/teams/self-driving/prompts/judge.md +0 -27
- package/.macro-agent/teams/self-driving/prompts/planner.md +0 -33
- package/.macro-agent/teams/self-driving/roles/grinder.yaml +0 -17
- package/.macro-agent/teams/self-driving/roles/judge.yaml +0 -24
- package/.macro-agent/teams/self-driving/roles/planner.yaml +0 -18
- package/.macro-agent/teams/self-driving/team.yaml +0 -103
- package/.macro-agent/teams/structured/prompts/developer.md +0 -26
- package/.macro-agent/teams/structured/prompts/lead.md +0 -25
- package/.macro-agent/teams/structured/prompts/reviewer.md +0 -24
- package/.macro-agent/teams/structured/roles/developer.yaml +0 -12
- package/.macro-agent/teams/structured/roles/lead.yaml +0 -11
- package/.macro-agent/teams/structured/roles/reviewer.yaml +0 -19
- package/.macro-agent/teams/structured/team.yaml +0 -89
- package/docs/sudocode-integration.md +0 -383
- package/src/task/backend/__tests__/backend-parity.test.ts +0 -451
- package/src/task/backend/__tests__/tool-provider-edge-cases.test.ts +0 -430
- package/src/task/backend/__tests__/tool-provider.test.ts +0 -983
- package/src/task/backend/sudocode/__tests__/backend-edge-cases.test.ts +0 -575
- package/src/task/backend/sudocode/__tests__/backend.test.ts +0 -1194
- package/src/task/backend/sudocode/__tests__/client-integration.test.ts +0 -418
- package/src/task/backend/sudocode/__tests__/client.test.ts +0 -345
- package/src/task/backend/sudocode/__tests__/e2e/backend.e2e.test.ts +0 -753
- package/src/task/backend/sudocode/__tests__/e2e/server-client.e2e.test.ts +0 -680
- package/src/task/backend/sudocode/__tests__/e2e-workflow.test.ts +0 -666
- package/src/task/backend/sudocode/__tests__/integration/standalone-client.integration.test.ts +0 -396
- package/src/task/backend/sudocode/__tests__/integration/sudocode-cli.integration.test.ts +0 -328
- package/src/task/backend/sudocode/__tests__/integration/test-utils.ts +0 -175
- package/src/task/backend/sudocode/__tests__/mapping-edge-cases.test.ts +0 -265
- package/src/task/backend/sudocode/__tests__/server-client.test.ts +0 -675
- package/src/task/backend/sudocode/__tests__/sync-policy-edge-cases.test.ts +0 -521
- package/src/task/backend/sudocode/__tests__/sync-policy.test.ts +0 -519
- package/src/task/backend/sudocode/__tests__/tools.test.ts +0 -471
- package/src/task/backend/sudocode/backend.ts +0 -1237
- package/src/task/backend/sudocode/client.ts +0 -515
- package/src/task/backend/sudocode/index.ts +0 -120
- package/src/task/backend/sudocode/mapping.ts +0 -93
- package/src/task/backend/sudocode/server-client.ts +0 -522
- package/src/task/backend/sudocode/standalone-client.ts +0 -623
- package/src/task/backend/sudocode/sync-policy.ts +0 -387
- package/src/task/backend/sudocode/tools.ts +0 -896
- package/src/task/backend/tool-provider.ts +0 -506
- package/test_fixtures/fixtures/sudocode/index.ts +0 -29
- package/test_fixtures/fixtures/sudocode/issues.ts +0 -185
- package/test_fixtures/fixtures/sudocode/specs.ts +0 -159
package/.sudocode/specs.jsonl
CHANGED
|
@@ -46,3 +46,7 @@
|
|
|
46
46
|
{"id":"s-5w36","uuid":"2e027264-1fcb-4943-bab6-4b2e35a5c2a0","title":"Session Continuations (Phase 4)","file_path":"specs/s-5w36_session_continuations_phase_4.md","content":"\n# Session Continuations (Phase 4)\n\nPersist agent session history so long-running agents can be resumed across process restarts.\n\n## Status: COMPLETE (untested continuation monitoring)\n\n## Components\n\n### continueAgent() (`src/agent/agent-manager.ts`, lines 1384-1450)\n1. Load original agent from EventStore\n2. Query status events (up to `maxMessages`, default 50)\n3. Format event summaries as \"Prior Session Context\" markdown\n4. Spawn new agent with same role/parent + resume context as `customPrompt`\n5. Emit continuation event (`continuation_of: agentId`)\n\n```typescript\ninterface ContinueAgentOptions {\n maxMessages?: number; // History depth (default: 50)\n task?: string; // Override task description\n additionalContext?: string; // Extra context to prepend\n}\n```\n\n### Continuation monitoring (`src/teams/team-runtime.ts`)\n- `monitorContinuations()` watches agent lifecycle events via `onLifecycleEvent()`\n- Monitors root and companion agent IDs\n- On unexpected stop (not \"completed\" or \"cancelled\"): wait 1s → `continueAgent()` → update tracking\n- Only active when `lifecycle.continuations.enabled === true` in team manifest\n- Unsubscribes on teardown\n\n## Known Gap\n- **No test coverage** for `monitorContinuations()` — edge cases untested (multiple lifecycle events, spawn failure, state consistency)\n","priority":1,"archived":0,"archived_at":null,"created_at":"2026-02-07 21:26:08","updated_at":"2026-02-07 21:26:08","parent_id":"s-1z9o","parent_uuid":"251030e1-ea2a-4857-95b3-2d94619f0b69","relationships":[{"from":"s-5w36","from_type":"spec","to":"s-1z9o","to_type":"spec","type":"implements"}],"tags":["continuations","phase-4","self-driving","teams"]}
|
|
47
47
|
{"id":"s-ir97","uuid":"9d8a27cd-2a68-4664-8384-a5c1bb657f71","title":"Autonomous Observability (Phase 5)","file_path":"specs/s-ir97_autonomous_observability_phase_5.md","content":"\n# Autonomous Observability (Phase 5)\n\nMetrics primitives for monitoring throughput, error rates, and agent utilization during long-running multi-agent runs.\n\n## Status: COMPLETE\n\n## Components\n\n### Metrics functions (`src/metrics/metrics.ts`, 280 LOC)\n\n| Function | Queries | Returns |\n|----------|---------|---------|\n| `getThroughputMetrics(store, windowMs)` | Task events | tasksCompleted, tasksFailed, tasksCreated, completedPerMinute, avgCompletionTimeMs |\n| `getUtilizationMetrics(store, windowMs)` | Agent spawn/terminate | activeAgents, totalSpawned, totalStopped, agentsByRole, agentsByState |\n| `getErrorMetrics(store, windowMs, limit)` | Failed status + task events | totalErrors, errorsByType, recentErrors |\n\nAll functions query EventStore directly — no new event types or materialized views needed.\n\n### REST API endpoints (`src/api/server.ts`)\n\n| Endpoint | Query Params | Description |\n|----------|-------------|-------------|\n| `GET /api/metrics/throughput` | `window_ms` (default: 5min) | Task completion rates |\n| `GET /api/metrics/utilization` | — | Agent counts by role and state |\n| `GET /api/metrics/errors` | `window_ms` (default: 30min), `limit` (default: 20) | Error counts and recent failures |\n","priority":1,"archived":0,"archived_at":null,"created_at":"2026-02-07 21:26:16","updated_at":"2026-02-07 21:26:16","parent_id":"s-1z9o","parent_uuid":"251030e1-ea2a-4857-95b3-2d94619f0b69","relationships":[{"from":"s-ir97","from_type":"spec","to":"s-1z9o","to_type":"spec","type":"implements"}],"tags":["metrics","phase-5","self-driving","teams"]}
|
|
48
48
|
{"id":"s-29pg","uuid":"7e8bbb6d-51df-403b-8929-5b2793603367","title":"Communication Topology Gaps","file_path":"specs/s-29pg_communication_topology_gaps.md","content":"\n# Communication Topology Gaps\n\nFeatures where YAML config was loaded and validated but not wired into runtime behavior. Identified in the post-implementation audit.\n\n## Status: COMPLETE\n\nAll 5 gaps resolved. Implementation feedback attached to each closed issue.\n\n## Gap 1: Signal Filtering — IMPLEMENTED\n\n**Issue**: `i-3o8g` (closed)\n\n`SignalFilter` callback on MessageRouter, installed by TeamRuntime. Checks two sources:\n1. Peer connection filters (per-agent-pair, directional) from `routing.peers[].signals`\n2. Channel subscription filters (per-role) from `subscriptions[role][].signals`\n\nSignal name carried in `details.signal` field. Untagged events always pass through.\n\n## Gap 2: Peer Routing from Config — IMPLEMENTED\n\n**Issue**: `i-96f6` (closed)\n\n`wirePeerRoutes()` in TeamRuntime reads `routing.peers`, maps `via` to subscription type:\n- `direct` → subtree subscription (directional)\n- `topic` → shared named topic for both agents\n- `scope` → role-based subscription\n\nDeferred wiring for roles not spawned at bootstrap. Signal filters stored per-peer.\n\n## Gap 3: Wake Logic for Status Delivery — IMPLEMENTED\n\n**Issue**: `i-4dh7` (closed)\n\nBoth `routeStatusToSubtreeSubscribers()` and `routeStatusToTopicSubscribers()` now call `wakeHandler` with `priority: \"normal\"` (wakes idle agents, queues for busy).\n\n## Gap 4: Emission Restrictions — IMPLEMENTED\n\n**Issue**: `i-1zso` (closed)\n\n`EmissionValidator` callback on MessageRouter. Checks agent role against `communication.emissions` allowlist. Enforcement mode determines action.\n\n## Gap 5: Enforcement Mode — IMPLEMENTED\n\n**Issue**: `i-1zso` (closed)\n\nBranches on enforcement mode in emission validator:\n- `strict` → reject (block emission)\n- `permissive` → warn (allow through)\n- `audit` → record `emission_violation` event in EventStore, allow through\n","priority":2,"archived":0,"archived_at":null,"created_at":"2026-02-07 21:26:38","updated_at":"2026-02-09 08:17:22","parent_id":"s-1z9o","parent_uuid":"251030e1-ea2a-4857-95b3-2d94619f0b69","relationships":[{"from":"s-29pg","from_type":"spec","to":"s-1z9o","to_type":"spec","type":"implements"}],"tags":["communication","gaps","self-driving","teams"]}
|
|
49
|
+
{"id":"s-7umt","uuid":"d8cca27a-4005-43dd-9732-33dde3ac85d5","title":"Multi-Team Support: Concurrent Teams on Single Server","file_path":"specs/s-7umt_multi_team_support_concurrent_teams_on_single_serv.md","content":"\n## Overview\n\nEnable multiple concurrent teams to coexist on a single macro-agent server instance. Currently the system supports exactly one team at a time due to global singleton callback slots (spawn interceptor, signal filter, emission validator) and a single `team_config` event in EventStore.\n\n## Key Design Decision: Multiplexer Pattern\n\nRather than making every global service team-aware (which would be invasive and break the clean separation of concerns), introduce a **TeamManager** that sits between the global services and multiple TeamRuntime instances. The TeamManager installs a single composite callback on each global service that dispatches to the correct TeamRuntime based on agent membership.\n\n## Requirements\n\n1. Multiple TeamRuntime instances coexist in same process\n2. Each team has isolated spawn interceptor logic, signal filters, emission validators\n3. Agents are associated with a specific team (persisted)\n4. Teams can be started/stopped independently\n5. Teams don't interfere with each other's communication topology\n6. Backward compatible: single team still works identically\n7. Agents not in any team continue to work normally (no team context applied)\n8. Cross-team messaging is blocked by default (agents can only communicate within their team)\n\n## Architecture\n\n```\nCLI (--team alpha --team beta)\n │\n ▼\n TeamManager\n ├── TeamRuntime(\"alpha\")\n │ ├── roleAgentMap\n │ ├── agentRoleMap\n │ ├── peerSignalFilters\n │ └── integrationStrategy\n ├── TeamRuntime(\"beta\")\n │ └── ...\n ├── compositeSpawnInterceptor → AgentManager.setSpawnInterceptor()\n ├── compositeSignalFilter → MessageRouter.setSignalFilter()\n └── compositeEmissionValidator → MessageRouter.setEmissionValidator()\n```\n\n## Phases\n\n### Phase 1: Agent Team Binding (Foundation)\n- Add `team_id` field to Agent record in EventStore\n- Pass `team_id` through spawn event payload\n- Update `applySpawnEvent` to persist team_id\n- Update `rowToAgent` to read team_id\n\n### Phase 2: TeamManager Core\n- New `src/teams/team-manager.ts` class\n- Registry of active TeamRuntime instances\n- Agent-to-team lookup via EventStore (team_id field)\n- Composite spawn interceptor that dispatches by parent team\n- Composite signal filter that dispatches by agent team\n- Composite emission validator that dispatches by agent team\n\n### Phase 3: EventStore Multi-Team Config\n- Change team_config event to include team_name in payload (already present)\n- Add query method to find team_config by team_name\n- MCP subprocess reads correct team_config for its agent's team\n\n### Phase 4: RoleRegistry Namespacing\n- Add optional team scope to custom role registration\n- Resolution: team-scoped custom > global custom > project > builtin\n- Prevent cross-team role name collisions\n\n### Phase 5: CLI and Config Changes\n- Support multiple `--team` flags or comma-separated values\n- Support `teams` array in config.json\n- Loop: load each team, add to TeamManager\n- Shutdown: teardown all teams\n\n### Phase 6: API and Observability\n- `GET /api/teams` endpoint listing all active teams\n- `GET /api/team/:name` endpoint for specific team info\n- Team-scoped agent/task filtering\n- Metrics per team\n\n## Cross-Team Messaging Policy\n\nBy default, cross-team messaging is blocked:\n- The composite signal filter returns `false` for messages between agents in different teams\n- Agents not in any team can communicate freely with each other\n- A future extension could add explicit cross-team channels\n\n## Error Cases\n\n- **Team name conflict**: Reject addTeam() if name already registered\n- **Team teardown with running agents**: Stop team agents before removing from registry\n- **Agent spawned by non-team parent for team role**: Spawn interceptor checks parent team membership\n- **MCP subprocess for agent in unknown team**: Falls back to no team context (backward compat)\n","priority":1,"archived":0,"archived_at":null,"created_at":"2026-02-18 09:33:32","updated_at":"2026-02-18 09:33:32","parent_id":null,"parent_uuid":null,"relationships":[],"tags":["architecture","multi-team","multiplexer"]}
|
|
50
|
+
{"id":"s-931n","uuid":"2d8ea3d7-c317-4d2e-8bb7-bd47d4a2affe","title":"Runtime Configuration Manager","file_path":"specs/s-931n_runtime_configuration_manager.md","content":"\n# Runtime Configuration Manager\n\n## Overview\n\nAdd a `ConfigManager` service that holds runtime configuration in memory, exposes typed getters/setters, and notifies subscribers of changes via an EventEmitter pattern. API endpoints write to ConfigManager; subscribing services (TeamRuntime, RoleRegistry) react to changes and update their own behavior accordingly.\n\n## Design Principles\n\n- **API-first**: Config changes flow through API endpoints, not file edits\n- **Decoupled**: ConfigManager doesn't know about MessageRouter, AgentManager, etc. — subscribers own the wiring to their services\n- **Layered**: File-based config is the base layer; runtime changes are an overlay that takes precedence\n- **Optional persistence**: Some changes write back to files (roles), others are ephemeral (tuning knobs reset to file defaults on restart)\n\n## Configuration Tiers\n\n### Tier 1: Infrastructure (static, load-once)\n**NOT managed by ConfigManager.** Stays as-is in `loadMergedConfig()`.\n- `port`, `host`\n- `auth.disabled`, `auth.secret`\n- `task.backend`, `task.opentasks.socket_path`\n\n### Tier 2: Templates (runtime-writable, affects future spawns)\n- **Role definitions** — capabilities, workspace, lifecycle, tools, prompts\n- **Team role definitions** — team-specific role overrides\n\n### Tier 3: Tuning (runtime-writable, affects running system)\n- `communication.enforcement` — strict | permissive | audit\n- `macro_agent.task_assignment.pull.*` — idle_timeout_s, claim_retry_delay_ms, max_concurrent_per_agent\n- `macro_agent.lifecycle.scaling.*` — min_workers, max_workers, idle_drain\n- `macro_agent.observability.*` — metrics_window_s, snapshot_interval_s\n- `macro_agent.integration.config.*` — max_retries, conflict_action (strategy params, not strategy choice)\n\n## ConfigManager Interface\n\n```typescript\ninterface ConfigManager extends EventEmitter {\n // ─── Read ────────────────────────────────────────────────\n /** Get a config value by dot-path. Returns runtime override if set, else file-based default. */\n get<T>(path: string): T | undefined;\n\n /** Get full section (e.g., \"roles\", \"tuning.scaling\") */\n getSection<T>(section: string): T | undefined;\n\n /** Get effective config: file base merged with runtime overrides */\n getEffective(): RuntimeConfig;\n\n // ─── Write ───────────────────────────────────────────────\n /** Set a runtime override. Emits \"config:<section>\" event. */\n set(path: string, value: unknown): void;\n\n /** Merge a partial config into a section. Emits \"config:<section>\" event. */\n merge(section: string, partial: Record<string, unknown>): void;\n\n /** Remove a runtime override, reverting to file-based default. */\n unset(path: string): void;\n\n // ─── Persistence ─────────────────────────────────────────\n /** Persist current runtime overrides to file (for sections that support it) */\n persist(section?: string): Promise<void>;\n\n // ─── Lifecycle ───────────────────────────────────────────\n /** Initialize from file-based config */\n initialize(fileConfig: MultiagentConfig, teamManifest?: TeamManifest): void;\n}\n```\n\n## Config Sections & Events\n\n| Section | Event name | Subscriber | Action on change |\n|---------|-----------|------------|-----------------|\n| `roles.<name>` | `config:roles` | RoleRegistry | `registerRole()` with updated definition |\n| `enforcement` | `config:enforcement` | TeamRuntime | Re-install emission validator via `setEmissionValidator()` |\n| `tuning.scaling` | `config:tuning.scaling` | TeamRuntime | Update scaling params (affects future spawn decisions) |\n| `tuning.task_assignment` | `config:tuning.task_assignment` | TeamRuntime | Update spawn interceptor with new pull-mode params |\n| `tuning.observability` | `config:tuning.observability` | Metrics service | Update metrics window/snapshot interval |\n| `tuning.integration` | `config:tuning.integration` | IntegrationStrategy | Update strategy params (max_retries, conflict_action) |\n\n## RuntimeConfig Schema\n\n```typescript\ninterface RuntimeConfig {\n /** Role overrides (Tier 2) */\n roles: Record<string, Partial<RoleDefinition>>;\n\n /** Communication enforcement level (Tier 3) */\n enforcement?: \"strict\" | \"permissive\" | \"audit\";\n\n /** Tuning knobs (Tier 3) */\n tuning: {\n scaling?: {\n min_workers?: number;\n max_workers?: number;\n idle_drain?: boolean;\n };\n task_assignment?: {\n idle_timeout_s?: number;\n claim_retry_delay_ms?: number;\n max_concurrent_per_agent?: number;\n };\n observability?: {\n metrics_window_s?: number;\n snapshot_interval_s?: number;\n };\n integration?: {\n max_retries?: number;\n conflict_action?: string;\n [key: string]: unknown; // strategy-specific params\n };\n };\n}\n```\n\n## API Endpoints\n\n```\nGET /api/config → full effective config (file base + runtime overrides)\nGET /api/config/:section → single section (e.g., /api/config/enforcement)\nPUT /api/config/:section → replace a section\nPATCH /api/config/:section → merge into a section\nDELETE /api/config/:section/:key → unset a runtime override (revert to file default)\nPOST /api/config/persist → write runtime overrides to disk (optional, section filter)\n```\n\n### Example requests\n\n```\nPATCH /api/config/enforcement\n{ \"value\": \"permissive\" }\n\nPATCH /api/config/tuning/scaling\n{ \"max_workers\": 8, \"idle_drain\": true }\n\nPUT /api/config/roles/worker\n{ \"capabilities\": [\"file.read\", \"file.write\", \"git.commit\", \"exec.command\"] }\n\nDELETE /api/config/tuning/scaling/max_workers\n(reverts to team.yaml default)\n```\n\n## Subscriber Wiring\n\nSubscribers register during initialization, not inside ConfigManager:\n\n```typescript\n// In TeamRuntime.initialize():\nconfigManager.on(\"config:enforcement\", (value) => {\n const newValidator = this.createEmissionValidator(value);\n this.messageRouter.setEmissionValidator(newValidator);\n});\n\nconfigManager.on(\"config:tuning.task_assignment\", (value) => {\n // Rebuild spawn interceptor with updated pull-mode params\n this.agentManager.setSpawnInterceptor(this.createSpawnInterceptor());\n});\n\n// In RoleRegistry (or wherever roles are managed):\nconfigManager.on(\"config:roles\", (roles) => {\n for (const [name, definition] of Object.entries(roles)) {\n registry.registerRole({ name, ...definition });\n }\n});\n```\n\n## Cross-Process Visibility\n\nWhen ConfigManager applies a change, it optionally emits a `config_update` event to EventStore:\n\n```typescript\neventStore.emit({\n type: \"config_update\",\n source: { agent_id: \"system\" },\n payload: {\n section: \"enforcement\",\n value: \"permissive\",\n timestamp: Date.now()\n }\n});\n```\n\nMCP subprocesses that need to read current config can query EventStore for the latest `config_update` events. This is secondary to the in-memory path — not all config changes need cross-process visibility.\n\n## Persistence Strategy\n\n| Section | Persists to | On restart |\n|---------|------------|-----------|\n| `roles.*` | `.multiagent/roles.json` | Roles survive restart |\n| `enforcement` | Not persisted | Reverts to `team.yaml` default |\n| `tuning.*` | Not persisted | Reverts to `team.yaml` default |\n\nRationale: Role changes are definitional (you want them to stick). Tuning knobs are operational (the YAML file is the source of truth for defaults; runtime tweaks are temporary adjustments).\n\nUsers can explicitly call `POST /api/config/persist` to write tuning overrides to file if they want them to survive restarts.\n\n## Initialization Flow\n\n```\nServer startup:\n 1. loadMergedConfig() → infrastructure config (port, host, auth, task)\n 2. new ConfigManager()\n 3. configManager.initialize(mergedConfig, teamManifest)\n → loads file-based defaults for roles, team tuning\n → runtime overlay starts empty\n 4. TeamRuntime.initialize(configManager)\n → subscribes to config:enforcement, config:tuning.*\n 5. RoleRegistry loaded, subscribes to config:roles\n 6. API server started with configManager reference\n```\n\n## File Layout\n\n```\nsrc/config/\n├── project-config.ts # Existing: static config loader (unchanged)\n├── config-manager.ts # NEW: runtime config manager\n├── types.ts # NEW: RuntimeConfig, ConfigSection types\n└── index.ts # Updated: export ConfigManager\n```\n\n## Out of Scope\n\n- Changing topology at runtime (root, companions, spawn rules, channels, subscriptions)\n- Swapping integration strategy (queue → trunk)\n- Changing task backend (memory → opentasks)\n- Config validation schemas (can add later)\n- Config diffing / rollback\n- WebSocket config change notifications to clients (can add later)\n","priority":1,"archived":0,"archived_at":null,"created_at":"2026-02-18 23:35:39","updated_at":"2026-02-18 23:35:39","parent_id":null,"parent_uuid":null,"relationships":[],"tags":["api","config","runtime"]}
|
|
51
|
+
{"id":"s-573k","uuid":"68b7357d-feaa-4200-abad-c689f9208ed9","title":"Recursive Teams: Composable Multi-Team Support","file_path":"specs/s-573k_recursive_teams_composable_multi_team_support.md","content":"## Overview\n\nEnable teams to be **composable and recursive** -- a team's topology can reference sub-teams, whose roots become children of the parent team's agents. This enables hierarchical multi-agent structures while keeping each team config self-contained and reusable.\n\n## Design Model\n\nTeams nest via the agent hierarchy. A sub-team's root agent is spawned as a **child** of a parent team agent. Each team is autonomous internally (own roles, communication, integration strategy). Cross-team communication flows through the hierarchy (parent-child subtree subscriptions) and optionally through shared topics.\n\n```\n[coordinator] team: project ← parent team's root\n├── [backend.lead] team: backend ← sub-team root (child of coordinator)\n│ ├── [worker] team: backend\n│ └── [reviewer] team: backend\n├── [frontend.lead] team: frontend ← sub-team root (child of coordinator)\n│ ├── [designer] team: frontend\n│ └── [implementer] team: frontend\n└── [qa-monitor] team: project ← parent team's companion\n```\n\n### Key Principles\n\n1. **Teams are self-contained**: A team.yaml doesn't know or care whether it's used standalone or as a sub-team\n2. **Nesting uses agent hierarchy**: Sub-team roots become children, not peers. Communication flows through parent-child relationships naturally\n3. **Each team governs itself**: Roles, communication channels, signal filters, emission validation, and integration strategy are scoped to each team's own agents\n4. **Cross-team communication**: Flows through hierarchy (subtree subscriptions) or shared topics bridged via the parent team\n\n## Config Schema\n\n### Sub-Team Reference (v1 - minimal)\n\nNew field `topology.teams` on team.yaml:\n\n```yaml\n# .multiagent/teams/project/team.yaml\nname: project\nroles: [coordinator, qa-monitor]\n\ntopology:\n root:\n role: coordinator\n companions:\n - role: qa-monitor\n teams: # NEW\n - name: backend # loads .multiagent/teams/backend/team.yaml\n - name: coding-team # can reuse same template twice\n as: frontend # instance name (becomes team_id)\n parent: root # which topology node owns this sub-team\n topics: [coordination] # parent-level topics sub-team root subscribes to\n\ncommunication:\n channels:\n - name: coordination\n signals: [status_update, blocking_issue, handoff]\n subscriptions:\n coordinator:\n - channel: coordination\n```\n\n### Sub-Team Reference Fields\n\n| Field | Required | Default | Description |\n|-------|----------|---------|-------------|\n| `name` | yes | — | Team template directory name under `.multiagent/teams/` |\n| `as` | no | same as `name` | Instance name. Becomes `team_id` for agents. Required when same template used twice. |\n| `parent` | no | `root` | Role name of the topology node that spawns this sub-team's root as its child |\n| `topics` | no | `[]` | Parent-level topic names the sub-team root auto-subscribes to |\n\n### Sub-team template (standalone, reusable)\n\n```yaml\n# .multiagent/teams/backend/team.yaml\nname: backend\nroles: [lead, worker, reviewer]\n\ntopology:\n root:\n role: lead\n companions:\n - role: worker\n - role: reviewer\n\ncommunication:\n channels:\n - name: work_coordination\n signals: [task_assigned, review_request, task_completed]\n subscriptions:\n lead:\n - channel: work_coordination\n worker:\n - channel: work_coordination\n reviewer:\n - channel: work_coordination\n```\n\nThis template works identically whether used standalone (`--team backend`) or as a sub-team of another team. When used as a sub-team, the only difference is its root agent gets a parent (instead of `parent: null`).\n\n### Recursion\n\nSub-teams can themselves reference sub-teams:\n\n```yaml\n# .multiagent/teams/backend/team.yaml\nname: backend\ntopology:\n root:\n role: lead\n companions:\n - role: reviewer\n teams:\n - name: api-team\n - name: database-team\n```\n\nThis composes arbitrarily deep.\n\n## Agent Records: `team_id`\n\nEvery agent gets a `team_id` field identifying which team it belongs to:\n\n- Set at spawn time (via spawn event payload)\n- Inherited from team context during bootstrap, or injected by spawn interceptor for dynamically spawned children\n- Persisted in EventStore agent materialized view\n- Used by TeamManager to dispatch callbacks to the correct TeamRuntime\n\n## TeamManager (Multiplexer)\n\nA flat registry of all active TeamRuntime instances (parent + all sub-teams). Installs single composite callbacks on global services:\n\n### Composite Spawn Interceptor\n1. Look up parent agent's `team_id` from EventStore\n2. If parent is in a team → delegate to that team's spawn interceptor\n3. Inject `team_id` into child spawn options (team membership inherits)\n4. For bootstrap spawns (`parent: null`), `team_id` is set explicitly\n\n### Composite Signal Filter\n1. Look up source and target agents' `team_id`\n2. Same team → delegate to that team's signal filter\n3. Cross-team → allow (the hierarchy handles visibility via subtree subscriptions)\n4. Unaffiliated → allow (no filtering for non-team agents)\n\n### Composite Emission Validator\n1. Look up emitting agent's `team_id`\n2. If in a team → delegate to that team's emission validator\n3. Unaffiliated → allow\n\n## Recursive Bootstrap Flow\n\n1. Parent team bootstraps normally (spawn root + companions)\n2. For each sub-team reference in `topology.teams`:\n a. Resolve the `parent` role → get parent agent ID from roleAgentMap\n b. Create child TeamRuntime from pre-loaded sub-team manifest\n c. Register child TeamRuntime with TeamManager\n d. Bootstrap child with `parentAgentId` set (root spawned as child, not peer)\n e. Subscribe sub-team root to bridged `topics`\n3. Sub-team may recursively bootstrap its own sub-teams (same process)\n\n## Role Namespacing\n\nWhen multiple teams define the same role name (e.g., both \"backend\" and \"frontend\" define \"lead\"):\n\n- **Internal to each team**: roles use short names (\"lead\", \"worker\")\n- **At parent level**: auto-prefixed with team instance name (\"backend.lead\", \"frontend.lead\")\n- **RoleRegistry**: team-scoped registration (`registerTeamRole(teamName, role)`)\n- **Resolution**: `resolveRole(\"lead\", teamName: \"backend\")` → backend's lead definition\n\n## Cross-Team Communication Patterns\n\n### Through Hierarchy (default)\nParent agent (coordinator) subscribes to sub-team root's subtree. Sees all events. Can relay messages between sub-teams.\n\n### Through Shared Topics (explicit)\nSub-team refs specify `topics: [coordination]`. Sub-team roots subscribe to parent-level topic channels. Enables direct pub/sub between sub-teams on parent-defined channels.\n\n### Direct Addressing (always available)\nAny agent can send to any other agent by ID. Team boundaries don't block direct messages -- they only scope signal filters and emission validators.\n\n## Backward Compatibility\n\n- No `topology.teams` → identical behavior to today\n- Existing team YAMLs → valid as-is, usable both standalone and as sub-team templates\n- Agents without `team_id` → unaffiliated, unchanged behavior\n- Single `--team` flag → TeamManager wraps the single team transparently\n","priority":1,"archived":0,"archived_at":null,"created_at":"2026-02-18 23:38:34","updated_at":"2026-02-18 23:38:34","parent_id":null,"parent_uuid":null,"relationships":[],"tags":["architecture","multi-team","recursive","teams"]}
|
|
52
|
+
{"id":"s-8bbq","uuid":"b03dc85d-f7f9-4f1b-9933-1fa945bfc9c4","title":"Auto-Start OpenTasks Daemon with Central + Per-Project Connection Model","file_path":"specs/s-8bbq_auto_start_opentasks_daemon_with_central_per_proje.md","content":"## Context\n\nThe macro-agent server orchestrates agents across arbitrary working directories. Each project may have its own `.opentasks/` graph (git-tracked task/spec data). The macro-agent needs a unified task view for orchestration while preserving per-project task ownership.\n\nCurrently, the opentasks backend requires a **pre-running external daemon** — if the daemon isn't available, macro-agent falls back to an in-memory task backend. This spec defines how macro-agent auto-starts and manages opentasks daemons.\n\n## Key Design Constraint: Task Provider Lifecycle\n\n**Daemon spawning is part of the task provider lifecycle.** The `createTaskBackend()` factory owns daemon start/stop — callers (CLI entry points) don't need to manage daemon lifecycle separately. This keeps daemon management encapsulated within the task backend module.\n\n```\ncreateTaskBackend({ backend: { type: \"opentasks\" } })\n └── DaemonManager.ensureDaemon()\n ├── checkExistingDaemon(centralPath)\n │ ├── Running → connect to existing socket\n │ └── Not running → createDaemonWithStore() + start()\n └── Return { client, socketPath, ownsDaemon }\n\nTaskBackendResult.shutdown()\n └── DaemonManager.shutdown()\n ├── ownsDaemon=true → daemon.stop()\n └── ownsDaemon=false → client.disconnect() only\n```\n\n## Architecture: Central Daemon + Per-Project Connections\n\n```\n~/.multiagent/\n├── config.json # global config (layered config system)\n├── opentasks/ # central opentasks location\n│ ├── graph.jsonl # orchestration-level tasks\n│ ├── config.json # location identity + connections list\n│ ├── daemon.sock # IPC socket\n│ ├── daemon.lock # exclusive lock\n│ └── cache.db # SQLite query cache\n└── <instanceId>/ # EventStore data (per-instance)\n └── events.db\n\n/projects/frontend/.opentasks/ # pre-existing project opentasks\n├── graph.jsonl # project tasks (git-tracked)\n└── config.json # connected to central as child\n\n/projects/backend/.opentasks/ # another project\n├── graph.jsonl\n└── config.json\n```\n\n### Central Daemon\n\n- Lives at `~/.multiagent/opentasks/`\n- Auto-started by `createTaskBackend()` when opentasks backend is configured\n- Owns orchestration-level tasks (cross-project coordination)\n- Maintains connections to per-project `.opentasks/` locations\n- Provides federated queries across all connected locations\n- Stopped via `TaskBackendResult.shutdown()` (only if we started it)\n\n### Per-Project Connections\n\n- When an agent is spawned into a cwd that has `.opentasks/`, the central daemon auto-connects to it\n- Connect-only model: macro-agent does **not** auto-init `.opentasks/` in new directories\n- Connections are declared in the central daemon's `config.json` via the opentasks connections API\n- Cross-project task references use URI notation: `opentasks://<project-hash>/t-abc`\n\n## Implementation\n\n### New Module: `src/task/backend/opentasks/daemon-manager.ts`\n\nInternal to the opentasks backend module — not exposed as a standalone service.\n\n```typescript\ninterface DaemonManagerConfig {\n /** Central daemon location (default: ~/.multiagent/opentasks) */\n centralPath?: string;\n /** Whether to auto-connect project .opentasks/ on connectProject() */\n connectOnSpawn?: boolean;\n}\n\ninterface DaemonManagerResult {\n /** Connected OpenTasks client */\n client: OpenTasksClient;\n /** Daemon socket path */\n socketPath: string;\n /** Whether we started the daemon (vs connecting to existing) */\n ownsDaemon: boolean;\n}\n\ninterface DaemonManager {\n /** Start or connect to central daemon */\n ensureDaemon(): Promise<DaemonManagerResult>;\n /** Connect a project's .opentasks/ to the central daemon */\n connectProject(projectPath: string): Promise<void>;\n /** Check if a project is already connected */\n isProjectConnected(projectPath: string): boolean;\n /** Stop the daemon if we started it, disconnect client */\n shutdown(): Promise<void>;\n}\n```\n\n### Updated `TaskBackendResult`\n\n```typescript\ninterface TaskBackendResult {\n backend: TaskBackend;\n openTasksClient?: OpenTasksClient;\n /** Shutdown function — stops daemon if we started it */\n shutdown?: () => Promise<void>;\n}\n```\n\n### Updated `createTaskBackend()` Flow\n\nWhen `backendConfig.type === \"opentasks\"`:\n\n```\n1. Create DaemonManager with config\n2. Call daemonManager.ensureDaemon()\n ├── Determine centralPath: config.centralPath ?? ~/.multiagent/opentasks/\n ├── mkdir -p centralPath (ensure directory exists)\n ├── checkExistingDaemon(centralPath)\n │ ├── running=true → connect client to existing socketPath\n │ └── running=false →\n │ a. createDaemonWithStore({ locationPath: centralPath, version })\n │ b. await daemon.start()\n │ c. connect client to daemon.socketPath\n │ d. Set ownsDaemon=true\n └── Return { client, socketPath, ownsDaemon }\n3. Create OpenTasksTaskBackend with client\n4. Return { backend, openTasksClient, shutdown: () => daemonManager.shutdown() }\n```\n\n### Config Integration\n\nThe `.multiagent/config.json` (layered config system) controls behavior:\n\n```json\n{\n \"task\": {\n \"backend\": \"opentasks\",\n \"opentasks\": {\n \"auto_start\": true,\n \"central_path\": \"~/.multiagent/opentasks\",\n \"connect_on_spawn\": true\n }\n }\n}\n```\n\n| Config Key | Default | Description |\n| --- | --- | --- |\n| `task.opentasks.auto_start` | `true` | Auto-start central daemon in createTaskBackend() |\n| `task.opentasks.central_path` | `~/.multiagent/opentasks` | Central daemon location |\n| `task.opentasks.connect_on_spawn` | `true` | Auto-connect project .opentasks/ on agent spawn |\n\n### CLI Entry Point Changes\n\nMinimal — daemon lifecycle is encapsulated in the backend:\n\n```typescript\n// In acp.ts / index.ts:\nconst result = await createTaskBackend(taskConfig, eventStore);\ntaskBackend = result.backend;\n// ...\nconst cleanup = async () => {\n await result.shutdown?.(); // Stops daemon if we started it\n await eventStore.close();\n};\n```\n\n### Connect-on-Spawn (Phase 2)\n\nStill wired via `agent-manager.ts` but calls into the daemon manager:\n\n```typescript\n// agent-manager.ts\nagentManager.onLifecycleEvent((event) => {\n if (event.type === \"spawned\" && daemonManager) {\n daemonManager.connectProject(event.agent.cwd);\n }\n});\n```\n\n## opentasks Package APIs Used\n\n| Operation | API | Import Path |\n| --- | --- | --- |\n| Check existing daemon | `checkExistingDaemon(locationPath)` | `opentasks` (dynamic) |\n| Create daemon with store | `createDaemonWithStore({ locationPath, version })` | `opentasks` (dynamic) |\n| Start/stop daemon | `daemon.start()` / `daemon.stop()` | Daemon instance |\n| Connect client | `IPCOpenTasksClient({ socketPath })` | local client.ts |\n| Create connection | `createConnection(targetPath, role, basePath)` | `opentasks` (dynamic) |\n| Discover locations | `discoverLocations(startDir, { direction })` | `opentasks` (dynamic) |\n\nAll opentasks imports are dynamic (`await import(\"opentasks\")`) to avoid hard dependencies.\n\n## Edge Cases\n\n### Multiple macro-agent instances on same machine\n\n- `checkExistingDaemon()` detects pre-existing daemon at `~/.multiagent/opentasks/`\n- Second instance connects to existing daemon (shared central graph)\n- Only the instance that started the daemon stops it (tracked via `ownsDaemon` flag)\n\n### opentasks package not installed\n\n- Dynamic import fails → fall back to memory backend (existing behavior in CLI entry points)\n- Log warning: \"opentasks package not available, using memory backend\"\n\n### Daemon crashes mid-session\n\n- Client operations throw `CONNECTION_FAILED`\n- For v1: fall back to memory backend on daemon loss (existing try/catch in CLI entry points)\n- Future: reconnect logic in daemon manager\n\n### Agent spawned in subdirectory of project with .opentasks/\n\n- Walk up from agent cwd to find nearest `.opentasks/`\n- Use `discoverLocations(cwd, { direction: 'up' })` from opentasks API\n- Connect the discovered location, not the agent's exact cwd\n\n## Phases\n\n### Phase 1: Auto-start central daemon (within createTaskBackend)\n\n- Create `DaemonManager` module at `src/task/backend/opentasks/daemon-manager.ts`\n- Integrate into `createTaskBackend()` factory\n- Add `shutdown` to `TaskBackendResult`\n- Update CLI cleanup to call `result.shutdown?.()`\n- Fall back to memory on failure (existing behavior)\n\n### Phase 2: Connect-on-spawn\n\n- Hook into agent spawn lifecycle via agent-manager\n- Auto-discover and connect project `.opentasks/` directories\n- Surface connected projects in API/health endpoint\n\n### Phase 3: Federated queries\n\n- Ensure `query({ ready: {} })` works across connected locations\n- Surface project origin in task metadata\n- Cross-project edge creation via URI references\n\n## Non-Goals\n\n- Auto-initializing `.opentasks/` in new project directories (connect-only model)\n- Running separate daemons per project (single central daemon)\n- Migrating existing EventStore tasks to opentasks (dual persistence continues)\n- Replacing the memory backend fallback (always available as safety net)","priority":1,"archived":0,"archived_at":null,"created_at":"2026-02-18 23:58:49","updated_at":"2026-02-19 00:52:32","parent_id":null,"parent_uuid":null,"relationships":[],"tags":["architecture","config","daemon","opentasks"]}
|
package/CLAUDE.md
CHANGED
|
@@ -10,7 +10,7 @@ macro-agent enables coordinated work across multiple AI agents with:
|
|
|
10
10
|
- **Pluggable integration strategies** (queue, trunk, optimistic)
|
|
11
11
|
- **Workspace isolation** via git worktrees
|
|
12
12
|
- **Merge queue** for serialized integration
|
|
13
|
-
- **Task backend** abstraction (memory or
|
|
13
|
+
- **Task backend** abstraction (memory or opentasks) with push and pull modes
|
|
14
14
|
- **In-flight steering** via context injection
|
|
15
15
|
- **Signal filtering and emission enforcement** for communication topology
|
|
16
16
|
- **Session continuations** for long-running daemon agents
|
|
@@ -46,7 +46,7 @@ macro-agent enables coordinated work across multiple AI agents with:
|
|
|
46
46
|
│ Roles │ │ Workspace │ │ Tasks │
|
|
47
47
|
│ Built-in + │ │ Bare Repo │ │ Backend │
|
|
48
48
|
│ Team-defined│ │ Worktrees │ │ (memory/ │
|
|
49
|
-
│ (via YAML) │ │ Strategies │ │
|
|
49
|
+
│ (via YAML) │ │ Strategies │ │ opentasks) │
|
|
50
50
|
│ │ │ (queue/ │ │ Push/Pull │
|
|
51
51
|
│ │ │ trunk/opt) │ │ modes │
|
|
52
52
|
└──────────────┘ └──────────────┘ └──────────────┘
|
|
@@ -92,7 +92,7 @@ src/
|
|
|
92
92
|
│ └── index.ts # CLI commands (start, chat, status, --team)
|
|
93
93
|
│
|
|
94
94
|
├── config/ # Project configuration
|
|
95
|
-
│ └── project-config.ts # .
|
|
95
|
+
│ └── project-config.ts # .multiagent/config.json loader
|
|
96
96
|
│
|
|
97
97
|
├── lifecycle/ # Agent lifecycle management
|
|
98
98
|
│ ├── handlers/ # Role-specific done() handlers
|
|
@@ -152,8 +152,8 @@ src/
|
|
|
152
152
|
│ └── backend/ # Pluggable task backends
|
|
153
153
|
│ ├── types.ts # TaskBackend interface (+ claim/unclaim/listClaimable)
|
|
154
154
|
│ ├── memory.ts # InMemoryTaskBackend (push + pull)
|
|
155
|
-
│ ├── tool-provider.ts #
|
|
156
|
-
│ └──
|
|
155
|
+
│ ├── unified-tool-provider.ts # Unified task MCP tool provider (7 tools)
|
|
156
|
+
│ └── opentasks/ # OpenTasks integration
|
|
157
157
|
│
|
|
158
158
|
├── teams/ # Team template system
|
|
159
159
|
│ ├── types.ts # TeamManifest, TeamTopology, TeamCommunication
|
|
@@ -219,9 +219,12 @@ Each worker gets an isolated git worktree:
|
|
|
219
219
|
|
|
220
220
|
Two backends available:
|
|
221
221
|
- **memory**: In-memory tasks with EventStore persistence (supports push + pull modes)
|
|
222
|
-
- **
|
|
222
|
+
- **opentasks**: External issue tracking with dependency management (supports push + pull modes)
|
|
223
223
|
|
|
224
|
-
|
|
224
|
+
The unified task tool provider exposes 7 MCP tools:
|
|
225
|
+
- Always available: `create_task`, `get_task`, `list_tasks`, `assign_task`
|
|
226
|
+
- When OpenTasks client available: `task` (upsert), `link`, `annotate`
|
|
227
|
+
- Pull mode adds: `claim_task`, `unclaim_task`, `list_claimable_tasks` (gated by `task.claim` capability)
|
|
225
228
|
|
|
226
229
|
### Communication Topology
|
|
227
230
|
|
|
@@ -301,23 +304,23 @@ npm run test:e2e # E2E tests (requires RUN_E2E_TESTS=true)
|
|
|
301
304
|
|
|
302
305
|
### Adding a Team Role (via YAML)
|
|
303
306
|
|
|
304
|
-
1. Create `.
|
|
307
|
+
1. Create `.multiagent/teams/<team>/roles/<role>.yaml` with `extends` base role
|
|
305
308
|
2. Add `capabilities_add`/`capabilities_remove` as needed
|
|
306
|
-
3. Create `.
|
|
309
|
+
3. Create `.multiagent/teams/<team>/prompts/<role>.md` for custom prompt
|
|
307
310
|
4. Reference the role in `team.yaml` topology and communication sections
|
|
308
311
|
|
|
309
312
|
### Modifying Task Backend
|
|
310
313
|
|
|
311
314
|
1. Update interface in `src/task/backend/types.ts`
|
|
312
|
-
2. Implement in both `memory.ts` and `
|
|
313
|
-
3. Update tool provider if adding new operations
|
|
315
|
+
2. Implement in both `memory.ts` and `opentasks/`
|
|
316
|
+
3. Update unified tool provider if adding new operations
|
|
314
317
|
|
|
315
318
|
## Environment Variables
|
|
316
319
|
|
|
317
320
|
| Variable | Description | Default |
|
|
318
321
|
|----------|-------------|---------|
|
|
319
|
-
| `MACRO_TASK_BACKEND` | Task backend: `memory` or `
|
|
320
|
-
| `
|
|
322
|
+
| `MACRO_TASK_BACKEND` | Task backend: `memory` or `opentasks` | `opentasks` |
|
|
323
|
+
| `OPENTASKS_SOCKET_PATH` | Path to OpenTasks socket | — |
|
|
321
324
|
| `MACRO_WORKSPACE_POOL_SIZE` | Max concurrent workspaces | `10` |
|
|
322
325
|
| `MACRO_MERGE_QUEUE_DB` | Merge queue SQLite path | `:memory:` |
|
|
323
326
|
| `MACRO_TEAM_NAME` | Team name (injected into agent env by team runtime) | — |
|
|
@@ -333,4 +336,3 @@ npm run test:e2e # E2E tests (requires RUN_E2E_TESTS=true)
|
|
|
333
336
|
- [docs/configuration.md](docs/configuration.md) - Configuration reference
|
|
334
337
|
- [docs/teams.md](docs/teams.md) - Team template schema reference
|
|
335
338
|
- [docs/team-templates.md](docs/team-templates.md) - Team template format and examples
|
|
336
|
-
- [docs/sudocode-integration.md](docs/sudocode-integration.md) - Sudocode backend details
|
package/README.md
CHANGED
|
@@ -19,28 +19,7 @@ A multi-agent orchestration system for spawning and managing hierarchical Claude
|
|
|
19
19
|
- **Context Injection** - Push context into running agents without waiting for message checks
|
|
20
20
|
- **Session Continuations** - Auto-resume long-running agents across process restarts
|
|
21
21
|
- **Observability** - Throughput, utilization, and error metrics via REST API
|
|
22
|
-
- **
|
|
23
|
-
|
|
24
|
-
## Sudocode Integration
|
|
25
|
-
|
|
26
|
-
macro-agent can integrate with [sudocode](https://github.com/sudocode-ai/sudocode) for external issue tracking:
|
|
27
|
-
|
|
28
|
-
```bash
|
|
29
|
-
# Enable sudocode backend
|
|
30
|
-
export MACRO_TASK_BACKEND=sudocode
|
|
31
|
-
export SUDOCODE_PROJECT_PATH=/path/to/project
|
|
32
|
-
|
|
33
|
-
# Start macro-agent server (full mode with ACP + MAP + REST)
|
|
34
|
-
npx multiagent
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
With sudocode enabled:
|
|
38
|
-
- Tasks are bound to sudocode issues via `external_id`
|
|
39
|
-
- Blocking relationships come from sudocode's issue links
|
|
40
|
-
- `listReady()` returns only tasks with no incomplete blockers
|
|
41
|
-
- Task status can sync with issue status
|
|
42
|
-
|
|
43
|
-
See [docs/sudocode-integration.md](docs/sudocode-integration.md) for full documentation.
|
|
22
|
+
- **OpenTasks Integration** - Optional issue tracking with dependency management
|
|
44
23
|
|
|
45
24
|
## Team Templates
|
|
46
25
|
|
|
@@ -50,15 +29,15 @@ Teams define multi-agent topologies as YAML configuration. A team template speci
|
|
|
50
29
|
# Start with a team template
|
|
51
30
|
npx multiagent --team self-driving
|
|
52
31
|
|
|
53
|
-
# Or set in project config (.
|
|
54
|
-
echo '{ "team": "self-driving" }' > .
|
|
32
|
+
# Or set in project config (.multiagent/config.json)
|
|
33
|
+
echo '{ "team": "self-driving" }' > .multiagent/config.json
|
|
55
34
|
npx multiagent
|
|
56
35
|
```
|
|
57
36
|
|
|
58
|
-
Teams are stored in `.
|
|
37
|
+
Teams are stored in `.multiagent/teams/<name>/`:
|
|
59
38
|
|
|
60
39
|
```
|
|
61
|
-
.
|
|
40
|
+
.multiagent/teams/self-driving/
|
|
62
41
|
├── team.yaml # Team manifest (topology, communication, strategy)
|
|
63
42
|
├── roles/
|
|
64
43
|
│ ├── planner.yaml # Custom role (extends coordinator)
|
|
@@ -295,7 +274,11 @@ Fallback chain: `inject()` → `interruptWith()` → high-priority message
|
|
|
295
274
|
| `stop_agent` | Terminate an agent |
|
|
296
275
|
| `create_task` | Create a new task |
|
|
297
276
|
| `get_task` | Get task details |
|
|
298
|
-
| `
|
|
277
|
+
| `list_tasks` | List tasks with optional filters |
|
|
278
|
+
| `assign_task` | Assign task to agent |
|
|
279
|
+
| `task` | Upsert task (OpenTasks only) |
|
|
280
|
+
| `link` | Link tasks (OpenTasks only) |
|
|
281
|
+
| `annotate` | Add annotations (OpenTasks only) |
|
|
299
282
|
| `claim_task` | Claim next available task (pull mode) |
|
|
300
283
|
| `unclaim_task` | Return claimed task to pool (pull mode) |
|
|
301
284
|
| `list_claimable_tasks` | List claimable tasks (pull mode) |
|
|
@@ -332,7 +315,7 @@ npx multiagent --acp --cwd /path/to/project
|
|
|
332
315
|
| `--port <port>` | Server port (default: 3001) |
|
|
333
316
|
| `--host <host>` | Server host (default: localhost) |
|
|
334
317
|
| `--cwd <path>` | Working directory for agents |
|
|
335
|
-
| `--team <name>` | Load team template from `.
|
|
318
|
+
| `--team <name>` | Load team template from `.multiagent/teams/<name>/` |
|
|
336
319
|
| `--acp` | Stdio ACP-only mode (for embedded use with acp-factory) |
|
|
337
320
|
|
|
338
321
|
### Multi-Client Architecture
|
|
@@ -454,7 +437,6 @@ RUN_E2E_TESTS=true ANTHROPIC_API_KEY=xxx npm run test:e2e
|
|
|
454
437
|
- [Configuration Reference](docs/configuration.md) - Environment variables and config options
|
|
455
438
|
- [Team Templates](docs/team-templates.md) - Team template format and examples
|
|
456
439
|
- [Team Schema Reference](docs/teams.md) - Full YAML schema reference
|
|
457
|
-
- [Sudocode Integration](docs/sudocode-integration.md) - External issue tracking
|
|
458
440
|
- [Troubleshooting Guide](docs/troubleshooting.md) - Common issues and solutions
|
|
459
441
|
|
|
460
442
|
## License
|
|
@@ -50,6 +50,8 @@ export declare class MacroAgent implements Agent {
|
|
|
50
50
|
private cancellationControllers;
|
|
51
51
|
/** Accumulates assistant response parts during prompt streaming for history persistence */
|
|
52
52
|
private promptBuffers;
|
|
53
|
+
/** Caches tool info (title, name, input) from initial tool_call events per session */
|
|
54
|
+
private toolInfoCaches;
|
|
53
55
|
constructor(connection: AgentSideConnection, config: MacroAgentConfig);
|
|
54
56
|
/**
|
|
55
57
|
* Initialize the connection and advertise capabilities
|
|
@@ -171,6 +173,10 @@ export declare class MacroAgent implements Agent {
|
|
|
171
173
|
* then calls the agent manager to cancel the pending permission.
|
|
172
174
|
*/
|
|
173
175
|
private handleCancelPermission;
|
|
176
|
+
/**
|
|
177
|
+
* Change the permission mode for a running agent at runtime
|
|
178
|
+
*/
|
|
179
|
+
private handleSetPermissionMode;
|
|
174
180
|
/**
|
|
175
181
|
* Resume a stopped/failed agent
|
|
176
182
|
*/
|
|
@@ -227,6 +233,17 @@ export declare class MacroAgent implements Agent {
|
|
|
227
233
|
* Record user and assistant turns after a prompt completes.
|
|
228
234
|
*/
|
|
229
235
|
private recordPromptTurns;
|
|
236
|
+
/**
|
|
237
|
+
* Handle _macro/getModels extension — returns the session's available models.
|
|
238
|
+
* Claude Code populates models asynchronously after session creation
|
|
239
|
+
* (via _model_state_update notification), so this allows the TUI to poll
|
|
240
|
+
* for the model list once it's available.
|
|
241
|
+
*
|
|
242
|
+
* Returns full model info (modelId + name) since Claude Code uses shorthand
|
|
243
|
+
* model IDs ("default", "sonnet") that don't match models.dev. The name
|
|
244
|
+
* field (e.g., "Claude Sonnet 4") enables better model registry matching.
|
|
245
|
+
*/
|
|
246
|
+
private handleGetModels;
|
|
230
247
|
/**
|
|
231
248
|
* Handle _macro/getHistory extension — returns conversation turns for a session
|
|
232
249
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"macro-agent.d.ts","sourceRoot":"","sources":["../../src/acp/macro-agent.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EACV,KAAK,EACL,mBAAmB,EACnB,iBAAiB,EACjB,kBAAkB,EAClB,iBAAiB,EACjB,kBAAkB,EAClB,kBAAkB,EAClB,mBAAmB,EACnB,mBAAmB,EACnB,oBAAoB,EACpB,aAAa,EACb,cAAc,EACd,kBAAkB,
|
|
1
|
+
{"version":3,"file":"macro-agent.d.ts","sourceRoot":"","sources":["../../src/acp/macro-agent.ts"],"names":[],"mappings":"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"}
|