Command Center
Command Center is a Next.js web application that provides a real-time operational dashboard for Equabot. It connects to the Equabot gateway and the local orchestration system to display agent status, task priorities, and system health.Architecture
Key components
| Component | Purpose |
|---|---|
| StatusDashboard | Real-time gateway health, compute metrics, agent summary, and queue counters |
| AgentMonitor | Active/blocked agent list with instruct and respawn actions |
| PriorityStack | Score-ranked task sidebar sourced from GitHub Projects or local stack data |
| ComputeMonitor | Focused compute panel (CPU/RAM/Ollama) with 10-second refresh |
| OrchestrationTree | Hierarchical orchestration/task visualization panel |
| QuickActions | Categorized command buttons (Tasks, Communication, Analysis, System) |
Setup
Prerequisites
- Node.js 22+
- Equabot gateway running on port 18789
Environment
Create.env.local:
Run
API routes
Core routes used by the Command Center UI:| Route | Method | Auth | Description |
|---|---|---|---|
/api/chat | POST | Yes | Routes chat and attachments to Ollama, OpenAI direct, or Equabot gateway |
/api/events | GET (SSE) | Yes | Real-time event stream consumed by useEventStream |
/api/health | GET | No | Gateway health check with latency |
/api/heartbeat/state | GET | Yes | Heartbeat state used by StatusDashboard |
/api/compute | GET | Yes | Local CPU, RAM, and Ollama metrics |
/api/gateway/config | GET | Yes | Gateway model defaults (primary, fallbacks, provider catalog) |
/api/models/status | GET | Yes | Aggregated local/gateway model availability |
/api/tasks/stack | GET | Yes | Priority stack data (GitHub Projects, local, remote, bundled fallback) |
/api/conversations | GET/POST | Yes | Conversation collection (list/create) |
/api/conversations/[id] | GET/PUT/DELETE | Yes | Conversation detail operations |
/api/conversations/[id]/messages | POST/DELETE | Yes | Conversation message append/clear |
/api/orchestration/status | GET | Yes | Aggregated agent/queue/blocker status |
/api/orchestration/instruct | POST | Yes | Send instruction to a blocked agent |
/api/orchestration/respawn | POST | Yes | Respawn a stuck agent session |
/api/orchestration/cleanup | POST | Yes | Deduplicate and TTL-prune blocked agents |
/api/comet/lifecycle | POST | No | Comet-Bridge run lifecycle sync (start/update/complete/abort/fail/get) |
/api/gateway-sessions/*, /api/task-threads, /api/docs/*, /api/threads/*, /api/preferences, /api/report-issue.
Task stack contract
/api/tasks/stack is the canonical normalization adapter. It ingests GitHub Project items (24-field inventory) and produces a unified TaskStackItem payload consumed by all UI surfaces.
The response includes a schemaVersion field for observability.
GitHub Project field inventory (24 fields)
GitHub Project field inventory (24 fields)
Last verified against source: 2026-02-28Visible fields (17 table columns)
Hidden fields (7 — configured but not displayed as columns)
View configuration (Stack Ranked Priority List)
The
gh project field-list --format json CLI does not distinguish text, number, and date fields — all report as ProjectV2Field. Only ProjectV2SingleSelectField is identified by type. The update-project-field.py helper infers field type from the value format (numeric values use --number, YYYY-MM-DD patterns use --date, otherwise --text).| # | Field Name | Field Type | Options / Details |
|---|---|---|---|
| 1 | Title | Title (built-in) | Issue/item title with link to source repo |
| 2 | Assignees | Assignees (built-in) | GitHub users |
| 3 | Linked pull requests | Linked PRs (built-in) | Auto-linked PRs (draft/open/merged) |
| 4 | Sub-issues progress | Sub-issues progress (built-in) | Segmented bar; numerical ratio (e.g. 2/5) |
| 5 | Priority | Single select (custom) | P0 - Critical, P1 - High, P2 - Medium, P3 - Low |
| 6 | Stack Rank | Number (custom) | Primary sort key; ascending |
| 7 | Urgency | Single select (custom) | Urgent, High, Normal, Low |
| 8 | Blocked By | Text (custom) | Free-text dependency/blocker references |
| 9 | Equabot Session | Text (custom) | Equabot session links or IDs |
| 10 | Comet Browser Thread | Text (custom) | Comet browser thread references |
| 11 | Comet Browser Space | Text (custom) | Comet browser space references |
| 12 | Gmail Email Thread | Text (custom) | Gmail thread links |
| 13 | Shortwave App | Text (custom) | Shortwave references |
| 14 | NotebookLM | Text (custom) | NotebookLM links |
| 15 | Google Drive Folder | Text (custom) | Google Drive folder URL |
| 16 | QBO Link | Text (custom) | QuickBooks Online links |
| 17 | Google Doc | Text (custom) | Google Doc links |
| # | Field Name | Field Type | Details |
|---|---|---|---|
| 18 | Status | Single select (built-in) | Todo, In Progress, Done; used by filter and board grouping |
| 19 | Labels | Labels (built-in) | GitHub issue labels |
| 20 | Milestone | Milestone (built-in) | GitHub milestones |
| 21 | Repository | Repository (built-in) | Multi-repo source field |
| 22 | Type | Type (built-in) | Issue type classification |
| 23 | Reviewers | Reviewers (built-in) | PR reviewers |
| 24 | Parent issue | Parent issue (built-in) | Hierarchy parent reference |
- Group by:
Priority - Sort:
Stack Rankascending (primary),Priorityascending (secondary) - Filter:
-status:Done - Field sum:
Count - Default repository:
Balancing-Rock/command-center-so
--project-owner explicitly to target the correct project.| Owner | Project # | Internal ID | Default in Scripts |
|---|---|---|---|
ShawnOwen | 4 | PVT_kwHOAX66ks4BOENI | update-project-field.py, sync-project-ranks.py |
Balancing-Rock | 4 | PVT_kwDOD2hUnc4BPXw1 | backfill-project4-fields.sh, project-sync.py |
Issue ingestion
Issues from 9 connected repositories are automatically added to Project #4 through two mechanisms. The GitHub Team plan limits built-in auto-add workflows to 5 per project; additional repos use a GitHub Actions workflow. Method A — Built-in Project Workflows (5 repos) Configured directly on the project under Settings > Workflows. Each triggers when a new or updated item matches theis:issue filter.
| Repository | Workflow Name |
|---|---|
stacks-ranking-priorities | Auto-add to project |
command-center-so | Auto-add: command-center-so |
stack-ranked-priorities | Auto-add: stack-ranked-priorities |
Food-Tracking_App | Auto-add: Food-Tracking_App |
sscs-qbo-sync | Auto-add: sscs-qbo-sync |
.github/workflows/auto-add-to-project.yml using actions/add-to-project@v1.0.2, authenticated via the ADD_TO_PROJECT_PAT classic PAT (repo + project scopes).
| Repository | Trigger | Auth |
|---|---|---|
task-threads | issues: [opened] | Org secret (Balancing-Rock) |
demo-repository | issues: [opened] | Org secret (Balancing-Rock) |
Speed-Reader-App | issues: [opened] | Org secret (Balancing-Rock) |
EQUAStart/equabot | issues: [opened, transferred, reopened] | Repo secret (cross-org) |
EQUAStart/equabot uses a repo-level secret because GitHub org secrets do not cross org boundaries. The PAT itself is scoped to the user account and covers both orgs.
Canonical architecture reference: project-auto-add-flowchart.md
Source priority
The stack adapter tries these sources in order:- GitHub Projects (live data via
ghCLI) - Local stack file (for local dev with recent syncs)
- Remote compute API (if configured)
- Bundled data (static fallback)
Task identity
Tasks use a composite identity with precedence:projectItemId(GitHub Project item ID — used for project mutations)githubIssueNumber(cross-repo references)slug(UI/session alias)
Priority and status authority
GitHub Project fields (Priority, Status, Stack Rank, Urgency) are authoritative. The UI may compute display-only decorations but does not override the normalized values from the API payload.
Blocker convention
TheBlocked By text field supports parseable tokens:
| Pattern | Example |
|---|---|
#N (same-repo issue) | #123 |
issue:N | issue:456 |
owner/repo#N (cross-repo) | Balancing-Rock/equabot#789 |
item:PVTI_xxx (project item) | item:PVTI_abc123 |
session:... (session dependency) | session:agent:main:task-thread:42 |
-- is stripped before parsing.
Session linkage
Sessions are linked to task threads using cascade matching:- Equabot session key (strongest match)
- GitHub issue number (extracted from session label)
- Slug (legacy fallback)
Runtime mapping
Each project field anchors a specific runtime entity:| System Entity | Project Fields | Purpose |
|---|---|---|
| Task Thread | Title, Repository, Type, Parent issue | Canonical thread identity and hierarchy |
| Priority Stack | Priority, Stack Rank, Urgency, Status | Ordering, triage, and lifecycle |
| Dependency Graph | Blocked By, Sub-issues progress | Blockers and aggregate completion |
| Agent Runtime Session | Equabot Session | Primary orchestrator/agent context |
| Browser Subagent Context | Comet Browser Thread, Comet Browser Space | Browser automation and research context |
| Conversation Context | Gmail Email Thread, Shortwave App, NotebookLM | Communication and knowledge context |
| Artifact Layer | Google Drive Folder, Google Doc, QBO Link | Persistent deliverables and finance links |
Task Thread → Agent Session → Subagent Context → Conversation Surfaces → Artifacts
Where:
- Agent Session is anchored by the
Equabot Sessionfield. - Subagent Context is anchored by the Comet Browser fields.
- Conversation Surfaces are anchored by email and research fields (Gmail, Shortwave, NotebookLM).
- Artifacts are anchored by Drive, Docs, and QBO fields.
Polling and real-time behavior
Command Center uses SSE as the primary mechanism for UI update triggers, with periodic polling as fallback.| Endpoint(s) | Mechanism | Interval | Component |
|---|---|---|---|
/api/events | SSE (primary) | Continuous | AgentMonitor, PriorityStack, others |
/api/orchestration/status | Poll fallback | 60s | AgentMonitor |
/api/tasks/stack | Poll | 15m | PriorityStack full data refresh |
/api/tasks/stack | Local recalculation | 60s | PriorityStack live score and age updates |
/api/compute | Poll | 10s | ComputeMonitor |
/api/compute, /api/orchestration/status, /api/health, /api/heartbeat/state | Batched poll | 30s | StatusDashboard |
Orchestration integration
Command Center reads these files from the orchestration directory:| File | Contents |
|---|---|
global-stack.json | Priority-ranked task list |
blocked-agents.json | Blocked agents and threads |
work-queue.json | Active sessions, completed tasks, stalled items |
learnings.jsonl | Daily learnings log |
Orchestration scripts
These Python scripts inequabot/orchestration/ interact with GitHub Project V2 fields:
| Script | Purpose | Invocation |
|---|---|---|
update-project-field.py | Update any project field by human-readable name | python3 update-project-field.py <issue_ref> <field_name> <value> |
sync-project-ranks.py | Sync Stack Rank from global-stack.json to project | Cron-driven; reads global-stack.json |
backfill-project4-fields.sh | Backfill Priority and Urgency from issue labels | Manual; one-time setup |
project-sync.py | Sync project items to Priority Stack cache | Cron-driven |
verify-sync-chain.py | Verify sync chain integrity across GDrive, local threads, global-stack, GitHub Project #4, and CC API | python3 verify-sync-chain.py [--issues REF,...] [--json] [--skip-gdrive] [--skip-cc] |
update-project-field.py
Unified helper for updating any GitHub Project V2 custom field by human-readable inputs. Resolves all identifiers at runtime via thegh CLI with zero raw GraphQL.
issue_ref— Issue URL (https://github.com/owner/repo/issues/N) or shortref (owner/repo#N)field_name— Human-readable project field name (e.g.,"Google Drive Folder","Priority","Stack Rank")value— Value to set. For single-select fields, use the option name (e.g.,"P1 - High")
--project-owner— GitHub project owner (default:ShawnOwen)--project-number— GitHub project number (default:4)--dry-run— Resolve all IDs and print thegh project item-editcommand without executing
gh CLI does not expose granular field types for text, number, and date fields (all report as ProjectV2Field). The script infers the correct gh project item-edit flag from the value format:
| Value Pattern | Detected Type | CLI Flag |
|---|---|---|
Has options in field metadata | Single select | --single-select-option-id |
Matches YYYY-MM-DD | Date | --date |
| Valid integer or float | Number | --number |
| Anything else | Text | --text |
gh CLI failures.
Tech stack
- Framework: Next.js 16 (App Router)
- Language: TypeScript
- Styling: Tailwind CSS 4
- Icons: Heroicons
- Auth: NextAuth.js middleware
- State: React hooks
Troubleshooting
Turbopack HMR errors
Known Next.js 16 issue (“Module factory not available”). Quick fixes:- Hard-refresh browser (
Cmd+Shift+R) - Restart dev server (
npm run dev) - Full cache clear (
rm -rf .next && npm run dev) - Fallback to webpack (
npx next dev --no-turbo)
404 on API routes during development
Usually caused by stale Turbopack cache state. Thepredev script clears the dev cache before startup to reduce this.
Related
- System Overview for how Command Center fits in the architecture
- Repository Map for project structure
- Developer Setup for local development
- Control UI for the Gateway built-in Control UI (separate from Command Center)