hungry-ghost-hive 0.3.0
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/LICENSE +111 -0
- package/README.md +352 -0
- package/dist/agents/base-agent.d.ts +63 -0
- package/dist/agents/base-agent.d.ts.map +1 -0
- package/dist/agents/base-agent.js +189 -0
- package/dist/agents/base-agent.js.map +1 -0
- package/dist/agents/index.d.ts +7 -0
- package/dist/agents/index.d.ts.map +1 -0
- package/dist/agents/index.js +7 -0
- package/dist/agents/index.js.map +1 -0
- package/dist/agents/intermediate.d.ts +15 -0
- package/dist/agents/intermediate.d.ts.map +1 -0
- package/dist/agents/intermediate.js +142 -0
- package/dist/agents/intermediate.js.map +1 -0
- package/dist/agents/junior.d.ts +15 -0
- package/dist/agents/junior.d.ts.map +1 -0
- package/dist/agents/junior.js +147 -0
- package/dist/agents/junior.js.map +1 -0
- package/dist/agents/qa.d.ts +23 -0
- package/dist/agents/qa.d.ts.map +1 -0
- package/dist/agents/qa.js +238 -0
- package/dist/agents/qa.js.map +1 -0
- package/dist/agents/senior.d.ts +18 -0
- package/dist/agents/senior.d.ts.map +1 -0
- package/dist/agents/senior.js +267 -0
- package/dist/agents/senior.js.map +1 -0
- package/dist/agents/tech-lead.d.ts +17 -0
- package/dist/agents/tech-lead.d.ts.map +1 -0
- package/dist/agents/tech-lead.js +274 -0
- package/dist/agents/tech-lead.js.map +1 -0
- package/dist/cli/commands/add-repo.d.ts +3 -0
- package/dist/cli/commands/add-repo.d.ts.map +1 -0
- package/dist/cli/commands/add-repo.js +84 -0
- package/dist/cli/commands/add-repo.js.map +1 -0
- package/dist/cli/commands/agents.d.ts +3 -0
- package/dist/cli/commands/agents.d.ts.map +1 -0
- package/dist/cli/commands/agents.js +214 -0
- package/dist/cli/commands/agents.js.map +1 -0
- package/dist/cli/commands/assign.d.ts +3 -0
- package/dist/cli/commands/assign.d.ts.map +1 -0
- package/dist/cli/commands/assign.js +81 -0
- package/dist/cli/commands/assign.js.map +1 -0
- package/dist/cli/commands/config.d.ts +3 -0
- package/dist/cli/commands/config.d.ts.map +1 -0
- package/dist/cli/commands/config.js +118 -0
- package/dist/cli/commands/config.js.map +1 -0
- package/dist/cli/commands/escalations.d.ts +3 -0
- package/dist/cli/commands/escalations.d.ts.map +1 -0
- package/dist/cli/commands/escalations.js +157 -0
- package/dist/cli/commands/escalations.js.map +1 -0
- package/dist/cli/commands/index.d.ts +17 -0
- package/dist/cli/commands/index.d.ts.map +1 -0
- package/dist/cli/commands/index.js +17 -0
- package/dist/cli/commands/index.js.map +1 -0
- package/dist/cli/commands/init.d.ts +3 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +59 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/manager.d.ts +3 -0
- package/dist/cli/commands/manager.d.ts.map +1 -0
- package/dist/cli/commands/manager.js +775 -0
- package/dist/cli/commands/manager.js.map +1 -0
- package/dist/cli/commands/manager.test.d.ts +2 -0
- package/dist/cli/commands/manager.test.d.ts.map +1 -0
- package/dist/cli/commands/manager.test.js +45 -0
- package/dist/cli/commands/manager.test.js.map +1 -0
- package/dist/cli/commands/msg.d.ts +3 -0
- package/dist/cli/commands/msg.d.ts.map +1 -0
- package/dist/cli/commands/msg.js +190 -0
- package/dist/cli/commands/msg.js.map +1 -0
- package/dist/cli/commands/my-stories.d.ts +3 -0
- package/dist/cli/commands/my-stories.d.ts.map +1 -0
- package/dist/cli/commands/my-stories.js +174 -0
- package/dist/cli/commands/my-stories.js.map +1 -0
- package/dist/cli/commands/nuke.d.ts +3 -0
- package/dist/cli/commands/nuke.d.ts.map +1 -0
- package/dist/cli/commands/nuke.js +189 -0
- package/dist/cli/commands/nuke.js.map +1 -0
- package/dist/cli/commands/pr.d.ts +3 -0
- package/dist/cli/commands/pr.d.ts.map +1 -0
- package/dist/cli/commands/pr.js +488 -0
- package/dist/cli/commands/pr.js.map +1 -0
- package/dist/cli/commands/req.d.ts +3 -0
- package/dist/cli/commands/req.d.ts.map +1 -0
- package/dist/cli/commands/req.js +212 -0
- package/dist/cli/commands/req.js.map +1 -0
- package/dist/cli/commands/resume.d.ts +3 -0
- package/dist/cli/commands/resume.d.ts.map +1 -0
- package/dist/cli/commands/resume.js +114 -0
- package/dist/cli/commands/resume.js.map +1 -0
- package/dist/cli/commands/status.d.ts +3 -0
- package/dist/cli/commands/status.d.ts.map +1 -0
- package/dist/cli/commands/status.js +259 -0
- package/dist/cli/commands/status.js.map +1 -0
- package/dist/cli/commands/stories.d.ts +3 -0
- package/dist/cli/commands/stories.d.ts.map +1 -0
- package/dist/cli/commands/stories.js +111 -0
- package/dist/cli/commands/stories.js.map +1 -0
- package/dist/cli/commands/teams.d.ts +3 -0
- package/dist/cli/commands/teams.d.ts.map +1 -0
- package/dist/cli/commands/teams.js +137 -0
- package/dist/cli/commands/teams.js.map +1 -0
- package/dist/cli/dashboard/index.d.ts +5 -0
- package/dist/cli/dashboard/index.d.ts.map +1 -0
- package/dist/cli/dashboard/index.js +128 -0
- package/dist/cli/dashboard/index.js.map +1 -0
- package/dist/cli/dashboard/panels/activity.d.ts +5 -0
- package/dist/cli/dashboard/panels/activity.d.ts.map +1 -0
- package/dist/cli/dashboard/panels/activity.js +64 -0
- package/dist/cli/dashboard/panels/activity.js.map +1 -0
- package/dist/cli/dashboard/panels/agents.d.ts +5 -0
- package/dist/cli/dashboard/panels/agents.d.ts.map +1 -0
- package/dist/cli/dashboard/panels/agents.js +196 -0
- package/dist/cli/dashboard/panels/agents.js.map +1 -0
- package/dist/cli/dashboard/panels/escalations.d.ts +5 -0
- package/dist/cli/dashboard/panels/escalations.d.ts.map +1 -0
- package/dist/cli/dashboard/panels/escalations.js +93 -0
- package/dist/cli/dashboard/panels/escalations.js.map +1 -0
- package/dist/cli/dashboard/panels/merge-queue.d.ts +5 -0
- package/dist/cli/dashboard/panels/merge-queue.d.ts.map +1 -0
- package/dist/cli/dashboard/panels/merge-queue.js +57 -0
- package/dist/cli/dashboard/panels/merge-queue.js.map +1 -0
- package/dist/cli/dashboard/panels/pipeline.d.ts +5 -0
- package/dist/cli/dashboard/panels/pipeline.d.ts.map +1 -0
- package/dist/cli/dashboard/panels/pipeline.js +54 -0
- package/dist/cli/dashboard/panels/pipeline.js.map +1 -0
- package/dist/cli/dashboard/panels/stories.d.ts +5 -0
- package/dist/cli/dashboard/panels/stories.d.ts.map +1 -0
- package/dist/cli/dashboard/panels/stories.js +79 -0
- package/dist/cli/dashboard/panels/stories.js.map +1 -0
- package/dist/cli-runtimes/claude.d.ts +8 -0
- package/dist/cli-runtimes/claude.d.ts.map +1 -0
- package/dist/cli-runtimes/claude.js +27 -0
- package/dist/cli-runtimes/claude.js.map +1 -0
- package/dist/cli-runtimes/codex.d.ts +8 -0
- package/dist/cli-runtimes/codex.d.ts.map +1 -0
- package/dist/cli-runtimes/codex.js +27 -0
- package/dist/cli-runtimes/codex.js.map +1 -0
- package/dist/cli-runtimes/gemini.d.ts +8 -0
- package/dist/cli-runtimes/gemini.d.ts.map +1 -0
- package/dist/cli-runtimes/gemini.js +29 -0
- package/dist/cli-runtimes/gemini.js.map +1 -0
- package/dist/cli-runtimes/index.d.ts +25 -0
- package/dist/cli-runtimes/index.d.ts.map +1 -0
- package/dist/cli-runtimes/index.js +48 -0
- package/dist/cli-runtimes/index.js.map +1 -0
- package/dist/cli-runtimes/index.test.d.ts +2 -0
- package/dist/cli-runtimes/index.test.d.ts.map +1 -0
- package/dist/cli-runtimes/index.test.js +216 -0
- package/dist/cli-runtimes/index.test.js.map +1 -0
- package/dist/cli-runtimes/types.d.ts +27 -0
- package/dist/cli-runtimes/types.d.ts.map +1 -0
- package/dist/cli-runtimes/types.js +2 -0
- package/dist/cli-runtimes/types.js.map +1 -0
- package/dist/config/index.d.ts +3 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +3 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/loader.d.ts +11 -0
- package/dist/config/loader.d.ts.map +1 -0
- package/dist/config/loader.js +72 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/config/schema.d.ts +660 -0
- package/dist/config/schema.d.ts.map +1 -0
- package/dist/config/schema.js +217 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/config/schema.test.d.ts +2 -0
- package/dist/config/schema.test.d.ts.map +1 -0
- package/dist/config/schema.test.js +123 -0
- package/dist/config/schema.test.js.map +1 -0
- package/dist/context-files/generator.d.ts +32 -0
- package/dist/context-files/generator.d.ts.map +1 -0
- package/dist/context-files/generator.js +120 -0
- package/dist/context-files/generator.js.map +1 -0
- package/dist/context-files/index.d.ts +38 -0
- package/dist/context-files/index.d.ts.map +1 -0
- package/dist/context-files/index.js +76 -0
- package/dist/context-files/index.js.map +1 -0
- package/dist/context-files/index.test.d.ts +2 -0
- package/dist/context-files/index.test.d.ts.map +1 -0
- package/dist/context-files/index.test.js +265 -0
- package/dist/context-files/index.test.js.map +1 -0
- package/dist/context-files/templates.d.ts +19 -0
- package/dist/context-files/templates.d.ts.map +1 -0
- package/dist/context-files/templates.js +266 -0
- package/dist/context-files/templates.js.map +1 -0
- package/dist/db/client.d.ts +95 -0
- package/dist/db/client.d.ts.map +1 -0
- package/dist/db/client.js +343 -0
- package/dist/db/client.js.map +1 -0
- package/dist/db/lock.d.ts +25 -0
- package/dist/db/lock.d.ts.map +1 -0
- package/dist/db/lock.js +56 -0
- package/dist/db/lock.js.map +1 -0
- package/dist/db/lock.test.d.ts +2 -0
- package/dist/db/lock.test.d.ts.map +1 -0
- package/dist/db/lock.test.js +73 -0
- package/dist/db/lock.test.js.map +1 -0
- package/dist/db/queries/agents.d.ts +31 -0
- package/dist/db/queries/agents.d.ts.map +1 -0
- package/dist/db/queries/agents.js +76 -0
- package/dist/db/queries/agents.js.map +1 -0
- package/dist/db/queries/escalations.d.ts +29 -0
- package/dist/db/queries/escalations.d.ts.map +1 -0
- package/dist/db/queries/escalations.js +105 -0
- package/dist/db/queries/escalations.js.map +1 -0
- package/dist/db/queries/heartbeat.d.ts +20 -0
- package/dist/db/queries/heartbeat.d.ts.map +1 -0
- package/dist/db/queries/heartbeat.js +61 -0
- package/dist/db/queries/heartbeat.js.map +1 -0
- package/dist/db/queries/index.d.ts +8 -0
- package/dist/db/queries/index.d.ts.map +1 -0
- package/dist/db/queries/index.js +8 -0
- package/dist/db/queries/index.js.map +1 -0
- package/dist/db/queries/logs.d.ts +21 -0
- package/dist/db/queries/logs.d.ts.map +1 -0
- package/dist/db/queries/logs.js +72 -0
- package/dist/db/queries/logs.js.map +1 -0
- package/dist/db/queries/messages.d.ts +17 -0
- package/dist/db/queries/messages.d.ts.map +1 -0
- package/dist/db/queries/messages.js +22 -0
- package/dist/db/queries/messages.js.map +1 -0
- package/dist/db/queries/pull-requests.d.ts +33 -0
- package/dist/db/queries/pull-requests.d.ts.map +1 -0
- package/dist/db/queries/pull-requests.js +130 -0
- package/dist/db/queries/pull-requests.js.map +1 -0
- package/dist/db/queries/requirements.d.ts +22 -0
- package/dist/db/queries/requirements.d.ts.map +1 -0
- package/dist/db/queries/requirements.js +53 -0
- package/dist/db/queries/requirements.js.map +1 -0
- package/dist/db/queries/stories.d.ts +42 -0
- package/dist/db/queries/stories.d.ts.map +1 -0
- package/dist/db/queries/stories.js +163 -0
- package/dist/db/queries/stories.js.map +1 -0
- package/dist/db/queries/teams.d.ts +14 -0
- package/dist/db/queries/teams.d.ts.map +1 -0
- package/dist/db/queries/teams.js +24 -0
- package/dist/db/queries/teams.js.map +1 -0
- package/dist/git/branches.d.ts +52 -0
- package/dist/git/branches.d.ts.map +1 -0
- package/dist/git/branches.js +133 -0
- package/dist/git/branches.js.map +1 -0
- package/dist/git/github.d.ts +75 -0
- package/dist/git/github.d.ts.map +1 -0
- package/dist/git/github.js +162 -0
- package/dist/git/github.js.map +1 -0
- package/dist/git/index.d.ts +4 -0
- package/dist/git/index.d.ts.map +1 -0
- package/dist/git/index.js +4 -0
- package/dist/git/index.js.map +1 -0
- package/dist/git/submodules.d.ts +47 -0
- package/dist/git/submodules.d.ts.map +1 -0
- package/dist/git/submodules.js +115 -0
- package/dist/git/submodules.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +62 -0
- package/dist/index.js.map +1 -0
- package/dist/llm/anthropic.d.ts +18 -0
- package/dist/llm/anthropic.d.ts.map +1 -0
- package/dist/llm/anthropic.js +111 -0
- package/dist/llm/anthropic.js.map +1 -0
- package/dist/llm/index.d.ts +6 -0
- package/dist/llm/index.d.ts.map +1 -0
- package/dist/llm/index.js +24 -0
- package/dist/llm/index.js.map +1 -0
- package/dist/llm/openai.d.ts +18 -0
- package/dist/llm/openai.d.ts.map +1 -0
- package/dist/llm/openai.js +103 -0
- package/dist/llm/openai.js.map +1 -0
- package/dist/llm/provider.d.ts +38 -0
- package/dist/llm/provider.d.ts.map +1 -0
- package/dist/llm/provider.js +17 -0
- package/dist/llm/provider.js.map +1 -0
- package/dist/orchestrator/index.d.ts +4 -0
- package/dist/orchestrator/index.d.ts.map +1 -0
- package/dist/orchestrator/index.js +4 -0
- package/dist/orchestrator/index.js.map +1 -0
- package/dist/orchestrator/scaler.d.ts +42 -0
- package/dist/orchestrator/scaler.d.ts.map +1 -0
- package/dist/orchestrator/scaler.js +154 -0
- package/dist/orchestrator/scaler.js.map +1 -0
- package/dist/orchestrator/scheduler.d.ts +90 -0
- package/dist/orchestrator/scheduler.d.ts.map +1 -0
- package/dist/orchestrator/scheduler.js +1003 -0
- package/dist/orchestrator/scheduler.js.map +1 -0
- package/dist/orchestrator/scheduler.test.d.ts +2 -0
- package/dist/orchestrator/scheduler.test.d.ts.map +1 -0
- package/dist/orchestrator/scheduler.test.js +242 -0
- package/dist/orchestrator/scheduler.test.js.map +1 -0
- package/dist/orchestrator/workflow.d.ts +18 -0
- package/dist/orchestrator/workflow.d.ts.map +1 -0
- package/dist/orchestrator/workflow.js +106 -0
- package/dist/orchestrator/workflow.js.map +1 -0
- package/dist/state-detectors/claude.d.ts +33 -0
- package/dist/state-detectors/claude.d.ts.map +1 -0
- package/dist/state-detectors/claude.js +237 -0
- package/dist/state-detectors/claude.js.map +1 -0
- package/dist/state-detectors/claude.test.d.ts +2 -0
- package/dist/state-detectors/claude.test.d.ts.map +1 -0
- package/dist/state-detectors/claude.test.js +127 -0
- package/dist/state-detectors/claude.test.js.map +1 -0
- package/dist/state-detectors/codex.d.ts +34 -0
- package/dist/state-detectors/codex.d.ts.map +1 -0
- package/dist/state-detectors/codex.js +233 -0
- package/dist/state-detectors/codex.js.map +1 -0
- package/dist/state-detectors/codex.test.d.ts +2 -0
- package/dist/state-detectors/codex.test.d.ts.map +1 -0
- package/dist/state-detectors/codex.test.js +85 -0
- package/dist/state-detectors/codex.test.js.map +1 -0
- package/dist/state-detectors/factory.d.ts +22 -0
- package/dist/state-detectors/factory.d.ts.map +1 -0
- package/dist/state-detectors/factory.js +37 -0
- package/dist/state-detectors/factory.js.map +1 -0
- package/dist/state-detectors/factory.test.d.ts +2 -0
- package/dist/state-detectors/factory.test.d.ts.map +1 -0
- package/dist/state-detectors/factory.test.js +44 -0
- package/dist/state-detectors/factory.test.js.map +1 -0
- package/dist/state-detectors/gemini.d.ts +34 -0
- package/dist/state-detectors/gemini.d.ts.map +1 -0
- package/dist/state-detectors/gemini.js +236 -0
- package/dist/state-detectors/gemini.js.map +1 -0
- package/dist/state-detectors/gemini.test.d.ts +2 -0
- package/dist/state-detectors/gemini.test.d.ts.map +1 -0
- package/dist/state-detectors/gemini.test.js +93 -0
- package/dist/state-detectors/gemini.test.js.map +1 -0
- package/dist/state-detectors/index.d.ts +20 -0
- package/dist/state-detectors/index.d.ts.map +1 -0
- package/dist/state-detectors/index.js +21 -0
- package/dist/state-detectors/index.js.map +1 -0
- package/dist/state-detectors/types.d.ts +67 -0
- package/dist/state-detectors/types.d.ts.map +1 -0
- package/dist/state-detectors/types.js +28 -0
- package/dist/state-detectors/types.js.map +1 -0
- package/dist/tmux/index.d.ts +2 -0
- package/dist/tmux/index.d.ts.map +1 -0
- package/dist/tmux/index.js +2 -0
- package/dist/tmux/index.js.map +1 -0
- package/dist/tmux/manager.d.ts +45 -0
- package/dist/tmux/manager.d.ts.map +1 -0
- package/dist/tmux/manager.js +252 -0
- package/dist/tmux/manager.js.map +1 -0
- package/dist/utils/claude-code-state.d.ts +46 -0
- package/dist/utils/claude-code-state.d.ts.map +1 -0
- package/dist/utils/claude-code-state.js +252 -0
- package/dist/utils/claude-code-state.js.map +1 -0
- package/dist/utils/cli-builder.d.ts +19 -0
- package/dist/utils/cli-builder.d.ts.map +1 -0
- package/dist/utils/cli-builder.js +58 -0
- package/dist/utils/cli-builder.js.map +1 -0
- package/dist/utils/cli-commands.d.ts +27 -0
- package/dist/utils/cli-commands.d.ts.map +1 -0
- package/dist/utils/cli-commands.js +69 -0
- package/dist/utils/cli-commands.js.map +1 -0
- package/dist/utils/index.d.ts +3 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +3 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/logger.d.ts +13 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +77 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/paths.d.ts +17 -0
- package/dist/utils/paths.d.ts.map +1 -0
- package/dist/utils/paths.js +33 -0
- package/dist/utils/paths.js.map +1 -0
- package/dist/utils/timeout.d.ts +25 -0
- package/dist/utils/timeout.d.ts.map +1 -0
- package/dist/utils/timeout.js +57 -0
- package/dist/utils/timeout.js.map +1 -0
- package/package.json +78 -0
- package/src/agents/base-agent.ts +255 -0
- package/src/agents/index.ts +6 -0
- package/src/agents/intermediate.ts +161 -0
- package/src/agents/junior.ts +166 -0
- package/src/agents/qa.ts +272 -0
- package/src/agents/senior.ts +307 -0
- package/src/agents/tech-lead.ts +324 -0
- package/src/cli/commands/add-repo.ts +89 -0
- package/src/cli/commands/agents.ts +247 -0
- package/src/cli/commands/assign.ts +86 -0
- package/src/cli/commands/config.ts +121 -0
- package/src/cli/commands/escalations.ts +179 -0
- package/src/cli/commands/index.ts +16 -0
- package/src/cli/commands/init.ts +66 -0
- package/src/cli/commands/manager.test.ts +52 -0
- package/src/cli/commands/manager.ts +916 -0
- package/src/cli/commands/msg.ts +232 -0
- package/src/cli/commands/my-stories.ts +198 -0
- package/src/cli/commands/nuke.ts +223 -0
- package/src/cli/commands/pr.ts +559 -0
- package/src/cli/commands/req.ts +231 -0
- package/src/cli/commands/resume.ts +129 -0
- package/src/cli/commands/status.ts +284 -0
- package/src/cli/commands/stories.ts +131 -0
- package/src/cli/commands/teams.ts +158 -0
- package/src/cli/dashboard/index.ts +141 -0
- package/src/cli/dashboard/panels/activity.ts +77 -0
- package/src/cli/dashboard/panels/agents.ts +244 -0
- package/src/cli/dashboard/panels/escalations.ts +109 -0
- package/src/cli/dashboard/panels/merge-queue.ts +65 -0
- package/src/cli/dashboard/panels/pipeline.ts +65 -0
- package/src/cli/dashboard/panels/stories.ts +87 -0
- package/src/cli-runtimes/claude.ts +31 -0
- package/src/cli-runtimes/codex.ts +31 -0
- package/src/cli-runtimes/gemini.ts +33 -0
- package/src/cli-runtimes/index.test.ts +261 -0
- package/src/cli-runtimes/index.ts +52 -0
- package/src/cli-runtimes/types.ts +30 -0
- package/src/config/index.ts +2 -0
- package/src/config/loader.ts +89 -0
- package/src/config/schema.test.ts +135 -0
- package/src/config/schema.ts +238 -0
- package/src/context-files/generator.ts +132 -0
- package/src/context-files/index.test.ts +323 -0
- package/src/context-files/index.ts +102 -0
- package/src/context-files/templates.ts +279 -0
- package/src/db/client.ts +475 -0
- package/src/db/lock.test.ts +93 -0
- package/src/db/lock.ts +74 -0
- package/src/db/migrations/001-initial.sql +121 -0
- package/src/db/migrations/005-add-agent-heartbeat.sql +4 -0
- package/src/db/queries/agents.ts +113 -0
- package/src/db/queries/escalations.ts +140 -0
- package/src/db/queries/heartbeat.ts +92 -0
- package/src/db/queries/index.ts +7 -0
- package/src/db/queries/logs.ts +136 -0
- package/src/db/queries/messages.ts +38 -0
- package/src/db/queries/pull-requests.ts +170 -0
- package/src/db/queries/requirements.ts +81 -0
- package/src/db/queries/stories.ts +223 -0
- package/src/db/queries/teams.ts +39 -0
- package/src/git/branches.ts +186 -0
- package/src/git/github.ts +247 -0
- package/src/git/index.ts +3 -0
- package/src/git/submodules.ts +141 -0
- package/src/index.ts +93 -0
- package/src/llm/anthropic.ts +134 -0
- package/src/llm/index.ts +26 -0
- package/src/llm/openai.ts +125 -0
- package/src/llm/provider.ts +60 -0
- package/src/orchestrator/index.ts +3 -0
- package/src/orchestrator/scaler.ts +201 -0
- package/src/orchestrator/scheduler.test.ts +288 -0
- package/src/orchestrator/scheduler.ts +1130 -0
- package/src/orchestrator/workflow.ts +137 -0
- package/src/state-detectors/claude.test.ts +149 -0
- package/src/state-detectors/claude.ts +256 -0
- package/src/state-detectors/codex.test.ts +100 -0
- package/src/state-detectors/codex.ts +252 -0
- package/src/state-detectors/factory.test.ts +51 -0
- package/src/state-detectors/factory.ts +40 -0
- package/src/state-detectors/gemini.test.ts +110 -0
- package/src/state-detectors/gemini.ts +255 -0
- package/src/state-detectors/index.ts +25 -0
- package/src/state-detectors/types.ts +80 -0
- package/src/tmux/index.ts +1 -0
- package/src/tmux/manager.ts +310 -0
- package/src/types/sql.js.d.ts +34 -0
- package/src/utils/claude-code-state.ts +281 -0
- package/src/utils/cli-builder.ts +78 -0
- package/src/utils/cli-commands.ts +84 -0
- package/src/utils/index.ts +2 -0
- package/src/utils/logger.ts +93 -0
- package/src/utils/paths.ts +49 -0
- package/src/utils/timeout.ts +84 -0
- package/tsconfig.json +25 -0
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
import { BaseAgent, type AgentContext } from './base-agent.js';
|
|
2
|
+
import { getTeamById, type TeamRow } from '../db/queries/teams.js';
|
|
3
|
+
import { getStoriesByTeam, updateStory, type StoryRow } from '../db/queries/stories.js';
|
|
4
|
+
import { createAgent, updateAgent, getTechLead } from '../db/queries/agents.js';
|
|
5
|
+
import { createEscalation } from '../db/queries/escalations.js';
|
|
6
|
+
import { spawnTmuxSession, generateSessionName } from '../tmux/manager.js';
|
|
7
|
+
import { loadConfig } from '../config/index.js';
|
|
8
|
+
import { getCliRuntimeBuilder } from '../cli-runtimes/index.js';
|
|
9
|
+
import { findHiveRoot, getHivePaths } from '../utils/paths.js';
|
|
10
|
+
|
|
11
|
+
export interface SeniorContext extends AgentContext {
|
|
12
|
+
teamId: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export class SeniorAgent extends BaseAgent {
|
|
16
|
+
private team: TeamRow | null = null;
|
|
17
|
+
private assignedStories: StoryRow[] = [];
|
|
18
|
+
|
|
19
|
+
constructor(context: SeniorContext) {
|
|
20
|
+
super(context);
|
|
21
|
+
if (context.teamId) {
|
|
22
|
+
this.team = getTeamById(this.db, context.teamId) || null;
|
|
23
|
+
this.assignedStories = getStoriesByTeam(this.db, context.teamId)
|
|
24
|
+
.filter(s => ['planned', 'in_progress', 'review'].includes(s.status));
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
getSystemPrompt(): string {
|
|
29
|
+
const teamInfo = this.team
|
|
30
|
+
? `Team: ${this.team.name}\nRepository: ${this.team.repo_url}\nPath: ${this.team.repo_path}`
|
|
31
|
+
: 'No team assigned';
|
|
32
|
+
|
|
33
|
+
const storiesInfo = this.assignedStories.length > 0
|
|
34
|
+
? this.assignedStories.map(s => `- ${s.id}: ${s.title} (${s.status}, complexity: ${s.complexity_score})`).join('\n')
|
|
35
|
+
: 'No stories assigned';
|
|
36
|
+
|
|
37
|
+
return `You are a Senior Developer responsible for a specific team and repository.
|
|
38
|
+
|
|
39
|
+
## Your Team
|
|
40
|
+
${teamInfo}
|
|
41
|
+
|
|
42
|
+
## Assigned Stories
|
|
43
|
+
${storiesInfo}
|
|
44
|
+
|
|
45
|
+
## Your Responsibilities
|
|
46
|
+
1. Conduct codebase analysis when requested
|
|
47
|
+
2. Estimate story complexity accurately
|
|
48
|
+
3. Delegate work based on complexity:
|
|
49
|
+
- 1-3 points → Delegate to Junior
|
|
50
|
+
- 4-5 points → Delegate to Intermediate
|
|
51
|
+
- 6+ points → Handle directly
|
|
52
|
+
4. Review code from delegated work
|
|
53
|
+
5. Handle complex implementations
|
|
54
|
+
6. Escalate blockers to Tech Lead
|
|
55
|
+
|
|
56
|
+
## Development Guidelines
|
|
57
|
+
- Create feature branches: feature/{story-id}-{slug}
|
|
58
|
+
- Write clean, tested code following existing patterns
|
|
59
|
+
- Update story status as you progress
|
|
60
|
+
- Commit frequently with clear messages
|
|
61
|
+
- If stuck after 2 attempts, escalate
|
|
62
|
+
|
|
63
|
+
## Current Context
|
|
64
|
+
${this.memoryState.conversationSummary || 'Starting fresh.'}`;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
async execute(): Promise<void> {
|
|
68
|
+
if (!this.team) {
|
|
69
|
+
this.log('CODEBASE_SWEEP_STARTED', 'No team assigned, waiting for assignment');
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
this.log('CODEBASE_SWEEP_STARTED', `Analyzing codebase for ${this.team.name}`);
|
|
74
|
+
|
|
75
|
+
// Perform codebase sweep
|
|
76
|
+
await this.analyzeCodebase();
|
|
77
|
+
|
|
78
|
+
// Process assigned stories
|
|
79
|
+
for (const story of this.assignedStories) {
|
|
80
|
+
if (story.status === 'planned') {
|
|
81
|
+
await this.processStory(story);
|
|
82
|
+
} else if (story.status === 'review') {
|
|
83
|
+
await this.reviewStory(story);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
private async analyzeCodebase(): Promise<void> {
|
|
89
|
+
const prompt = `Analyze the codebase structure for this repository.
|
|
90
|
+
|
|
91
|
+
Working directory: ${this.workDir}
|
|
92
|
+
|
|
93
|
+
Please identify:
|
|
94
|
+
1. Main technology stack
|
|
95
|
+
2. Key directories and their purposes
|
|
96
|
+
3. Coding patterns and conventions used
|
|
97
|
+
4. Testing setup
|
|
98
|
+
5. Build/deployment configuration
|
|
99
|
+
|
|
100
|
+
This will help with story estimation and implementation.`;
|
|
101
|
+
|
|
102
|
+
const analysis = await this.chat(prompt);
|
|
103
|
+
|
|
104
|
+
this.memoryState.context.codebaseNotes = analysis;
|
|
105
|
+
this.saveMemoryState();
|
|
106
|
+
|
|
107
|
+
this.log('CODEBASE_SWEEP_COMPLETED', 'Codebase analysis complete', {
|
|
108
|
+
summary: analysis.substring(0, 200),
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
private async processStory(story: StoryRow): Promise<void> {
|
|
113
|
+
const complexity = story.complexity_score || 5;
|
|
114
|
+
|
|
115
|
+
this.setCurrentTask(story.id, 'processing');
|
|
116
|
+
this.log('STORY_STARTED', `Processing story: ${story.title}`, { storyId: story.id });
|
|
117
|
+
|
|
118
|
+
if (complexity <= 3) {
|
|
119
|
+
// Delegate to Junior
|
|
120
|
+
await this.delegateStory(story, 'junior');
|
|
121
|
+
} else if (complexity <= 5) {
|
|
122
|
+
// Delegate to Intermediate
|
|
123
|
+
await this.delegateStory(story, 'intermediate');
|
|
124
|
+
} else {
|
|
125
|
+
// Handle directly
|
|
126
|
+
await this.implementStory(story);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
private async delegateStory(story: StoryRow, agentType: 'junior' | 'intermediate'): Promise<void> {
|
|
131
|
+
this.log('STORY_ASSIGNED', `Delegating to ${agentType}`, {
|
|
132
|
+
storyId: story.id,
|
|
133
|
+
agentType,
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
// Create subordinate agent
|
|
137
|
+
const subordinate = createAgent(this.db, {
|
|
138
|
+
type: agentType,
|
|
139
|
+
teamId: this.teamId,
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
// Spawn tmux session
|
|
143
|
+
const sessionName = generateSessionName(agentType, this.team?.name);
|
|
144
|
+
try {
|
|
145
|
+
// Load config and get CLI runtime settings for the subordinate agent type
|
|
146
|
+
const hiveRoot = findHiveRoot(this.workDir);
|
|
147
|
+
if (!hiveRoot) {
|
|
148
|
+
throw new Error('Hive root not found');
|
|
149
|
+
}
|
|
150
|
+
const paths = getHivePaths(hiveRoot);
|
|
151
|
+
const config = loadConfig(paths.hiveDir);
|
|
152
|
+
const agentConfig = config.models[agentType];
|
|
153
|
+
const cliTool = agentConfig.cli_tool;
|
|
154
|
+
const model = agentConfig.model;
|
|
155
|
+
|
|
156
|
+
// Build spawn command using CLI runtime builder (spawn fresh session, will be resumed later)
|
|
157
|
+
const runtimeBuilder = getCliRuntimeBuilder(cliTool);
|
|
158
|
+
const commandArray = runtimeBuilder.buildSpawnCommand(model);
|
|
159
|
+
const command = commandArray.join(' ');
|
|
160
|
+
|
|
161
|
+
await spawnTmuxSession({
|
|
162
|
+
sessionName,
|
|
163
|
+
workDir: this.workDir,
|
|
164
|
+
command,
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
updateAgent(this.db, subordinate.id, {
|
|
168
|
+
tmuxSession: sessionName,
|
|
169
|
+
status: 'working',
|
|
170
|
+
currentStoryId: story.id,
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
// Update story assignment
|
|
174
|
+
updateStory(this.db, story.id, {
|
|
175
|
+
assignedAgentId: subordinate.id,
|
|
176
|
+
status: 'in_progress',
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
this.log('AGENT_SPAWNED', `${agentType} spawned for story ${story.id}`, {
|
|
180
|
+
agentId: subordinate.id,
|
|
181
|
+
storyId: story.id,
|
|
182
|
+
});
|
|
183
|
+
} catch (err) {
|
|
184
|
+
// If delegation fails, handle it ourselves
|
|
185
|
+
this.log('STORY_PROGRESS_UPDATE', `Failed to delegate, handling directly: ${err instanceof Error ? err.message : 'Unknown error'}`, {
|
|
186
|
+
storyId: story.id,
|
|
187
|
+
});
|
|
188
|
+
await this.implementStory(story);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
private async implementStory(story: StoryRow): Promise<void> {
|
|
193
|
+
// Update assignment
|
|
194
|
+
updateStory(this.db, story.id, {
|
|
195
|
+
assignedAgentId: this.agentId,
|
|
196
|
+
status: 'in_progress',
|
|
197
|
+
});
|
|
198
|
+
updateAgent(this.db, this.agentId, { currentStoryId: story.id });
|
|
199
|
+
|
|
200
|
+
// Create feature branch
|
|
201
|
+
const branchName = `feature/${story.id.toLowerCase()}-${story.title.toLowerCase().replace(/[^a-z0-9]+/g, '-').substring(0, 30)}`;
|
|
202
|
+
|
|
203
|
+
this.log('STORY_STARTED', `Implementing: ${story.title}`, { branchName });
|
|
204
|
+
|
|
205
|
+
const prompt = `Implement this story:
|
|
206
|
+
|
|
207
|
+
## Story: ${story.id}
|
|
208
|
+
**Title:** ${story.title}
|
|
209
|
+
|
|
210
|
+
**Description:**
|
|
211
|
+
${story.description}
|
|
212
|
+
|
|
213
|
+
**Acceptance Criteria:**
|
|
214
|
+
${story.acceptance_criteria ? JSON.parse(story.acceptance_criteria).join('\n- ') : 'None specified'}
|
|
215
|
+
|
|
216
|
+
## Instructions
|
|
217
|
+
1. First, create a feature branch: ${branchName}
|
|
218
|
+
2. Analyze the codebase to understand where changes need to be made
|
|
219
|
+
3. Implement the changes following existing patterns
|
|
220
|
+
4. Write/update tests as needed
|
|
221
|
+
5. Commit your changes with clear messages
|
|
222
|
+
6. Report when complete
|
|
223
|
+
|
|
224
|
+
Let me know when you're ready to proceed or if you have questions.`;
|
|
225
|
+
|
|
226
|
+
const response = await this.chat(prompt);
|
|
227
|
+
this.updateTaskProgress('Implementation started', []);
|
|
228
|
+
|
|
229
|
+
// Continue the conversation to complete implementation
|
|
230
|
+
// In a real scenario, this would be an iterative process
|
|
231
|
+
this.log('STORY_PROGRESS_UPDATE', response.substring(0, 200), { storyId: story.id });
|
|
232
|
+
|
|
233
|
+
// Mark for review when done (simplified)
|
|
234
|
+
updateStory(this.db, story.id, {
|
|
235
|
+
branchName,
|
|
236
|
+
status: 'review',
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
this.log('STORY_COMPLETED', `Implementation complete, ready for review`, {
|
|
240
|
+
storyId: story.id,
|
|
241
|
+
branchName,
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
private async reviewStory(story: StoryRow): Promise<void> {
|
|
246
|
+
if (story.assigned_agent_id === this.agentId) {
|
|
247
|
+
// Self-review, move to QA
|
|
248
|
+
updateStory(this.db, story.id, { status: 'qa' });
|
|
249
|
+
this.log('STORY_REVIEW_REQUESTED', 'Self-implemented, moving to QA', { storyId: story.id });
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
this.log('STORY_REVIEW_REQUESTED', `Reviewing story: ${story.title}`, { storyId: story.id });
|
|
254
|
+
|
|
255
|
+
const prompt = `Review the code for this story:
|
|
256
|
+
|
|
257
|
+
## Story: ${story.id}
|
|
258
|
+
**Title:** ${story.title}
|
|
259
|
+
**Branch:** ${story.branch_name}
|
|
260
|
+
|
|
261
|
+
Please review:
|
|
262
|
+
1. Code quality and adherence to patterns
|
|
263
|
+
2. Test coverage
|
|
264
|
+
3. Potential bugs or issues
|
|
265
|
+
4. Performance considerations
|
|
266
|
+
|
|
267
|
+
If issues found, describe them. If approved, confirm.`;
|
|
268
|
+
|
|
269
|
+
const review = await this.chat(prompt);
|
|
270
|
+
|
|
271
|
+
// Parse review result (simplified)
|
|
272
|
+
const hasIssues = review.toLowerCase().includes('issue') ||
|
|
273
|
+
review.toLowerCase().includes('problem') ||
|
|
274
|
+
review.toLowerCase().includes('fix');
|
|
275
|
+
|
|
276
|
+
if (hasIssues) {
|
|
277
|
+
// Send back for fixes
|
|
278
|
+
updateStory(this.db, story.id, { status: 'in_progress' });
|
|
279
|
+
this.log('STORY_PROGRESS_UPDATE', 'Review issues found, sent back for fixes', {
|
|
280
|
+
storyId: story.id,
|
|
281
|
+
review: review.substring(0, 200),
|
|
282
|
+
});
|
|
283
|
+
} else {
|
|
284
|
+
// Approve and move to QA
|
|
285
|
+
updateStory(this.db, story.id, { status: 'qa' });
|
|
286
|
+
this.log('STORY_REVIEW_REQUESTED', 'Review passed, moving to QA', { storyId: story.id });
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
async escalateToTechLead(reason: string): Promise<void> {
|
|
291
|
+
const techLead = getTechLead(this.db);
|
|
292
|
+
|
|
293
|
+
const escalation = createEscalation(this.db, {
|
|
294
|
+
storyId: this.memoryState.currentTask?.storyId,
|
|
295
|
+
fromAgentId: this.agentId,
|
|
296
|
+
toAgentId: techLead?.id,
|
|
297
|
+
reason,
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
this.log('ESCALATION_CREATED', reason, {
|
|
301
|
+
escalationId: escalation.id,
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
this.updateStatus('blocked');
|
|
305
|
+
this.addBlocker(`Escalated to Tech Lead: ${reason}`);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
import { BaseAgent, type AgentContext } from './base-agent.js';
|
|
2
|
+
import { getAllTeams, type TeamRow } from '../db/queries/teams.js';
|
|
3
|
+
import { getRequirementById, updateRequirement, type RequirementRow } from '../db/queries/requirements.js';
|
|
4
|
+
import { createStory, updateStory, getStoryById } from '../db/queries/stories.js';
|
|
5
|
+
import { createAgent, getAgentsByType, updateAgent } from '../db/queries/agents.js';
|
|
6
|
+
import { createEscalation } from '../db/queries/escalations.js';
|
|
7
|
+
import { spawnTmuxSession, generateSessionName } from '../tmux/manager.js';
|
|
8
|
+
import { queryAll } from '../db/client.js';
|
|
9
|
+
import { addStoryDependency } from '../db/queries/stories.js';
|
|
10
|
+
import { loadConfig } from '../config/index.js';
|
|
11
|
+
import { getCliRuntimeBuilder } from '../cli-runtimes/index.js';
|
|
12
|
+
import { findHiveRoot, getHivePaths } from '../utils/paths.js';
|
|
13
|
+
|
|
14
|
+
export interface TechLeadContext extends AgentContext {
|
|
15
|
+
requirementId?: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export class TechLeadAgent extends BaseAgent {
|
|
19
|
+
private teams: TeamRow[] = [];
|
|
20
|
+
private requirementId?: string;
|
|
21
|
+
private requirement?: RequirementRow;
|
|
22
|
+
|
|
23
|
+
constructor(context: TechLeadContext) {
|
|
24
|
+
super(context);
|
|
25
|
+
this.requirementId = context.requirementId;
|
|
26
|
+
this.teams = getAllTeams(this.db);
|
|
27
|
+
|
|
28
|
+
if (this.requirementId) {
|
|
29
|
+
this.requirement = getRequirementById(this.db, this.requirementId);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
getSystemPrompt(): string {
|
|
34
|
+
const teamList = this.teams
|
|
35
|
+
.map(t => `- ${t.name} (${t.repo_path}): ${t.repo_url}`)
|
|
36
|
+
.join('\n');
|
|
37
|
+
|
|
38
|
+
return `You are the Tech Lead of Hive, an AI development team orchestrator.
|
|
39
|
+
|
|
40
|
+
## Your Role
|
|
41
|
+
You coordinate multiple autonomous teams, each responsible for a specific service/repository. You are the strategic decision maker who:
|
|
42
|
+
1. Analyzes requirements and breaks them into implementable stories
|
|
43
|
+
2. Identifies affected teams and cross-repo dependencies
|
|
44
|
+
3. Coordinates with Senior developers for estimation and planning
|
|
45
|
+
4. Manages escalations from teams
|
|
46
|
+
5. Ensures consistent progress across all teams
|
|
47
|
+
|
|
48
|
+
## Teams Under Your Coordination
|
|
49
|
+
${teamList || 'No teams configured yet.'}
|
|
50
|
+
|
|
51
|
+
## Current Context
|
|
52
|
+
${this.memoryState.conversationSummary || 'Starting fresh.'}
|
|
53
|
+
|
|
54
|
+
## Guidelines
|
|
55
|
+
- Break down requirements into atomic, testable stories
|
|
56
|
+
- Each story should have clear acceptance criteria
|
|
57
|
+
- Identify dependencies between stories across repos
|
|
58
|
+
- Estimate complexity using Fibonacci scale (1, 2, 3, 5, 8, 13)
|
|
59
|
+
- Delegate appropriately:
|
|
60
|
+
- 1-3 points: Junior can handle
|
|
61
|
+
- 4-5 points: Intermediate level
|
|
62
|
+
- 6+ points: Senior should handle directly
|
|
63
|
+
|
|
64
|
+
## Communication
|
|
65
|
+
You communicate via this conversation. Log important decisions and progress updates.
|
|
66
|
+
When you need to spawn Senior agents for team-specific work, describe what you need and I'll help coordinate.
|
|
67
|
+
|
|
68
|
+
## Escalation Protocol
|
|
69
|
+
Escalate to human (me) only for:
|
|
70
|
+
- Ambiguous requirements that need clarification
|
|
71
|
+
- Architectural decisions with significant trade-offs
|
|
72
|
+
- Security concerns
|
|
73
|
+
- External dependency blockers`;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
async execute(): Promise<void> {
|
|
77
|
+
if (!this.requirement) {
|
|
78
|
+
this.log('PLANNING_STARTED', 'Tech Lead ready, waiting for requirement');
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
this.log('PLANNING_STARTED', `Analyzing requirement: ${this.requirement.title}`);
|
|
83
|
+
|
|
84
|
+
// Analyze the requirement
|
|
85
|
+
const analysis = await this.analyzeRequirement();
|
|
86
|
+
|
|
87
|
+
// If we need human input, escalate
|
|
88
|
+
if (analysis.needsHumanInput) {
|
|
89
|
+
await this.escalateToHuman(analysis.escalationReason || 'Clarification needed');
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Create stories based on analysis
|
|
94
|
+
const stories = await this.createStories(analysis);
|
|
95
|
+
|
|
96
|
+
// Spawn Seniors to estimate and potentially begin work
|
|
97
|
+
await this.coordinateWithSeniors(stories);
|
|
98
|
+
|
|
99
|
+
// Update requirement status
|
|
100
|
+
updateRequirement(this.db, this.requirement.id, { status: 'planned' });
|
|
101
|
+
this.log('PLANNING_COMPLETED', `Created ${stories.length} stories`);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
private async analyzeRequirement(): Promise<{
|
|
105
|
+
affectedTeams: string[];
|
|
106
|
+
stories: Array<{
|
|
107
|
+
title: string;
|
|
108
|
+
description: string;
|
|
109
|
+
acceptanceCriteria: string[];
|
|
110
|
+
teamName: string;
|
|
111
|
+
estimatedComplexity: number;
|
|
112
|
+
dependencies?: string[];
|
|
113
|
+
}>;
|
|
114
|
+
needsHumanInput: boolean;
|
|
115
|
+
escalationReason?: string;
|
|
116
|
+
}> {
|
|
117
|
+
const prompt = `Analyze this requirement and create a plan:
|
|
118
|
+
|
|
119
|
+
## Requirement
|
|
120
|
+
Title: ${this.requirement!.title}
|
|
121
|
+
|
|
122
|
+
Description:
|
|
123
|
+
${this.requirement!.description}
|
|
124
|
+
|
|
125
|
+
## Available Teams
|
|
126
|
+
${this.teams.map(t => `- ${t.name}: ${t.repo_path}`).join('\n')}
|
|
127
|
+
|
|
128
|
+
## Instructions
|
|
129
|
+
1. Identify which teams are affected
|
|
130
|
+
2. Break down into atomic stories (each completable in a single session)
|
|
131
|
+
3. For each story provide:
|
|
132
|
+
- Title (concise, action-oriented)
|
|
133
|
+
- Description (what needs to be done)
|
|
134
|
+
- Acceptance criteria (testable conditions)
|
|
135
|
+
- Team assignment
|
|
136
|
+
- Estimated complexity (1-13 Fibonacci)
|
|
137
|
+
- Dependencies on other stories (if any)
|
|
138
|
+
4. If anything is unclear, indicate that human input is needed
|
|
139
|
+
|
|
140
|
+
Respond in JSON format:
|
|
141
|
+
{
|
|
142
|
+
"affectedTeams": ["team-name"],
|
|
143
|
+
"stories": [
|
|
144
|
+
{
|
|
145
|
+
"title": "...",
|
|
146
|
+
"description": "...",
|
|
147
|
+
"acceptanceCriteria": ["..."],
|
|
148
|
+
"teamName": "...",
|
|
149
|
+
"estimatedComplexity": 3,
|
|
150
|
+
"dependencies": []
|
|
151
|
+
}
|
|
152
|
+
],
|
|
153
|
+
"needsHumanInput": false,
|
|
154
|
+
"escalationReason": null
|
|
155
|
+
}`;
|
|
156
|
+
|
|
157
|
+
const response = await this.chat(prompt);
|
|
158
|
+
|
|
159
|
+
// Parse the JSON response
|
|
160
|
+
try {
|
|
161
|
+
const jsonMatch = response.match(/\{[\s\S]*\}/);
|
|
162
|
+
if (jsonMatch) {
|
|
163
|
+
return JSON.parse(jsonMatch[0]);
|
|
164
|
+
}
|
|
165
|
+
} catch {
|
|
166
|
+
// If parsing fails, request clarification
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
return {
|
|
170
|
+
affectedTeams: [],
|
|
171
|
+
stories: [],
|
|
172
|
+
needsHumanInput: true,
|
|
173
|
+
escalationReason: 'Could not parse requirement analysis. Please review and clarify.',
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
private async createStories(analysis: Awaited<ReturnType<typeof this.analyzeRequirement>>): Promise<string[]> {
|
|
178
|
+
const storyIds: string[] = [];
|
|
179
|
+
const storyIdMap: Record<string, string> = {};
|
|
180
|
+
|
|
181
|
+
for (const story of analysis.stories) {
|
|
182
|
+
const team = this.teams.find(t => t.name === story.teamName);
|
|
183
|
+
|
|
184
|
+
const storyRow = createStory(this.db, {
|
|
185
|
+
requirementId: this.requirement!.id,
|
|
186
|
+
teamId: team?.id,
|
|
187
|
+
title: story.title,
|
|
188
|
+
description: story.description,
|
|
189
|
+
acceptanceCriteria: story.acceptanceCriteria,
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
// Update with complexity
|
|
193
|
+
updateStory(this.db, storyRow.id, {
|
|
194
|
+
complexityScore: story.estimatedComplexity,
|
|
195
|
+
storyPoints: story.estimatedComplexity,
|
|
196
|
+
status: 'estimated',
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
storyIds.push(storyRow.id);
|
|
200
|
+
storyIdMap[story.title] = storyRow.id;
|
|
201
|
+
|
|
202
|
+
this.log('STORY_CREATED', story.title, {
|
|
203
|
+
storyId: storyRow.id,
|
|
204
|
+
teamId: team?.id,
|
|
205
|
+
complexity: story.estimatedComplexity,
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// Set up dependencies
|
|
210
|
+
for (const story of analysis.stories) {
|
|
211
|
+
if (story.dependencies && story.dependencies.length > 0) {
|
|
212
|
+
const storyId = storyIdMap[story.title];
|
|
213
|
+
for (const depTitle of story.dependencies) {
|
|
214
|
+
const depId = storyIdMap[depTitle];
|
|
215
|
+
if (depId) {
|
|
216
|
+
addStoryDependency(this.db, storyId, depId);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
return storyIds;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
private async coordinateWithSeniors(storyIds: string[]): Promise<void> {
|
|
226
|
+
// Get unique teams from stories
|
|
227
|
+
const teamIds = new Set<string>();
|
|
228
|
+
for (const storyId of storyIds) {
|
|
229
|
+
const story = getStoryById(this.db, storyId);
|
|
230
|
+
if (story?.team_id) {
|
|
231
|
+
teamIds.add(story.team_id);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// Spawn or assign Senior for each team
|
|
236
|
+
for (const teamId of teamIds) {
|
|
237
|
+
const team = this.teams.find(t => t.id === teamId);
|
|
238
|
+
if (!team) continue;
|
|
239
|
+
|
|
240
|
+
// Check if Senior already exists for this team
|
|
241
|
+
let seniors = getAgentsByType(this.db, 'senior').filter(s => s.team_id === teamId);
|
|
242
|
+
|
|
243
|
+
if (seniors.length === 0) {
|
|
244
|
+
// Create a new Senior agent
|
|
245
|
+
const senior = createAgent(this.db, {
|
|
246
|
+
type: 'senior',
|
|
247
|
+
teamId,
|
|
248
|
+
});
|
|
249
|
+
seniors = [senior];
|
|
250
|
+
|
|
251
|
+
// Spawn tmux session for the Senior
|
|
252
|
+
const sessionName = generateSessionName('senior', team.name);
|
|
253
|
+
try {
|
|
254
|
+
// Load config and get CLI runtime settings for the senior agent type
|
|
255
|
+
const hiveRoot = findHiveRoot(this.workDir);
|
|
256
|
+
if (!hiveRoot) {
|
|
257
|
+
throw new Error('Hive root not found');
|
|
258
|
+
}
|
|
259
|
+
const paths = getHivePaths(hiveRoot);
|
|
260
|
+
const config = loadConfig(paths.hiveDir);
|
|
261
|
+
const agentConfig = config.models.senior;
|
|
262
|
+
const cliTool = agentConfig.cli_tool;
|
|
263
|
+
const model = agentConfig.model;
|
|
264
|
+
|
|
265
|
+
// Build spawn command using CLI runtime builder (spawn fresh session, will be resumed later)
|
|
266
|
+
const runtimeBuilder = getCliRuntimeBuilder(cliTool);
|
|
267
|
+
const commandArray = runtimeBuilder.buildSpawnCommand(model);
|
|
268
|
+
const command = commandArray.join(' ');
|
|
269
|
+
|
|
270
|
+
await spawnTmuxSession({
|
|
271
|
+
sessionName,
|
|
272
|
+
workDir: `${this.workDir}/${team.repo_path}`,
|
|
273
|
+
command,
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
updateAgent(this.db, senior.id, {
|
|
277
|
+
tmuxSession: sessionName,
|
|
278
|
+
status: 'working',
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
this.log('AGENT_SPAWNED', `Senior spawned for team ${team.name}`, {
|
|
282
|
+
agentId: senior.id,
|
|
283
|
+
teamId,
|
|
284
|
+
tmuxSession: sessionName,
|
|
285
|
+
});
|
|
286
|
+
} catch (err) {
|
|
287
|
+
this.log('AGENT_SPAWNED', `Failed to spawn Senior tmux session: ${err instanceof Error ? err.message : 'Unknown error'}`, {
|
|
288
|
+
agentId: senior.id,
|
|
289
|
+
teamId,
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// Assign stories to the Senior
|
|
295
|
+
const teamStories = queryAll<{ id: string }>(this.db, `
|
|
296
|
+
SELECT id FROM stories WHERE team_id = ? AND status = 'estimated'
|
|
297
|
+
`, [teamId]);
|
|
298
|
+
|
|
299
|
+
for (const story of teamStories) {
|
|
300
|
+
updateStory(this.db, story.id, { status: 'planned' });
|
|
301
|
+
this.log('STORY_ASSIGNED', `Story ${story.id} assigned to team ${team.name}`, {
|
|
302
|
+
storyId: story.id,
|
|
303
|
+
teamId,
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
private async escalateToHuman(reason: string): Promise<void> {
|
|
310
|
+
const escalation = createEscalation(this.db, {
|
|
311
|
+
storyId: null,
|
|
312
|
+
fromAgentId: this.agentId,
|
|
313
|
+
toAgentId: null, // null = human
|
|
314
|
+
reason,
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
this.log('ESCALATION_CREATED', reason, {
|
|
318
|
+
escalationId: escalation.id,
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
this.updateStatus('blocked');
|
|
322
|
+
this.addBlocker(`Waiting for human input: ${reason}`);
|
|
323
|
+
}
|
|
324
|
+
}
|