Skip to content

Commit c405ec0

Browse files
rafiki270claude
andcommitted
feat: WebUI blocked status display, sidebar reorder, git-lifecycle guard, codex timeout
- WebUI: blocked_error/blocked_conflict status badges and blocked_reason banner - WebUI: sidebar reordered (Dashboard, Projects, Runners first) - WebUI: wakeup modal sorted by action priority - git-lifecycle: .steroids tracking guard blocks tasks with blocked_error - git-lifecycle: re-establish symlink after git reset --hard - AGENTS.md/CLAUDE.md: codex timeout bumped to 1800s - Design doc for task deps/description/reset features Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 39f2a31 commit c405ec0

File tree

10 files changed

+534
-6
lines changed

10 files changed

+534
-6
lines changed

AGENTS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ Any change to the dispatch pipeline requires two independent adversarial reviews
3737
- Non-interactive mode only — never use flags that trigger interactive prompts.
3838
- Never pass model flags or aliases unless explicitly requested.
3939
- Before use: `codex --help` to verify availability; `codex exec "say hi"` as a smoke check.
40-
- Cap long analysis runs at 5 minutes: `timeout 300 codex exec "<prompt>"`
40+
- Use at least 20-minute timeout for reviews: `timeout 1800 codex exec "<prompt>"`
4141
- Do not kill an active process; only terminate after sustained inactivity and ~0% CPU.
4242

4343
### When to Request a Cross-Provider Review

CLAUDE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ Task tool:
2525
```
2626
Task tool:
2727
subagent_type: Bash
28-
prompt: "Run: timeout 300 codex exec \"[adversarial review prompt with full design text]\""
28+
prompt: "Run: timeout 1800 codex exec \"[adversarial review prompt with full design text]\""
2929
```
3030

3131
Both calls go in a **single message** so they execute in parallel. When both return, assess each finding independently per AGENTS.md §"How to Conduct a Review" and append a Cross-Provider Review section to the design doc with adopt/defer/reject decisions for each finding.

WebUI/src/components/layouts/Sidebar.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,10 @@ export const Sidebar: React.FC<SidebarProps> = ({ onClose }) => {
6161

6262
const navItems = [
6363
{ to: '/', icon: HomeIcon, label: 'Dashboard' },
64+
{ to: '/projects', icon: FolderIcon, label: 'Projects' },
65+
{ to: '/runners', icon: PlayIcon, label: 'Runners' },
6466
{ to: '/intake', icon: ExclamationTriangleIcon, label: 'Intake' },
6567
{ to: '/model-usage', icon: ChartBarIcon, label: 'Model Usage' },
66-
{ to: '/runners', icon: PlayIcon, label: 'Runners' },
67-
{ to: '/projects', icon: FolderIcon, label: 'Projects' },
6868
{ to: '/logs', icon: DocumentTextIcon, label: 'System Logs' },
6969
{ to: '/skills', icon: BookOpenIcon, label: 'Skills' },
7070
{ to: '/settings', icon: Cog6ToothIcon, label: 'Settings' },

WebUI/src/components/molecules/WakeupModal.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,13 @@ export const WakeupModal: React.FC<WakeupModalProps> = ({ results, onClose }) =>
3939
}
4040
};
4141

42+
const actionPriority: Record<string, number> = {
43+
started: 0, restarted: 1, error: 2, would_start: 3, cleaned: 4, none: 5, skipped: 6,
44+
};
45+
const sortedResults = [...results].sort(
46+
(a, b) => (actionPriority[a.action] ?? 9) - (actionPriority[b.action] ?? 9)
47+
);
48+
4249
const totalStarted = results.filter(r => r.action === 'started' || r.action === 'restarted').length;
4350
const isGlobalMessage = results.length === 1 && !results[0].projectPath;
4451

@@ -77,7 +84,7 @@ export const WakeupModal: React.FC<WakeupModalProps> = ({ results, onClose }) =>
7784
</div>
7885
) : (
7986
<div className="space-y-3">
80-
{results.map((result, idx) => (
87+
{sortedResults.map((result, idx) => (
8188
<div key={idx} className="flex items-start gap-4 p-4 rounded-lg bg-bg-surface border border-border">
8289
<div className="mt-0.5">
8390
{getIcon(result.action)}

WebUI/src/pages/ProjectTasksPage.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ const STATUS_LABELS: Record<TaskStatus, string> = {
1313
skipped: 'Skipped',
1414
failed: 'Failed',
1515
disputed: 'Disputed',
16+
blocked_error: 'Blocked',
17+
blocked_conflict: 'Conflict',
1618
};
1719

1820
type IssueFilter = 'failed_retries' | 'stale';
@@ -30,6 +32,8 @@ const STATUS_VARIANTS: Record<TaskStatus, 'success' | 'danger' | 'warning' | 'in
3032
skipped: 'warning',
3133
failed: 'danger',
3234
disputed: 'danger',
35+
blocked_error: 'danger',
36+
blocked_conflict: 'warning',
3337
};
3438

3539
// Queue statuses for "next to run" sorting (pending first, then in_progress, then review)

WebUI/src/pages/TaskDetailComponents.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ const STATUS_VARIANTS: Record<string, 'success' | 'danger' | 'warning' | 'info'
1717
skipped: 'warning',
1818
failed: 'danger',
1919
disputed: 'danger',
20+
blocked_error: 'danger',
21+
blocked_conflict: 'warning',
2022
};
2123

2224
export function formatDuration(seconds: number): string {

WebUI/src/pages/TaskDetailPage.tsx

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ const STATUS_LABELS: Record<TaskStatus, string> = {
1616
skipped: 'Skipped',
1717
failed: 'Failed',
1818
disputed: 'Disputed',
19+
blocked_error: 'Blocked',
20+
blocked_conflict: 'Conflict',
1921
};
2022

2123
const STATUS_VARIANTS: Record<TaskStatus, 'success' | 'danger' | 'warning' | 'info' | 'default'> = {
@@ -26,6 +28,8 @@ const STATUS_VARIANTS: Record<TaskStatus, 'success' | 'danger' | 'warning' | 'in
2628
skipped: 'warning',
2729
failed: 'danger',
2830
disputed: 'danger',
31+
blocked_error: 'danger',
32+
blocked_conflict: 'warning',
2933
};
3034

3135
// Strip GUID prefix from task title (format: "#<uuid>: <title>")
@@ -298,6 +302,19 @@ export const TaskDetailPage: React.FC = () => {
298302
)}
299303
</div>
300304

305+
{/* Blocked Reason Banner */}
306+
{task.blocked_reason && ['blocked_error', 'blocked_conflict'].includes(task.status) && (
307+
<div className="mb-6 p-4 rounded-lg border border-danger/30 bg-danger/10">
308+
<div className="flex items-start gap-3">
309+
<i className="fa-solid fa-circle-exclamation text-danger text-lg mt-0.5"></i>
310+
<div>
311+
<h3 className="font-semibold text-danger mb-1">Task Blocked</h3>
312+
<p className="text-sm text-text-primary font-mono whitespace-pre-wrap">{task.blocked_reason}</p>
313+
</div>
314+
</div>
315+
</div>
316+
)}
317+
301318
{/* Stats Cards */}
302319
<div className="grid grid-cols-3 gap-4 mb-6">
303320
<div className="card p-4 text-center">

WebUI/src/types/task.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
* Task detail types for task pages
33
*/
44

5-
export type TaskStatus = 'pending' | 'in_progress' | 'review' | 'completed' | 'skipped' | 'failed' | 'disputed';
5+
export type TaskStatus = 'pending' | 'in_progress' | 'review' | 'completed' | 'skipped' | 'failed' | 'disputed' | 'blocked_error' | 'blocked_conflict';
66

77
export interface AuditEntry {
88
id: number;
@@ -81,6 +81,7 @@ export interface TaskDetails {
8181
section_name: string | null;
8282
source_file: string | null;
8383
rejection_count: number;
84+
blocked_reason: string | null;
8485
created_at: string;
8586
updated_at: string;
8687
duration: TaskDuration;
@@ -118,6 +119,7 @@ export interface TaskListItem {
118119
source_file: string | null;
119120
rejection_count: number;
120121
failure_count: number;
122+
blocked_reason: string | null;
121123
created_at: string;
122124
updated_at: string;
123125
}

0 commit comments

Comments
 (0)