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
|
@@ -167,7 +167,12 @@ import { autoRejectCommentOnlyReviews } from './index.js';
|
|
|
167
167
|
// ── Helpers ────────────────────────────────────────────────────────────────
|
|
168
168
|
|
|
169
169
|
function makeMockCtx(overrides: Partial<ManagerCheckContext> = {}): ManagerCheckContext {
|
|
170
|
-
const mockDb = {
|
|
170
|
+
const mockDb = {
|
|
171
|
+
db: {} as any,
|
|
172
|
+
provider: { withTransaction: vi.fn(async (fn: () => unknown) => fn()) },
|
|
173
|
+
save: vi.fn(),
|
|
174
|
+
close: vi.fn(),
|
|
175
|
+
};
|
|
171
176
|
return {
|
|
172
177
|
root: '/test/project',
|
|
173
178
|
verbose: false,
|
|
@@ -228,7 +233,7 @@ describe('autoRejectCommentOnlyReviews', () => {
|
|
|
228
233
|
});
|
|
229
234
|
|
|
230
235
|
it('should return early when no PRs are in reviewing status', async () => {
|
|
231
|
-
vi.mocked(getPullRequestsByStatus).
|
|
236
|
+
vi.mocked(getPullRequestsByStatus).mockResolvedValue([]);
|
|
232
237
|
|
|
233
238
|
const ctx = makeMockCtx();
|
|
234
239
|
await autoRejectCommentOnlyReviews(ctx);
|
|
@@ -239,7 +244,7 @@ describe('autoRejectCommentOnlyReviews', () => {
|
|
|
239
244
|
});
|
|
240
245
|
|
|
241
246
|
it('should return early when reviewing PRs have no github_pr_number', async () => {
|
|
242
|
-
vi.mocked(getPullRequestsByStatus).
|
|
247
|
+
vi.mocked(getPullRequestsByStatus).mockResolvedValue([
|
|
243
248
|
makeReviewingPR({ github_pr_number: null }),
|
|
244
249
|
] as any);
|
|
245
250
|
|
|
@@ -250,8 +255,8 @@ describe('autoRejectCommentOnlyReviews', () => {
|
|
|
250
255
|
});
|
|
251
256
|
|
|
252
257
|
it('should skip PRs where QA agent is not idle', async () => {
|
|
253
|
-
vi.mocked(getPullRequestsByStatus).
|
|
254
|
-
vi.mocked(getAllTeams).
|
|
258
|
+
vi.mocked(getPullRequestsByStatus).mockResolvedValue([makeReviewingPR()] as any);
|
|
259
|
+
vi.mocked(getAllTeams).mockResolvedValue([
|
|
255
260
|
{ id: 'team-1', repo_path: 'repos/mini-marty' },
|
|
256
261
|
] as any);
|
|
257
262
|
|
|
@@ -275,8 +280,8 @@ describe('autoRejectCommentOnlyReviews', () => {
|
|
|
275
280
|
});
|
|
276
281
|
|
|
277
282
|
it('should skip PRs when QA has formal APPROVED review on GitHub', async () => {
|
|
278
|
-
vi.mocked(getPullRequestsByStatus).
|
|
279
|
-
vi.mocked(getAllTeams).
|
|
283
|
+
vi.mocked(getPullRequestsByStatus).mockResolvedValue([makeReviewingPR()] as any);
|
|
284
|
+
vi.mocked(getAllTeams).mockResolvedValue([
|
|
280
285
|
{ id: 'team-1', repo_path: 'repos/mini-marty' },
|
|
281
286
|
] as any);
|
|
282
287
|
|
|
@@ -304,8 +309,8 @@ describe('autoRejectCommentOnlyReviews', () => {
|
|
|
304
309
|
});
|
|
305
310
|
|
|
306
311
|
it('should auto-reject when QA left CHANGES_REQUESTED review', async () => {
|
|
307
|
-
vi.mocked(getPullRequestsByStatus).
|
|
308
|
-
vi.mocked(getAllTeams).
|
|
312
|
+
vi.mocked(getPullRequestsByStatus).mockResolvedValue([makeReviewingPR()] as any);
|
|
313
|
+
vi.mocked(getAllTeams).mockResolvedValue([
|
|
309
314
|
{ id: 'team-1', repo_path: 'repos/mini-marty' },
|
|
310
315
|
] as any);
|
|
311
316
|
|
|
@@ -352,8 +357,8 @@ describe('autoRejectCommentOnlyReviews', () => {
|
|
|
352
357
|
});
|
|
353
358
|
|
|
354
359
|
it('should auto-reject when QA left substantive comments (>= 20 chars)', async () => {
|
|
355
|
-
vi.mocked(getPullRequestsByStatus).
|
|
356
|
-
vi.mocked(getAllTeams).
|
|
360
|
+
vi.mocked(getPullRequestsByStatus).mockResolvedValue([makeReviewingPR()] as any);
|
|
361
|
+
vi.mocked(getAllTeams).mockResolvedValue([
|
|
357
362
|
{ id: 'team-1', repo_path: 'repos/mini-marty' },
|
|
358
363
|
] as any);
|
|
359
364
|
|
|
@@ -392,8 +397,8 @@ describe('autoRejectCommentOnlyReviews', () => {
|
|
|
392
397
|
});
|
|
393
398
|
|
|
394
399
|
it('should ignore short comments (< 20 chars) and not reject', async () => {
|
|
395
|
-
vi.mocked(getPullRequestsByStatus).
|
|
396
|
-
vi.mocked(getAllTeams).
|
|
400
|
+
vi.mocked(getPullRequestsByStatus).mockResolvedValue([makeReviewingPR()] as any);
|
|
401
|
+
vi.mocked(getAllTeams).mockResolvedValue([
|
|
397
402
|
{ id: 'team-1', repo_path: 'repos/mini-marty' },
|
|
398
403
|
] as any);
|
|
399
404
|
|
|
@@ -421,8 +426,8 @@ describe('autoRejectCommentOnlyReviews', () => {
|
|
|
421
426
|
});
|
|
422
427
|
|
|
423
428
|
it('should skip bot "Looks good to me" comments under 100 chars', async () => {
|
|
424
|
-
vi.mocked(getPullRequestsByStatus).
|
|
425
|
-
vi.mocked(getAllTeams).
|
|
429
|
+
vi.mocked(getPullRequestsByStatus).mockResolvedValue([makeReviewingPR()] as any);
|
|
430
|
+
vi.mocked(getAllTeams).mockResolvedValue([
|
|
426
431
|
{ id: 'team-1', repo_path: 'repos/mini-marty' },
|
|
427
432
|
] as any);
|
|
428
433
|
|
|
@@ -453,8 +458,8 @@ describe('autoRejectCommentOnlyReviews', () => {
|
|
|
453
458
|
});
|
|
454
459
|
|
|
455
460
|
it('should gracefully skip PR when GitHub API call fails', async () => {
|
|
456
|
-
vi.mocked(getPullRequestsByStatus).
|
|
457
|
-
vi.mocked(getAllTeams).
|
|
461
|
+
vi.mocked(getPullRequestsByStatus).mockResolvedValue([makeReviewingPR()] as any);
|
|
462
|
+
vi.mocked(getAllTeams).mockResolvedValue([
|
|
458
463
|
{ id: 'team-1', repo_path: 'repos/mini-marty' },
|
|
459
464
|
] as any);
|
|
460
465
|
|
|
@@ -481,8 +486,8 @@ describe('autoRejectCommentOnlyReviews', () => {
|
|
|
481
486
|
});
|
|
482
487
|
|
|
483
488
|
it('should notify developer agent via tmux after rejection', async () => {
|
|
484
|
-
vi.mocked(getPullRequestsByStatus).
|
|
485
|
-
vi.mocked(getAllTeams).
|
|
489
|
+
vi.mocked(getPullRequestsByStatus).mockResolvedValue([makeReviewingPR()] as any);
|
|
490
|
+
vi.mocked(getAllTeams).mockResolvedValue([
|
|
486
491
|
{ id: 'team-1', repo_path: 'repos/mini-marty' },
|
|
487
492
|
] as any);
|
|
488
493
|
|
|
@@ -514,8 +519,8 @@ describe('autoRejectCommentOnlyReviews', () => {
|
|
|
514
519
|
});
|
|
515
520
|
|
|
516
521
|
it('should handle idle status from agent record even without agentStates entry', async () => {
|
|
517
|
-
vi.mocked(getPullRequestsByStatus).
|
|
518
|
-
vi.mocked(getAllTeams).
|
|
522
|
+
vi.mocked(getPullRequestsByStatus).mockResolvedValue([makeReviewingPR()] as any);
|
|
523
|
+
vi.mocked(getAllTeams).mockResolvedValue([
|
|
519
524
|
{ id: 'team-1', repo_path: 'repos/mini-marty' },
|
|
520
525
|
] as any);
|
|
521
526
|
|
|
@@ -541,8 +546,8 @@ describe('autoRejectCommentOnlyReviews', () => {
|
|
|
541
546
|
});
|
|
542
547
|
|
|
543
548
|
it('should combine feedback from both reviews and comments in rejection reason', async () => {
|
|
544
|
-
vi.mocked(getPullRequestsByStatus).
|
|
545
|
-
vi.mocked(getAllTeams).
|
|
549
|
+
vi.mocked(getPullRequestsByStatus).mockResolvedValue([makeReviewingPR()] as any);
|
|
550
|
+
vi.mocked(getAllTeams).mockResolvedValue([
|
|
546
551
|
{ id: 'team-1', repo_path: 'repos/mini-marty' },
|
|
547
552
|
] as any);
|
|
548
553
|
|
|
@@ -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 type { DatabaseProvider } from '../../../db/provider.js';
|
|
5
5
|
import { AgentState } from '../../../state-detectors/types.js';
|
|
6
6
|
import {
|
|
7
7
|
buildHumanApprovalReason,
|
|
@@ -146,19 +146,19 @@ describe('handleEscalationAndNudge interruption recovery progression', () => {
|
|
|
146
146
|
agentStates.clear();
|
|
147
147
|
const { getRecentEscalationsForAgent, getActiveEscalationsForAgent } =
|
|
148
148
|
await import('../../../db/queries/escalations.js');
|
|
149
|
-
vi.mocked(getRecentEscalationsForAgent).
|
|
150
|
-
vi.mocked(getActiveEscalationsForAgent).
|
|
149
|
+
vi.mocked(getRecentEscalationsForAgent).mockResolvedValue([]);
|
|
150
|
+
vi.mocked(getActiveEscalationsForAgent).mockResolvedValue([]);
|
|
151
151
|
});
|
|
152
152
|
|
|
153
153
|
function makeCtx() {
|
|
154
|
-
const dbInstance = {} as
|
|
154
|
+
const dbInstance = {} as DatabaseProvider;
|
|
155
155
|
return {
|
|
156
156
|
ctx: {
|
|
157
157
|
verbose: false,
|
|
158
158
|
escalatedSessions: new Set<string>(),
|
|
159
159
|
counters: { nudged: 0, escalationsCreated: 0, escalationsResolved: 0 },
|
|
160
160
|
config: { manager: { nudge_cooldown_ms: 60000 } },
|
|
161
|
-
withDb: async (fn: (db: { db:
|
|
161
|
+
withDb: async (fn: (db: { db: DatabaseProvider; save: () => void }) => Promise<unknown>) =>
|
|
162
162
|
fn({ db: dbInstance, save: vi.fn() }),
|
|
163
163
|
},
|
|
164
164
|
};
|
|
@@ -268,14 +268,14 @@ describe('handleEscalationAndNudge — fromAgentId FK fix', () => {
|
|
|
268
268
|
});
|
|
269
269
|
|
|
270
270
|
function makeCtx() {
|
|
271
|
-
const dbInstance = {} as
|
|
271
|
+
const dbInstance = {} as DatabaseProvider;
|
|
272
272
|
return {
|
|
273
273
|
ctx: {
|
|
274
274
|
verbose: false,
|
|
275
275
|
escalatedSessions: new Set<string>(),
|
|
276
276
|
counters: { nudged: 0, escalationsCreated: 0, escalationsResolved: 0 },
|
|
277
277
|
config: { manager: { nudge_cooldown_ms: 60000 } },
|
|
278
|
-
withDb: async (fn: (db: { db:
|
|
278
|
+
withDb: async (fn: (db: { db: DatabaseProvider; save: () => void }) => Promise<unknown>) =>
|
|
279
279
|
fn({ db: dbInstance, save: vi.fn() }),
|
|
280
280
|
},
|
|
281
281
|
dbInstance,
|
|
@@ -285,8 +285,8 @@ describe('handleEscalationAndNudge — fromAgentId FK fix', () => {
|
|
|
285
285
|
it('uses agent.id (not session name) as fromAgentId when creating an escalation', async () => {
|
|
286
286
|
const { createEscalation, getRecentEscalationsForAgent } =
|
|
287
287
|
await import('../../../db/queries/escalations.js');
|
|
288
|
-
vi.mocked(getRecentEscalationsForAgent).
|
|
289
|
-
vi.mocked(createEscalation).
|
|
288
|
+
vi.mocked(getRecentEscalationsForAgent).mockResolvedValue([]);
|
|
289
|
+
vi.mocked(createEscalation).mockResolvedValue({
|
|
290
290
|
id: 'ESC-TEST',
|
|
291
291
|
story_id: 'STORY-001',
|
|
292
292
|
from_agent_id: 'senior-AbCdEf',
|
|
@@ -299,7 +299,7 @@ describe('handleEscalationAndNudge — fromAgentId FK fix', () => {
|
|
|
299
299
|
});
|
|
300
300
|
|
|
301
301
|
const { createLog } = await import('../../../db/queries/logs.js');
|
|
302
|
-
vi.mocked(createLog).
|
|
302
|
+
vi.mocked(createLog).mockResolvedValue(undefined as never);
|
|
303
303
|
|
|
304
304
|
const { ctx } = makeCtx();
|
|
305
305
|
const sessionName = 'hive-senior-AbCdEf'; // tmux session name with hive- prefix
|
|
@@ -327,8 +327,8 @@ describe('handleEscalationAndNudge — fromAgentId FK fix', () => {
|
|
|
327
327
|
it('uses null as fromAgentId when agent is undefined', async () => {
|
|
328
328
|
const { createEscalation, getRecentEscalationsForAgent } =
|
|
329
329
|
await import('../../../db/queries/escalations.js');
|
|
330
|
-
vi.mocked(getRecentEscalationsForAgent).
|
|
331
|
-
vi.mocked(createEscalation).
|
|
330
|
+
vi.mocked(getRecentEscalationsForAgent).mockResolvedValue([]);
|
|
331
|
+
vi.mocked(createEscalation).mockResolvedValue({
|
|
332
332
|
id: 'ESC-NULL',
|
|
333
333
|
story_id: null,
|
|
334
334
|
from_agent_id: null,
|
|
@@ -341,7 +341,7 @@ describe('handleEscalationAndNudge — fromAgentId FK fix', () => {
|
|
|
341
341
|
});
|
|
342
342
|
|
|
343
343
|
const { createLog } = await import('../../../db/queries/logs.js');
|
|
344
|
-
vi.mocked(createLog).
|
|
344
|
+
vi.mocked(createLog).mockResolvedValue(undefined as never);
|
|
345
345
|
|
|
346
346
|
const { ctx } = makeCtx();
|
|
347
347
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Licensed under the Hungry Ghost Hive License. See LICENSE.
|
|
2
2
|
|
|
3
3
|
import chalk from 'chalk';
|
|
4
|
-
import type {
|
|
4
|
+
import type { AgentRow } from '../../../db/queries/agents.js';
|
|
5
5
|
import {
|
|
6
6
|
createEscalation,
|
|
7
7
|
getActiveEscalationsForAgent,
|
|
@@ -131,7 +131,7 @@ export function buildRateLimitRecoveryPrompt(
|
|
|
131
131
|
export async function handleEscalationAndNudge(
|
|
132
132
|
ctx: ManagerCheckContext,
|
|
133
133
|
sessionName: string,
|
|
134
|
-
agent:
|
|
134
|
+
agent: AgentRow | undefined,
|
|
135
135
|
stateResult: {
|
|
136
136
|
state: import('../../../state-detectors/types.js').AgentState;
|
|
137
137
|
isWaiting: boolean;
|
|
@@ -221,7 +221,7 @@ export async function handleEscalationAndNudge(
|
|
|
221
221
|
}
|
|
222
222
|
|
|
223
223
|
await ctx.withDb(async db => {
|
|
224
|
-
createLog(db.
|
|
224
|
+
await createLog(db.provider, {
|
|
225
225
|
agentId: 'manager',
|
|
226
226
|
storyId: agent?.current_story_id || undefined,
|
|
227
227
|
eventType: 'STORY_PROGRESS_UPDATE',
|
|
@@ -265,7 +265,7 @@ export async function handleEscalationAndNudge(
|
|
|
265
265
|
await killTmuxSession(sessionName);
|
|
266
266
|
interruptionRecoveryAttempts.delete(sessionName);
|
|
267
267
|
await ctx.withDb(async db => {
|
|
268
|
-
createLog(db.
|
|
268
|
+
await createLog(db.provider, {
|
|
269
269
|
agentId: 'manager',
|
|
270
270
|
storyId: agent?.current_story_id || undefined,
|
|
271
271
|
eventType: 'STORY_PROGRESS_UPDATE',
|
|
@@ -334,7 +334,7 @@ export async function handleEscalationAndNudge(
|
|
|
334
334
|
}
|
|
335
335
|
|
|
336
336
|
await ctx.withDb(async db => {
|
|
337
|
-
createLog(db.
|
|
337
|
+
await createLog(db.provider, {
|
|
338
338
|
agentId: 'manager',
|
|
339
339
|
storyId: agent?.current_story_id || undefined,
|
|
340
340
|
eventType: 'STORY_PROGRESS_UPDATE',
|
|
@@ -370,8 +370,13 @@ export async function handleEscalationAndNudge(
|
|
|
370
370
|
(agentId !== null &&
|
|
371
371
|
(await ctx.withDb(
|
|
372
372
|
async db =>
|
|
373
|
-
|
|
374
|
-
|
|
373
|
+
(
|
|
374
|
+
await getRecentEscalationsForAgent(
|
|
375
|
+
db.provider,
|
|
376
|
+
agentId,
|
|
377
|
+
RECENT_ESCALATION_LOOKBACK_MINUTES
|
|
378
|
+
)
|
|
379
|
+
).length > 0
|
|
375
380
|
)));
|
|
376
381
|
verboseLog(ctx, `escalationCheck: ${sessionName} hasRecentEscalation=${hasRecentEscalation}`);
|
|
377
382
|
|
|
@@ -387,13 +392,13 @@ export async function handleEscalationAndNudge(
|
|
|
387
392
|
);
|
|
388
393
|
|
|
389
394
|
await ctx.withDb(async db => {
|
|
390
|
-
const escalation = createEscalation(db.
|
|
395
|
+
const escalation = await createEscalation(db.provider, {
|
|
391
396
|
storyId,
|
|
392
397
|
fromAgentId: agentId,
|
|
393
398
|
toAgentId: null,
|
|
394
399
|
reason: escalationReason,
|
|
395
400
|
});
|
|
396
|
-
createLog(db.
|
|
401
|
+
await createLog(db.provider, {
|
|
397
402
|
agentId: 'manager',
|
|
398
403
|
storyId,
|
|
399
404
|
eventType: 'ESCALATION_CREATED',
|
|
@@ -444,16 +449,18 @@ export async function handleEscalationAndNudge(
|
|
|
444
449
|
interruptionRecoveryAttempts.delete(sessionName);
|
|
445
450
|
// Agent recovered - auto-resolve active escalations
|
|
446
451
|
const resolvedCount = await ctx.withDb(async db => {
|
|
447
|
-
const activeEscalations = agentId
|
|
452
|
+
const activeEscalations = agentId
|
|
453
|
+
? await getActiveEscalationsForAgent(db.provider, agentId)
|
|
454
|
+
: [];
|
|
448
455
|
for (const escalation of activeEscalations) {
|
|
449
|
-
updateEscalation(db.
|
|
456
|
+
await updateEscalation(db.provider, escalation.id, {
|
|
450
457
|
status: 'resolved',
|
|
451
458
|
resolution: `Agent recovered: no longer in waiting state`,
|
|
452
459
|
});
|
|
453
460
|
ctx.counters.escalationsResolved++;
|
|
454
461
|
}
|
|
455
462
|
if (activeEscalations.length > 0) {
|
|
456
|
-
createLog(db.
|
|
463
|
+
await createLog(db.provider, {
|
|
457
464
|
agentId: 'manager',
|
|
458
465
|
eventType: 'ESCALATION_RESOLVED',
|
|
459
466
|
message: `${sessionName} recovered and manager auto-resolved ${activeEscalations.length} escalation(s)`,
|
|
@@ -53,7 +53,14 @@ import { checkFeatureSignOff } from './feature-sign-off.js';
|
|
|
53
53
|
import type { ManagerCheckContext } from './types.js';
|
|
54
54
|
|
|
55
55
|
function makeCtx(overrides: Partial<ManagerCheckContext> = {}): ManagerCheckContext {
|
|
56
|
-
const
|
|
56
|
+
const mockProvider = {} as never;
|
|
57
|
+
const mockDb = {
|
|
58
|
+
db: {} as never,
|
|
59
|
+
provider: mockProvider,
|
|
60
|
+
save: vi.fn(),
|
|
61
|
+
close: vi.fn(),
|
|
62
|
+
runMigrations: vi.fn(),
|
|
63
|
+
};
|
|
57
64
|
const mockScheduler = {
|
|
58
65
|
spawnFeatureTest: vi.fn().mockResolvedValue({ id: 'team-1-feature-test-1' }),
|
|
59
66
|
};
|
|
@@ -172,7 +179,7 @@ describe('checkFeatureSignOff', () => {
|
|
|
172
179
|
|
|
173
180
|
it('should skip when no in_progress requirements with feature branches exist', async () => {
|
|
174
181
|
const ctx = makeCtx();
|
|
175
|
-
mockGetRequirementsByStatus.
|
|
182
|
+
mockGetRequirementsByStatus.mockResolvedValue([]);
|
|
176
183
|
|
|
177
184
|
await checkFeatureSignOff(ctx);
|
|
178
185
|
|
|
@@ -181,7 +188,7 @@ describe('checkFeatureSignOff', () => {
|
|
|
181
188
|
|
|
182
189
|
it('should skip requirements without feature_branch and with default target_branch (main)', async () => {
|
|
183
190
|
const ctx = makeCtx();
|
|
184
|
-
mockGetRequirementsByStatus.
|
|
191
|
+
mockGetRequirementsByStatus.mockResolvedValue([
|
|
185
192
|
makeRequirement({ feature_branch: null, target_branch: 'main' }),
|
|
186
193
|
]);
|
|
187
194
|
|
|
@@ -194,9 +201,9 @@ describe('checkFeatureSignOff', () => {
|
|
|
194
201
|
it('should process requirements with target_branch but no feature_branch', async () => {
|
|
195
202
|
const ctx = makeCtx();
|
|
196
203
|
const req = makeRequirement({ feature_branch: null, target_branch: 'feature/REQ-TEST1234' });
|
|
197
|
-
mockGetRequirementsByStatus.
|
|
198
|
-
mockGetStoriesByRequirement.
|
|
199
|
-
mockGetAllTeams.
|
|
204
|
+
mockGetRequirementsByStatus.mockResolvedValue([req]);
|
|
205
|
+
mockGetStoriesByRequirement.mockResolvedValue([makeStory({ status: 'merged' })]);
|
|
206
|
+
mockGetAllTeams.mockResolvedValue([makeTeam()]);
|
|
200
207
|
|
|
201
208
|
await checkFeatureSignOff(ctx);
|
|
202
209
|
|
|
@@ -218,12 +225,12 @@ describe('checkFeatureSignOff', () => {
|
|
|
218
225
|
|
|
219
226
|
it('should skip when not all stories are merged', async () => {
|
|
220
227
|
const ctx = makeCtx();
|
|
221
|
-
mockGetRequirementsByStatus.
|
|
222
|
-
mockGetStoriesByRequirement.
|
|
228
|
+
mockGetRequirementsByStatus.mockResolvedValue([makeRequirement()]);
|
|
229
|
+
mockGetStoriesByRequirement.mockResolvedValue([
|
|
223
230
|
makeStory({ id: 'STORY-1', status: 'merged' }),
|
|
224
231
|
makeStory({ id: 'STORY-2', status: 'in_progress' }),
|
|
225
232
|
]);
|
|
226
|
-
mockGetAllTeams.
|
|
233
|
+
mockGetAllTeams.mockResolvedValue([makeTeam()]);
|
|
227
234
|
|
|
228
235
|
await checkFeatureSignOff(ctx);
|
|
229
236
|
|
|
@@ -232,9 +239,9 @@ describe('checkFeatureSignOff', () => {
|
|
|
232
239
|
|
|
233
240
|
it('should skip requirements with no stories', async () => {
|
|
234
241
|
const ctx = makeCtx();
|
|
235
|
-
mockGetRequirementsByStatus.
|
|
236
|
-
mockGetStoriesByRequirement.
|
|
237
|
-
mockGetAllTeams.
|
|
242
|
+
mockGetRequirementsByStatus.mockResolvedValue([makeRequirement()]);
|
|
243
|
+
mockGetStoriesByRequirement.mockResolvedValue([]);
|
|
244
|
+
mockGetAllTeams.mockResolvedValue([makeTeam()]);
|
|
238
245
|
|
|
239
246
|
await checkFeatureSignOff(ctx);
|
|
240
247
|
|
|
@@ -244,12 +251,12 @@ describe('checkFeatureSignOff', () => {
|
|
|
244
251
|
it('should spawn feature_test agent when all stories are merged', async () => {
|
|
245
252
|
const ctx = makeCtx();
|
|
246
253
|
const req = makeRequirement();
|
|
247
|
-
mockGetRequirementsByStatus.
|
|
248
|
-
mockGetStoriesByRequirement.
|
|
254
|
+
mockGetRequirementsByStatus.mockResolvedValue([req]);
|
|
255
|
+
mockGetStoriesByRequirement.mockResolvedValue([
|
|
249
256
|
makeStory({ id: 'STORY-1', status: 'merged' }),
|
|
250
257
|
makeStory({ id: 'STORY-2', status: 'merged' }),
|
|
251
258
|
]);
|
|
252
|
-
mockGetAllTeams.
|
|
259
|
+
mockGetAllTeams.mockResolvedValue([makeTeam()]);
|
|
253
260
|
|
|
254
261
|
await checkFeatureSignOff(ctx);
|
|
255
262
|
|
|
@@ -278,9 +285,9 @@ describe('checkFeatureSignOff', () => {
|
|
|
278
285
|
|
|
279
286
|
it('should create log entries on successful spawn', async () => {
|
|
280
287
|
const ctx = makeCtx();
|
|
281
|
-
mockGetRequirementsByStatus.
|
|
282
|
-
mockGetStoriesByRequirement.
|
|
283
|
-
mockGetAllTeams.
|
|
288
|
+
mockGetRequirementsByStatus.mockResolvedValue([makeRequirement()]);
|
|
289
|
+
mockGetStoriesByRequirement.mockResolvedValue([makeStory({ status: 'merged' })]);
|
|
290
|
+
mockGetAllTeams.mockResolvedValue([makeTeam()]);
|
|
284
291
|
|
|
285
292
|
await checkFeatureSignOff(ctx);
|
|
286
293
|
|
|
@@ -304,14 +311,16 @@ describe('checkFeatureSignOff', () => {
|
|
|
304
311
|
const ctx = makeCtx();
|
|
305
312
|
const req1 = makeRequirement({ id: 'REQ-AAA', feature_branch: 'feature/REQ-AAA' });
|
|
306
313
|
const req2 = makeRequirement({ id: 'REQ-BBB', feature_branch: 'feature/REQ-BBB' });
|
|
307
|
-
mockGetRequirementsByStatus.
|
|
314
|
+
mockGetRequirementsByStatus.mockResolvedValue([req1, req2]);
|
|
308
315
|
mockGetStoriesByRequirement
|
|
309
|
-
.
|
|
310
|
-
|
|
316
|
+
.mockResolvedValueOnce([
|
|
317
|
+
makeStory({ id: 'S-1', status: 'merged', requirement_id: 'REQ-AAA' }),
|
|
318
|
+
])
|
|
319
|
+
.mockResolvedValueOnce([
|
|
311
320
|
makeStory({ id: 'S-2', status: 'merged', requirement_id: 'REQ-BBB' }),
|
|
312
321
|
makeStory({ id: 'S-3', status: 'in_progress', requirement_id: 'REQ-BBB' }),
|
|
313
322
|
]);
|
|
314
|
-
mockGetAllTeams.
|
|
323
|
+
mockGetAllTeams.mockResolvedValue([makeTeam()]);
|
|
315
324
|
|
|
316
325
|
await checkFeatureSignOff(ctx);
|
|
317
326
|
|
|
@@ -325,11 +334,11 @@ describe('checkFeatureSignOff', () => {
|
|
|
325
334
|
|
|
326
335
|
it('should skip when story has no team_id', async () => {
|
|
327
336
|
const ctx = makeCtx();
|
|
328
|
-
mockGetRequirementsByStatus.
|
|
329
|
-
mockGetStoriesByRequirement.
|
|
337
|
+
mockGetRequirementsByStatus.mockResolvedValue([makeRequirement()]);
|
|
338
|
+
mockGetStoriesByRequirement.mockResolvedValue([
|
|
330
339
|
makeStory({ status: 'merged', team_id: null as unknown as string }),
|
|
331
340
|
]);
|
|
332
|
-
mockGetAllTeams.
|
|
341
|
+
mockGetAllTeams.mockResolvedValue([makeTeam()]);
|
|
333
342
|
|
|
334
343
|
await checkFeatureSignOff(ctx);
|
|
335
344
|
|
|
@@ -338,11 +347,11 @@ describe('checkFeatureSignOff', () => {
|
|
|
338
347
|
|
|
339
348
|
it('should skip when team is not found', async () => {
|
|
340
349
|
const ctx = makeCtx();
|
|
341
|
-
mockGetRequirementsByStatus.
|
|
342
|
-
mockGetStoriesByRequirement.
|
|
350
|
+
mockGetRequirementsByStatus.mockResolvedValue([makeRequirement()]);
|
|
351
|
+
mockGetStoriesByRequirement.mockResolvedValue([
|
|
343
352
|
makeStory({ status: 'merged', team_id: 'team-unknown' }),
|
|
344
353
|
]);
|
|
345
|
-
mockGetAllTeams.
|
|
354
|
+
mockGetAllTeams.mockResolvedValue([makeTeam({ id: 'team-other' })]);
|
|
346
355
|
|
|
347
356
|
await checkFeatureSignOff(ctx);
|
|
348
357
|
|
|
@@ -355,9 +364,9 @@ describe('checkFeatureSignOff', () => {
|
|
|
355
364
|
spawnFeatureTest: ReturnType<typeof vi.fn>;
|
|
356
365
|
};
|
|
357
366
|
mockScheduler.spawnFeatureTest.mockRejectedValue(new Error('spawn failed'));
|
|
358
|
-
mockGetRequirementsByStatus.
|
|
359
|
-
mockGetStoriesByRequirement.
|
|
360
|
-
mockGetAllTeams.
|
|
367
|
+
mockGetRequirementsByStatus.mockResolvedValue([makeRequirement()]);
|
|
368
|
+
mockGetStoriesByRequirement.mockResolvedValue([makeStory({ status: 'merged' })]);
|
|
369
|
+
mockGetAllTeams.mockResolvedValue([makeTeam()]);
|
|
361
370
|
|
|
362
371
|
await checkFeatureSignOff(ctx);
|
|
363
372
|
|
|
@@ -19,18 +19,18 @@ export async function checkFeatureSignOff(ctx: ManagerCheckContext): Promise<voi
|
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
await ctx.withDb(async (db, scheduler) => {
|
|
22
|
-
const inProgressReqs = getRequirementsByStatus(db.
|
|
22
|
+
const inProgressReqs = (await getRequirementsByStatus(db.provider, 'in_progress')).filter(
|
|
23
23
|
req => req.feature_branch || req.target_branch !== 'main'
|
|
24
24
|
);
|
|
25
25
|
verboseLogCtx(ctx, `checkFeatureSignOff: candidates=${inProgressReqs.length}`);
|
|
26
26
|
|
|
27
27
|
if (inProgressReqs.length === 0) return;
|
|
28
28
|
|
|
29
|
-
const teams = getAllTeams(db.
|
|
29
|
+
const teams = await getAllTeams(db.provider);
|
|
30
30
|
const e2eTestsPath = ctx.config.e2e_tests!.path;
|
|
31
31
|
|
|
32
32
|
for (const req of inProgressReqs) {
|
|
33
|
-
const stories = getStoriesByRequirement(db.
|
|
33
|
+
const stories = await getStoriesByRequirement(db.provider, req.id);
|
|
34
34
|
if (stories.length === 0) {
|
|
35
35
|
verboseLogCtx(ctx, `checkFeatureSignOff: req=${req.id} skip=no_stories`);
|
|
36
36
|
continue;
|
|
@@ -68,7 +68,7 @@ export async function checkFeatureSignOff(ctx: ManagerCheckContext): Promise<voi
|
|
|
68
68
|
|
|
69
69
|
try {
|
|
70
70
|
// Transition requirement to sign_off
|
|
71
|
-
updateRequirement(db.
|
|
71
|
+
await updateRequirement(db.provider, req.id, { status: 'sign_off' });
|
|
72
72
|
|
|
73
73
|
// Spawn feature_test agent
|
|
74
74
|
const agent = await scheduler.spawnFeatureTest(teamId, team.name, team.repo_path, {
|
|
@@ -77,7 +77,7 @@ export async function checkFeatureSignOff(ctx: ManagerCheckContext): Promise<voi
|
|
|
77
77
|
e2eTestsPath,
|
|
78
78
|
});
|
|
79
79
|
|
|
80
|
-
createLog(db.
|
|
80
|
+
await createLog(db.provider, {
|
|
81
81
|
agentId: agent.id,
|
|
82
82
|
eventType: 'FEATURE_TEST_SPAWNED',
|
|
83
83
|
message: `Spawned feature_test agent for requirement ${req.id} (branch: ${effectiveBranch})`,
|
|
@@ -88,7 +88,7 @@ export async function checkFeatureSignOff(ctx: ManagerCheckContext): Promise<voi
|
|
|
88
88
|
stories_merged: stories.length,
|
|
89
89
|
},
|
|
90
90
|
});
|
|
91
|
-
createLog(db.
|
|
91
|
+
await createLog(db.provider, {
|
|
92
92
|
agentId: 'manager',
|
|
93
93
|
eventType: 'FEATURE_SIGN_OFF_TRIGGERED',
|
|
94
94
|
message: `All ${stories.length} stories merged for ${req.id} — triggered feature sign-off`,
|
|
@@ -108,7 +108,7 @@ export async function checkFeatureSignOff(ctx: ManagerCheckContext): Promise<voi
|
|
|
108
108
|
);
|
|
109
109
|
} catch (err) {
|
|
110
110
|
// Revert status on failure
|
|
111
|
-
updateRequirement(db.
|
|
111
|
+
await updateRequirement(db.provider, req.id, { status: 'in_progress' });
|
|
112
112
|
db.save();
|
|
113
113
|
console.error(
|
|
114
114
|
chalk.red(` Feature sign-off failed for ${req.id}:`),
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import chalk from 'chalk';
|
|
4
4
|
import { execSync } from 'child_process';
|
|
5
5
|
import { join } from 'path';
|
|
6
|
-
import {
|
|
6
|
+
import type { AgentLogRow } from '../../../db/client.js';
|
|
7
7
|
import { getAgentsByType } from '../../../db/queries/agents.js';
|
|
8
8
|
import { createLog } from '../../../db/queries/logs.js';
|
|
9
9
|
import { getRequirementById, updateRequirement } from '../../../db/queries/requirements.js';
|
|
@@ -33,7 +33,7 @@ interface FeatureTestCandidate {
|
|
|
33
33
|
export async function checkFeatureTestResult(ctx: ManagerCheckContext): Promise<void> {
|
|
34
34
|
// Phase 1: Read DB to find candidates (brief lock)
|
|
35
35
|
const candidates = await ctx.withDb(async db => {
|
|
36
|
-
const featureTestAgents = getAgentsByType(db.
|
|
36
|
+
const featureTestAgents = await getAgentsByType(db.provider, 'feature_test');
|
|
37
37
|
verboseLogCtx(ctx, `checkFeatureTestResult: agents=${featureTestAgents.length}`);
|
|
38
38
|
|
|
39
39
|
if (featureTestAgents.length === 0) return [];
|
|
@@ -41,8 +41,7 @@ export async function checkFeatureTestResult(ctx: ManagerCheckContext): Promise<
|
|
|
41
41
|
const result: FeatureTestCandidate[] = [];
|
|
42
42
|
|
|
43
43
|
for (const agent of featureTestAgents) {
|
|
44
|
-
const recentLogs = queryAll<AgentLogRow>(
|
|
45
|
-
db.db,
|
|
44
|
+
const recentLogs = await db.provider.queryAll<AgentLogRow>(
|
|
46
45
|
`
|
|
47
46
|
SELECT * FROM agent_logs
|
|
48
47
|
WHERE agent_id = ?
|
|
@@ -62,8 +61,7 @@ export async function checkFeatureTestResult(ctx: ManagerCheckContext): Promise<
|
|
|
62
61
|
const resultLog = recentLogs[0];
|
|
63
62
|
const message = resultLog.message || '';
|
|
64
63
|
|
|
65
|
-
const alreadyProcessed = queryAll<AgentLogRow>(
|
|
66
|
-
db.db,
|
|
64
|
+
const alreadyProcessed = await db.provider.queryAll<AgentLogRow>(
|
|
67
65
|
`
|
|
68
66
|
SELECT * FROM agent_logs
|
|
69
67
|
WHERE agent_id = 'manager'
|
|
@@ -79,8 +77,7 @@ export async function checkFeatureTestResult(ctx: ManagerCheckContext): Promise<
|
|
|
79
77
|
continue;
|
|
80
78
|
}
|
|
81
79
|
|
|
82
|
-
const spawnLog = queryAll<AgentLogRow>(
|
|
83
|
-
db.db,
|
|
80
|
+
const spawnLog = await db.provider.queryAll<AgentLogRow>(
|
|
84
81
|
`
|
|
85
82
|
SELECT * FROM agent_logs
|
|
86
83
|
WHERE agent_id = ?
|
|
@@ -104,7 +101,7 @@ export async function checkFeatureTestResult(ctx: ManagerCheckContext): Promise<
|
|
|
104
101
|
continue;
|
|
105
102
|
}
|
|
106
103
|
|
|
107
|
-
const requirement = getRequirementById(db.
|
|
104
|
+
const requirement = await getRequirementById(db.provider, requirementId);
|
|
108
105
|
if (!requirement) {
|
|
109
106
|
verboseLogCtx(
|
|
110
107
|
ctx,
|
|
@@ -142,7 +139,7 @@ export async function checkFeatureTestResult(ctx: ManagerCheckContext): Promise<
|
|
|
142
139
|
}
|
|
143
140
|
|
|
144
141
|
// Find repo path
|
|
145
|
-
const teams = getAllTeams(db.
|
|
142
|
+
const teams = await getAllTeams(db.provider);
|
|
146
143
|
const team = teams.length > 0 ? teams[0] : null;
|
|
147
144
|
if (!team) {
|
|
148
145
|
verboseLogCtx(ctx, `checkFeatureTestResult: agent=${agent.id} skip=no_team`);
|
|
@@ -223,8 +220,8 @@ Co-Authored-By: Feature Test Agent <noreply@hive>`;
|
|
|
223
220
|
|
|
224
221
|
// Phase 2b: DB writes (brief lock)
|
|
225
222
|
await ctx.withDb(async db => {
|
|
226
|
-
updateRequirement(db.
|
|
227
|
-
createLog(db.
|
|
223
|
+
await updateRequirement(db.provider, requirementId, { status: 'sign_off_passed' });
|
|
224
|
+
await createLog(db.provider, {
|
|
228
225
|
agentId: 'manager',
|
|
229
226
|
eventType: 'FEATURE_SIGN_OFF_PASSED',
|
|
230
227
|
message: `Feature sign-off PASSED for ${requirementId} — feature branch ${featureBranch} merged to main`,
|
|
@@ -247,8 +244,8 @@ Co-Authored-By: Feature Test Agent <noreply@hive>`;
|
|
|
247
244
|
} catch (err) {
|
|
248
245
|
// Revert status on failure (brief lock)
|
|
249
246
|
await ctx.withDb(async db => {
|
|
250
|
-
updateRequirement(db.
|
|
251
|
-
createLog(db.
|
|
247
|
+
await updateRequirement(db.provider, requirementId, { status: 'sign_off' });
|
|
248
|
+
await createLog(db.provider, {
|
|
252
249
|
agentId: 'manager',
|
|
253
250
|
eventType: 'FEATURE_SIGN_OFF_FAILED',
|
|
254
251
|
status: 'error',
|
|
@@ -281,8 +278,8 @@ async function handleTestFailure(
|
|
|
281
278
|
);
|
|
282
279
|
|
|
283
280
|
await ctx.withDb(async db => {
|
|
284
|
-
updateRequirement(db.
|
|
285
|
-
createLog(db.
|
|
281
|
+
await updateRequirement(db.provider, requirementId, { status: 'sign_off_failed' });
|
|
282
|
+
await createLog(db.provider, {
|
|
286
283
|
agentId: 'manager',
|
|
287
284
|
eventType: 'FEATURE_SIGN_OFF_FAILED',
|
|
288
285
|
message: `Feature sign-off FAILED for ${requirementId} — E2E tests failed on ${featureBranch}`,
|