feat: Add getHeadquartersDashboard tRPC procedure for HQ action items

Aggregates all user-blocking action items into a single composite query:
- waitingForInput: agents paused on questions (oldest first)
- pendingReviewInitiatives: initiatives awaiting content review
- pendingReviewPhases: phases awaiting diff review
- planningInitiatives: active initiatives with all phases pending and no running agents
- blockedPhases: phases in blocked state with optional last-message snippet

Wired into appRouter and covered by 10 unit tests using in-memory Drizzle DB
and an inline MockAgentManager (no real processes required).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Lukas May
2026-03-06 15:35:54 +01:00
parent 2bef0fa682
commit 89c98d38cc
4 changed files with 560 additions and 0 deletions

View File

@@ -272,3 +272,27 @@ Persistent chat loop for iterative phase/task refinement via agent.
`sendChatMessage` finds or creates an active session, stores the user message, then either resumes the existing agent (if `waiting_for_input`) or spawns a fresh one with full chat history + initiative context. Agent runs in `'chat'` mode and signals `"questions"` after applying changes, staying alive for the next message.
Context dependency: `requireChatSessionRepository(ctx)`, `requireAgentManager(ctx)`, `requireInitiativeRepository(ctx)`, `requireTaskRepository(ctx)`.
## Headquarters Procedures
Composite dashboard query aggregating all action items that require user intervention.
| Procedure | Type | Description |
|-----------|------|-------------|
| `getHeadquartersDashboard` | query | Returns 5 typed arrays of action items (no input required) |
### Return Shape
```typescript
{
waitingForInput: Array<{ agentId, agentName, initiativeId, initiativeName, questionText, waitingSince }>;
pendingReviewInitiatives: Array<{ initiativeId, initiativeName, since }>;
pendingReviewPhases: Array<{ initiativeId, initiativeName, phaseId, phaseName, since }>;
planningInitiatives: Array<{ initiativeId, initiativeName, pendingPhaseCount, since }>;
blockedPhases: Array<{ initiativeId, initiativeName, phaseId, phaseName, lastMessage, since }>;
}
```
Each array is sorted ascending by timestamp (oldest-first). All timestamps are ISO 8601 strings. `lastMessage` is truncated to 160 chars and is `null` when no messages exist or the message repository is not wired.
Context dependency: `requireInitiativeRepository(ctx)`, `requirePhaseRepository(ctx)`, `requireAgentManager(ctx)`. Task/message repos are accessed via optional `ctx` fields for `blockedPhases.lastMessage`.