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
package/src/utils/paths.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Licensed under the Hungry Ghost Hive License. See LICENSE.
|
|
2
2
|
|
|
3
|
-
import { existsSync } from 'fs';
|
|
3
|
+
import { existsSync, readFileSync } from 'fs';
|
|
4
4
|
import { join, resolve } from 'path';
|
|
5
5
|
|
|
6
6
|
export const HIVE_DIR_NAME = '.hive';
|
|
@@ -14,6 +14,7 @@ export interface HivePaths {
|
|
|
14
14
|
hiveDir: string;
|
|
15
15
|
dbPath: string;
|
|
16
16
|
configPath: string;
|
|
17
|
+
workspaceIdPath: string;
|
|
17
18
|
agentsDir: string;
|
|
18
19
|
logsDir: string;
|
|
19
20
|
reposDir: string;
|
|
@@ -42,6 +43,7 @@ export function getHivePaths(rootDir: string): HivePaths {
|
|
|
42
43
|
hiveDir,
|
|
43
44
|
dbPath: join(hiveDir, 'hive.db'),
|
|
44
45
|
configPath: join(hiveDir, 'hive.config.yaml'),
|
|
46
|
+
workspaceIdPath: join(hiveDir, 'workspace.id'),
|
|
45
47
|
agentsDir: join(hiveDir, AGENTS_DIR_NAME),
|
|
46
48
|
logsDir: join(hiveDir, LOGS_DIR_NAME),
|
|
47
49
|
reposDir: join(rootDir, REPOS_DIR_NAME),
|
|
@@ -52,3 +54,14 @@ export function getHivePaths(rootDir: string): HivePaths {
|
|
|
52
54
|
export function isHiveWorkspace(dir: string): boolean {
|
|
53
55
|
return existsSync(join(dir, HIVE_DIR_NAME));
|
|
54
56
|
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Read the workspace ID from .hive/workspace.id.
|
|
60
|
+
* Returns null if the file does not exist (non-distributed mode).
|
|
61
|
+
*/
|
|
62
|
+
export function getWorkspaceId(paths: HivePaths): string | null {
|
|
63
|
+
if (!existsSync(paths.workspaceIdPath)) {
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
return readFileSync(paths.workspaceIdPath, 'utf-8').trim();
|
|
67
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Licensed under the Hungry Ghost Hive License. See LICENSE.
|
|
2
2
|
|
|
3
|
-
import type { Database } from 'sql.js';
|
|
4
3
|
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
4
|
+
import { SqliteProvider } from '../db/provider.js';
|
|
5
5
|
import { createPullRequest } from '../db/queries/pull-requests.js';
|
|
6
6
|
import { createTestDatabase } from '../db/queries/test-helpers.js';
|
|
7
7
|
import { closeStaleGitHubPRs, getExistingPRIdentifiers, syncOpenGitHubPRs } from './pr-sync.js';
|
|
@@ -14,64 +14,65 @@ import { execa } from 'execa';
|
|
|
14
14
|
|
|
15
15
|
const mockExeca = vi.mocked(execa);
|
|
16
16
|
|
|
17
|
-
let db:
|
|
17
|
+
let db: SqliteProvider;
|
|
18
18
|
|
|
19
19
|
beforeEach(async () => {
|
|
20
20
|
vi.clearAllMocks();
|
|
21
|
-
|
|
21
|
+
const rawDb = await createTestDatabase();
|
|
22
|
+
db = new SqliteProvider(rawDb);
|
|
22
23
|
// Create a 'manager' agent for logging (required by foreign key constraint)
|
|
23
|
-
db.run("INSERT INTO agents (id, type, status) VALUES ('manager', 'tech_lead', 'idle')");
|
|
24
|
+
db.db.run("INSERT INTO agents (id, type, status) VALUES ('manager', 'tech_lead', 'idle')");
|
|
24
25
|
});
|
|
25
26
|
|
|
26
27
|
describe('getExistingPRIdentifiers', () => {
|
|
27
|
-
it('should return empty sets when no PRs exist', () => {
|
|
28
|
-
const { existingBranches, existingPrNumbers } = getExistingPRIdentifiers(db);
|
|
28
|
+
it('should return empty sets when no PRs exist', async () => {
|
|
29
|
+
const { existingBranches, existingPrNumbers } = await getExistingPRIdentifiers(db);
|
|
29
30
|
|
|
30
31
|
expect(existingBranches.size).toBe(0);
|
|
31
32
|
expect(existingPrNumbers.size).toBe(0);
|
|
32
33
|
});
|
|
33
34
|
|
|
34
|
-
it('should include all branch names when includeTerminalBranches is true', () => {
|
|
35
|
-
createPullRequest(db, { branchName: 'feature/open', githubPrNumber: 1 });
|
|
36
|
-
const mergedPR = createPullRequest(db, {
|
|
35
|
+
it('should include all branch names when includeTerminalBranches is true', async () => {
|
|
36
|
+
await createPullRequest(db, { branchName: 'feature/open', githubPrNumber: 1 });
|
|
37
|
+
const mergedPR = await createPullRequest(db, {
|
|
37
38
|
branchName: 'feature/merged',
|
|
38
39
|
githubPrNumber: 2,
|
|
39
40
|
});
|
|
40
41
|
// Manually set status to merged
|
|
41
|
-
db.run("UPDATE pull_requests SET status = 'merged' WHERE id = ?", [mergedPR.id]);
|
|
42
|
+
db.db.run("UPDATE pull_requests SET status = 'merged' WHERE id = ?", [mergedPR.id]);
|
|
42
43
|
|
|
43
|
-
const { existingBranches } = getExistingPRIdentifiers(db, true);
|
|
44
|
+
const { existingBranches } = await getExistingPRIdentifiers(db, true);
|
|
44
45
|
|
|
45
46
|
expect(existingBranches.has('feature/open')).toBe(true);
|
|
46
47
|
expect(existingBranches.has('feature/merged')).toBe(true);
|
|
47
48
|
});
|
|
48
49
|
|
|
49
|
-
it('should exclude terminal branch names when includeTerminalBranches is false', () => {
|
|
50
|
-
createPullRequest(db, { branchName: 'feature/open', githubPrNumber: 1 });
|
|
51
|
-
const mergedPR = createPullRequest(db, {
|
|
50
|
+
it('should exclude terminal branch names when includeTerminalBranches is false', async () => {
|
|
51
|
+
await createPullRequest(db, { branchName: 'feature/open', githubPrNumber: 1 });
|
|
52
|
+
const mergedPR = await createPullRequest(db, {
|
|
52
53
|
branchName: 'feature/merged',
|
|
53
54
|
githubPrNumber: 2,
|
|
54
55
|
});
|
|
55
|
-
const closedPR = createPullRequest(db, {
|
|
56
|
+
const closedPR = await createPullRequest(db, {
|
|
56
57
|
branchName: 'feature/closed',
|
|
57
58
|
githubPrNumber: 3,
|
|
58
59
|
});
|
|
59
|
-
db.run("UPDATE pull_requests SET status = 'merged' WHERE id = ?", [mergedPR.id]);
|
|
60
|
-
db.run("UPDATE pull_requests SET status = 'closed' WHERE id = ?", [closedPR.id]);
|
|
60
|
+
db.db.run("UPDATE pull_requests SET status = 'merged' WHERE id = ?", [mergedPR.id]);
|
|
61
|
+
db.db.run("UPDATE pull_requests SET status = 'closed' WHERE id = ?", [closedPR.id]);
|
|
61
62
|
|
|
62
|
-
const { existingBranches } = getExistingPRIdentifiers(db, false);
|
|
63
|
+
const { existingBranches } = await getExistingPRIdentifiers(db, false);
|
|
63
64
|
|
|
64
65
|
expect(existingBranches.has('feature/open')).toBe(true);
|
|
65
66
|
expect(existingBranches.has('feature/merged')).toBe(false);
|
|
66
67
|
expect(existingBranches.has('feature/closed')).toBe(false);
|
|
67
68
|
});
|
|
68
69
|
|
|
69
|
-
it('should collect PR numbers and filter out nulls', () => {
|
|
70
|
-
createPullRequest(db, { branchName: 'feature/a', githubPrNumber: 42 });
|
|
71
|
-
createPullRequest(db, { branchName: 'feature/b', githubPrNumber: null });
|
|
72
|
-
createPullRequest(db, { branchName: 'feature/c', githubPrNumber: 99 });
|
|
70
|
+
it('should collect PR numbers and filter out nulls', async () => {
|
|
71
|
+
await createPullRequest(db, { branchName: 'feature/a', githubPrNumber: 42 });
|
|
72
|
+
await createPullRequest(db, { branchName: 'feature/b', githubPrNumber: null });
|
|
73
|
+
await createPullRequest(db, { branchName: 'feature/c', githubPrNumber: 99 });
|
|
73
74
|
|
|
74
|
-
const { existingPrNumbers } = getExistingPRIdentifiers(db);
|
|
75
|
+
const { existingPrNumbers } = await getExistingPRIdentifiers(db);
|
|
75
76
|
|
|
76
77
|
expect(existingPrNumbers.has(42)).toBe(true);
|
|
77
78
|
expect(existingPrNumbers.has(99)).toBe(true);
|
|
@@ -200,7 +201,7 @@ describe('syncOpenGitHubPRs', () => {
|
|
|
200
201
|
expect(existingBranches.has('feature/shared')).toBe(true);
|
|
201
202
|
expect(existingPrNumbers.has(10)).toBe(true);
|
|
202
203
|
|
|
203
|
-
const countResult = db.exec('SELECT COUNT(*) as count FROM pull_requests');
|
|
204
|
+
const countResult = db.db.exec('SELECT COUNT(*) as count FROM pull_requests');
|
|
204
205
|
expect(countResult[0].values[0][0]).toBe(1);
|
|
205
206
|
});
|
|
206
207
|
|
|
@@ -238,7 +239,7 @@ describe('syncOpenGitHubPRs', () => {
|
|
|
238
239
|
} as any);
|
|
239
240
|
|
|
240
241
|
// Create a team so foreign key is satisfied
|
|
241
|
-
db.run(
|
|
242
|
+
db.db.run(
|
|
242
243
|
"INSERT INTO teams (id, repo_url, repo_path, name) VALUES ('team-1', 'https://test', 'repo', 'Test')"
|
|
243
244
|
);
|
|
244
245
|
|
|
@@ -246,13 +247,13 @@ describe('syncOpenGitHubPRs', () => {
|
|
|
246
247
|
|
|
247
248
|
expect(result.synced).toBe(1);
|
|
248
249
|
// Verify the PR was created with the team ID
|
|
249
|
-
const prs = db.exec('SELECT team_id FROM pull_requests');
|
|
250
|
+
const prs = db.db.exec('SELECT team_id FROM pull_requests');
|
|
250
251
|
expect(prs[0].values[0][0]).toBe('team-1');
|
|
251
252
|
});
|
|
252
253
|
|
|
253
254
|
it('should extract story IDs from branch names that match the story ID pattern', async () => {
|
|
254
255
|
// Create a story so the FK constraint is satisfied
|
|
255
|
-
db.run(
|
|
256
|
+
db.db.run(
|
|
256
257
|
"INSERT INTO stories (id, title, description, status) VALUES ('STORY-GOD-001', 'Test', 'Test', 'planned')"
|
|
257
258
|
);
|
|
258
259
|
|
|
@@ -270,7 +271,7 @@ describe('syncOpenGitHubPRs', () => {
|
|
|
270
271
|
|
|
271
272
|
await syncOpenGitHubPRs(db, '/repo', null, new Set(), new Set());
|
|
272
273
|
|
|
273
|
-
const prs = db.exec('SELECT story_id FROM pull_requests');
|
|
274
|
+
const prs = db.db.exec('SELECT story_id FROM pull_requests');
|
|
274
275
|
expect(prs[0].values[0][0]).toBe('STORY-GOD-001');
|
|
275
276
|
});
|
|
276
277
|
|
|
@@ -293,7 +294,7 @@ describe('syncOpenGitHubPRs', () => {
|
|
|
293
294
|
expect(result.imported).toHaveLength(1);
|
|
294
295
|
|
|
295
296
|
// Verify the PR was created with null story_id
|
|
296
|
-
const prs = db.exec('SELECT story_id FROM pull_requests');
|
|
297
|
+
const prs = db.db.exec('SELECT story_id FROM pull_requests');
|
|
297
298
|
expect(prs[0].values[0][0]).toBeNull();
|
|
298
299
|
});
|
|
299
300
|
|
|
@@ -318,7 +319,7 @@ describe('syncOpenGitHubPRs', () => {
|
|
|
318
319
|
|
|
319
320
|
it('should skip PRs where story status is merged', async () => {
|
|
320
321
|
// Create a merged story
|
|
321
|
-
db.run(
|
|
322
|
+
db.db.run(
|
|
322
323
|
"INSERT INTO stories (id, title, description, status) VALUES ('STORY-MERGED-001', 'Merged Story', 'Test', 'merged')"
|
|
323
324
|
);
|
|
324
325
|
|
|
@@ -342,7 +343,7 @@ describe('syncOpenGitHubPRs', () => {
|
|
|
342
343
|
|
|
343
344
|
it('should import PRs with active (non-merged) stories', async () => {
|
|
344
345
|
// Create an active story
|
|
345
|
-
db.run(
|
|
346
|
+
db.db.run(
|
|
346
347
|
"INSERT INTO stories (id, title, description, status) VALUES ('STORY-ACTIVE-001', 'Active Story', 'Test', 'in_progress')"
|
|
347
348
|
);
|
|
348
349
|
|
|
@@ -367,10 +368,10 @@ describe('syncOpenGitHubPRs', () => {
|
|
|
367
368
|
|
|
368
369
|
it('should filter mixed PRs - import active stories and PRs without story IDs', async () => {
|
|
369
370
|
// Create stories with different statuses
|
|
370
|
-
db.run(
|
|
371
|
+
db.db.run(
|
|
371
372
|
"INSERT INTO stories (id, title, description, status) VALUES ('STORY-ACTIVE-001', 'Active', 'Test', 'planned')"
|
|
372
373
|
);
|
|
373
|
-
db.run(
|
|
374
|
+
db.db.run(
|
|
374
375
|
"INSERT INTO stories (id, title, description, status) VALUES ('STORY-MERGED-001', 'Merged', 'Test', 'merged')"
|
|
375
376
|
);
|
|
376
377
|
|
|
@@ -491,7 +492,7 @@ describe('syncOpenGitHubPRs', () => {
|
|
|
491
492
|
await syncOpenGitHubPRs(db, '/repo', null, new Set(), new Set(), null, maxAgeHours);
|
|
492
493
|
|
|
493
494
|
// Check that a log entry was created
|
|
494
|
-
const logs = db.exec("SELECT * FROM agent_logs WHERE event_type = 'PR_SYNC_SKIPPED'");
|
|
495
|
+
const logs = db.db.exec("SELECT * FROM agent_logs WHERE event_type = 'PR_SYNC_SKIPPED'");
|
|
495
496
|
expect(logs.length).toBeGreaterThan(0);
|
|
496
497
|
expect(logs[0].values.length).toBeGreaterThan(0);
|
|
497
498
|
});
|
|
@@ -512,7 +513,7 @@ describe('syncOpenGitHubPRs', () => {
|
|
|
512
513
|
await syncOpenGitHubPRs(db, '/repo', null, new Set(), new Set());
|
|
513
514
|
|
|
514
515
|
// Check that a log entry was created
|
|
515
|
-
const logs = db.exec("SELECT * FROM agent_logs WHERE event_type = 'PR_SYNC_SKIPPED'");
|
|
516
|
+
const logs = db.db.exec("SELECT * FROM agent_logs WHERE event_type = 'PR_SYNC_SKIPPED'");
|
|
516
517
|
expect(logs.length).toBeGreaterThan(0);
|
|
517
518
|
expect(logs[0].values.length).toBeGreaterThan(0);
|
|
518
519
|
});
|
|
@@ -521,14 +522,14 @@ describe('syncOpenGitHubPRs', () => {
|
|
|
521
522
|
describe('closeStaleGitHubPRs', () => {
|
|
522
523
|
beforeEach(() => {
|
|
523
524
|
// Insert a team so the function can iterate teams
|
|
524
|
-
db.run(
|
|
525
|
+
db.db.run(
|
|
525
526
|
"INSERT INTO teams (id, repo_url, repo_path, name) VALUES ('team-1', 'https://github.com/test/repo', 'repos/test', 'Test')"
|
|
526
527
|
);
|
|
527
528
|
});
|
|
528
529
|
|
|
529
530
|
it('should return empty array when no teams exist', async () => {
|
|
530
531
|
// Remove the team inserted in beforeEach
|
|
531
|
-
db.run("DELETE FROM teams WHERE id = 'team-1'");
|
|
532
|
+
db.db.run("DELETE FROM teams WHERE id = 'team-1'");
|
|
532
533
|
|
|
533
534
|
const result = await closeStaleGitHubPRs('/root', db);
|
|
534
535
|
|
|
@@ -564,10 +565,10 @@ describe('closeStaleGitHubPRs', () => {
|
|
|
564
565
|
});
|
|
565
566
|
|
|
566
567
|
it('should skip a GitHub PR that is already in the queue', async () => {
|
|
567
|
-
db.run(
|
|
568
|
+
db.db.run(
|
|
568
569
|
"INSERT INTO stories (id, title, description, status) VALUES ('STORY-TST-001', 'Test', 'Test', 'in_progress')"
|
|
569
570
|
);
|
|
570
|
-
const pr = createPullRequest(db, {
|
|
571
|
+
const pr = await createPullRequest(db, {
|
|
571
572
|
storyId: 'STORY-TST-001',
|
|
572
573
|
branchName: 'feature/STORY-TST-001-work',
|
|
573
574
|
githubPrNumber: 10,
|
|
@@ -598,11 +599,11 @@ describe('closeStaleGitHubPRs', () => {
|
|
|
598
599
|
});
|
|
599
600
|
|
|
600
601
|
it('should close a stale GitHub PR and return ClosedPRInfo', async () => {
|
|
601
|
-
db.run(
|
|
602
|
+
db.db.run(
|
|
602
603
|
"INSERT INTO stories (id, title, description, status) VALUES ('STORY-TST-002', 'Test', 'Test', 'in_progress')"
|
|
603
604
|
);
|
|
604
605
|
// Queue PR has github_pr_number 20 (the newer one)
|
|
605
|
-
createPullRequest(db, {
|
|
606
|
+
await createPullRequest(db, {
|
|
606
607
|
storyId: 'STORY-TST-002',
|
|
607
608
|
branchName: 'feature/STORY-TST-002-v2',
|
|
608
609
|
githubPrNumber: 20,
|
|
@@ -634,10 +635,10 @@ describe('closeStaleGitHubPRs', () => {
|
|
|
634
635
|
});
|
|
635
636
|
|
|
636
637
|
it('should include superseding PR number in the log message', async () => {
|
|
637
|
-
db.run(
|
|
638
|
+
db.db.run(
|
|
638
639
|
"INSERT INTO stories (id, title, description, status) VALUES ('STORY-TST-003', 'Test', 'Test', 'in_progress')"
|
|
639
640
|
);
|
|
640
|
-
createPullRequest(db, {
|
|
641
|
+
await createPullRequest(db, {
|
|
641
642
|
storyId: 'STORY-TST-003',
|
|
642
643
|
branchName: 'feature/STORY-TST-003-v2',
|
|
643
644
|
githubPrNumber: 30,
|
|
@@ -660,7 +661,9 @@ describe('closeStaleGitHubPRs', () => {
|
|
|
660
661
|
|
|
661
662
|
await closeStaleGitHubPRs('/root', db);
|
|
662
663
|
|
|
663
|
-
const logs = db.exec(
|
|
664
|
+
const logs = db.db.exec(
|
|
665
|
+
"SELECT message, metadata FROM agent_logs WHERE event_type = 'PR_CLOSED'"
|
|
666
|
+
);
|
|
664
667
|
expect(logs.length).toBeGreaterThan(0);
|
|
665
668
|
const message = logs[0].values[0][0] as string;
|
|
666
669
|
expect(message).toContain('#15');
|
|
@@ -671,10 +674,10 @@ describe('closeStaleGitHubPRs', () => {
|
|
|
671
674
|
});
|
|
672
675
|
|
|
673
676
|
it('should not close if gh CLI throws and should not include in result', async () => {
|
|
674
|
-
db.run(
|
|
677
|
+
db.db.run(
|
|
675
678
|
"INSERT INTO stories (id, title, description, status) VALUES ('STORY-TST-004', 'Test', 'Test', 'in_progress')"
|
|
676
679
|
);
|
|
677
|
-
createPullRequest(db, {
|
|
680
|
+
await createPullRequest(db, {
|
|
678
681
|
storyId: 'STORY-TST-004',
|
|
679
682
|
branchName: 'feature/STORY-TST-004-v2',
|
|
680
683
|
githubPrNumber: 40,
|
|
@@ -702,10 +705,10 @@ describe('closeStaleGitHubPRs', () => {
|
|
|
702
705
|
});
|
|
703
706
|
|
|
704
707
|
it('should skip PRs not targeting the configured base branch', async () => {
|
|
705
|
-
db.run(
|
|
708
|
+
db.db.run(
|
|
706
709
|
"INSERT INTO stories (id, title, description, status) VALUES ('STORY-TST-005', 'Test', 'Test', 'in_progress')"
|
|
707
710
|
);
|
|
708
|
-
createPullRequest(db, {
|
|
711
|
+
await createPullRequest(db, {
|
|
709
712
|
storyId: 'STORY-TST-005',
|
|
710
713
|
branchName: 'feature/STORY-TST-005-v2',
|
|
711
714
|
githubPrNumber: 50,
|
|
@@ -736,10 +739,10 @@ describe('closeStaleGitHubPRs', () => {
|
|
|
736
739
|
});
|
|
737
740
|
|
|
738
741
|
it('should only close PRs targeting the configured base branch when it is non-main', async () => {
|
|
739
|
-
db.run(
|
|
742
|
+
db.db.run(
|
|
740
743
|
"INSERT INTO stories (id, title, description, status) VALUES ('STORY-TST-006', 'Test', 'Test', 'in_progress')"
|
|
741
744
|
);
|
|
742
|
-
createPullRequest(db, {
|
|
745
|
+
await createPullRequest(db, {
|
|
743
746
|
storyId: 'STORY-TST-006',
|
|
744
747
|
branchName: 'feature/STORY-TST-006-v2',
|
|
745
748
|
githubPrNumber: 60,
|
|
@@ -768,10 +771,10 @@ describe('closeStaleGitHubPRs', () => {
|
|
|
768
771
|
});
|
|
769
772
|
|
|
770
773
|
it('should not close PRs targeting main when configured base branch is feat/memento-refactor', async () => {
|
|
771
|
-
db.run(
|
|
774
|
+
db.db.run(
|
|
772
775
|
"INSERT INTO stories (id, title, description, status) VALUES ('STORY-TST-007', 'Test', 'Test', 'in_progress')"
|
|
773
776
|
);
|
|
774
|
-
createPullRequest(db, {
|
|
777
|
+
await createPullRequest(db, {
|
|
775
778
|
storyId: 'STORY-TST-007',
|
|
776
779
|
branchName: 'feature/STORY-TST-007-v2',
|
|
777
780
|
githubPrNumber: 70,
|
package/src/utils/pr-sync.ts
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
// Licensed under the Hungry Ghost Hive License. See LICENSE.
|
|
2
2
|
|
|
3
3
|
import { execa } from 'execa';
|
|
4
|
-
import type { Database } from 'sql.js';
|
|
5
4
|
import { syncStatusForStory } from '../connectors/project-management/operations.js';
|
|
6
|
-
import {
|
|
5
|
+
import type { DatabaseProvider } from '../db/provider.js';
|
|
7
6
|
import { createLog } from '../db/queries/logs.js';
|
|
8
7
|
import { createPullRequest } from '../db/queries/pull-requests.js';
|
|
9
8
|
import { updateStory } from '../db/queries/stories.js';
|
|
@@ -53,23 +52,22 @@ interface ExistingPRNumberRow {
|
|
|
53
52
|
/**
|
|
54
53
|
* Build sets of existing branch names and PR numbers from the database.
|
|
55
54
|
*
|
|
56
|
-
* @param db -
|
|
55
|
+
* @param db - DatabaseProvider instance
|
|
57
56
|
* @param includeTerminalBranches - If true, include merged/closed PR branches
|
|
58
57
|
* in the returned set (prevents re-importing previously synced PRs).
|
|
59
58
|
* Defaults to true.
|
|
60
59
|
*/
|
|
61
|
-
export function getExistingPRIdentifiers(
|
|
62
|
-
db:
|
|
60
|
+
export async function getExistingPRIdentifiers(
|
|
61
|
+
db: DatabaseProvider,
|
|
63
62
|
includeTerminalBranches = true
|
|
64
|
-
): { existingBranches: Set<string>; existingPrNumbers: Set<number> } {
|
|
63
|
+
): Promise<{ existingBranches: Set<string>; existingPrNumbers: Set<number> }> {
|
|
65
64
|
const branchQuery = includeTerminalBranches
|
|
66
65
|
? 'SELECT branch_name FROM pull_requests'
|
|
67
66
|
: "SELECT branch_name FROM pull_requests WHERE status NOT IN ('merged', 'closed')";
|
|
68
|
-
const branchRows = queryAll<ExistingPRBranchRow>(
|
|
67
|
+
const branchRows = await db.queryAll<ExistingPRBranchRow>(branchQuery);
|
|
69
68
|
const existingBranches = new Set(branchRows.map(row => row.branch_name));
|
|
70
69
|
|
|
71
|
-
const numberRows = queryAll<ExistingPRNumberRow>(
|
|
72
|
-
db,
|
|
70
|
+
const numberRows = await db.queryAll<ExistingPRNumberRow>(
|
|
73
71
|
`
|
|
74
72
|
SELECT DISTINCT github_pr_number
|
|
75
73
|
FROM pull_requests
|
|
@@ -111,7 +109,7 @@ export async function fetchOpenGitHubPRs(
|
|
|
111
109
|
* - PRs with story IDs are only imported if the story exists and is not merged
|
|
112
110
|
* - PRs older than maxAgeHours are skipped (age-based filtering)
|
|
113
111
|
*
|
|
114
|
-
* @param db -
|
|
112
|
+
* @param db - DatabaseProvider instance
|
|
115
113
|
* @param repoDir - Absolute path to the git repository
|
|
116
114
|
* @param teamId - Team ID to associate with created PRs (null for CLI usage)
|
|
117
115
|
* @param existingBranches - Set of branch names already in the queue
|
|
@@ -120,7 +118,7 @@ export async function fetchOpenGitHubPRs(
|
|
|
120
118
|
* @param maxAgeHours - Optional max age in hours for PRs (default: no limit)
|
|
121
119
|
*/
|
|
122
120
|
export async function syncOpenGitHubPRs(
|
|
123
|
-
db:
|
|
121
|
+
db: DatabaseProvider,
|
|
124
122
|
repoDir: string,
|
|
125
123
|
teamId: string | null,
|
|
126
124
|
existingBranches: Set<string>,
|
|
@@ -142,7 +140,7 @@ export async function syncOpenGitHubPRs(
|
|
|
142
140
|
const ageHours = (Date.now() - prCreatedAt.getTime()) / (1000 * 60 * 60);
|
|
143
141
|
|
|
144
142
|
if (ageHours > maxAgeHours) {
|
|
145
|
-
createLog(db, {
|
|
143
|
+
await createLog(db, {
|
|
146
144
|
agentId: 'manager',
|
|
147
145
|
eventType: 'PR_SYNC_SKIPPED',
|
|
148
146
|
status: 'info',
|
|
@@ -164,15 +162,14 @@ export async function syncOpenGitHubPRs(
|
|
|
164
162
|
// If the PR has a story ID, check if the story is active
|
|
165
163
|
if (storyId) {
|
|
166
164
|
// Check if the story exists and is active (not merged)
|
|
167
|
-
const storyRows = queryAll<{ id: string; status: string }>(
|
|
168
|
-
db,
|
|
165
|
+
const storyRows = await db.queryAll<{ id: string; status: string }>(
|
|
169
166
|
`SELECT id, status FROM stories WHERE id = ? COLLATE NOCASE AND status != 'merged'`,
|
|
170
167
|
[storyId]
|
|
171
168
|
);
|
|
172
169
|
|
|
173
170
|
// Skip PRs where story doesn't exist or is merged
|
|
174
171
|
if (storyRows.length === 0) {
|
|
175
|
-
createLog(db, {
|
|
172
|
+
await createLog(db, {
|
|
176
173
|
agentId: 'manager',
|
|
177
174
|
eventType: 'PR_SYNC_SKIPPED',
|
|
178
175
|
status: 'info',
|
|
@@ -188,7 +185,7 @@ export async function syncOpenGitHubPRs(
|
|
|
188
185
|
}
|
|
189
186
|
}
|
|
190
187
|
|
|
191
|
-
const pr = createPullRequest(db, {
|
|
188
|
+
const pr = await createPullRequest(db, {
|
|
192
189
|
storyId,
|
|
193
190
|
teamId,
|
|
194
191
|
branchName: ghPR.headRefName,
|
|
@@ -222,14 +219,14 @@ export async function syncOpenGitHubPRs(
|
|
|
222
219
|
*/
|
|
223
220
|
export async function syncAllTeamOpenPRs(
|
|
224
221
|
root: string,
|
|
225
|
-
db:
|
|
222
|
+
db: DatabaseProvider,
|
|
226
223
|
saveFn: () => void,
|
|
227
224
|
maxAgeHours?: number
|
|
228
225
|
): Promise<number> {
|
|
229
|
-
const teams = getAllTeams(db);
|
|
226
|
+
const teams = await getAllTeams(db);
|
|
230
227
|
if (teams.length === 0) return 0;
|
|
231
228
|
|
|
232
|
-
const { existingBranches, existingPrNumbers } = getExistingPRIdentifiers(db, true);
|
|
229
|
+
const { existingBranches, existingPrNumbers } = await getExistingPRIdentifiers(db, true);
|
|
233
230
|
let totalSynced = 0;
|
|
234
231
|
|
|
235
232
|
for (const team of teams) {
|
|
@@ -265,10 +262,10 @@ export async function syncAllTeamOpenPRs(
|
|
|
265
262
|
*/
|
|
266
263
|
export async function syncMergedPRsFromGitHub(
|
|
267
264
|
root: string,
|
|
268
|
-
db:
|
|
265
|
+
db: DatabaseProvider,
|
|
269
266
|
saveFn: () => void
|
|
270
267
|
): Promise<number> {
|
|
271
|
-
const teams = getAllTeams(db);
|
|
268
|
+
const teams = await getAllTeams(db);
|
|
272
269
|
if (teams.length === 0) return 0;
|
|
273
270
|
|
|
274
271
|
let storiesUpdated = 0;
|
|
@@ -308,8 +305,7 @@ export async function syncMergedPRsFromGitHub(
|
|
|
308
305
|
}
|
|
309
306
|
|
|
310
307
|
const placeholders = candidateStoryIds.map(() => '?').join(',');
|
|
311
|
-
const updatableStories = queryAll<{ id: string }>(
|
|
312
|
-
db,
|
|
308
|
+
const updatableStories = await db.queryAll<{ id: string }>(
|
|
313
309
|
`
|
|
314
310
|
SELECT id
|
|
315
311
|
FROM stories
|
|
@@ -333,10 +329,10 @@ export async function syncMergedPRsFromGitHub(
|
|
|
333
329
|
continue;
|
|
334
330
|
}
|
|
335
331
|
|
|
336
|
-
await withTransaction(
|
|
332
|
+
await db.withTransaction(async () => {
|
|
337
333
|
for (const update of toUpdate) {
|
|
338
|
-
updateStory(db, update.storyId, { status: 'merged', assignedAgentId: null });
|
|
339
|
-
createLog(db, {
|
|
334
|
+
await updateStory(db, update.storyId, { status: 'merged', assignedAgentId: null });
|
|
335
|
+
await createLog(db, {
|
|
340
336
|
agentId: 'manager',
|
|
341
337
|
storyId: update.storyId,
|
|
342
338
|
eventType: 'STORY_MERGED',
|
|
@@ -378,15 +374,15 @@ export interface ClosedPRInfo {
|
|
|
378
374
|
* in the hive merge queue (i.e., the GitHub PR is stale/orphaned).
|
|
379
375
|
*
|
|
380
376
|
* @param root - Root directory
|
|
381
|
-
* @param db -
|
|
377
|
+
* @param db - DatabaseProvider instance
|
|
382
378
|
* @returns Array of ClosedPRInfo for each PR that was closed.
|
|
383
379
|
*/
|
|
384
380
|
export async function closeStaleGitHubPRs(
|
|
385
381
|
root: string,
|
|
386
|
-
db:
|
|
382
|
+
db: DatabaseProvider,
|
|
387
383
|
baseBranch = 'main'
|
|
388
384
|
): Promise<ClosedPRInfo[]> {
|
|
389
|
-
const teams = getAllTeams(db);
|
|
385
|
+
const teams = await getAllTeams(db);
|
|
390
386
|
if (teams.length === 0) return [];
|
|
391
387
|
|
|
392
388
|
const closed: ClosedPRInfo[] = [];
|
|
@@ -408,8 +404,7 @@ export async function closeStaleGitHubPRs(
|
|
|
408
404
|
if (!storyId) continue;
|
|
409
405
|
|
|
410
406
|
// Check if there are other PRs for this story in the queue
|
|
411
|
-
const prsForStory = queryAll<{ id: string; github_pr_number: number | null }>(
|
|
412
|
-
db,
|
|
407
|
+
const prsForStory = await db.queryAll<{ id: string; github_pr_number: number | null }>(
|
|
413
408
|
`
|
|
414
409
|
SELECT id, github_pr_number
|
|
415
410
|
FROM pull_requests
|
|
@@ -444,7 +439,7 @@ export async function closeStaleGitHubPRs(
|
|
|
444
439
|
cwd: repoDir,
|
|
445
440
|
timeout: GH_CLI_TIMEOUT_MS,
|
|
446
441
|
});
|
|
447
|
-
createLog(db, {
|
|
442
|
+
await createLog(db, {
|
|
448
443
|
agentId: 'manager',
|
|
449
444
|
storyId,
|
|
450
445
|
eventType: 'PR_CLOSED',
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import chalk from 'chalk';
|
|
4
4
|
import { join } from 'path';
|
|
5
|
+
import { loadConfig } from '../config/loader.js';
|
|
5
6
|
import {
|
|
6
7
|
getDatabase,
|
|
7
8
|
getReadOnlyDatabase,
|
|
@@ -9,7 +10,8 @@ import {
|
|
|
9
10
|
type ReadOnlyDatabaseClient,
|
|
10
11
|
} from '../db/client.js';
|
|
11
12
|
import { acquireLock } from '../db/lock.js';
|
|
12
|
-
import {
|
|
13
|
+
import { createPostgresProvider } from '../db/postgres-provider.js';
|
|
14
|
+
import { findHiveRoot, getHivePaths, getWorkspaceId, type HivePaths } from './paths.js';
|
|
13
15
|
|
|
14
16
|
export interface HiveContext {
|
|
15
17
|
root: string;
|
|
@@ -38,8 +40,25 @@ function resolveRoot(): { root: string; paths: HivePaths } {
|
|
|
38
40
|
return { root, paths };
|
|
39
41
|
}
|
|
40
42
|
|
|
43
|
+
/**
|
|
44
|
+
* Check if this workspace is running in distributed (Postgres) mode.
|
|
45
|
+
*/
|
|
46
|
+
function isDistributedMode(paths: HivePaths): boolean {
|
|
47
|
+
try {
|
|
48
|
+
const config = loadConfig(paths.hiveDir);
|
|
49
|
+
return config.distributed === true;
|
|
50
|
+
} catch {
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
41
55
|
export async function withHiveContext<T>(fn: (ctx: HiveContext) => Promise<T> | T): Promise<T> {
|
|
42
56
|
const { root, paths } = resolveRoot();
|
|
57
|
+
|
|
58
|
+
if (isDistributedMode(paths)) {
|
|
59
|
+
return withDistributedHiveContext(root, paths, fn);
|
|
60
|
+
}
|
|
61
|
+
|
|
43
62
|
const dbLockPath = join(paths.hiveDir, 'db');
|
|
44
63
|
|
|
45
64
|
// Acquire database lock to prevent concurrent access and race conditions
|
|
@@ -93,11 +112,51 @@ export async function withHiveContext<T>(fn: (ctx: HiveContext) => Promise<T> |
|
|
|
93
112
|
}
|
|
94
113
|
}
|
|
95
114
|
|
|
115
|
+
async function withDistributedHiveContext<T>(
|
|
116
|
+
root: string,
|
|
117
|
+
paths: HivePaths,
|
|
118
|
+
fn: (ctx: HiveContext) => Promise<T> | T
|
|
119
|
+
): Promise<T> {
|
|
120
|
+
const workspaceId = getWorkspaceId(paths);
|
|
121
|
+
if (!workspaceId) {
|
|
122
|
+
throw new Error(
|
|
123
|
+
'Distributed mode is enabled but workspace.id file is missing. ' +
|
|
124
|
+
'Re-run "hive init --distributed" to fix.'
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const provider = await createPostgresProvider(workspaceId);
|
|
129
|
+
// Create a DatabaseClient-compatible wrapper around the Postgres provider
|
|
130
|
+
const db: DatabaseClient = {
|
|
131
|
+
db: null as never, // No sql.js database in distributed mode
|
|
132
|
+
provider,
|
|
133
|
+
close: () => {
|
|
134
|
+
provider.close();
|
|
135
|
+
},
|
|
136
|
+
save: () => {
|
|
137
|
+
provider.save();
|
|
138
|
+
},
|
|
139
|
+
runMigrations: () => {
|
|
140
|
+
provider.runMigrations();
|
|
141
|
+
},
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
try {
|
|
145
|
+
return await fn({ root, paths, db });
|
|
146
|
+
} finally {
|
|
147
|
+
await provider.close();
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
96
151
|
export async function withReadOnlyHiveContext<T>(
|
|
97
152
|
fn: (ctx: ReadOnlyHiveContext) => Promise<T> | T
|
|
98
153
|
): Promise<T> {
|
|
99
154
|
const { root, paths } = resolveRoot();
|
|
100
155
|
|
|
156
|
+
if (isDistributedMode(paths)) {
|
|
157
|
+
return withDistributedReadOnlyHiveContext(root, paths, fn);
|
|
158
|
+
}
|
|
159
|
+
|
|
101
160
|
const db = await getReadOnlyDatabase(paths.hiveDir);
|
|
102
161
|
try {
|
|
103
162
|
return await fn({ root, paths, db });
|
|
@@ -106,6 +165,35 @@ export async function withReadOnlyHiveContext<T>(
|
|
|
106
165
|
}
|
|
107
166
|
}
|
|
108
167
|
|
|
168
|
+
async function withDistributedReadOnlyHiveContext<T>(
|
|
169
|
+
root: string,
|
|
170
|
+
paths: HivePaths,
|
|
171
|
+
fn: (ctx: ReadOnlyHiveContext) => Promise<T> | T
|
|
172
|
+
): Promise<T> {
|
|
173
|
+
const workspaceId = getWorkspaceId(paths);
|
|
174
|
+
if (!workspaceId) {
|
|
175
|
+
throw new Error(
|
|
176
|
+
'Distributed mode is enabled but workspace.id file is missing. ' +
|
|
177
|
+
'Re-run "hive init --distributed" to fix.'
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
const provider = await createPostgresProvider(workspaceId);
|
|
182
|
+
const db: ReadOnlyDatabaseClient = {
|
|
183
|
+
db: null as never, // No sql.js database in distributed mode
|
|
184
|
+
provider,
|
|
185
|
+
close: () => {
|
|
186
|
+
provider.close();
|
|
187
|
+
},
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
try {
|
|
191
|
+
return await fn({ root, paths, db });
|
|
192
|
+
} finally {
|
|
193
|
+
await provider.close();
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
109
197
|
export function withHiveRoot<T>(fn: (ctx: HiveRootContext) => T): T {
|
|
110
198
|
const { root, paths } = resolveRoot();
|
|
111
199
|
return fn({ root, paths });
|