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,166 @@
|
|
|
1
|
+
import { BaseAgent, type AgentContext } from './base-agent.js';
|
|
2
|
+
import { getTeamById, type TeamRow } from '../db/queries/teams.js';
|
|
3
|
+
import { updateStory, getStoryById, type StoryRow } from '../db/queries/stories.js';
|
|
4
|
+
import { getAgentsByTeam } from '../db/queries/agents.js';
|
|
5
|
+
import { createEscalation } from '../db/queries/escalations.js';
|
|
6
|
+
|
|
7
|
+
export interface JuniorContext extends AgentContext {
|
|
8
|
+
storyId?: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export class JuniorAgent extends BaseAgent {
|
|
12
|
+
private team: TeamRow | null = null;
|
|
13
|
+
private story: StoryRow | null = null;
|
|
14
|
+
private retryCount = 0;
|
|
15
|
+
|
|
16
|
+
constructor(context: JuniorContext) {
|
|
17
|
+
super(context);
|
|
18
|
+
if (context.agentRow.team_id) {
|
|
19
|
+
this.team = getTeamById(this.db, context.agentRow.team_id) || null;
|
|
20
|
+
}
|
|
21
|
+
if (context.storyId) {
|
|
22
|
+
this.story = getStoryById(this.db, context.storyId) || null;
|
|
23
|
+
} else if (context.agentRow.current_story_id) {
|
|
24
|
+
this.story = getStoryById(this.db, context.agentRow.current_story_id) || null;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
getSystemPrompt(): string {
|
|
29
|
+
const teamInfo = this.team
|
|
30
|
+
? `Team: ${this.team.name}\nRepository: ${this.team.repo_path}`
|
|
31
|
+
: 'No team assigned';
|
|
32
|
+
|
|
33
|
+
const storyInfo = this.story
|
|
34
|
+
? `Current Story: ${this.story.id}\nTitle: ${this.story.title}\nStatus: ${this.story.status}`
|
|
35
|
+
: 'No story assigned';
|
|
36
|
+
|
|
37
|
+
return `You are a Junior Developer working on simple, well-defined stories.
|
|
38
|
+
|
|
39
|
+
## Your Team
|
|
40
|
+
${teamInfo}
|
|
41
|
+
|
|
42
|
+
## Assignment
|
|
43
|
+
${storyInfo}
|
|
44
|
+
|
|
45
|
+
## Your Responsibilities
|
|
46
|
+
1. Implement simple stories (1-3 complexity points)
|
|
47
|
+
2. Follow coding patterns exactly as shown in the codebase
|
|
48
|
+
3. Write basic tests
|
|
49
|
+
4. Ask questions when unsure
|
|
50
|
+
5. Escalate to Senior quickly if stuck
|
|
51
|
+
|
|
52
|
+
## Development Guidelines
|
|
53
|
+
- Always read existing code before making changes
|
|
54
|
+
- Match the coding style exactly
|
|
55
|
+
- Keep changes minimal and focused
|
|
56
|
+
- Commit small, atomic changes
|
|
57
|
+
- Ask for help early rather than struggling
|
|
58
|
+
|
|
59
|
+
## Important
|
|
60
|
+
- You should NOT make architectural decisions
|
|
61
|
+
- You should NOT refactor unrelated code
|
|
62
|
+
- You should ask for clarification rather than guessing
|
|
63
|
+
- Escalate any blockers to Senior immediately
|
|
64
|
+
|
|
65
|
+
## Current Context
|
|
66
|
+
${this.memoryState.conversationSummary || 'Starting fresh.'}`;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
async execute(): Promise<void> {
|
|
70
|
+
if (!this.story) {
|
|
71
|
+
this.log('STORY_PROGRESS_UPDATE', 'No story assigned, waiting');
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
this.setCurrentTask(this.story.id, 'implementation');
|
|
76
|
+
this.log('STORY_STARTED', `Working on: ${this.story.title}`, { storyId: this.story.id });
|
|
77
|
+
|
|
78
|
+
try {
|
|
79
|
+
await this.implementStory();
|
|
80
|
+
} catch (err) {
|
|
81
|
+
this.retryCount++;
|
|
82
|
+
// Juniors escalate after just 1 retry
|
|
83
|
+
if (this.retryCount >= 1) {
|
|
84
|
+
await this.escalateToSenior(`Encountered error: ${err instanceof Error ? err.message : 'Unknown error'}`);
|
|
85
|
+
} else {
|
|
86
|
+
this.log('STORY_PROGRESS_UPDATE', `Error: ${err instanceof Error ? err.message : 'Unknown error'}`, {
|
|
87
|
+
storyId: this.story.id,
|
|
88
|
+
});
|
|
89
|
+
await this.execute();
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
private async implementStory(): Promise<void> {
|
|
95
|
+
if (!this.story) return;
|
|
96
|
+
|
|
97
|
+
const branchName = this.story.branch_name ||
|
|
98
|
+
`feature/${this.story.id.toLowerCase()}-${this.story.title.toLowerCase().replace(/[^a-z0-9]+/g, '-').substring(0, 30)}`;
|
|
99
|
+
|
|
100
|
+
if (!this.story.branch_name) {
|
|
101
|
+
updateStory(this.db, this.story.id, { branchName });
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const prompt = `I need to implement this simple story:
|
|
105
|
+
|
|
106
|
+
## Story: ${this.story.id}
|
|
107
|
+
**Title:** ${this.story.title}
|
|
108
|
+
|
|
109
|
+
**Description:**
|
|
110
|
+
${this.story.description}
|
|
111
|
+
|
|
112
|
+
**Acceptance Criteria:**
|
|
113
|
+
${this.story.acceptance_criteria ? JSON.parse(this.story.acceptance_criteria).join('\n- ') : 'None specified'}
|
|
114
|
+
|
|
115
|
+
**Branch:** ${branchName}
|
|
116
|
+
|
|
117
|
+
This is a simple task (complexity ${this.story.complexity_score || 1}-3).
|
|
118
|
+
|
|
119
|
+
## My Approach
|
|
120
|
+
1. First, I'll read the relevant files
|
|
121
|
+
2. Make the minimal required changes
|
|
122
|
+
3. Follow the existing patterns exactly
|
|
123
|
+
4. Write a simple test if applicable
|
|
124
|
+
5. Commit the changes
|
|
125
|
+
|
|
126
|
+
Please help me identify which files I need to read and modify.`;
|
|
127
|
+
|
|
128
|
+
await this.chat(prompt);
|
|
129
|
+
this.updateTaskProgress('Analyzing task', []);
|
|
130
|
+
this.log('STORY_PROGRESS_UPDATE', 'Analyzing requirements', { storyId: this.story.id });
|
|
131
|
+
|
|
132
|
+
// Get guidance and implement
|
|
133
|
+
const implementPrompt = `Based on the analysis, show me the exact code changes to make. Keep it simple and minimal.`;
|
|
134
|
+
await this.chat(implementPrompt);
|
|
135
|
+
this.log('STORY_PROGRESS_UPDATE', 'Making code changes', { storyId: this.story.id });
|
|
136
|
+
|
|
137
|
+
// Complete
|
|
138
|
+
updateStory(this.db, this.story.id, { status: 'review' });
|
|
139
|
+
this.log('STORY_COMPLETED', 'Implementation complete, ready for review', {
|
|
140
|
+
storyId: this.story.id,
|
|
141
|
+
branchName,
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
private async escalateToSenior(reason: string): Promise<void> {
|
|
146
|
+
const seniors = getAgentsByTeam(this.db, this.teamId!)
|
|
147
|
+
.filter(a => a.type === 'senior' && a.status !== 'terminated');
|
|
148
|
+
|
|
149
|
+
const seniorId = seniors[0]?.id;
|
|
150
|
+
|
|
151
|
+
const escalation = createEscalation(this.db, {
|
|
152
|
+
storyId: this.story?.id,
|
|
153
|
+
fromAgentId: this.agentId,
|
|
154
|
+
toAgentId: seniorId,
|
|
155
|
+
reason,
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
this.log('ESCALATION_CREATED', reason, {
|
|
159
|
+
escalationId: escalation.id,
|
|
160
|
+
toAgent: seniorId,
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
this.updateStatus('blocked');
|
|
164
|
+
this.addBlocker(`Escalated to Senior: ${reason}`);
|
|
165
|
+
}
|
|
166
|
+
}
|
package/src/agents/qa.ts
ADDED
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
import { BaseAgent, type AgentContext } from './base-agent.js';
|
|
2
|
+
import { getTeamById, type TeamRow } from '../db/queries/teams.js';
|
|
3
|
+
import { getStoriesByStatus, updateStory, type StoryRow } from '../db/queries/stories.js';
|
|
4
|
+
import { createPullRequest, getPullRequestByStory } from '../db/queries/pull-requests.js';
|
|
5
|
+
import { execa } from 'execa';
|
|
6
|
+
|
|
7
|
+
export interface QAContext extends AgentContext {
|
|
8
|
+
qaConfig: {
|
|
9
|
+
qualityChecks: string[];
|
|
10
|
+
buildCommand: string;
|
|
11
|
+
testCommand?: string;
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export class QAAgent extends BaseAgent {
|
|
16
|
+
private team: TeamRow | null = null;
|
|
17
|
+
private qaConfig: QAContext['qaConfig'];
|
|
18
|
+
private pendingStories: StoryRow[] = [];
|
|
19
|
+
|
|
20
|
+
constructor(context: QAContext) {
|
|
21
|
+
super(context);
|
|
22
|
+
this.qaConfig = context.qaConfig;
|
|
23
|
+
|
|
24
|
+
if (context.agentRow.team_id) {
|
|
25
|
+
this.team = getTeamById(this.db, context.agentRow.team_id) || null;
|
|
26
|
+
this.pendingStories = getStoriesByStatus(this.db, 'qa')
|
|
27
|
+
.filter(s => s.team_id === context.agentRow.team_id);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
getSystemPrompt(): string {
|
|
32
|
+
const teamInfo = this.team
|
|
33
|
+
? `Team: ${this.team.name}\nRepository: ${this.team.repo_path}`
|
|
34
|
+
: 'No team assigned';
|
|
35
|
+
|
|
36
|
+
return `You are the QA Agent ensuring code quality before PR submission.
|
|
37
|
+
|
|
38
|
+
## Your Team
|
|
39
|
+
${teamInfo}
|
|
40
|
+
|
|
41
|
+
## Quality Checklist
|
|
42
|
+
- Code passes linting
|
|
43
|
+
- Code passes type checking
|
|
44
|
+
- Build succeeds
|
|
45
|
+
- Tests pass (if configured)
|
|
46
|
+
- Changes align with acceptance criteria
|
|
47
|
+
- No obvious security issues
|
|
48
|
+
- Code follows repository patterns
|
|
49
|
+
|
|
50
|
+
## Commands
|
|
51
|
+
Quality checks: ${this.qaConfig.qualityChecks.join(', ')}
|
|
52
|
+
Build: ${this.qaConfig.buildCommand}
|
|
53
|
+
${this.qaConfig.testCommand ? `Test: ${this.qaConfig.testCommand}` : ''}
|
|
54
|
+
|
|
55
|
+
## On Failure
|
|
56
|
+
- Mark story as 'qa_failed'
|
|
57
|
+
- Log specific failures with actionable feedback
|
|
58
|
+
- Story returns to developer for fixes
|
|
59
|
+
|
|
60
|
+
## On Success
|
|
61
|
+
- Create GitHub PR
|
|
62
|
+
- Mark story as 'pr_submitted'
|
|
63
|
+
|
|
64
|
+
## Current Context
|
|
65
|
+
${this.memoryState.conversationSummary || 'Starting fresh.'}`;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
async execute(): Promise<void> {
|
|
69
|
+
if (this.pendingStories.length === 0) {
|
|
70
|
+
this.log('STORY_QA_STARTED', 'No stories pending QA');
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
for (const story of this.pendingStories) {
|
|
75
|
+
await this.processStory(story);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
private async processStory(story: StoryRow): Promise<void> {
|
|
80
|
+
this.setCurrentTask(story.id, 'qa');
|
|
81
|
+
this.log('STORY_QA_STARTED', `QA for story: ${story.title}`, { storyId: story.id });
|
|
82
|
+
|
|
83
|
+
// Checkout the branch
|
|
84
|
+
if (story.branch_name) {
|
|
85
|
+
try {
|
|
86
|
+
await execa('git', ['checkout', story.branch_name], { cwd: this.workDir });
|
|
87
|
+
} catch (err) {
|
|
88
|
+
this.log('STORY_QA_FAILED', `Failed to checkout branch: ${err instanceof Error ? err.message : 'Unknown error'}`, {
|
|
89
|
+
storyId: story.id,
|
|
90
|
+
});
|
|
91
|
+
updateStory(this.db, story.id, { status: 'qa_failed' });
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Run quality checks
|
|
97
|
+
const qualityPassed = await this.runQualityChecks(story.id);
|
|
98
|
+
if (!qualityPassed) {
|
|
99
|
+
updateStory(this.db, story.id, { status: 'qa_failed' });
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Run build
|
|
104
|
+
const buildPassed = await this.runBuild(story.id);
|
|
105
|
+
if (!buildPassed) {
|
|
106
|
+
updateStory(this.db, story.id, { status: 'qa_failed' });
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Run tests if configured
|
|
111
|
+
if (this.qaConfig.testCommand) {
|
|
112
|
+
const testsPassed = await this.runTests(story.id);
|
|
113
|
+
if (!testsPassed) {
|
|
114
|
+
updateStory(this.db, story.id, { status: 'qa_failed' });
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// All checks passed
|
|
120
|
+
this.log('STORY_QA_PASSED', 'All QA checks passed', { storyId: story.id });
|
|
121
|
+
|
|
122
|
+
// Create PR
|
|
123
|
+
await this.createPR(story);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
private async runQualityChecks(storyId: string): Promise<boolean> {
|
|
127
|
+
this.log('CODE_QUALITY_CHECK_STARTED', 'Running quality checks', { storyId });
|
|
128
|
+
|
|
129
|
+
for (const check of this.qaConfig.qualityChecks) {
|
|
130
|
+
try {
|
|
131
|
+
const [cmd, ...args] = check.split(' ');
|
|
132
|
+
await execa(cmd, args, { cwd: this.workDir });
|
|
133
|
+
} catch (err) {
|
|
134
|
+
const error = err as { stderr?: string; stdout?: string };
|
|
135
|
+
this.log('CODE_QUALITY_CHECK_FAILED', `Check failed: ${check}`, {
|
|
136
|
+
storyId,
|
|
137
|
+
error: error.stderr || error.stdout,
|
|
138
|
+
});
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
this.log('CODE_QUALITY_CHECK_PASSED', 'All quality checks passed', { storyId });
|
|
144
|
+
return true;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
private async runBuild(storyId: string): Promise<boolean> {
|
|
148
|
+
this.log('BUILD_STARTED', 'Running build', { storyId });
|
|
149
|
+
|
|
150
|
+
try {
|
|
151
|
+
const [cmd, ...args] = this.qaConfig.buildCommand.split(' ');
|
|
152
|
+
await execa(cmd, args, { cwd: this.workDir });
|
|
153
|
+
this.log('BUILD_PASSED', 'Build succeeded', { storyId });
|
|
154
|
+
return true;
|
|
155
|
+
} catch (err) {
|
|
156
|
+
const error = err as { stderr?: string; stdout?: string };
|
|
157
|
+
this.log('BUILD_FAILED', 'Build failed', {
|
|
158
|
+
storyId,
|
|
159
|
+
error: error.stderr || error.stdout,
|
|
160
|
+
});
|
|
161
|
+
return false;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
private async runTests(storyId: string): Promise<boolean> {
|
|
166
|
+
if (!this.qaConfig.testCommand) return true;
|
|
167
|
+
|
|
168
|
+
this.log('BUILD_STARTED', 'Running tests', { storyId });
|
|
169
|
+
|
|
170
|
+
try {
|
|
171
|
+
const [cmd, ...args] = this.qaConfig.testCommand.split(' ');
|
|
172
|
+
await execa(cmd, args, { cwd: this.workDir });
|
|
173
|
+
this.log('BUILD_PASSED', 'Tests passed', { storyId });
|
|
174
|
+
return true;
|
|
175
|
+
} catch (err) {
|
|
176
|
+
const error = err as { stderr?: string; stdout?: string };
|
|
177
|
+
this.log('BUILD_FAILED', 'Tests failed', {
|
|
178
|
+
storyId,
|
|
179
|
+
error: error.stderr || error.stdout,
|
|
180
|
+
});
|
|
181
|
+
return false;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
private async createPR(story: StoryRow): Promise<void> {
|
|
186
|
+
if (!story.branch_name) {
|
|
187
|
+
this.log('STORY_PR_CREATED', 'No branch name, skipping PR creation', { storyId: story.id });
|
|
188
|
+
updateStory(this.db, story.id, { status: 'pr_submitted' });
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// Check if PR already exists
|
|
193
|
+
const existingPR = getPullRequestByStory(this.db, story.id);
|
|
194
|
+
if (existingPR) {
|
|
195
|
+
this.log('STORY_PR_CREATED', 'PR already exists', {
|
|
196
|
+
storyId: story.id,
|
|
197
|
+
prUrl: existingPR.github_pr_url,
|
|
198
|
+
});
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// Create PR using gh CLI
|
|
203
|
+
try {
|
|
204
|
+
const title = `${story.id}: ${story.title}`;
|
|
205
|
+
const body = this.generatePRBody(story);
|
|
206
|
+
|
|
207
|
+
const { stdout } = await execa('gh', [
|
|
208
|
+
'pr', 'create',
|
|
209
|
+
'--title', title,
|
|
210
|
+
'--body', body,
|
|
211
|
+
'--base', 'main',
|
|
212
|
+
'--head', story.branch_name,
|
|
213
|
+
], { cwd: this.workDir });
|
|
214
|
+
|
|
215
|
+
// Extract PR URL from output
|
|
216
|
+
const prUrl = stdout.trim();
|
|
217
|
+
const prNumberMatch = prUrl.match(/\/pull\/(\d+)/);
|
|
218
|
+
const prNumber = prNumberMatch ? parseInt(prNumberMatch[1], 10) : undefined;
|
|
219
|
+
|
|
220
|
+
// Create PR record
|
|
221
|
+
const pr = createPullRequest(this.db, {
|
|
222
|
+
storyId: story.id,
|
|
223
|
+
teamId: story.team_id,
|
|
224
|
+
branchName: story.branch_name || `feature/${story.id}`,
|
|
225
|
+
githubPrNumber: prNumber,
|
|
226
|
+
githubPrUrl: prUrl,
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
// Update story
|
|
230
|
+
updateStory(this.db, story.id, {
|
|
231
|
+
prUrl,
|
|
232
|
+
status: 'pr_submitted',
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
this.log('STORY_PR_CREATED', `PR created: ${prUrl}`, {
|
|
236
|
+
storyId: story.id,
|
|
237
|
+
prId: pr.id,
|
|
238
|
+
prNumber,
|
|
239
|
+
});
|
|
240
|
+
} catch (err) {
|
|
241
|
+
const error = err as { stderr?: string };
|
|
242
|
+
this.log('STORY_PR_CREATED', `Failed to create PR: ${error.stderr || 'Unknown error'}`, {
|
|
243
|
+
storyId: story.id,
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
// Still mark as pr_submitted since QA passed
|
|
247
|
+
updateStory(this.db, story.id, { status: 'pr_submitted' });
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
private generatePRBody(story: StoryRow): string {
|
|
252
|
+
const acceptanceCriteria = story.acceptance_criteria
|
|
253
|
+
? JSON.parse(story.acceptance_criteria).map((c: string) => `- [ ] ${c}`).join('\n')
|
|
254
|
+
: 'N/A';
|
|
255
|
+
|
|
256
|
+
return `## Story: ${story.id}
|
|
257
|
+
|
|
258
|
+
${story.description}
|
|
259
|
+
|
|
260
|
+
### Acceptance Criteria
|
|
261
|
+
${acceptanceCriteria}
|
|
262
|
+
|
|
263
|
+
### QA Checklist
|
|
264
|
+
- [x] Code passes linting
|
|
265
|
+
- [x] Code passes type checking
|
|
266
|
+
- [x] Build succeeds
|
|
267
|
+
- [x] Changes align with acceptance criteria
|
|
268
|
+
|
|
269
|
+
---
|
|
270
|
+
*Generated by Hive QA Agent*`;
|
|
271
|
+
}
|
|
272
|
+
}
|