hungry-ghost-hive 0.48.0 → 0.49.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/dist/agents/base-agent.d.ts +11 -11
- package/dist/agents/base-agent.d.ts.map +1 -1
- package/dist/agents/base-agent.js +25 -25
- package/dist/agents/base-agent.js.map +1 -1
- package/dist/agents/base-agent.test.js +2 -1
- package/dist/agents/base-agent.test.js.map +1 -1
- package/dist/agents/intermediate.d.ts +2 -0
- package/dist/agents/intermediate.d.ts.map +1 -1
- package/dist/agents/intermediate.js +25 -18
- package/dist/agents/intermediate.js.map +1 -1
- package/dist/agents/junior.d.ts +2 -0
- package/dist/agents/junior.d.ts.map +1 -1
- package/dist/agents/junior.js +25 -18
- package/dist/agents/junior.js.map +1 -1
- package/dist/agents/qa.d.ts +2 -0
- package/dist/agents/qa.d.ts.map +1 -1
- package/dist/agents/qa.js +47 -38
- package/dist/agents/qa.js.map +1 -1
- package/dist/agents/senior.d.ts +2 -0
- package/dist/agents/senior.d.ts.map +1 -1
- package/dist/agents/senior.js +40 -27
- package/dist/agents/senior.js.map +1 -1
- package/dist/agents/tech-lead.d.ts +2 -0
- package/dist/agents/tech-lead.d.ts.map +1 -1
- package/dist/agents/tech-lead.js +37 -31
- package/dist/agents/tech-lead.js.map +1 -1
- package/dist/cli/commands/add-repo.js +2 -2
- package/dist/cli/commands/add-repo.js.map +1 -1
- package/dist/cli/commands/add-repo.test.js +1 -1
- package/dist/cli/commands/add-repo.test.js.map +1 -1
- package/dist/cli/commands/agents.d.ts.map +1 -1
- package/dist/cli/commands/agents.js +12 -10
- package/dist/cli/commands/agents.js.map +1 -1
- package/dist/cli/commands/agents.test.js +7 -7
- package/dist/cli/commands/agents.test.js.map +1 -1
- package/dist/cli/commands/approach.js +2 -2
- package/dist/cli/commands/approach.js.map +1 -1
- package/dist/cli/commands/approvals.js +7 -7
- package/dist/cli/commands/approvals.js.map +1 -1
- package/dist/cli/commands/approvals.test.js +8 -8
- package/dist/cli/commands/approvals.test.js.map +1 -1
- package/dist/cli/commands/assign.js +4 -4
- package/dist/cli/commands/assign.js.map +1 -1
- package/dist/cli/commands/assign.test.js +18 -16
- package/dist/cli/commands/assign.test.js.map +1 -1
- package/dist/cli/commands/cleanup.d.ts.map +1 -1
- package/dist/cli/commands/cleanup.js +8 -8
- package/dist/cli/commands/cleanup.js.map +1 -1
- package/dist/cli/commands/cleanup.test.js +5 -1
- package/dist/cli/commands/cleanup.test.js.map +1 -1
- package/dist/cli/commands/escalations.js +9 -7
- package/dist/cli/commands/escalations.js.map +1 -1
- package/dist/cli/commands/escalations.test.js +2 -2
- package/dist/cli/commands/escalations.test.js.map +1 -1
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +48 -5
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/init.test.js +4 -0
- package/dist/cli/commands/init.test.js.map +1 -1
- package/dist/cli/commands/manager/agent-monitoring.d.ts +2 -2
- package/dist/cli/commands/manager/agent-monitoring.d.ts.map +1 -1
- package/dist/cli/commands/manager/agent-monitoring.js +1 -1
- package/dist/cli/commands/manager/agent-monitoring.js.map +1 -1
- package/dist/cli/commands/manager/auditor-lifecycle.js +3 -3
- package/dist/cli/commands/manager/auditor-lifecycle.js.map +1 -1
- package/dist/cli/commands/manager/auditor-lifecycle.test.js +21 -14
- package/dist/cli/commands/manager/auditor-lifecycle.test.js.map +1 -1
- package/dist/cli/commands/manager/auto-reject-comment-only-reviews.test.js +28 -23
- package/dist/cli/commands/manager/auto-reject-comment-only-reviews.test.js.map +1 -1
- package/dist/cli/commands/manager/escalation-handler.d.ts +2 -2
- package/dist/cli/commands/manager/escalation-handler.d.ts.map +1 -1
- package/dist/cli/commands/manager/escalation-handler.js +11 -10
- package/dist/cli/commands/manager/escalation-handler.js.map +1 -1
- package/dist/cli/commands/manager/escalation-handler.test.js +8 -8
- package/dist/cli/commands/manager/escalation-handler.test.js.map +1 -1
- package/dist/cli/commands/manager/feature-sign-off.js +7 -7
- package/dist/cli/commands/manager/feature-sign-off.js.map +1 -1
- package/dist/cli/commands/manager/feature-sign-off.test.js +40 -31
- package/dist/cli/commands/manager/feature-sign-off.test.js.map +1 -1
- package/dist/cli/commands/manager/feature-test-result.d.ts.map +1 -1
- package/dist/cli/commands/manager/feature-test-result.js +12 -13
- package/dist/cli/commands/manager/feature-test-result.js.map +1 -1
- package/dist/cli/commands/manager/handoff-recovery.d.ts.map +1 -1
- package/dist/cli/commands/manager/handoff-recovery.js +14 -15
- package/dist/cli/commands/manager/handoff-recovery.js.map +1 -1
- package/dist/cli/commands/manager/index.d.ts.map +1 -1
- package/dist/cli/commands/manager/index.js +26 -26
- package/dist/cli/commands/manager/index.js.map +1 -1
- package/dist/cli/commands/manager/index.test.js +3 -3
- package/dist/cli/commands/manager/index.test.js.map +1 -1
- package/dist/cli/commands/manager/merged-story-cleanup.d.ts +2 -2
- package/dist/cli/commands/manager/merged-story-cleanup.d.ts.map +1 -1
- package/dist/cli/commands/manager/merged-story-cleanup.js +6 -7
- package/dist/cli/commands/manager/merged-story-cleanup.js.map +1 -1
- package/dist/cli/commands/manager/merged-story-cleanup.test.js +27 -18
- package/dist/cli/commands/manager/merged-story-cleanup.test.js.map +1 -1
- package/dist/cli/commands/manager/pr-sync-orchestrator.d.ts.map +1 -1
- package/dist/cli/commands/manager/pr-sync-orchestrator.js +46 -38
- package/dist/cli/commands/manager/pr-sync-orchestrator.js.map +1 -1
- package/dist/cli/commands/manager/qa-review-handler.d.ts.map +1 -1
- package/dist/cli/commands/manager/qa-review-handler.js +25 -22
- package/dist/cli/commands/manager/qa-review-handler.js.map +1 -1
- package/dist/cli/commands/manager/spin-down.d.ts.map +1 -1
- package/dist/cli/commands/manager/spin-down.js +23 -19
- package/dist/cli/commands/manager/spin-down.js.map +1 -1
- package/dist/cli/commands/manager/stale-escalations.d.ts +2 -3
- package/dist/cli/commands/manager/stale-escalations.d.ts.map +1 -1
- package/dist/cli/commands/manager/stale-escalations.js.map +1 -1
- package/dist/cli/commands/manager/stuck-story-helpers.js +8 -8
- package/dist/cli/commands/manager/stuck-story-helpers.js.map +1 -1
- package/dist/cli/commands/manager/stuck-story-processor.d.ts +2 -2
- package/dist/cli/commands/manager/stuck-story-processor.d.ts.map +1 -1
- package/dist/cli/commands/manager/stuck-story-processor.js +23 -22
- package/dist/cli/commands/manager/stuck-story-processor.js.map +1 -1
- package/dist/cli/commands/manager/tech-lead-lifecycle.js +6 -6
- package/dist/cli/commands/manager/tech-lead-lifecycle.js.map +1 -1
- package/dist/cli/commands/manager/types.d.ts +2 -3
- package/dist/cli/commands/manager/types.d.ts.map +1 -1
- package/dist/cli/commands/manager/types.js.map +1 -1
- package/dist/cli/commands/msg.test.js +2 -2
- package/dist/cli/commands/msg.test.js.map +1 -1
- package/dist/cli/commands/my-stories.d.ts.map +1 -1
- package/dist/cli/commands/my-stories.js +17 -18
- package/dist/cli/commands/my-stories.js.map +1 -1
- package/dist/cli/commands/my-stories.test.js +2 -2
- package/dist/cli/commands/my-stories.test.js.map +1 -1
- package/dist/cli/commands/nuke.test.js +1 -1
- package/dist/cli/commands/nuke.test.js.map +1 -1
- package/dist/cli/commands/pr.js +32 -32
- package/dist/cli/commands/pr.js.map +1 -1
- package/dist/cli/commands/pr.test.js +10 -6
- package/dist/cli/commands/pr.test.js.map +1 -1
- package/dist/cli/commands/progress.d.ts.map +1 -1
- package/dist/cli/commands/progress.js +4 -5
- package/dist/cli/commands/progress.js.map +1 -1
- package/dist/cli/commands/progress.test.js +1 -1
- package/dist/cli/commands/progress.test.js.map +1 -1
- package/dist/cli/commands/req-headless.test.d.ts +2 -0
- package/dist/cli/commands/req-headless.test.d.ts.map +1 -0
- package/dist/cli/commands/req-headless.test.js +128 -0
- package/dist/cli/commands/req-headless.test.js.map +1 -0
- package/dist/cli/commands/req-spawn.test.js +5 -1
- package/dist/cli/commands/req-spawn.test.js.map +1 -1
- package/dist/cli/commands/req.d.ts.map +1 -1
- package/dist/cli/commands/req.js +13 -14
- package/dist/cli/commands/req.js.map +1 -1
- package/dist/cli/commands/resume.d.ts.map +1 -1
- package/dist/cli/commands/resume.js +7 -8
- package/dist/cli/commands/resume.js.map +1 -1
- package/dist/cli/commands/resume.test.js +1 -1
- package/dist/cli/commands/resume.test.js.map +1 -1
- package/dist/cli/commands/status.d.ts.map +1 -1
- package/dist/cli/commands/status.js +42 -40
- package/dist/cli/commands/status.js.map +1 -1
- package/dist/cli/commands/status.test.js +1 -1
- package/dist/cli/commands/status.test.js.map +1 -1
- package/dist/cli/commands/stories.js +9 -9
- package/dist/cli/commands/stories.js.map +1 -1
- package/dist/cli/commands/stories.test.js +2 -2
- package/dist/cli/commands/stories.test.js.map +1 -1
- package/dist/cli/commands/teams.js +11 -11
- package/dist/cli/commands/teams.js.map +1 -1
- package/dist/cli/commands/teams.test.js +2 -2
- package/dist/cli/commands/teams.test.js.map +1 -1
- package/dist/cli/dashboard/index.d.ts +2 -2
- package/dist/cli/dashboard/index.d.ts.map +1 -1
- package/dist/cli/dashboard/index.js +29 -20
- package/dist/cli/dashboard/index.js.map +1 -1
- package/dist/cli/dashboard/index.test.js +34 -32
- package/dist/cli/dashboard/index.test.js.map +1 -1
- package/dist/cli/dashboard/panels/activity.d.ts +3 -3
- package/dist/cli/dashboard/panels/activity.d.ts.map +1 -1
- package/dist/cli/dashboard/panels/activity.js +1 -1
- package/dist/cli/dashboard/panels/activity.js.map +1 -1
- package/dist/cli/dashboard/panels/agents.d.ts +3 -3
- package/dist/cli/dashboard/panels/agents.d.ts.map +1 -1
- package/dist/cli/dashboard/panels/agents.js +2 -2
- package/dist/cli/dashboard/panels/agents.js.map +1 -1
- package/dist/cli/dashboard/panels/escalations.d.ts +3 -3
- package/dist/cli/dashboard/panels/escalations.d.ts.map +1 -1
- package/dist/cli/dashboard/panels/escalations.js +1 -1
- package/dist/cli/dashboard/panels/escalations.js.map +1 -1
- package/dist/cli/dashboard/panels/merge-queue.d.ts +3 -3
- package/dist/cli/dashboard/panels/merge-queue.d.ts.map +1 -1
- package/dist/cli/dashboard/panels/merge-queue.js +1 -1
- package/dist/cli/dashboard/panels/merge-queue.js.map +1 -1
- package/dist/cli/dashboard/panels/pipeline.d.ts +3 -3
- package/dist/cli/dashboard/panels/pipeline.d.ts.map +1 -1
- package/dist/cli/dashboard/panels/pipeline.js +1 -1
- package/dist/cli/dashboard/panels/pipeline.js.map +1 -1
- package/dist/config/schema.d.ts +85 -82
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/config/schema.js +1 -0
- package/dist/config/schema.js.map +1 -1
- package/dist/connectors/project-management/operations.d.ts +7 -7
- package/dist/connectors/project-management/operations.d.ts.map +1 -1
- package/dist/connectors/project-management/operations.js +2 -3
- package/dist/connectors/project-management/operations.js.map +1 -1
- package/dist/context-files/index.test.js +1 -0
- package/dist/context-files/index.test.js.map +1 -1
- package/dist/db/client.d.ts +6 -0
- package/dist/db/client.d.ts.map +1 -1
- package/dist/db/client.js +7 -0
- package/dist/db/client.js.map +1 -1
- package/dist/db/postgres-provider.d.ts +43 -0
- package/dist/db/postgres-provider.d.ts.map +1 -0
- package/dist/db/postgres-provider.integration.test.d.ts +2 -0
- package/dist/db/postgres-provider.integration.test.d.ts.map +1 -0
- package/dist/db/postgres-provider.integration.test.js +399 -0
- package/dist/db/postgres-provider.integration.test.js.map +1 -0
- package/dist/db/postgres-provider.js +315 -0
- package/dist/db/postgres-provider.js.map +1 -0
- package/dist/db/postgres-provider.test.d.ts +2 -0
- package/dist/db/postgres-provider.test.d.ts.map +1 -0
- package/dist/db/postgres-provider.test.js +72 -0
- package/dist/db/postgres-provider.test.js.map +1 -0
- package/dist/db/provider.d.ts +59 -0
- package/dist/db/provider.d.ts.map +1 -0
- package/dist/db/provider.js +121 -0
- package/dist/db/provider.js.map +1 -0
- package/dist/db/provider.test.d.ts +2 -0
- package/dist/db/provider.test.d.ts.map +1 -0
- package/dist/db/provider.test.js +226 -0
- package/dist/db/provider.test.js.map +1 -0
- package/dist/db/queries/agents.d.ts +13 -13
- package/dist/db/queries/agents.d.ts.map +1 -1
- package/dist/db/queries/agents.js +27 -28
- package/dist/db/queries/agents.js.map +1 -1
- package/dist/db/queries/agents.test.js +113 -111
- package/dist/db/queries/agents.test.js.map +1 -1
- package/dist/db/queries/escalations.d.ts +16 -16
- package/dist/db/queries/escalations.d.ts.map +1 -1
- package/dist/db/queries/escalations.js +34 -35
- package/dist/db/queries/escalations.js.map +1 -1
- package/dist/db/queries/escalations.test.js +133 -131
- package/dist/db/queries/escalations.test.js.map +1 -1
- package/dist/db/queries/heartbeat.d.ts +5 -5
- package/dist/db/queries/heartbeat.d.ts.map +1 -1
- package/dist/db/queries/heartbeat.js +7 -23
- package/dist/db/queries/heartbeat.js.map +1 -1
- package/dist/db/queries/heartbeat.test.js +76 -76
- package/dist/db/queries/heartbeat.test.js.map +1 -1
- package/dist/db/queries/integration-sync.d.ts +7 -7
- package/dist/db/queries/integration-sync.d.ts.map +1 -1
- package/dist/db/queries/integration-sync.js +13 -14
- package/dist/db/queries/integration-sync.js.map +1 -1
- package/dist/db/queries/logs.d.ts +10 -10
- package/dist/db/queries/logs.d.ts.map +1 -1
- package/dist/db/queries/logs.js +44 -42
- package/dist/db/queries/logs.js.map +1 -1
- package/dist/db/queries/logs.test.js +149 -146
- package/dist/db/queries/logs.test.js.map +1 -1
- package/dist/db/queries/messages.d.ts +6 -6
- package/dist/db/queries/messages.d.ts.map +1 -1
- package/dist/db/queries/messages.js +12 -11
- package/dist/db/queries/messages.js.map +1 -1
- package/dist/db/queries/messages.test.js +47 -46
- package/dist/db/queries/messages.test.js.map +1 -1
- package/dist/db/queries/pull-requests.d.ts +18 -18
- package/dist/db/queries/pull-requests.d.ts.map +1 -1
- package/dist/db/queries/pull-requests.js +50 -48
- package/dist/db/queries/pull-requests.js.map +1 -1
- package/dist/db/queries/pull-requests.test.js +195 -198
- package/dist/db/queries/pull-requests.test.js.map +1 -1
- package/dist/db/queries/requirements.d.ts +8 -8
- package/dist/db/queries/requirements.d.ts.map +1 -1
- package/dist/db/queries/requirements.js +17 -18
- package/dist/db/queries/requirements.js.map +1 -1
- package/dist/db/queries/requirements.test.js +83 -81
- package/dist/db/queries/requirements.test.js.map +1 -1
- package/dist/db/queries/stories.d.ts +29 -29
- package/dist/db/queries/stories.d.ts.map +1 -1
- package/dist/db/queries/stories.js +58 -64
- package/dist/db/queries/stories.js.map +1 -1
- package/dist/db/queries/stories.test.js +172 -170
- package/dist/db/queries/stories.test.js.map +1 -1
- package/dist/db/queries/teams.d.ts +6 -6
- package/dist/db/queries/teams.d.ts.map +1 -1
- package/dist/db/queries/teams.js +11 -12
- package/dist/db/queries/teams.js.map +1 -1
- package/dist/db/queries/teams.test.js +36 -34
- package/dist/db/queries/teams.test.js.map +1 -1
- package/dist/integrations/jira/repair.test.js +26 -24
- package/dist/integrations/jira/repair.test.js.map +1 -1
- package/dist/integrations/jira/stories.d.ts +3 -3
- package/dist/integrations/jira/stories.d.ts.map +1 -1
- package/dist/integrations/jira/stories.js +12 -12
- package/dist/integrations/jira/stories.js.map +1 -1
- package/dist/integrations/jira/stories.test.js +10 -8
- package/dist/integrations/jira/stories.test.js.map +1 -1
- package/dist/integrations/jira/sync.d.ts +7 -7
- package/dist/integrations/jira/sync.d.ts.map +1 -1
- package/dist/integrations/jira/sync.js +17 -20
- package/dist/integrations/jira/sync.js.map +1 -1
- package/dist/integrations/jira/sync.test.js +63 -62
- package/dist/integrations/jira/sync.test.js.map +1 -1
- package/dist/integrations/jira/transitions.d.ts +3 -3
- package/dist/integrations/jira/transitions.d.ts.map +1 -1
- package/dist/integrations/jira/transitions.js +3 -3
- package/dist/integrations/jira/transitions.js.map +1 -1
- package/dist/orchestrator/agent-selector.d.ts +3 -3
- package/dist/orchestrator/agent-selector.d.ts.map +1 -1
- package/dist/orchestrator/agent-selector.js +5 -6
- package/dist/orchestrator/agent-selector.js.map +1 -1
- package/dist/orchestrator/dependency-resolver.d.ts +4 -4
- package/dist/orchestrator/dependency-resolver.d.ts.map +1 -1
- package/dist/orchestrator/dependency-resolver.js +6 -6
- package/dist/orchestrator/dependency-resolver.js.map +1 -1
- package/dist/orchestrator/feature-branch.d.ts +3 -3
- package/dist/orchestrator/feature-branch.d.ts.map +1 -1
- package/dist/orchestrator/feature-branch.js +9 -10
- package/dist/orchestrator/feature-branch.js.map +1 -1
- package/dist/orchestrator/feature-branch.test.js +80 -78
- package/dist/orchestrator/feature-branch.test.js.map +1 -1
- package/dist/orchestrator/orphan-recovery.d.ts +2 -2
- package/dist/orchestrator/orphan-recovery.d.ts.map +1 -1
- package/dist/orchestrator/orphan-recovery.js +10 -10
- package/dist/orchestrator/orphan-recovery.js.map +1 -1
- package/dist/orchestrator/scheduler.d.ts +4 -4
- package/dist/orchestrator/scheduler.d.ts.map +1 -1
- package/dist/orchestrator/scheduler.js +90 -76
- package/dist/orchestrator/scheduler.js.map +1 -1
- package/dist/orchestrator/scheduler.test.js +496 -374
- package/dist/orchestrator/scheduler.test.js.map +1 -1
- package/dist/utils/auto-merge.d.ts.map +1 -1
- package/dist/utils/auto-merge.js +74 -56
- package/dist/utils/auto-merge.js.map +1 -1
- package/dist/utils/auto-merge.test.js +101 -66
- package/dist/utils/auto-merge.test.js.map +1 -1
- package/dist/utils/cli-helpers.d.ts +5 -5
- package/dist/utils/cli-helpers.d.ts.map +1 -1
- package/dist/utils/cli-helpers.js +8 -9
- package/dist/utils/cli-helpers.js.map +1 -1
- package/dist/utils/cli-helpers.test.js +28 -30
- package/dist/utils/cli-helpers.test.js.map +1 -1
- package/dist/utils/paths.d.ts +6 -0
- package/dist/utils/paths.d.ts.map +1 -1
- package/dist/utils/paths.js +12 -1
- package/dist/utils/paths.js.map +1 -1
- package/dist/utils/paths.test.js +1 -0
- package/dist/utils/paths.test.js.map +1 -1
- package/dist/utils/pr-sync.d.ts +10 -10
- package/dist/utils/pr-sync.d.ts.map +1 -1
- package/dist/utils/pr-sync.js +20 -21
- package/dist/utils/pr-sync.js.map +1 -1
- package/dist/utils/pr-sync.test.js +52 -50
- package/dist/utils/pr-sync.test.js.map +1 -1
- package/dist/utils/with-hive-context.d.ts.map +1 -1
- package/dist/utils/with-hive-context.js +70 -1
- package/dist/utils/with-hive-context.js.map +1 -1
- package/package.json +3 -1
- package/src/agents/base-agent.test.ts +2 -1
- package/src/agents/base-agent.ts +32 -28
- package/src/agents/intermediate.ts +27 -18
- package/src/agents/junior.ts +27 -18
- package/src/agents/qa.ts +54 -40
- package/src/agents/senior.ts +42 -27
- package/src/agents/tech-lead.ts +42 -32
- package/src/cli/commands/add-repo.test.ts +1 -1
- package/src/cli/commands/add-repo.ts +2 -2
- package/src/cli/commands/agents.test.ts +7 -7
- package/src/cli/commands/agents.ts +12 -10
- package/src/cli/commands/approach.ts +2 -2
- package/src/cli/commands/approvals.test.ts +8 -8
- package/src/cli/commands/approvals.ts +9 -7
- package/src/cli/commands/assign.test.ts +19 -18
- package/src/cli/commands/assign.ts +4 -4
- package/src/cli/commands/cleanup.test.ts +5 -1
- package/src/cli/commands/cleanup.ts +11 -9
- package/src/cli/commands/escalations.test.ts +2 -2
- package/src/cli/commands/escalations.ts +9 -7
- package/src/cli/commands/init.test.ts +5 -0
- package/src/cli/commands/init.ts +53 -5
- package/src/cli/commands/manager/agent-monitoring.ts +3 -3
- package/src/cli/commands/manager/auditor-lifecycle.test.ts +21 -14
- package/src/cli/commands/manager/auditor-lifecycle.ts +3 -3
- package/src/cli/commands/manager/auto-reject-comment-only-reviews.test.ts +28 -23
- package/src/cli/commands/manager/escalation-handler.test.ts +13 -13
- package/src/cli/commands/manager/escalation-handler.ts +19 -12
- package/src/cli/commands/manager/feature-sign-off.test.ts +40 -31
- package/src/cli/commands/manager/feature-sign-off.ts +7 -7
- package/src/cli/commands/manager/feature-test-result.ts +13 -16
- package/src/cli/commands/manager/handoff-recovery.ts +20 -20
- package/src/cli/commands/manager/index.test.ts +4 -4
- package/src/cli/commands/manager/index.ts +58 -59
- package/src/cli/commands/manager/merged-story-cleanup.test.ts +28 -19
- package/src/cli/commands/manager/merged-story-cleanup.ts +11 -14
- package/src/cli/commands/manager/pr-sync-orchestrator.ts +115 -110
- package/src/cli/commands/manager/qa-review-handler.ts +50 -63
- package/src/cli/commands/manager/spin-down.ts +27 -25
- package/src/cli/commands/manager/stale-escalations.ts +2 -3
- package/src/cli/commands/manager/stuck-story-helpers.ts +10 -10
- package/src/cli/commands/manager/stuck-story-processor.ts +56 -62
- package/src/cli/commands/manager/tech-lead-lifecycle.ts +6 -6
- package/src/cli/commands/manager/types.ts +2 -3
- package/src/cli/commands/msg.test.ts +2 -2
- package/src/cli/commands/my-stories.test.ts +4 -2
- package/src/cli/commands/my-stories.ts +22 -27
- package/src/cli/commands/nuke.test.ts +1 -1
- package/src/cli/commands/pr.test.ts +10 -6
- package/src/cli/commands/pr.ts +41 -32
- package/src/cli/commands/progress.test.ts +1 -1
- package/src/cli/commands/progress.ts +11 -6
- package/src/cli/commands/req-headless.test.ts +170 -0
- package/src/cli/commands/req-spawn.test.ts +12 -2
- package/src/cli/commands/req.ts +13 -14
- package/src/cli/commands/resume.test.ts +1 -1
- package/src/cli/commands/resume.ts +7 -8
- package/src/cli/commands/status.test.ts +1 -1
- package/src/cli/commands/status.ts +52 -40
- package/src/cli/commands/stories.test.ts +4 -2
- package/src/cli/commands/stories.ts +11 -11
- package/src/cli/commands/teams.test.ts +2 -2
- package/src/cli/commands/teams.ts +11 -11
- package/src/cli/dashboard/index.test.ts +35 -34
- package/src/cli/dashboard/index.ts +34 -23
- package/src/cli/dashboard/panels/activity.ts +10 -4
- package/src/cli/dashboard/panels/agents.ts +8 -5
- package/src/cli/dashboard/panels/escalations.ts +4 -4
- package/src/cli/dashboard/panels/merge-queue.ts +4 -4
- package/src/cli/dashboard/panels/pipeline.ts +10 -4
- package/src/config/schema.ts +1 -0
- package/src/connectors/project-management/operations.ts +9 -10
- package/src/context-files/index.test.ts +1 -0
- package/src/db/client.ts +17 -0
- package/src/db/pg-migrations/001-full-schema.sql +209 -0
- package/src/db/postgres-provider.integration.test.ts +574 -0
- package/src/db/postgres-provider.test.ts +97 -0
- package/src/db/postgres-provider.ts +364 -0
- package/src/db/provider.test.ts +283 -0
- package/src/db/provider.ts +161 -0
- package/src/db/queries/agents.test.ts +114 -113
- package/src/db/queries/agents.ts +50 -36
- package/src/db/queries/escalations.test.ts +134 -133
- package/src/db/queries/escalations.ts +72 -57
- package/src/db/queries/heartbeat.test.ts +77 -78
- package/src/db/queries/heartbeat.ts +24 -46
- package/src/db/queries/integration-sync.ts +26 -26
- package/src/db/queries/logs.test.ts +151 -148
- package/src/db/queries/logs.ts +78 -53
- package/src/db/queries/messages.test.ts +48 -50
- package/src/db/queries/messages.ts +26 -18
- package/src/db/queries/pull-requests.test.ts +194 -199
- package/src/db/queries/pull-requests.ts +117 -88
- package/src/db/queries/requirements.test.ts +84 -83
- package/src/db/queries/requirements.ts +33 -28
- package/src/db/queries/stories.test.ts +173 -172
- package/src/db/queries/stories.ts +141 -110
- package/src/db/queries/teams.test.ts +37 -36
- package/src/db/queries/teams.ts +22 -14
- package/src/integrations/jira/repair.test.ts +27 -26
- package/src/integrations/jira/stories.test.ts +15 -16
- package/src/integrations/jira/stories.ts +15 -15
- package/src/integrations/jira/sync.test.ts +68 -68
- package/src/integrations/jira/sync.ts +29 -39
- package/src/integrations/jira/transitions.ts +6 -6
- package/src/orchestrator/agent-selector.ts +9 -8
- package/src/orchestrator/dependency-resolver.ts +16 -7
- package/src/orchestrator/feature-branch.test.ts +85 -80
- package/src/orchestrator/feature-branch.ts +13 -14
- package/src/orchestrator/orphan-recovery.ts +14 -13
- package/src/orchestrator/scheduler.test.ts +536 -394
- package/src/orchestrator/scheduler.ts +129 -115
- package/src/utils/auto-merge.test.ts +102 -68
- package/src/utils/auto-merge.ts +161 -168
- package/src/utils/cli-helpers.test.ts +30 -32
- package/src/utils/cli-helpers.ts +15 -11
- package/src/utils/paths.test.ts +1 -0
- package/src/utils/paths.ts +14 -1
- package/src/utils/pr-sync.test.ts +55 -52
- package/src/utils/pr-sync.ts +27 -32
- package/src/utils/with-hive-context.ts +89 -1
|
@@ -63,8 +63,10 @@ approvalsCommand
|
|
|
63
63
|
.action(async (options: { all?: boolean; json?: boolean }) => {
|
|
64
64
|
await withHiveContext(async ({ db }) => {
|
|
65
65
|
const approvals = options.all
|
|
66
|
-
? getAllEscalations(db.
|
|
67
|
-
|
|
66
|
+
? (await getAllEscalations(db.provider)).filter(
|
|
67
|
+
escalation => escalation.to_agent_id === null
|
|
68
|
+
)
|
|
69
|
+
: await getPendingHumanEscalations(db.provider);
|
|
68
70
|
|
|
69
71
|
if (options.json) {
|
|
70
72
|
console.log(JSON.stringify(approvals, null, 2));
|
|
@@ -107,7 +109,7 @@ approvalsCommand
|
|
|
107
109
|
.description('Show a human approval request')
|
|
108
110
|
.action(async (id: string) => {
|
|
109
111
|
await withHiveContext(async ({ db }) => {
|
|
110
|
-
const approval = ensureHumanApprovalEscalation(getEscalationById(db.
|
|
112
|
+
const approval = ensureHumanApprovalEscalation(await getEscalationById(db.provider, id), id);
|
|
111
113
|
const type = classifyApproval(approval.reason);
|
|
112
114
|
|
|
113
115
|
console.log(chalk.bold(`\nApproval: ${approval.id}\n`));
|
|
@@ -132,14 +134,14 @@ approvalsCommand
|
|
|
132
134
|
.option('-m, --message <message>', 'Optional guidance sent as approval context')
|
|
133
135
|
.action(async (id: string, options: { message?: string }) => {
|
|
134
136
|
await withHiveContext(async ({ db }) => {
|
|
135
|
-
const approval = ensureHumanApprovalEscalation(getEscalationById(db.
|
|
137
|
+
const approval = ensureHumanApprovalEscalation(await getEscalationById(db.provider, id), id);
|
|
136
138
|
if (approval.status === 'resolved') {
|
|
137
139
|
console.log(chalk.yellow(`Approval ${id} is already resolved.`));
|
|
138
140
|
return;
|
|
139
141
|
}
|
|
140
142
|
|
|
141
143
|
const note = options.message?.trim() || 'Approved by human reviewer.';
|
|
142
|
-
resolveEscalation(db.
|
|
144
|
+
await resolveEscalation(db.provider, id, `APPROVED: ${note}`);
|
|
143
145
|
console.log(chalk.green(`Approved ${id}.`));
|
|
144
146
|
});
|
|
145
147
|
});
|
|
@@ -150,13 +152,13 @@ approvalsCommand
|
|
|
150
152
|
.requiredOption('-m, --message <message>', 'Reason/guidance for denial')
|
|
151
153
|
.action(async (id: string, options: { message: string }) => {
|
|
152
154
|
await withHiveContext(async ({ db }) => {
|
|
153
|
-
const approval = ensureHumanApprovalEscalation(getEscalationById(db.
|
|
155
|
+
const approval = ensureHumanApprovalEscalation(await getEscalationById(db.provider, id), id);
|
|
154
156
|
if (approval.status === 'resolved') {
|
|
155
157
|
console.log(chalk.yellow(`Approval ${id} is already resolved.`));
|
|
156
158
|
return;
|
|
157
159
|
}
|
|
158
160
|
|
|
159
|
-
resolveEscalation(db.
|
|
161
|
+
await resolveEscalation(db.provider, id, `DENIED: ${options.message}`);
|
|
160
162
|
console.log(chalk.green(`Denied ${id}.`));
|
|
161
163
|
});
|
|
162
164
|
});
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// Licensed under the Hungry Ghost Hive License. See LICENSE.
|
|
2
2
|
|
|
3
|
-
import type { Database } from 'sql.js';
|
|
4
3
|
import initSqlJs from 'sql.js';
|
|
5
4
|
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
5
|
+
import { SqliteProvider } from '../../db/provider.js';
|
|
6
6
|
import { getPlannedStories } from '../../db/queries/stories.js';
|
|
7
7
|
import { getTeamById } from '../../db/queries/teams.js';
|
|
8
8
|
|
|
@@ -16,7 +16,7 @@ vi.mock('../../db/queries/stories.js');
|
|
|
16
16
|
vi.mock('../../db/queries/teams.js');
|
|
17
17
|
|
|
18
18
|
describe('Assign Command', () => {
|
|
19
|
-
let db:
|
|
19
|
+
let db: SqliteProvider;
|
|
20
20
|
|
|
21
21
|
const mockConfig = {
|
|
22
22
|
scaling: {
|
|
@@ -90,22 +90,23 @@ CREATE TABLE IF NOT EXISTS stories (
|
|
|
90
90
|
|
|
91
91
|
beforeEach(async () => {
|
|
92
92
|
const SQL = await initSqlJs();
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
93
|
+
const rawDb = new SQL.Database();
|
|
94
|
+
rawDb.run('PRAGMA foreign_keys = ON');
|
|
95
|
+
rawDb.run(INITIAL_MIGRATION);
|
|
96
|
+
db = new SqliteProvider(rawDb);
|
|
96
97
|
vi.clearAllMocks();
|
|
97
98
|
});
|
|
98
99
|
|
|
99
100
|
describe('--dry-run flag', () => {
|
|
100
|
-
it('should return empty when no stories are planned', () => {
|
|
101
|
+
it('should return empty when no stories are planned', async () => {
|
|
101
102
|
// Mock empty planned stories
|
|
102
|
-
vi.mocked(getPlannedStories).
|
|
103
|
+
vi.mocked(getPlannedStories).mockResolvedValue([]);
|
|
103
104
|
|
|
104
|
-
const plannedStories = getPlannedStories(db);
|
|
105
|
+
const plannedStories = await getPlannedStories(db);
|
|
105
106
|
expect(plannedStories).toEqual([]);
|
|
106
107
|
});
|
|
107
108
|
|
|
108
|
-
it('should show stories grouped by team without making assignments', () => {
|
|
109
|
+
it('should show stories grouped by team without making assignments', async () => {
|
|
109
110
|
// Mock planned stories with team association
|
|
110
111
|
const mockStories = [
|
|
111
112
|
{
|
|
@@ -168,8 +169,8 @@ CREATE TABLE IF NOT EXISTS stories (
|
|
|
168
169
|
},
|
|
169
170
|
];
|
|
170
171
|
|
|
171
|
-
vi.mocked(getPlannedStories).
|
|
172
|
-
vi.mocked(getTeamById).
|
|
172
|
+
vi.mocked(getPlannedStories).mockResolvedValue(mockStories);
|
|
173
|
+
vi.mocked(getTeamById).mockResolvedValue({
|
|
173
174
|
id: 'team-1',
|
|
174
175
|
repo_url: 'https://github.com/test/repo',
|
|
175
176
|
repo_path: '/path/to/repo',
|
|
@@ -177,7 +178,7 @@ CREATE TABLE IF NOT EXISTS stories (
|
|
|
177
178
|
created_at: new Date().toISOString(),
|
|
178
179
|
});
|
|
179
180
|
|
|
180
|
-
const plannedStories = getPlannedStories(db);
|
|
181
|
+
const plannedStories = await getPlannedStories(db);
|
|
181
182
|
expect(plannedStories).toHaveLength(2);
|
|
182
183
|
expect(plannedStories[0].team_id).toBe('team-1');
|
|
183
184
|
});
|
|
@@ -220,7 +221,7 @@ CREATE TABLE IF NOT EXISTS stories (
|
|
|
220
221
|
expect(targetLevel).toBe('Senior');
|
|
221
222
|
});
|
|
222
223
|
|
|
223
|
-
it('should not make database changes during dry-run', () => {
|
|
224
|
+
it('should not make database changes during dry-run', async () => {
|
|
224
225
|
// The dry-run option should only call getPlannedStories without making any changes
|
|
225
226
|
const mockStories = [
|
|
226
227
|
{
|
|
@@ -254,17 +255,17 @@ CREATE TABLE IF NOT EXISTS stories (
|
|
|
254
255
|
},
|
|
255
256
|
];
|
|
256
257
|
|
|
257
|
-
vi.mocked(getPlannedStories).
|
|
258
|
+
vi.mocked(getPlannedStories).mockResolvedValue(mockStories);
|
|
258
259
|
|
|
259
260
|
// In dry-run mode, we should only read data, not write
|
|
260
|
-
const plannedStories = getPlannedStories(db);
|
|
261
|
+
const plannedStories = await getPlannedStories(db);
|
|
261
262
|
expect(plannedStories).toHaveLength(1);
|
|
262
263
|
|
|
263
264
|
// Verify that no assignment operations were performed
|
|
264
265
|
// (This would be verified by checking that Scheduler.assignStories was not called)
|
|
265
266
|
});
|
|
266
267
|
|
|
267
|
-
it('should handle multiple teams in planned stories', () => {
|
|
268
|
+
it('should handle multiple teams in planned stories', async () => {
|
|
268
269
|
const mockStories = [
|
|
269
270
|
{
|
|
270
271
|
id: 'STORY-001',
|
|
@@ -326,9 +327,9 @@ CREATE TABLE IF NOT EXISTS stories (
|
|
|
326
327
|
},
|
|
327
328
|
];
|
|
328
329
|
|
|
329
|
-
vi.mocked(getPlannedStories).
|
|
330
|
+
vi.mocked(getPlannedStories).mockResolvedValue(mockStories);
|
|
330
331
|
|
|
331
|
-
const plannedStories = getPlannedStories(db);
|
|
332
|
+
const plannedStories = await getPlannedStories(db);
|
|
332
333
|
expect(plannedStories).toHaveLength(2);
|
|
333
334
|
|
|
334
335
|
// Verify stories are grouped by team
|
|
@@ -48,11 +48,11 @@ export const assignCommand = new Command('assign')
|
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
// Check if godmode is active
|
|
51
|
-
const plannedStories = getPlannedStories(db.
|
|
51
|
+
const plannedStories = await getPlannedStories(db.provider);
|
|
52
52
|
let godmodeActive = false;
|
|
53
53
|
for (const story of plannedStories) {
|
|
54
54
|
if (story.requirement_id) {
|
|
55
|
-
const requirement = getRequirementById(db.
|
|
55
|
+
const requirement = await getRequirementById(db.provider, story.requirement_id);
|
|
56
56
|
if (requirement && requirement.godmode) {
|
|
57
57
|
godmodeActive = true;
|
|
58
58
|
break;
|
|
@@ -85,7 +85,7 @@ export const assignCommand = new Command('assign')
|
|
|
85
85
|
|
|
86
86
|
// Display planned assignments
|
|
87
87
|
for (const [teamId, stories] of storiesByTeam) {
|
|
88
|
-
const team = getTeamById(db.
|
|
88
|
+
const team = await getTeamById(db.provider, teamId);
|
|
89
89
|
if (!team) continue;
|
|
90
90
|
|
|
91
91
|
console.log(chalk.cyan(`\n📦 Team: ${team.name}\n`));
|
|
@@ -114,7 +114,7 @@ export const assignCommand = new Command('assign')
|
|
|
114
114
|
console.log(chalk.yellow('⚡ GODMODE is active - all agents will use Opus 4.6\n'));
|
|
115
115
|
}
|
|
116
116
|
|
|
117
|
-
const scheduler = new Scheduler(db.
|
|
117
|
+
const scheduler = new Scheduler(db.provider, {
|
|
118
118
|
scaling: config.scaling,
|
|
119
119
|
models: config.models,
|
|
120
120
|
qa: config.qa,
|
|
@@ -19,7 +19,11 @@ vi.mock('../../tmux/manager.js', () => ({
|
|
|
19
19
|
|
|
20
20
|
vi.mock('../../utils/with-hive-context.js', () => ({
|
|
21
21
|
withHiveContext: vi.fn(callback =>
|
|
22
|
-
callback({
|
|
22
|
+
callback({
|
|
23
|
+
db: { db: {}, provider: {}, save: vi.fn() },
|
|
24
|
+
root: '/tmp',
|
|
25
|
+
paths: { hiveDir: '/tmp/.hive' },
|
|
26
|
+
})
|
|
23
27
|
),
|
|
24
28
|
}));
|
|
25
29
|
|
|
@@ -47,7 +47,7 @@ async function findOrphanedWorktrees(root: string, db: DatabaseClient): Promise<
|
|
|
47
47
|
|
|
48
48
|
try {
|
|
49
49
|
const entries = await fs.readdir(reposDir, { withFileTypes: true });
|
|
50
|
-
const allAgents = getAllAgents(db.
|
|
50
|
+
const allAgents = await getAllAgents(db.provider);
|
|
51
51
|
const agentWorktrees = new Set(
|
|
52
52
|
allAgents.filter(a => a.worktree_path).map(a => a.worktree_path)
|
|
53
53
|
);
|
|
@@ -110,7 +110,7 @@ async function findDeadTmuxSessions(db: DatabaseClient): Promise<string[]> {
|
|
|
110
110
|
|
|
111
111
|
try {
|
|
112
112
|
const hiveSessions = await getHiveSessions();
|
|
113
|
-
const allAgents = getAllAgents(db.
|
|
113
|
+
const allAgents = await getAllAgents(db.provider);
|
|
114
114
|
const agentSessionNames = new Set(
|
|
115
115
|
allAgents.filter(a => a.tmux_session).map(a => a.tmux_session)
|
|
116
116
|
);
|
|
@@ -132,9 +132,11 @@ async function findDeadTmuxSessions(db: DatabaseClient): Promise<string[]> {
|
|
|
132
132
|
return deadSessions;
|
|
133
133
|
}
|
|
134
134
|
|
|
135
|
-
function findOrphanedAssignments(
|
|
135
|
+
async function findOrphanedAssignments(
|
|
136
|
+
db: DatabaseClient
|
|
137
|
+
): Promise<Array<{ id: string; agent_id: string }>> {
|
|
136
138
|
try {
|
|
137
|
-
return getStoriesWithOrphanedAssignments(db.
|
|
139
|
+
return await getStoriesWithOrphanedAssignments(db.provider);
|
|
138
140
|
} catch (err) {
|
|
139
141
|
console.error(
|
|
140
142
|
chalk.yellow(
|
|
@@ -225,11 +227,11 @@ async function cleanupDeadTmuxSessions(deadSessions: string[], dryRun: boolean):
|
|
|
225
227
|
return cleaned;
|
|
226
228
|
}
|
|
227
229
|
|
|
228
|
-
function cleanupOrphanedAssignments(
|
|
230
|
+
async function cleanupOrphanedAssignments(
|
|
229
231
|
db: DatabaseClient,
|
|
230
232
|
orphaned: Array<{ id: string; agent_id: string }>,
|
|
231
233
|
dryRun: boolean
|
|
232
|
-
): number {
|
|
234
|
+
): Promise<number> {
|
|
233
235
|
let cleaned = 0;
|
|
234
236
|
|
|
235
237
|
for (const assignment of orphaned) {
|
|
@@ -237,7 +239,7 @@ function cleanupOrphanedAssignments(
|
|
|
237
239
|
if (dryRun) {
|
|
238
240
|
console.log(chalk.gray(` Would unassign: ${assignment.id} from ${assignment.agent_id}`));
|
|
239
241
|
} else {
|
|
240
|
-
updateStoryAssignment(db.
|
|
242
|
+
await updateStoryAssignment(db.provider, assignment.id, null);
|
|
241
243
|
console.log(chalk.gray(` ✓ Unassigned: ${assignment.id}`));
|
|
242
244
|
cleaned++;
|
|
243
245
|
}
|
|
@@ -300,7 +302,7 @@ export const cleanupCommand = new Command('cleanup')
|
|
|
300
302
|
stats.deadTmuxSessions = await findDeadTmuxSessions(db);
|
|
301
303
|
}
|
|
302
304
|
if (shouldCleanupAssignments) {
|
|
303
|
-
stats.orphanedStories = findOrphanedAssignments(db);
|
|
305
|
+
stats.orphanedStories = await findOrphanedAssignments(db);
|
|
304
306
|
}
|
|
305
307
|
|
|
306
308
|
stats.totalIssuesFound =
|
|
@@ -395,7 +397,7 @@ export const cleanupCommand = new Command('cleanup')
|
|
|
395
397
|
|
|
396
398
|
if (stats.orphanedStories.length > 0) {
|
|
397
399
|
console.log(chalk.cyan('Unassigning orphaned stories:'));
|
|
398
|
-
const cleaned = cleanupOrphanedAssignments(db, stats.orphanedStories, false);
|
|
400
|
+
const cleaned = await cleanupOrphanedAssignments(db, stats.orphanedStories, false);
|
|
399
401
|
totalCleaned += cleaned;
|
|
400
402
|
db.save();
|
|
401
403
|
console.log();
|
|
@@ -16,8 +16,8 @@ vi.mock('../../db/queries/logs.js', () => ({
|
|
|
16
16
|
}));
|
|
17
17
|
|
|
18
18
|
vi.mock('../../utils/with-hive-context.js', () => ({
|
|
19
|
-
withHiveContext: vi.fn(callback => callback({ db: { db: {} } })),
|
|
20
|
-
withReadOnlyHiveContext: vi.fn(callback => callback({ db: { db: {} } })),
|
|
19
|
+
withHiveContext: vi.fn(callback => callback({ db: { db: {}, provider: {} } })),
|
|
20
|
+
withReadOnlyHiveContext: vi.fn(callback => callback({ db: { db: {}, provider: {} } })),
|
|
21
21
|
}));
|
|
22
22
|
|
|
23
23
|
import { escalationsCommand } from './escalations.js';
|
|
@@ -21,7 +21,9 @@ escalationsCommand
|
|
|
21
21
|
.option('--json', 'Output as JSON')
|
|
22
22
|
.action(async (options: { all?: boolean; json?: boolean }) => {
|
|
23
23
|
await withReadOnlyHiveContext(async ({ db }) => {
|
|
24
|
-
const escalations = options.all
|
|
24
|
+
const escalations = options.all
|
|
25
|
+
? await getAllEscalations(db.provider)
|
|
26
|
+
: await getPendingEscalations(db.provider);
|
|
25
27
|
|
|
26
28
|
if (options.json) {
|
|
27
29
|
console.log(JSON.stringify(escalations, null, 2));
|
|
@@ -64,7 +66,7 @@ escalationsCommand
|
|
|
64
66
|
.description('Show escalation details')
|
|
65
67
|
.action(async (id: string) => {
|
|
66
68
|
await withReadOnlyHiveContext(async ({ db }) => {
|
|
67
|
-
const escalation = getEscalationById(db.
|
|
69
|
+
const escalation = await getEscalationById(db.provider, id);
|
|
68
70
|
if (!escalation) {
|
|
69
71
|
console.error(chalk.red(`Escalation not found: ${id}`));
|
|
70
72
|
process.exit(1);
|
|
@@ -95,7 +97,7 @@ escalationsCommand
|
|
|
95
97
|
.requiredOption('-m, --message <message>', 'Resolution message/guidance')
|
|
96
98
|
.action(async (id: string, options: { message: string }) => {
|
|
97
99
|
await withHiveContext(async ({ db }) => {
|
|
98
|
-
const escalation = getEscalationById(db.
|
|
100
|
+
const escalation = await getEscalationById(db.provider, id);
|
|
99
101
|
if (!escalation) {
|
|
100
102
|
console.error(chalk.red(`Escalation not found: ${id}`));
|
|
101
103
|
process.exit(1);
|
|
@@ -106,11 +108,11 @@ escalationsCommand
|
|
|
106
108
|
return;
|
|
107
109
|
}
|
|
108
110
|
|
|
109
|
-
const resolved = resolveEscalation(db.
|
|
111
|
+
const resolved = await resolveEscalation(db.provider, id, options.message);
|
|
110
112
|
|
|
111
113
|
// Log the resolution
|
|
112
114
|
if (escalation.from_agent_id) {
|
|
113
|
-
createLog(db.
|
|
115
|
+
await createLog(db.provider, {
|
|
114
116
|
agentId: escalation.from_agent_id,
|
|
115
117
|
storyId: escalation.story_id,
|
|
116
118
|
eventType: 'ESCALATION_RESOLVED',
|
|
@@ -129,7 +131,7 @@ escalationsCommand
|
|
|
129
131
|
.description('Acknowledge an escalation (mark as being worked on)')
|
|
130
132
|
.action(async (id: string) => {
|
|
131
133
|
await withHiveContext(async ({ db }) => {
|
|
132
|
-
const escalation = getEscalationById(db.
|
|
134
|
+
const escalation = await getEscalationById(db.provider, id);
|
|
133
135
|
if (!escalation) {
|
|
134
136
|
console.error(chalk.red(`Escalation not found: ${id}`));
|
|
135
137
|
process.exit(1);
|
|
@@ -140,7 +142,7 @@ escalationsCommand
|
|
|
140
142
|
return;
|
|
141
143
|
}
|
|
142
144
|
|
|
143
|
-
acknowledgeEscalation(db.
|
|
145
|
+
await acknowledgeEscalation(db.provider, id);
|
|
144
146
|
console.log(chalk.green(`Escalation ${id} acknowledged.`));
|
|
145
147
|
});
|
|
146
148
|
});
|
|
@@ -85,5 +85,10 @@ describe('init command', () => {
|
|
|
85
85
|
const jiraOpt = initCommand.options.find(opt => opt.long === '--jira-project');
|
|
86
86
|
expect(jiraOpt).toBeDefined();
|
|
87
87
|
});
|
|
88
|
+
|
|
89
|
+
it('should have --distributed option', () => {
|
|
90
|
+
const distributedOpt = initCommand.options.find(opt => opt.long === '--distributed');
|
|
91
|
+
expect(distributedOpt).toBeDefined();
|
|
92
|
+
});
|
|
88
93
|
});
|
|
89
94
|
});
|
package/src/cli/commands/init.ts
CHANGED
|
@@ -3,12 +3,14 @@
|
|
|
3
3
|
import chalk from 'chalk';
|
|
4
4
|
import { Command } from 'commander';
|
|
5
5
|
import { execa } from 'execa';
|
|
6
|
-
import { existsSync, mkdirSync } from 'fs';
|
|
6
|
+
import { existsSync, mkdirSync, writeFileSync } from 'fs';
|
|
7
|
+
import { nanoid } from 'nanoid';
|
|
7
8
|
import ora from 'ora';
|
|
8
9
|
import { join } from 'path';
|
|
9
10
|
import { createDefaultConfig, loadConfig, saveConfig } from '../../config/loader.js';
|
|
10
11
|
import type { HiveConfig } from '../../config/schema.js';
|
|
11
12
|
import { createDatabase } from '../../db/client.js';
|
|
13
|
+
import { createPostgresProvider } from '../../db/postgres-provider.js';
|
|
12
14
|
import { getHivePaths, isHiveWorkspace } from '../../utils/paths.js';
|
|
13
15
|
import type { AgentRuntime } from '../wizard/init-wizard.js';
|
|
14
16
|
import { runInitWizard } from '../wizard/init-wizard.js';
|
|
@@ -23,6 +25,7 @@ export const initCommand = new Command('init')
|
|
|
23
25
|
.option('--agent-runtime <runtime>', 'Agent runtime (claude, codex)')
|
|
24
26
|
.option('--jira-project <key>', 'Jira project key (for non-interactive mode)')
|
|
25
27
|
.option('--e2e-test-path <path>', 'Path to E2E tests directory')
|
|
28
|
+
.option('--distributed', 'Use Postgres for distributed multi-workspace mode')
|
|
26
29
|
.action(
|
|
27
30
|
async (options: {
|
|
28
31
|
force?: boolean;
|
|
@@ -33,6 +36,7 @@ export const initCommand = new Command('init')
|
|
|
33
36
|
agentRuntime?: string;
|
|
34
37
|
jiraProject?: string;
|
|
35
38
|
e2eTestPath?: string;
|
|
39
|
+
distributed?: boolean;
|
|
36
40
|
}) => {
|
|
37
41
|
const rootDir = process.cwd();
|
|
38
42
|
const paths = getHivePaths(rootDir);
|
|
@@ -59,10 +63,15 @@ export const initCommand = new Command('init')
|
|
|
59
63
|
createDefaultConfig(paths.hiveDir);
|
|
60
64
|
|
|
61
65
|
// Initialize database
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
+
if (options.distributed) {
|
|
67
|
+
spinner.text = 'Validating Postgres connection...';
|
|
68
|
+
await initDistributedDatabase(paths.workspaceIdPath);
|
|
69
|
+
} else {
|
|
70
|
+
spinner.text = 'Initializing database...';
|
|
71
|
+
const db = await createDatabase(paths.dbPath);
|
|
72
|
+
db.runMigrations();
|
|
73
|
+
db.close();
|
|
74
|
+
}
|
|
66
75
|
|
|
67
76
|
// Initialize git repository if not already in one
|
|
68
77
|
spinner.text = 'Initializing git repository...';
|
|
@@ -106,6 +115,9 @@ export const initCommand = new Command('init')
|
|
|
106
115
|
}
|
|
107
116
|
}
|
|
108
117
|
}
|
|
118
|
+
if (options.distributed) {
|
|
119
|
+
config.distributed = true;
|
|
120
|
+
}
|
|
109
121
|
saveConfig(paths.hiveDir, config);
|
|
110
122
|
|
|
111
123
|
console.log();
|
|
@@ -116,6 +128,11 @@ export const initCommand = new Command('init')
|
|
|
116
128
|
console.log(chalk.cyan(' hive req "Your requirement here"'));
|
|
117
129
|
console.log(chalk.gray(' 3. View dashboard:'));
|
|
118
130
|
console.log(chalk.cyan(' hive dashboard'));
|
|
131
|
+
if (options.distributed) {
|
|
132
|
+
console.log();
|
|
133
|
+
console.log(chalk.gray(' Distributed mode enabled. Database: Postgres'));
|
|
134
|
+
console.log(chalk.gray(` Workspace ID stored in: ${paths.workspaceIdPath}`));
|
|
135
|
+
}
|
|
119
136
|
console.log();
|
|
120
137
|
} catch (err) {
|
|
121
138
|
spinner.fail(chalk.red('Failed to initialize Hive workspace'));
|
|
@@ -125,6 +142,37 @@ export const initCommand = new Command('init')
|
|
|
125
142
|
}
|
|
126
143
|
);
|
|
127
144
|
|
|
145
|
+
/**
|
|
146
|
+
* Initialize distributed mode: validate HIVE_DATABASE_URL, test connection,
|
|
147
|
+
* generate workspace_id, and run Postgres migrations.
|
|
148
|
+
*/
|
|
149
|
+
async function initDistributedDatabase(workspaceIdPath: string): Promise<void> {
|
|
150
|
+
// Load .env if available
|
|
151
|
+
try {
|
|
152
|
+
const dotenv = await import('dotenv');
|
|
153
|
+
dotenv.config();
|
|
154
|
+
} catch {
|
|
155
|
+
// dotenv not available
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const connectionString = process.env.HIVE_DATABASE_URL;
|
|
159
|
+
if (!connectionString) {
|
|
160
|
+
throw new Error(
|
|
161
|
+
'HIVE_DATABASE_URL environment variable is not set.\n' +
|
|
162
|
+
'Set it in your environment or in a .env file before running hive init --distributed.\n' +
|
|
163
|
+
'Example: HIVE_DATABASE_URL=postgres://user:pass@host:5432/hive'
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Generate unique workspace ID
|
|
168
|
+
const workspaceId = nanoid();
|
|
169
|
+
writeFileSync(workspaceIdPath, workspaceId, 'utf-8');
|
|
170
|
+
|
|
171
|
+
// Test connection and run migrations
|
|
172
|
+
const provider = await createPostgresProvider(workspaceId);
|
|
173
|
+
await provider.close();
|
|
174
|
+
}
|
|
175
|
+
|
|
128
176
|
function applyAgentRuntimePreset(config: HiveConfig, agentRuntime: AgentRuntime): void {
|
|
129
177
|
const provider = agentRuntime === 'codex' ? 'openai' : 'anthropic';
|
|
130
178
|
const cliTool = agentRuntime;
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import chalk from 'chalk';
|
|
4
4
|
import { randomUUID } from 'crypto';
|
|
5
5
|
import type { HiveConfig } from '../../../config/schema.js';
|
|
6
|
-
import type {
|
|
6
|
+
import type { AgentRow } from '../../../db/queries/agents.js';
|
|
7
7
|
import { createLog } from '../../../db/queries/logs.js';
|
|
8
8
|
import { getStateDetector, type StateDetectionResult } from '../../../state-detectors/index.js';
|
|
9
9
|
import { AgentState } from '../../../state-detectors/types.js';
|
|
@@ -189,7 +189,7 @@ export function describeAgentState(state: AgentState, cliTool: CLITool): string
|
|
|
189
189
|
|
|
190
190
|
export function getAgentSafetyMode(
|
|
191
191
|
config: HiveConfig,
|
|
192
|
-
agent:
|
|
192
|
+
agent: AgentRow | undefined
|
|
193
193
|
): 'safe' | 'unsafe' {
|
|
194
194
|
if (!agent) return 'unsafe';
|
|
195
195
|
return config.models[agent.type].safety_mode;
|
|
@@ -252,7 +252,7 @@ export async function handlePermissionPrompt(
|
|
|
252
252
|
const approved = await autoApprovePermission(sessionName);
|
|
253
253
|
if (approved) {
|
|
254
254
|
await ctx.withDb(async db => {
|
|
255
|
-
createLog(db.
|
|
255
|
+
createLog(db.provider, {
|
|
256
256
|
agentId: 'manager',
|
|
257
257
|
eventType: 'STORY_PROGRESS_UPDATE',
|
|
258
258
|
message: `Auto-approved permission prompt for ${sessionName}`,
|
|
@@ -52,7 +52,14 @@ function makeCtx(
|
|
|
52
52
|
overrides: Partial<ManagerCheckContext> = {},
|
|
53
53
|
schedulerOverrides: Record<string, unknown> = {}
|
|
54
54
|
): ManagerCheckContext {
|
|
55
|
-
const
|
|
55
|
+
const mockProvider = {} as never;
|
|
56
|
+
const mockDb = {
|
|
57
|
+
db: {} as never,
|
|
58
|
+
provider: mockProvider,
|
|
59
|
+
save: vi.fn(),
|
|
60
|
+
close: vi.fn(),
|
|
61
|
+
runMigrations: vi.fn(),
|
|
62
|
+
};
|
|
56
63
|
const mockScheduler = {
|
|
57
64
|
spawnAuditor: vi.fn().mockResolvedValue({ id: 'auditor-abc123' }),
|
|
58
65
|
...schedulerOverrides,
|
|
@@ -118,8 +125,8 @@ describe('spawnAuditorIfNeeded', () => {
|
|
|
118
125
|
});
|
|
119
126
|
|
|
120
127
|
it('spawns auditor when interval elapsed and no active auditor', async () => {
|
|
121
|
-
mockGetAgentsByType.
|
|
122
|
-
mockGetAllTeams.
|
|
128
|
+
mockGetAgentsByType.mockResolvedValue([]);
|
|
129
|
+
mockGetAllTeams.mockResolvedValue([{ id: 'team-1', name: 'alpha', repo_path: '/repo' }]);
|
|
123
130
|
|
|
124
131
|
const ctx = makeCtx();
|
|
125
132
|
const result = await spawnAuditorIfNeeded(ctx);
|
|
@@ -135,8 +142,8 @@ describe('spawnAuditorIfNeeded', () => {
|
|
|
135
142
|
});
|
|
136
143
|
|
|
137
144
|
it('skips spawn when interval has not elapsed', async () => {
|
|
138
|
-
mockGetAgentsByType.
|
|
139
|
-
mockGetAllTeams.
|
|
145
|
+
mockGetAgentsByType.mockResolvedValue([]);
|
|
146
|
+
mockGetAllTeams.mockResolvedValue([{ id: 'team-1', name: 'alpha', repo_path: '/repo' }]);
|
|
140
147
|
|
|
141
148
|
const ctx = makeCtx();
|
|
142
149
|
|
|
@@ -151,7 +158,7 @@ describe('spawnAuditorIfNeeded', () => {
|
|
|
151
158
|
});
|
|
152
159
|
|
|
153
160
|
it('skips spawn when an active auditor is running', async () => {
|
|
154
|
-
mockGetAgentsByType.
|
|
161
|
+
mockGetAgentsByType.mockResolvedValue([
|
|
155
162
|
{ id: 'auditor-existing', type: 'auditor', status: 'working' },
|
|
156
163
|
]);
|
|
157
164
|
|
|
@@ -166,8 +173,8 @@ describe('spawnAuditorIfNeeded', () => {
|
|
|
166
173
|
});
|
|
167
174
|
|
|
168
175
|
it('skips spawn when no teams exist', async () => {
|
|
169
|
-
mockGetAgentsByType.
|
|
170
|
-
mockGetAllTeams.
|
|
176
|
+
mockGetAgentsByType.mockResolvedValue([]);
|
|
177
|
+
mockGetAllTeams.mockResolvedValue([]);
|
|
171
178
|
|
|
172
179
|
const ctx = makeCtx();
|
|
173
180
|
const result = await spawnAuditorIfNeeded(ctx);
|
|
@@ -177,8 +184,8 @@ describe('spawnAuditorIfNeeded', () => {
|
|
|
177
184
|
});
|
|
178
185
|
|
|
179
186
|
it('handles spawn errors gracefully', async () => {
|
|
180
|
-
mockGetAgentsByType.
|
|
181
|
-
mockGetAllTeams.
|
|
187
|
+
mockGetAgentsByType.mockResolvedValue([]);
|
|
188
|
+
mockGetAllTeams.mockResolvedValue([{ id: 'team-1', name: 'alpha', repo_path: '/repo' }]);
|
|
182
189
|
|
|
183
190
|
const ctx = makeCtx(
|
|
184
191
|
{},
|
|
@@ -193,10 +200,10 @@ describe('spawnAuditorIfNeeded', () => {
|
|
|
193
200
|
});
|
|
194
201
|
|
|
195
202
|
it('does not count terminated auditors as active', async () => {
|
|
196
|
-
mockGetAgentsByType.
|
|
203
|
+
mockGetAgentsByType.mockResolvedValue([
|
|
197
204
|
{ id: 'auditor-old', type: 'auditor', status: 'terminated' },
|
|
198
205
|
]);
|
|
199
|
-
mockGetAllTeams.
|
|
206
|
+
mockGetAllTeams.mockResolvedValue([{ id: 'team-1', name: 'alpha', repo_path: '/repo' }]);
|
|
200
207
|
|
|
201
208
|
const ctx = makeCtx();
|
|
202
209
|
const result = await spawnAuditorIfNeeded(ctx);
|
|
@@ -206,8 +213,8 @@ describe('spawnAuditorIfNeeded', () => {
|
|
|
206
213
|
});
|
|
207
214
|
|
|
208
215
|
it('updates lastAuditorSpawnTime after successful spawn', async () => {
|
|
209
|
-
mockGetAgentsByType.
|
|
210
|
-
mockGetAllTeams.
|
|
216
|
+
mockGetAgentsByType.mockResolvedValue([]);
|
|
217
|
+
mockGetAllTeams.mockResolvedValue([{ id: 'team-1', name: 'alpha', repo_path: '/repo' }]);
|
|
211
218
|
|
|
212
219
|
expect(getLastAuditorSpawnTime()).toBe(0);
|
|
213
220
|
|
|
@@ -55,7 +55,7 @@ export async function spawnAuditorIfNeeded(ctx: ManagerCheckContext): Promise<bo
|
|
|
55
55
|
|
|
56
56
|
// Check if a previous auditor is still running
|
|
57
57
|
const hasActiveAuditor = await ctx.withDb(async db => {
|
|
58
|
-
const auditors = getAgentsByType(db.
|
|
58
|
+
const auditors = await getAgentsByType(db.provider, 'auditor');
|
|
59
59
|
return auditors.some(a => a.status === 'idle' || a.status === 'working');
|
|
60
60
|
});
|
|
61
61
|
|
|
@@ -67,7 +67,7 @@ export async function spawnAuditorIfNeeded(ctx: ManagerCheckContext): Promise<bo
|
|
|
67
67
|
// Spawn a new auditor agent
|
|
68
68
|
try {
|
|
69
69
|
const agent = await ctx.withDb(async (db, scheduler) => {
|
|
70
|
-
const teams = getAllTeams(db.
|
|
70
|
+
const teams = await getAllTeams(db.provider);
|
|
71
71
|
if (teams.length === 0) {
|
|
72
72
|
verboseLogCtx(ctx, 'spawnAuditorIfNeeded: skip=no_teams');
|
|
73
73
|
return null;
|
|
@@ -76,7 +76,7 @@ export async function spawnAuditorIfNeeded(ctx: ManagerCheckContext): Promise<bo
|
|
|
76
76
|
const team = teams[0];
|
|
77
77
|
const spawned = await scheduler.spawnAuditor(team.id, team.name, team.repo_path);
|
|
78
78
|
|
|
79
|
-
createLog(db.
|
|
79
|
+
await createLog(db.provider, {
|
|
80
80
|
agentId: spawned.id,
|
|
81
81
|
eventType: 'AGENT_SPAWNED',
|
|
82
82
|
message: `Spawned auditor agent ${spawned.id} for team ${team.name}`,
|