Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .claude/commands/approve-merge.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ If merge queue is detected (or forced via config):
- Write a merge queue marker file so the dashboard can track the PR:
```bash
Comment thread
xsovad06 marked this conversation as resolved.
mkdir -p .claude/agent-control
python3 -c "import json; print(json.dumps({'pr_number': <PR_NUMBER>, 'repo': '<OWNER/REPO>', 'issue_number': '<ISSUE_NUMBER>', 'branch_name': '<HEAD_BRANCH>'}))" > .claude/agent-control/merge-queue.json
python3 -c "import json; print(json.dumps({'pr_number': <PR_NUMBER>, 'repo': '<OWNER/REPO>', 'issue_number': <ISSUE_NUMBER>, 'branch_name': '<HEAD_BRANCH>'}))" > .claude/agent-control/merge-queue.json
```
- Proceed to queue polling (step 3b)

Expand Down
2 changes: 1 addition & 1 deletion .claude/commands/integrate-pr.md
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ If merge queue is detected:
- If enqueued, write a merge queue marker file so the dashboard can track the PR:
```bash
mkdir -p .claude/agent-control
Comment thread
xsovad06 marked this conversation as resolved.
python3 -c "import json; print(json.dumps({'pr_number': <PR_NUMBER>, 'repo': '<OWNER/REPO>', 'issue_number': '<ISSUE_NUMBER>', 'branch_name': '<HEAD_BRANCH>'}))" > .claude/agent-control/merge-queue.json
python3 -c "import json; print(json.dumps({'pr_number': <PR_NUMBER>, 'repo': '<OWNER/REPO>', 'issue_number': <ISSUE_NUMBER>, 'branch_name': '<HEAD_BRANCH>'}))" > .claude/agent-control/merge-queue.json
```
- Then poll merge queue status via GraphQL every `merge_queue_poll_interval` seconds (default 30)
- On MERGED: proceed to Phase 6. If `delete_branch = true`, delete remote branch via GitHub API
Expand Down
2 changes: 1 addition & 1 deletion .claude/rules/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ SOVA has four main components:
- `core/state.py` -- 19-state TaskStatus StrEnum with transition validation
- `core/context.py` -- ExecutionContext dataclass threading state through steps
- `core/output.py` -- OutputWriter for per-run DB-backed output persistence, read_lines, retention cleanup
- `core/steps/` -- 29 BaseStep implementations with execute/validate_output/can_skip. Four pipeline variants:
- `core/steps/` -- 31 BaseStep implementations with execute/validate_output/can_skip. Four pipeline variants:
- **Developer pipeline** (16 steps): sync -> assess -> create_worktree -> capture_baseline -> develop -> simplify -> self_review -> commit -> validate -> push -> create_pr -> wait_for_external_reviews -> address_external_findings -> monitor_ci -> extract_memory -> handoff_to_reviewer
- **Address-review pipeline** (10 steps): ensure_worktree -> rebase -> address_review -> rearrange_commits -> validate -> push -> monitor_ci -> resolve_external_reviews -> extract_memory -> handoff_to_user
- **Researcher pipeline** (4 steps): fetch_task -> research -> spec -> extract_memory
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ test-bash: lint-bash ## Validate bash scripts (shellcheck + --help)
done

test-py: ## Run pytest suite (excludes runtime/stress/chaos)
$(PYTEST) tests/ -v -m "not runtime and not stress and not chaos"
$(PYTEST) tests/ -v -m "not runtime and not stress and not chaos" -n auto

test-runtime: ## Run runtime, stress, and chaos tests (manual)
$(PYTEST) tests/ -v -m "runtime or stress or chaos" --timeout=120
Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ dev = [
"pytest-asyncio>=0.24",
"pytest-cov>=6.0",
"pytest-timeout>=2.3",
"pytest-xdist>=3.0",
"ruff>=0.4",
"respx>=0.22",
]
Expand Down
28 changes: 27 additions & 1 deletion sova/dashboard/static/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -895,7 +895,33 @@ if (document.getElementById('activity-dot')) {
initGlobalBatch();

/* ============================================================
Comment thread
xsovad06 marked this conversation as resolved.
12. ROLE COLORS
12. PRIORITY ICONS
============================================================ */

// Keep in sync with priority_map in _components.html
var _PRIORITY_ICON_MAP = {
critical: 'blocker',
high: 'high',
medium: 'medium',
low: 'low'
};

function priorityIconUrl(priority) {
var p = (priority || '').toString().toLowerCase().trim();
var iconName = _PRIORITY_ICON_MAP[p] || 'undefined';
return '/static/priority/' + iconName + '.svg';
}

function _extractPriority(labels) {
for (var i = 0; i < (labels || []).length; i++) {
var l = labels[i];
if (l.indexOf('priority:') === 0) return l.replace('priority: ', '').replace('priority:', '').trim();
}
return '';
}

/* ============================================================
13. ROLE COLORS
============================================================ */

function _roleHex(key) {
Expand Down
5 changes: 5 additions & 0 deletions sova/dashboard/static/priority/blocker.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions sova/dashboard/static/priority/critical.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions sova/dashboard/static/priority/high.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions sova/dashboard/static/priority/low.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions sova/dashboard/static/priority/medium.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions sova/dashboard/static/priority/undefined.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 14 additions & 0 deletions sova/dashboard/templates/_components.html
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,17 @@ <h3 class="text-sm font-medium text-gray-400"{% if title_id %} id="{{ title_id }
{%- endif %}
</div>
{%- endmacro -%}

{%- macro priority_icon(priority, size="16") -%}
{#- Keep in sync with _PRIORITY_ICON_MAP in app.js -#}
{%- set priority_map = {
'critical': 'blocker',
'high': 'high',
'medium': 'medium',
'low': 'low'
} -%}
{%- set priority_lower = (priority|string|lower).strip() if priority else '' -%}
{%- set icon_name = priority_map.get(priority_lower, 'undefined') -%}
{%- set alt_text = priority_lower.capitalize() if priority_lower else 'Undefined' -%}
<img src="/static/priority/{{ icon_name }}.svg" alt="{{ alt_text }} priority" width="{{ size }}" height="{{ size }}" class="inline-block align-middle" loading="lazy">
{%- endmacro -%}
21 changes: 4 additions & 17 deletions sova/dashboard/templates/agents.html
Original file line number Diff line number Diff line change
Expand Up @@ -482,14 +482,6 @@ <h3 class="text-sm font-semibold text-white leading-tight">Launch Agent</h3>
renderTaskCards();
}

function _extractPriority(labels) {
for (var i = 0; i < (labels || []).length; i++) {
var l = labels[i];
if (l.indexOf('priority:') === 0) return l.replace('priority: ', '').replace('priority:', '').trim();
}
return '';
}

var _priorityOrder = { critical: 0, high: 1, medium: 2, low: 3 };

function _renderHandoffBtn(ha, issueNumber) {
Expand Down Expand Up @@ -552,8 +544,7 @@ <h3 class="text-sm font-semibold text-white leading-tight">Launch Agent</h3>
var issueKey = item.issue_number || ('pr:' + item.pr_number);
var isRunning = item.state === 'agent_running';
var p = _extractPriority(item.labels);
var pDots = { critical: 'bg-accent-red', high: 'bg-accent-yellow', medium: 'bg-gray-500', low: 'bg-gray-600' };
var pDot = p ? '<span class="w-1.5 h-1.5 rounded-full shrink-0 ' + (pDots[p] || 'bg-gray-600') + '"></span>' : '';
var priorityIcon = p ? '<img src="' + priorityIconUrl(p) + '" alt="' + escapeHtml(p) + ' priority" width="16" height="16" class="inline-block align-middle shrink-0">' : '';
Comment thread
xsovad06 marked this conversation as resolved.

var handoffActions = item.handoff_actions || [];
var isSpecReview = item.state === 'spec_review';
Expand Down Expand Up @@ -694,7 +685,7 @@ <h3 class="text-sm font-semibold text-white leading-tight">Launch Agent</h3>
: '';

var mainRow = '<div class="flex items-center gap-3 px-4 py-2.5">' +
(needsAttention ? attentionDot : pDot) +
(needsAttention ? attentionDot : priorityIcon) +
issueRef +
'<span class="text-sm text-gray-300 truncate flex-1">' + escapeHtml(item.title) + '</span>' +
metaStrip +
Expand Down Expand Up @@ -1543,14 +1534,10 @@ <h3 class="text-sm font-semibold text-white leading-tight">Launch Agent</h3>
}

var taskListHtml = tasks.map(function(t, i) {
var priorityColors = {
critical: 'text-accent-red', high: 'text-accent-yellow',
medium: 'text-accent', low: 'text-gray-400'
};
var pColor = priorityColors[t.priority] || 'text-gray-400';
var iconUrl = priorityIconUrl(t.priority);
return '<label class="flex items-start gap-2 py-1 text-xs cursor-pointer" onclick="event.stopPropagation()">' +
'<input type="checkbox" checked class="mt-0.5 planner-task-check" data-idx="' + i + '">' +
'<span class="flex-1"><span class="' + pColor + ' font-medium">[' + escapeHtml(t.priority) + ']</span> ' + escapeHtml(t.title) + '</span>' +
'<span class="flex-1"><img src="' + iconUrl + '" alt="' + escapeHtml(t.priority || 'undefined') + ' priority" width="12" height="12" class="inline-block align-middle mr-1"> ' + escapeHtml(t.title) + '</span>' +
Comment thread
xsovad06 marked this conversation as resolved.
'</label>';
}).join('');

Expand Down
4 changes: 4 additions & 0 deletions sova/dashboard/templates/queue.html
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,9 @@ <h2 class="text-2xl font-semibold">Priority Queue</h2>

var typeBadge = issueTypeBadge(item.issue_type);

var priority = _extractPriority(item.labels || []);
var priorityIcon = '<img src="' + priorityIconUrl(priority) + '" alt="' + escapeHtml(priority || 'undefined') + ' priority" width="14" height="14" class="inline-block align-middle shrink-0">';

var displayLabels = (item.labels || []).filter(function(l) {
return l.indexOf('agent:') !== 0 && l.indexOf('priority:') !== 0 && l.indexOf('role:') !== 0;
});
Expand Down Expand Up @@ -314,6 +317,7 @@ <h2 class="text-2xl font-semibold">Priority Queue</h2>
'<input type="checkbox" id="cb-' + escapeHtml(item.issue) + '" ' + (isSelected ? 'checked ' : '') +
'onchange="toggleSelection(\'' + escapeHtml(item.issue) + '\', \'' + escapeHtml(item.state) + '\')" ' +
'class="rounded border-gray-600 bg-surface text-accent focus:ring-accent/50 cursor-pointer shrink-0">' +
priorityIcon +
'<span class="px-2 py-1 rounded text-xs font-bold ' + style.badge + '">' + item.priority_label + '</span>' +
'<div class="flex-1 min-w-0">' +
'<div class="flex items-center gap-2">' +
Expand Down
Loading
Loading