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,238 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
// Model configuration for each agent type
|
|
4
|
+
const ModelConfigSchema = z.object({
|
|
5
|
+
provider: z.enum(['anthropic', 'openai']),
|
|
6
|
+
model: z.string(),
|
|
7
|
+
max_tokens: z.number().int().positive().default(8000),
|
|
8
|
+
temperature: z.number().min(0).max(2).default(0.5),
|
|
9
|
+
cli_tool: z.enum(['claude', 'codex', 'gemini']).optional().default('claude'),
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
// Models configuration for all agent types
|
|
13
|
+
const ModelsConfigSchema = z.object({
|
|
14
|
+
tech_lead: ModelConfigSchema.default({
|
|
15
|
+
provider: 'anthropic',
|
|
16
|
+
model: 'claude-opus-4-20250514',
|
|
17
|
+
max_tokens: 16000,
|
|
18
|
+
temperature: 0.7,
|
|
19
|
+
cli_tool: 'claude',
|
|
20
|
+
}),
|
|
21
|
+
senior: ModelConfigSchema.default({
|
|
22
|
+
provider: 'anthropic',
|
|
23
|
+
model: 'claude-sonnet-4-20250514',
|
|
24
|
+
max_tokens: 8000,
|
|
25
|
+
temperature: 0.5,
|
|
26
|
+
cli_tool: 'claude',
|
|
27
|
+
}),
|
|
28
|
+
intermediate: ModelConfigSchema.default({
|
|
29
|
+
provider: 'anthropic',
|
|
30
|
+
model: 'claude-haiku-3-5-20241022',
|
|
31
|
+
max_tokens: 4000,
|
|
32
|
+
temperature: 0.3,
|
|
33
|
+
cli_tool: 'claude',
|
|
34
|
+
}),
|
|
35
|
+
junior: ModelConfigSchema.default({
|
|
36
|
+
provider: 'openai',
|
|
37
|
+
model: 'gpt-4o-mini',
|
|
38
|
+
max_tokens: 4000,
|
|
39
|
+
temperature: 0.2,
|
|
40
|
+
cli_tool: 'claude',
|
|
41
|
+
}),
|
|
42
|
+
qa: ModelConfigSchema.default({
|
|
43
|
+
provider: 'anthropic',
|
|
44
|
+
model: 'claude-sonnet-4-20250514',
|
|
45
|
+
max_tokens: 8000,
|
|
46
|
+
temperature: 0.2,
|
|
47
|
+
cli_tool: 'claude',
|
|
48
|
+
}),
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
// Scaling rules
|
|
52
|
+
const ScalingConfigSchema = z.object({
|
|
53
|
+
// Story points threshold before hiring additional senior
|
|
54
|
+
senior_capacity: z.number().int().positive().default(20),
|
|
55
|
+
// Complexity threshold for delegation to junior
|
|
56
|
+
junior_max_complexity: z.number().int().min(1).max(13).default(3),
|
|
57
|
+
// Complexity threshold for delegation to intermediate
|
|
58
|
+
intermediate_max_complexity: z.number().int().min(1).max(13).default(5),
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
// GitHub integration
|
|
62
|
+
const GitHubConfigSchema = z.object({
|
|
63
|
+
// Base branch for PRs
|
|
64
|
+
base_branch: z.string().default('main'),
|
|
65
|
+
// PR template
|
|
66
|
+
pr_template: z.string().default(`## Story: {story_id}
|
|
67
|
+
|
|
68
|
+
{description}
|
|
69
|
+
|
|
70
|
+
### Acceptance Criteria
|
|
71
|
+
{acceptance_criteria}
|
|
72
|
+
|
|
73
|
+
### Changes
|
|
74
|
+
{changes}`),
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
// QA configuration
|
|
78
|
+
const QAConfigSchema = z.object({
|
|
79
|
+
// Commands to run for quality checks
|
|
80
|
+
quality_checks: z.array(z.string()).default(['npm run lint', 'npm run type-check']),
|
|
81
|
+
// Build command
|
|
82
|
+
build_command: z.string().default('npm run build'),
|
|
83
|
+
// Test command (optional)
|
|
84
|
+
test_command: z.string().optional(),
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
// Agent behavior configuration
|
|
88
|
+
const AgentsConfigSchema = z.object({
|
|
89
|
+
// Polling interval for state checks (ms)
|
|
90
|
+
poll_interval: z.number().int().positive().default(5000),
|
|
91
|
+
// Max retries before escalation
|
|
92
|
+
max_retries: z.number().int().nonnegative().default(2),
|
|
93
|
+
// Token threshold for checkpoint
|
|
94
|
+
checkpoint_threshold: z.number().int().positive().default(14000),
|
|
95
|
+
// LLM call timeout in milliseconds (default: 30 minutes)
|
|
96
|
+
llm_timeout_ms: z.number().int().positive().default(1800000),
|
|
97
|
+
// Max retries for LLM calls on timeout
|
|
98
|
+
llm_max_retries: z.number().int().nonnegative().default(2),
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
// Manager daemon configuration
|
|
102
|
+
const ManagerConfigSchema = z.object({
|
|
103
|
+
fast_poll_interval: z.number().int().positive().default(15000),
|
|
104
|
+
slow_poll_interval: z.number().int().positive().default(60000),
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
// Logging configuration
|
|
108
|
+
const LoggingConfigSchema = z.object({
|
|
109
|
+
// Log level
|
|
110
|
+
level: z.enum(['debug', 'info', 'warn', 'error']).default('info'),
|
|
111
|
+
// Retain logs for N days
|
|
112
|
+
retention_days: z.number().int().positive().default(30),
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
// Main configuration schema
|
|
116
|
+
export const HiveConfigSchema = z.object({
|
|
117
|
+
version: z.string().default('1.0'),
|
|
118
|
+
models: ModelsConfigSchema.default({}),
|
|
119
|
+
scaling: ScalingConfigSchema.default({}),
|
|
120
|
+
github: GitHubConfigSchema.default({}),
|
|
121
|
+
qa: QAConfigSchema.default({}),
|
|
122
|
+
agents: AgentsConfigSchema.default({}),
|
|
123
|
+
manager: ManagerConfigSchema.default({}),
|
|
124
|
+
logging: LoggingConfigSchema.default({}),
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
// Export types
|
|
128
|
+
export type ModelConfig = z.infer<typeof ModelConfigSchema>;
|
|
129
|
+
export type ModelsConfig = z.infer<typeof ModelsConfigSchema>;
|
|
130
|
+
export type ScalingConfig = z.infer<typeof ScalingConfigSchema>;
|
|
131
|
+
export type GitHubConfig = z.infer<typeof GitHubConfigSchema>;
|
|
132
|
+
export type QAConfig = z.infer<typeof QAConfigSchema>;
|
|
133
|
+
export type AgentsConfig = z.infer<typeof AgentsConfigSchema>;
|
|
134
|
+
export type ManagerConfig = z.infer<typeof ManagerConfigSchema>;
|
|
135
|
+
export type LoggingConfig = z.infer<typeof LoggingConfigSchema>;
|
|
136
|
+
export type HiveConfig = z.infer<typeof HiveConfigSchema>;
|
|
137
|
+
|
|
138
|
+
// Default configuration
|
|
139
|
+
export const DEFAULT_CONFIG: HiveConfig = HiveConfigSchema.parse({});
|
|
140
|
+
|
|
141
|
+
// Generate default config YAML content
|
|
142
|
+
export function generateDefaultConfigYaml(): string {
|
|
143
|
+
return `# Hive Orchestrator Configuration
|
|
144
|
+
version: "1.0"
|
|
145
|
+
|
|
146
|
+
# Model assignments per agent tier
|
|
147
|
+
models:
|
|
148
|
+
tech_lead:
|
|
149
|
+
provider: anthropic
|
|
150
|
+
model: claude-opus-4-20250514
|
|
151
|
+
max_tokens: 16000
|
|
152
|
+
temperature: 0.7
|
|
153
|
+
# CLI tool used to spawn agents (claude, codex, or gemini)
|
|
154
|
+
cli_tool: claude
|
|
155
|
+
|
|
156
|
+
senior:
|
|
157
|
+
provider: anthropic
|
|
158
|
+
model: claude-sonnet-4-20250514
|
|
159
|
+
max_tokens: 8000
|
|
160
|
+
temperature: 0.5
|
|
161
|
+
cli_tool: claude
|
|
162
|
+
|
|
163
|
+
intermediate:
|
|
164
|
+
provider: anthropic
|
|
165
|
+
model: claude-haiku-3-5-20241022
|
|
166
|
+
max_tokens: 4000
|
|
167
|
+
temperature: 0.3
|
|
168
|
+
cli_tool: claude
|
|
169
|
+
|
|
170
|
+
junior:
|
|
171
|
+
provider: openai
|
|
172
|
+
model: gpt-4o-mini
|
|
173
|
+
max_tokens: 4000
|
|
174
|
+
temperature: 0.2
|
|
175
|
+
cli_tool: claude
|
|
176
|
+
|
|
177
|
+
qa:
|
|
178
|
+
provider: anthropic
|
|
179
|
+
model: claude-sonnet-4-20250514
|
|
180
|
+
max_tokens: 8000
|
|
181
|
+
temperature: 0.2
|
|
182
|
+
cli_tool: claude
|
|
183
|
+
|
|
184
|
+
# Team scaling rules
|
|
185
|
+
scaling:
|
|
186
|
+
# Story points threshold before hiring additional senior
|
|
187
|
+
senior_capacity: 20
|
|
188
|
+
# Complexity threshold for delegation
|
|
189
|
+
junior_max_complexity: 3
|
|
190
|
+
intermediate_max_complexity: 5
|
|
191
|
+
|
|
192
|
+
# GitHub integration
|
|
193
|
+
github:
|
|
194
|
+
# Base branch for PRs
|
|
195
|
+
base_branch: main
|
|
196
|
+
# PR template
|
|
197
|
+
pr_template: |
|
|
198
|
+
## Story: {story_id}
|
|
199
|
+
|
|
200
|
+
{description}
|
|
201
|
+
|
|
202
|
+
### Acceptance Criteria
|
|
203
|
+
{acceptance_criteria}
|
|
204
|
+
|
|
205
|
+
### Changes
|
|
206
|
+
{changes}
|
|
207
|
+
|
|
208
|
+
# QA configuration
|
|
209
|
+
qa:
|
|
210
|
+
# Commands to run for quality checks
|
|
211
|
+
quality_checks:
|
|
212
|
+
- npm run lint
|
|
213
|
+
- npm run type-check
|
|
214
|
+
# Build command
|
|
215
|
+
build_command: npm run build
|
|
216
|
+
# Test command (optional)
|
|
217
|
+
# test_command: npm test
|
|
218
|
+
|
|
219
|
+
# Agent behavior
|
|
220
|
+
agents:
|
|
221
|
+
# Polling interval for state checks (ms)
|
|
222
|
+
poll_interval: 5000
|
|
223
|
+
# Max retries before escalation
|
|
224
|
+
max_retries: 2
|
|
225
|
+
# Token threshold for checkpoint
|
|
226
|
+
checkpoint_threshold: 14000
|
|
227
|
+
# LLM call timeout in milliseconds (default: 30 minutes)
|
|
228
|
+
llm_timeout_ms: 1800000
|
|
229
|
+
# Max retries for LLM calls on timeout
|
|
230
|
+
llm_max_retries: 2
|
|
231
|
+
|
|
232
|
+
# Logging
|
|
233
|
+
logging:
|
|
234
|
+
level: info
|
|
235
|
+
# Retain logs for N days
|
|
236
|
+
retention_days: 30
|
|
237
|
+
`;
|
|
238
|
+
}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Context File Content Generator
|
|
3
|
+
*
|
|
4
|
+
* Generates the actual content for context files based on CLI tool type
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { claudeCodeTemplate, codexTemplate, geminiTemplate } from './templates.js';
|
|
8
|
+
import type { ContextFileOptions } from './index.js';
|
|
9
|
+
import type { StoryRow } from '../db/queries/stories.js';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Generate context file content for the specified CLI tool
|
|
13
|
+
*/
|
|
14
|
+
export function generateContextFileContent(options: ContextFileOptions): string {
|
|
15
|
+
const { cliTool } = options;
|
|
16
|
+
|
|
17
|
+
// Get the appropriate template for the CLI tool
|
|
18
|
+
let template: (options: ContextFileOptions) => string;
|
|
19
|
+
|
|
20
|
+
switch (cliTool) {
|
|
21
|
+
case 'claude-code':
|
|
22
|
+
template = claudeCodeTemplate;
|
|
23
|
+
break;
|
|
24
|
+
case 'codex':
|
|
25
|
+
template = codexTemplate;
|
|
26
|
+
break;
|
|
27
|
+
case 'gemini':
|
|
28
|
+
template = geminiTemplate;
|
|
29
|
+
break;
|
|
30
|
+
default:
|
|
31
|
+
throw new Error(`Unsupported CLI tool: ${cliTool}`);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return template(options);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Format stories for display in context files
|
|
39
|
+
*/
|
|
40
|
+
export function formatStoriesForContext(stories: StoryRow[]): string {
|
|
41
|
+
if (stories.length === 0) {
|
|
42
|
+
return 'No active stories';
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return stories
|
|
46
|
+
.map(story => `
|
|
47
|
+
### ${story.id}: ${story.title}
|
|
48
|
+
- **Status**: ${story.status}
|
|
49
|
+
- **Complexity**: ${story.complexity_score || 'Not estimated'}
|
|
50
|
+
- **Story Points**: ${story.story_points || 'Not estimated'}
|
|
51
|
+
- **Description**: ${story.description}
|
|
52
|
+
${story.acceptance_criteria && story.acceptance_criteria.length > 0
|
|
53
|
+
? `**Acceptance Criteria**:\n${(Array.isArray(story.acceptance_criteria) ? story.acceptance_criteria : JSON.parse(story.acceptance_criteria || '[]')).map((c: string) => ` - ${c}`).join('\n')}`
|
|
54
|
+
: ''}`)
|
|
55
|
+
.join('\n\n');
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Format quality check commands for display
|
|
60
|
+
*/
|
|
61
|
+
export function formatQualityChecks(commands: string[]): string {
|
|
62
|
+
return commands.map(cmd => `\`${cmd}\``).join('\n');
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Format agent role description
|
|
67
|
+
*/
|
|
68
|
+
export function getAgentRoleDescription(agentType: string): string {
|
|
69
|
+
switch (agentType) {
|
|
70
|
+
case 'tech_lead':
|
|
71
|
+
return 'Tech Lead - Orchestrates multiple teams, manages cross-repo dependencies, and escalation endpoint';
|
|
72
|
+
case 'senior':
|
|
73
|
+
return 'Senior Developer - Team lead, estimates complexity, delegates work, reviews code';
|
|
74
|
+
case 'intermediate':
|
|
75
|
+
return 'Intermediate Developer - Handles moderate complexity tasks, works on delegated stories';
|
|
76
|
+
case 'junior':
|
|
77
|
+
return 'Junior Developer - Works on simple tasks under senior guidance, learns from code reviews';
|
|
78
|
+
case 'qa':
|
|
79
|
+
return 'QA Agent - Runs quality checks, builds, and validates code before PR submission';
|
|
80
|
+
default:
|
|
81
|
+
return `${agentType} Agent`;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Format hive msg command examples
|
|
87
|
+
*/
|
|
88
|
+
export function formatHiveMsgCommands(agentId?: string): string {
|
|
89
|
+
return `
|
|
90
|
+
## Communication with Hive Team
|
|
91
|
+
|
|
92
|
+
Use \`hive msg\` to communicate with other team members:
|
|
93
|
+
|
|
94
|
+
\`\`\`bash
|
|
95
|
+
# Send a message to your senior
|
|
96
|
+
hive msg send hive-senior-<team> "Your question here"
|
|
97
|
+
|
|
98
|
+
# Send a message to the tech lead
|
|
99
|
+
hive msg send hive-tech-lead "Your question here"
|
|
100
|
+
|
|
101
|
+
# Check your inbox
|
|
102
|
+
hive msg inbox ${agentId || 'your-agent-id'}
|
|
103
|
+
|
|
104
|
+
# Reply to a message
|
|
105
|
+
hive msg reply <msg-id> "Your response here"
|
|
106
|
+
\`\`\`
|
|
107
|
+
|
|
108
|
+
${agentId ? `**Your Agent ID**: \`${agentId}\`` : ''}
|
|
109
|
+
`;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Format git workflow instructions
|
|
114
|
+
*/
|
|
115
|
+
export function formatGitWorkflow(): string {
|
|
116
|
+
return `
|
|
117
|
+
## Git Workflow
|
|
118
|
+
|
|
119
|
+
1. **Create feature branch**: \`git checkout -b feature/<story-id>-<description>\`
|
|
120
|
+
2. **Commit changes**: \`git commit -m "<message>"\` with clear, focused messages
|
|
121
|
+
3. **Keep commits clean**: One logical change per commit
|
|
122
|
+
4. **Push regularly**: \`git push origin feature/<story-id>-<description>\`
|
|
123
|
+
5. **Create PR**: Use GitHub to create a PR with story ID in title
|
|
124
|
+
6. **Link to story**: Include story ID in PR description for tracking
|
|
125
|
+
|
|
126
|
+
### Naming Conventions
|
|
127
|
+
|
|
128
|
+
- **Branches**: \`feature/STORY-123-short-description\`
|
|
129
|
+
- **Commits**: \`STORY-123: Brief description of what changed\`
|
|
130
|
+
- **PR Titles**: \`Story STORY-123: Feature title\`
|
|
131
|
+
`;
|
|
132
|
+
}
|
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
2
|
+
import { tmpdir } from 'os';
|
|
3
|
+
import { join } from 'path';
|
|
4
|
+
import { mkdirSync, readFileSync, rmSync, existsSync } from 'fs';
|
|
5
|
+
import {
|
|
6
|
+
getContextFileName,
|
|
7
|
+
getContextFilePath,
|
|
8
|
+
contextFileExists,
|
|
9
|
+
generateContextFile,
|
|
10
|
+
type ContextFileOptions,
|
|
11
|
+
} from './index.js';
|
|
12
|
+
import type { TeamRow } from '../db/queries/teams.js';
|
|
13
|
+
import type { StoryRow } from '../db/queries/stories.js';
|
|
14
|
+
import type { HiveConfig } from '../config/schema.js';
|
|
15
|
+
|
|
16
|
+
describe('context-files module', () => {
|
|
17
|
+
let testDir: string;
|
|
18
|
+
|
|
19
|
+
beforeEach(() => {
|
|
20
|
+
testDir = join(tmpdir(), `hive-test-${Date.now()}-${Math.random().toString(36).slice(2)}`);
|
|
21
|
+
mkdirSync(testDir, { recursive: true });
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
afterEach(() => {
|
|
25
|
+
if (existsSync(testDir)) {
|
|
26
|
+
rmSync(testDir, { recursive: true, force: true });
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
describe('getContextFileName', () => {
|
|
31
|
+
it('should return CLAUDE.md for claude-code', () => {
|
|
32
|
+
expect(getContextFileName('claude-code')).toBe('CLAUDE.md');
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('should return AGENTS.md for codex', () => {
|
|
36
|
+
expect(getContextFileName('codex')).toBe('AGENTS.md');
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('should return GEMINI.md for gemini', () => {
|
|
40
|
+
expect(getContextFileName('gemini')).toBe('GEMINI.md');
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
describe('getContextFilePath', () => {
|
|
45
|
+
it('should construct correct file path', () => {
|
|
46
|
+
const path = getContextFilePath('/repos/service-a', 'claude-code');
|
|
47
|
+
expect(path).toBe('/repos/service-a/CLAUDE.md');
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('should work for different CLI tools', () => {
|
|
51
|
+
const claudePath = getContextFilePath('/repo', 'claude-code');
|
|
52
|
+
const codexPath = getContextFilePath('/repo', 'codex');
|
|
53
|
+
const geminiPath = getContextFilePath('/repo', 'gemini');
|
|
54
|
+
|
|
55
|
+
expect(claudePath).toContain('CLAUDE.md');
|
|
56
|
+
expect(codexPath).toContain('AGENTS.md');
|
|
57
|
+
expect(geminiPath).toContain('GEMINI.md');
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
describe('contextFileExists', () => {
|
|
62
|
+
it('should return false when file does not exist', () => {
|
|
63
|
+
expect(contextFileExists(testDir, 'claude-code')).toBe(false);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it('should return true when file exists', () => {
|
|
67
|
+
const filePath = getContextFilePath(testDir, 'claude-code');
|
|
68
|
+
mkdirSync(testDir, { recursive: true });
|
|
69
|
+
require('fs').writeFileSync(filePath, 'test content');
|
|
70
|
+
|
|
71
|
+
expect(contextFileExists(testDir, 'claude-code')).toBe(true);
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
describe('generateContextFile', () => {
|
|
76
|
+
const mockTeam: TeamRow = {
|
|
77
|
+
id: 'team-test',
|
|
78
|
+
name: 'test-team',
|
|
79
|
+
repo_path: '',
|
|
80
|
+
repo_url: 'https://github.com/test/repo.git',
|
|
81
|
+
created_at: new Date().toISOString(),
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
const mockStory: StoryRow = {
|
|
85
|
+
id: 'STORY-001',
|
|
86
|
+
requirement_id: 'REQ-001',
|
|
87
|
+
team_id: 'team-test',
|
|
88
|
+
title: 'Implement authentication',
|
|
89
|
+
description: 'Add OAuth2 support',
|
|
90
|
+
acceptance_criteria: JSON.stringify(['User can login', 'Token is valid']),
|
|
91
|
+
complexity_score: 5,
|
|
92
|
+
story_points: 5,
|
|
93
|
+
status: 'in_progress',
|
|
94
|
+
assigned_agent_id: 'agent-001',
|
|
95
|
+
branch_name: 'feature/STORY-001-auth',
|
|
96
|
+
pr_url: 'https://github.com/test/repo/pull/1',
|
|
97
|
+
created_at: new Date().toISOString(),
|
|
98
|
+
updated_at: new Date().toISOString(),
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
const mockConfig: HiveConfig = {
|
|
102
|
+
version: '1.0',
|
|
103
|
+
models: {
|
|
104
|
+
tech_lead: { provider: 'anthropic', model: 'claude-opus', max_tokens: 16000, temperature: 0.7, cli_tool: 'claude' },
|
|
105
|
+
senior: { provider: 'anthropic', model: 'claude-sonnet', max_tokens: 8000, temperature: 0.5, cli_tool: 'claude' },
|
|
106
|
+
intermediate: { provider: 'anthropic', model: 'claude-haiku', max_tokens: 4000, temperature: 0.3, cli_tool: 'claude' },
|
|
107
|
+
junior: { provider: 'openai', model: 'gpt-4o-mini', max_tokens: 4000, temperature: 0.2, cli_tool: 'claude' },
|
|
108
|
+
qa: { provider: 'anthropic', model: 'claude-sonnet', max_tokens: 8000, temperature: 0.2, cli_tool: 'claude' },
|
|
109
|
+
},
|
|
110
|
+
scaling: { senior_capacity: 20, junior_max_complexity: 3, intermediate_max_complexity: 5 },
|
|
111
|
+
github: { base_branch: 'main', pr_template: '' },
|
|
112
|
+
qa: {
|
|
113
|
+
quality_checks: ['npm run lint', 'npm run type-check'],
|
|
114
|
+
build_command: 'npm run build',
|
|
115
|
+
},
|
|
116
|
+
agents: {
|
|
117
|
+
poll_interval: 5000,
|
|
118
|
+
max_retries: 2,
|
|
119
|
+
checkpoint_threshold: 14000,
|
|
120
|
+
llm_timeout_ms: 1800000,
|
|
121
|
+
llm_max_retries: 2,
|
|
122
|
+
},
|
|
123
|
+
manager: { fast_poll_interval: 15000, slow_poll_interval: 60000 },
|
|
124
|
+
logging: { level: 'info', retention_days: 30 },
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
it('should create a new context file if it does not exist', () => {
|
|
128
|
+
const team = { ...mockTeam, repo_path: testDir };
|
|
129
|
+
const options: ContextFileOptions = {
|
|
130
|
+
cliTool: 'claude-code',
|
|
131
|
+
team,
|
|
132
|
+
stories: [mockStory],
|
|
133
|
+
agentType: 'intermediate',
|
|
134
|
+
config: mockConfig,
|
|
135
|
+
agentId: 'agent-001',
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
generateContextFile(options);
|
|
139
|
+
|
|
140
|
+
expect(contextFileExists(testDir, 'claude-code')).toBe(true);
|
|
141
|
+
const content = readFileSync(getContextFilePath(testDir, 'claude-code'), 'utf-8');
|
|
142
|
+
expect(content).toContain('<!-- HIVE:START -->');
|
|
143
|
+
expect(content).toContain('<!-- HIVE:END -->');
|
|
144
|
+
expect(content).toContain('STORY-001');
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
it('should include story information in generated file', () => {
|
|
148
|
+
const team = { ...mockTeam, repo_path: testDir };
|
|
149
|
+
const options: ContextFileOptions = {
|
|
150
|
+
cliTool: 'claude-code',
|
|
151
|
+
team,
|
|
152
|
+
stories: [mockStory],
|
|
153
|
+
agentType: 'senior',
|
|
154
|
+
config: mockConfig,
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
generateContextFile(options);
|
|
158
|
+
|
|
159
|
+
const content = readFileSync(getContextFilePath(testDir, 'claude-code'), 'utf-8');
|
|
160
|
+
expect(content).toContain('STORY-001');
|
|
161
|
+
expect(content).toContain('Implement authentication');
|
|
162
|
+
expect(content).toContain('OAuth2');
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
it('should generate different content for different CLI tools', () => {
|
|
166
|
+
const team = { ...mockTeam, repo_path: testDir };
|
|
167
|
+
const baseOptions: ContextFileOptions = {
|
|
168
|
+
cliTool: 'claude-code',
|
|
169
|
+
team,
|
|
170
|
+
stories: [mockStory],
|
|
171
|
+
agentType: 'intermediate',
|
|
172
|
+
config: mockConfig,
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
// Generate for Claude Code
|
|
176
|
+
generateContextFile({ ...baseOptions, cliTool: 'claude-code' });
|
|
177
|
+
const claudeContent = readFileSync(getContextFilePath(testDir, 'claude-code'), 'utf-8');
|
|
178
|
+
|
|
179
|
+
// Clean up and generate for Codex
|
|
180
|
+
rmSync(testDir, { recursive: true, force: true });
|
|
181
|
+
mkdirSync(testDir, { recursive: true });
|
|
182
|
+
|
|
183
|
+
generateContextFile({ ...baseOptions, cliTool: 'codex' });
|
|
184
|
+
const codexContent = readFileSync(getContextFilePath(testDir, 'codex'), 'utf-8');
|
|
185
|
+
|
|
186
|
+
// Both should have markers and story info, but different headers
|
|
187
|
+
expect(claudeContent).toContain('Claude Code');
|
|
188
|
+
expect(codexContent).toContain('Codex');
|
|
189
|
+
expect(claudeContent).toContain('STORY-001');
|
|
190
|
+
expect(codexContent).toContain('STORY-001');
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
it('should update existing file preserving content outside markers', () => {
|
|
194
|
+
const team = { ...mockTeam, repo_path: testDir };
|
|
195
|
+
const filePath = getContextFilePath(testDir, 'claude-code');
|
|
196
|
+
|
|
197
|
+
// Write initial file with custom content
|
|
198
|
+
mkdirSync(testDir, { recursive: true });
|
|
199
|
+
const initialContent = `# My Custom Header
|
|
200
|
+
|
|
201
|
+
This is my custom content that should be preserved.
|
|
202
|
+
|
|
203
|
+
<!-- HIVE:START -->
|
|
204
|
+
Old Hive content
|
|
205
|
+
<!-- HIVE:END -->
|
|
206
|
+
|
|
207
|
+
## Footer
|
|
208
|
+
|
|
209
|
+
More custom content here.`;
|
|
210
|
+
|
|
211
|
+
require('fs').writeFileSync(filePath, initialContent);
|
|
212
|
+
|
|
213
|
+
// Generate new context
|
|
214
|
+
const options: ContextFileOptions = {
|
|
215
|
+
cliTool: 'claude-code',
|
|
216
|
+
team,
|
|
217
|
+
stories: [mockStory],
|
|
218
|
+
agentType: 'junior',
|
|
219
|
+
config: mockConfig,
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
generateContextFile(options);
|
|
223
|
+
|
|
224
|
+
const updatedContent = readFileSync(filePath, 'utf-8');
|
|
225
|
+
|
|
226
|
+
// Original content should be preserved
|
|
227
|
+
expect(updatedContent).toContain('# My Custom Header');
|
|
228
|
+
expect(updatedContent).toContain('This is my custom content');
|
|
229
|
+
expect(updatedContent).toContain('## Footer');
|
|
230
|
+
expect(updatedContent).toContain('More custom content here');
|
|
231
|
+
|
|
232
|
+
// Hive content should be updated
|
|
233
|
+
expect(updatedContent).toContain('STORY-001');
|
|
234
|
+
expect(updatedContent).not.toContain('Old Hive content');
|
|
235
|
+
expect(updatedContent).toContain('<!-- HIVE:START -->');
|
|
236
|
+
expect(updatedContent).toContain('<!-- HIVE:END -->');
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
it('should append Hive section if markers do not exist', () => {
|
|
240
|
+
const team = { ...mockTeam, repo_path: testDir };
|
|
241
|
+
const filePath = getContextFilePath(testDir, 'claude-code');
|
|
242
|
+
|
|
243
|
+
// Write initial file without markers
|
|
244
|
+
mkdirSync(testDir, { recursive: true });
|
|
245
|
+
const initialContent = '# Existing README\n\nSome content here.';
|
|
246
|
+
require('fs').writeFileSync(filePath, initialContent);
|
|
247
|
+
|
|
248
|
+
// Generate context
|
|
249
|
+
const options: ContextFileOptions = {
|
|
250
|
+
cliTool: 'claude-code',
|
|
251
|
+
team,
|
|
252
|
+
stories: [mockStory],
|
|
253
|
+
agentType: 'qa',
|
|
254
|
+
config: mockConfig,
|
|
255
|
+
};
|
|
256
|
+
|
|
257
|
+
generateContextFile(options);
|
|
258
|
+
|
|
259
|
+
const updatedContent = readFileSync(filePath, 'utf-8');
|
|
260
|
+
|
|
261
|
+
// Original content should be preserved
|
|
262
|
+
expect(updatedContent).toContain('# Existing README');
|
|
263
|
+
expect(updatedContent).toContain('Some content here');
|
|
264
|
+
|
|
265
|
+
// Hive content should be appended
|
|
266
|
+
expect(updatedContent).toContain('<!-- HIVE:START -->');
|
|
267
|
+
expect(updatedContent).toContain('STORY-001');
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
it('should work with empty stories list', () => {
|
|
271
|
+
const team = { ...mockTeam, repo_path: testDir };
|
|
272
|
+
const options: ContextFileOptions = {
|
|
273
|
+
cliTool: 'claude-code',
|
|
274
|
+
team,
|
|
275
|
+
stories: [],
|
|
276
|
+
agentType: 'senior',
|
|
277
|
+
config: mockConfig,
|
|
278
|
+
};
|
|
279
|
+
|
|
280
|
+
generateContextFile(options);
|
|
281
|
+
|
|
282
|
+
const content = readFileSync(getContextFilePath(testDir, 'claude-code'), 'utf-8');
|
|
283
|
+
expect(content).toContain('<!-- HIVE:START -->');
|
|
284
|
+
expect(content).toContain('No active stories');
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
it('should include quality check commands from config', () => {
|
|
288
|
+
const team = { ...mockTeam, repo_path: testDir };
|
|
289
|
+
const options: ContextFileOptions = {
|
|
290
|
+
cliTool: 'claude-code',
|
|
291
|
+
team,
|
|
292
|
+
stories: [mockStory],
|
|
293
|
+
agentType: 'intermediate',
|
|
294
|
+
config: mockConfig,
|
|
295
|
+
};
|
|
296
|
+
|
|
297
|
+
generateContextFile(options);
|
|
298
|
+
|
|
299
|
+
const content = readFileSync(getContextFilePath(testDir, 'claude-code'), 'utf-8');
|
|
300
|
+
expect(content).toContain('npm run lint');
|
|
301
|
+
expect(content).toContain('npm run type-check');
|
|
302
|
+
expect(content).toContain('npm run build');
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
it('should include agent ID when provided', () => {
|
|
306
|
+
const team = { ...mockTeam, repo_path: testDir };
|
|
307
|
+
const agentId = 'intermediate-abc123def456';
|
|
308
|
+
const options: ContextFileOptions = {
|
|
309
|
+
cliTool: 'claude-code',
|
|
310
|
+
team,
|
|
311
|
+
stories: [mockStory],
|
|
312
|
+
agentType: 'intermediate',
|
|
313
|
+
config: mockConfig,
|
|
314
|
+
agentId,
|
|
315
|
+
};
|
|
316
|
+
|
|
317
|
+
generateContextFile(options);
|
|
318
|
+
|
|
319
|
+
const content = readFileSync(getContextFilePath(testDir, 'claude-code'), 'utf-8');
|
|
320
|
+
expect(content).toContain(agentId);
|
|
321
|
+
});
|
|
322
|
+
});
|
|
323
|
+
});
|