14 Commits
| Author | SHA1 | Message | Date |
|---|---|---|---|
|
|
b3ff0d9b85 |
feat(web): Project-scoped dashboard with sidebar navigation (#381)
* feat(web): add project-based dashboard architecture - Add project query parameter to API routes - Filter sessions by project in both SSR and SSE - Update useSessionEvents hook to accept project param - Update Dashboard and pass project to hook - Add unit tests for project filtering - Add architecture spec document Implements project-based architecture as defined in docs/specs/project-based-dashboard-architecture.md: - GET /api/sessions?project=X returns sessions for project X - GET /api/events?project=X streams only sessions for project X - Dashboard uses project filter from config - SSE URL includes project param when provided - Project matching uses projectId and sessionPrefix - Full backward compatibility maintained (no param = all sessions) * fix: remove duplicate export default in page.tsx * fix(web): clean project-scoped dashboard verification * fix(web): scope dashboard using project id * fix(web): address Bugbot findings in project-scoped dashboard - Consolidate triplicated matchesProject into shared lib/project-utils.ts - Fix Dashboard to receive both projectId (for SSE filtering) and projectName (for display) - Remove inline matchesProject definitions from page.tsx, sessions/route.ts, events/route.ts * fix(web): resolve Bugbot issues in project-scoped dashboard - Add ?project=all query param support in SSR page to show all sessions (previously getPrimaryProjectId() always returned non-empty, making else branches unreachable) - Exclude orchestrator sessions from SSE stream to match SSR/API behavior (orchestrator sessions get their own button, not a card) - Add tests for SSE stream orchestrator exclusion and project filtering Addresses Bugbot issues: - #2903595986: Dead else branches when project filter always applied - #2903595995: SSE stream includes orchestrator sessions unlike SSR/API * feat(web): add project navigation sidebar Add visible left sidebar with project navigation for multi-project setups: - ProjectSidebar component with active state styling - /api/projects endpoint to fetch configured projects - getAllProjects() helper in project-name.ts - Sidebar appears only when 2+ projects configured - Click navigation updates ?project= query param - Active project highlighted with accent color Tests: - ProjectSidebar component tests (8 tests) - API routes tests with proper mocking - All 386 web tests passing Manual test steps: 1. Configure 2+ projects in agent-orchestrator.yaml 2. Start dashboard - sidebar should appear on left 3. Click different projects - URL updates, sessions filter 4. Click "All Projects" - shows all sessions across projects 5. Active project highlighted in sidebar * fix(web): remove duplicate import in test file * fix(web): consolidate ProjectInfo type to shared source Remove duplicated ProjectInfo interface definitions from Dashboard.tsx and ProjectSidebar.tsx. Both now import the type from @/lib/project-name where it is exported as the single source of truth. This addresses Bugbot issue #2906835895: Triplicated ProjectInfo type instead of shared import. * fix(web): integrate globalPause state from main * fix(web): consolidate duplicate @/lib/types import * feat(web): add project-based dashboard architecture - Add project query parameter to API routes - Filter sessions by project in both SSR and SSE - Update useSessionEvents hook to accept project param - Update Dashboard and pass project to hook - Add unit tests for project filtering - Add architecture spec document Implements project-based architecture as defined in docs/specs/project-based-dashboard-architecture.md: - GET /api/sessions?project=X returns sessions for project X - GET /api/events?project=X streams only sessions for project X - Dashboard uses project filter from config - SSE URL includes project param when provided - Project matching uses projectId and sessionPrefix - Full backward compatibility maintained (no param = all sessions) * fix: remove duplicate export default in page.tsx * fix(web): clean project-scoped dashboard verification * fix(web): scope dashboard using project id * fix(web): address Bugbot findings in project-scoped dashboard - Consolidate triplicated matchesProject into shared lib/project-utils.ts - Fix Dashboard to receive both projectId (for SSE filtering) and projectName (for display) - Remove inline matchesProject definitions from page.tsx, sessions/route.ts, events/route.ts * fix(web): resolve Bugbot issues in project-scoped dashboard - Add ?project=all query param support in SSR page to show all sessions (previously getPrimaryProjectId() always returned non-empty, making else branches unreachable) - Exclude orchestrator sessions from SSE stream to match SSR/API behavior (orchestrator sessions get their own button, not a card) - Add tests for SSE stream orchestrator exclusion and project filtering Addresses Bugbot issues: - #2903595986: Dead else branches when project filter always applied - #2903595995: SSE stream includes orchestrator sessions unlike SSR/API * feat(web): add project navigation sidebar Add visible left sidebar with project navigation for multi-project setups: - ProjectSidebar component with active state styling - /api/projects endpoint to fetch configured projects - getAllProjects() helper in project-name.ts - Sidebar appears only when 2+ projects configured - Click navigation updates ?project= query param - Active project highlighted with accent color Tests: - ProjectSidebar component tests (8 tests) - API routes tests with proper mocking - All 386 web tests passing Manual test steps: 1. Configure 2+ projects in agent-orchestrator.yaml 2. Start dashboard - sidebar should appear on left 3. Click different projects - URL updates, sessions filter 4. Click "All Projects" - shows all sessions across projects 5. Active project highlighted in sidebar * fix(web): remove duplicate import in test file * fix(web): consolidate ProjectInfo type to shared source Remove duplicated ProjectInfo interface definitions from Dashboard.tsx and ProjectSidebar.tsx. Both now import the type from @/lib/project-name where it is exported as the single source of truth. This addresses Bugbot issue #2906835895: Triplicated ProjectInfo type instead of shared import. * fix(web): integrate globalPause state from main * fix(web): consolidate duplicate @/lib/types import * fix(web): restore global pause state and membership refresh * fix(web): satisfy lint in project-scoped page defaults * fix(web): remove dead global pause reducer action Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * fix(web): restore global pause resume time Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * chore(web): retrigger bugbot after thread reset * refactor(web): centralize project session filtering helpers * fix(web): reset pause banner dismissal on new pause * fix(web): remove useless orchestrator assignment * fix(web): derive header stats from live session state * fix(web): restore project name in dashboard header * fix(web): restore backlog poller startup in events stream * refactor(web): keep project-utils helpers internal * chore: retrigger bugbot evaluation * chore: retrigger stuck bugbot check * fix: address latest bugbot findings for dashboard events * test(web): add dashboard bugbot regression coverage * refactor(web): simplify projectId selection in dashboard props * fix(web): derive selected project name from project filter * refactor(web): initialize dashboard defaults before service load * fix(web): satisfy lint in dashboard page error path |
|
|
|
1e56cb62c0 | docs: remove remaining PR-specific review artifact | |
|
|
c490ff4b31 |
feat(core): add feedback tools contracts, validation, storage, and dedupe
* feat(core): add feedback report tool contracts and storage * fix(core): stabilize feedback dedupe and clear lint blocker * fix(core): harden feedback report parsing and resilience * docs: add feedback routing architecture and PR explainer * fix(core): remove dedupe collisions and share atomic writes * docs: add final PR403 bugbot resolution status * docs: formalize feedback pipeline and fork-aware execution design * docs: remove PR-specific review artifacts * docs: add durable feedback pipeline explainer * docs: add consent gates and journal semantics to feedback design * docs: add pr403 confidence checklist with openclaw dogfood evidence * docs: add work openclaw validation prompt helper page * docs: record work openclaw validation evidence * docs: remove pr-specific review artifacts from repo * fix(core): ignore confidence in feedback dedupe key |
|
|
|
4e2144d99e
|
feat: OpenCode session lifecycle and CLI controls (#315)
* feat: refine OpenCode session reuse strategy and cleanup * fix: harden OpenCode session selection and lint errors * refactor: centralize OpenCode reuse resolution flow * fix: return 404 for missing session in message route * feat: replace force remap with terminal reload control * fix: protect project path from session kill cleanup * fix: preserve fullscreen alignment without reload action * fix: harden OpenCode session id handling and title reuse selection * fix: show OpenCode reload control and remap before restart * fix: preserve title-only OpenCode reuse with fallback mapping persistence * fix: resolve remaining PR315 Bugbot findings * fix: keep OpenCode discovery title-based without timestamp sorting * fix: avoid enrichment race fallout in session listing * fix: guard OpenCode discovery parse with array check * fix: stabilize Linear comment integration check * fix: harden OpenCode discovery and prompt option flow * ux: clarify OpenCode terminal restart action * fix: remap OpenCode session fresh on each restart * fix: validate remap session ids before reuse * fix: clean archived metadata only after purge * docs: align OpenCode remap selection with title-based behavior * fix: harden opencode cleanup and ignore local sisyphus state * test: add timeout cleanup coverage for session enrichment * fix: harden Linear integration helper against transient non-JSON errors * fix: make linear integration assertions resilient to eventual consistency * fix: remove unused fs import after rebase * fix: address remaining Bugbot blockers for opencode session handling * fix: avoid stale metadata overwrite during restore post-launch * fix: forward subagent in orchestrator flows and defer reuse lookup * fix: apply configured subagent fallback for session spawn * fix: scope archived cleanup by project and delay archive restore write * fix: normalize orchestrator strategy aliases in start display logic * fix: centralize orchestrator strategy normalization in core * fix: derive orchestrator reuse display from spawn result * fix: keep cleanup results consistent across project-id collisions * fix: namespace cleanup results when session IDs collide * fix: harden GitHub issue stateReason fallback Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * fix: avoid false failing CI state mapping Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * fix: add tmux command timeouts Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * fix: bound session API enrichment latency Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * fix: repair scm-github merge resolution Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * fix: repair lifecycle-manager test merge Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * fix: delay archive metadata recreation until restore passes Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * test: restore claim-pr session mocks Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * fix: address review findings for OpenCode lifecycle PR - Fix stripControlChars to preserve newlines for reload commands - Add SessionNotFoundError and use instanceof checks in API routes - Document orchestratorSessionStrategy in YAML example - Validate existingSessionId with asValidOpenCodeSessionId() - Extract inline Node script to buildSessionLookupScript helper - Create OpenCodeSessionManager interface for remap capability - Create OpenCodeAgentConfig type for agent-specific config - Change default orchestratorSessionStrategy from delete to reuse Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: guard reused session display without metadata * chore: add agent config files to .gitignore Agent configuration files (CLAUDE.md, AGENTS.md, IMPROVEMENTS.md, etc.) are personal and project-specific. They should not be committed to the repository. Changes: - Remove CLAUDE.md from git tracking - Add agent config files to .gitignore - Create .gitignore-template for reference Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * chore: update gitignore for agent config folder structure Reorganized agent configuration files: - CLAUDE.md and AGENTS.md stay in root (agents read them there) - Tracking files move to .opencode/ (IMPROVEMENTS.md, etc.) - Optional Claude files in .claude/ Updated .gitignore to ignore folders instead of individual files. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: tighten opencode remap and session discovery safeguards * fix: address Bugbot findings in session manager * fix: scope opencode discovery to opencode sessions * fix: restore concurrent listing and strict permission literals * fix: throw SessionNotFoundError, parallelize list enrichment, fix permissions type - Session manager now throws SessionNotFoundError instead of plain Error for missing sessions, so web API routes correctly return 404 (not 500) - Parallelize session enrichment in list() — was sequential, causing O(N) latency for N sessions with subprocess enrichment - Fix AgentLaunchConfig.permissions type to accept legacy "skip" value (AgentPermissionInput instead of AgentPermissionMode) - Add happy-path and validation tests for /api/sessions/:id/message route - Update all test mocks to use SessionNotFoundError Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: route ao send through session manager * feat: add purge option to orchestrator stop * fix: register opencode agent in web services * test: align web API missing-session coverage * fix: match notifier config by plugin name * refactor: dedupe session lookup and tmux buffer send flow * test: update send lifecycle wait expectation * fix: harden send routing and cleanup purge controls --------- Co-authored-by: Harsh <harsh@Ubuntu-24-Forrest.lan> Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> Co-authored-by: Prateek <karnalprateek@gmail.com> |
|
|
|
8801502871
|
feat: add PR claim flow for agent sessions (#326)
* feat: add PR claim flow for agent sessions
* feat: support PR claim during spawn
* fix: address PR review feedback
* feat: add lifecycle worker automation
* fix: prevent duplicate messages on unconfirmed delivery and deduplicate review prompt
sendWithConfirmation now treats unconfirmed delivery as a soft success
since the message was already sent, preventing the dispatch hash from
staying stale and causing duplicate sends on the next poll cycle.
review-check command now sources its prompt from the lifecycle reaction
config instead of hardcoding it, keeping both paths aligned.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: pass AO_CONFIG_PATH to spawned lifecycle worker and log duplicate-worker early exit
The spawned lifecycle worker now receives AO_CONFIG_PATH in its
environment so it finds the correct config regardless of CWD. Also
added a log message when exiting early due to an existing worker.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: prevent lifecycle worker from clearing metadata on SCM fetch failures
SCM methods (getPendingComments, getAutomatedComments) silently returned []
on error, causing maybeDispatchReviewBacklog to treat fetch failures as
"no comments" and clear all tracking metadata every poll cycle. The worker
appeared to do nothing because it kept resetting its own state.
- SCM methods now propagate errors instead of returning []
- maybeDispatchReviewBacklog distinguishes null (fetch failed, skip) from
[] (confirmed empty, safe to clear)
- pollAll() logs errors instead of silently swallowing them
- Added heartbeat logging and stdout flush before process.exit
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: add debug breadcrumbs when review comment fetch fails
Logs a console.debug message when getPendingComments or
getAutomatedComments fails, making it clear the lifecycle loop is
preserving metadata due to a fetch failure rather than genuinely
having no comments.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: scope lifecycle worker polling to its project and add missing test
pollAll() now passes the worker's projectId to sessionManager.list(),
so each per-project lifecycle worker only polls its own sessions. This
prevents duplicate SCM API calls and race conditions in multi-project
configs.
Also fixed misleading test name and added a test verifying that
--no-dashboard alone still starts the lifecycle worker.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: remove dead confirmation check and respect project-level reaction overrides
Removed the unreachable "could not be confirmed" guard from the retry
logic since sendWithConfirmation now returns silently on unconfirmed
delivery.
review-check now resolves the prompt per-session by checking
project-level reaction overrides before falling back to the global
config, matching lifecycle worker behavior.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: close TOCTOU race in lifecycle worker spawn and unexport getRegistry
Write the child PID from the parent immediately after spawn, closing
the window where a concurrent ensureLifecycleWorker could pass the
"not running" check and spawn a duplicate worker.
Also removed the unnecessary export on getRegistry since it has no
external consumers.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: always include ao base prompt on spawn
* fix: clear heartbeat on shutdown and add initial delay to confirmation loop
Clear the heartbeat interval in the shutdown handler to prevent it
firing during the stream-flush window after lifecycle.stop().
Move the sleep in sendWithConfirmation to before each check (including
the first), so the runtime has time to reflect the message before
the first confirmation attempt.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: resolve lint errors in lifecycle and session manager
- Replace dynamic delete with object reconstruction in lifecycle-manager
- Add { cause } to re-thrown errors in session-manager for preserve-caught-error rule
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
|
|
|
|
17c79b21a0 | Add Composio banner to README | |
|
|
001d411219
|
Vibrant 3D gradient CTA buttons for README (#209)
* docs: add demo video and article links to README Add tweet screenshot for the video demo prominently after the intro, and link to the full article thread. Replaces the TODO placeholder. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs: use article screenshot for README article link Replace text-only article link with clickable screenshot showing the article title, preview image, and engagement stats. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs: replace demo video screenshot with higher quality version Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs: vibrant 3D gradient CTA buttons for README - Replace flat black shields.io badges with custom SVG buttons - Purple gradient for "Watch the Demo" with play icon - Coral gradient for "Read the Full Article" with book icon - Both have 3D shine effect (top highlight, bottom shadow) - High contrast on both GitHub light and dark mode - Update article screenshot with cleaner version - Images remain clickable (already wrapped in <a> tags) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs: remove white borders from CTA buttons Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs: use manually captured PNG buttons instead of SVGs Playwright screenshots introduce 1-2px border artifacts on SVG img elements (microsoft/playwright#35014). Use clean manually-captured PNG screenshots instead. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> |
|
|
|
2c6f9e56b3
|
Update article screenshot and make CTA buttons prominent (#208)
* docs: add demo video and article links to README Add tweet screenshot for the video demo prominently after the intro, and link to the full article thread. Replaces the TODO placeholder. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs: use article screenshot for README article link Replace text-only article link with clickable screenshot showing the article title, preview image, and engagement stats. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs: replace demo video screenshot with higher quality version Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs: update article screenshot and make CTAs more prominent - Replace article screenshot with cleaner version showing title/preview - Replace small <sub> text links with shields.io badge-style buttons for "Watch the demo on X" and "Read the full article on X" Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> |
|
|
|
a98c5a1e30
|
Add demo video and article links to README (#206)
* docs: add demo video and article links to README Add tweet screenshot for the video demo prominently after the intro, and link to the full article thread. Replaces the TODO placeholder. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs: use article screenshot for README article link Replace text-only article link with clickable screenshot showing the article title, preview image, and engagement stats. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs: replace demo video screenshot with higher quality version Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> |
|
|
|
40c1906d41
|
feat(web): redesign dashboard, session detail, and orchestrator terminal (#125)
* docs: add design research artifacts — briefs, token reference, screenshots Comprehensive design research package for the ao dashboard, session detail page, and orchestrator terminal. Produced via competitive analysis of 14 products (Linear, Vercel, Railway, Fly.io, Inngest, WandB, LangSmith, Supabase, and more) + Playwright CSS extraction from live sites + full codebase audit. Artifacts: - docs/design/design-brief.md Main design brief (v2, Playwright-updated) - docs/design/session-detail-design-brief.md /sessions/[id] design spec - docs/design/orchestrator-terminal-design-brief.md Orchestrator page spec - docs/design/token-reference.css Drop-in CSS replacement for globals.css - docs/design/competitive-analysis-raw.md Raw research notes, all 14 sites - docs/design/design-brief-v1.md Original text-only brief (pre-Playwright) - docs/design/README.md Index + research methods summary - docs/design/screenshots/linear-homepage.png Playwright-captured screenshot - docs/design/screenshots/railway-homepage.png Playwright-captured screenshot Key findings: - Linear CSS token values verified via Playwright (body bg #08090A, accent #7070FF, Berkeley Mono monospace, type scale, radius, transitions) - Recommended palette: #0C0C11 base (blue-cast dark vs current GitHub #0d1117) - Highest-impact change: load Inter Variable via next/font/google - Orchestrator terminal needs visual differentiation (violet accent, status strip) - token-reference.css is ready to drop into packages/web/src/app/globals.css Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(web): redesign dashboard, session detail, and orchestrator terminal Implements a cohesive dense dark-mode design system across all three main views. - New color token palette: #0c0c11 base, #141419 surface, #1c1c25 elevated - Accent blue #5b7ef8, status semantics (ready/error/attention/working/idle/done) - Violet accent #a371f7 reserved for orchestrator - Inter Variable + JetBrains Mono loaded via next/font with CSS variables - activity-pulse keyframe for live agent dots - AttentionZone header: dot + label + flex divider + count pill + chevron - Sessions laid out in responsive 1→2→3 column grid - Solid green merge button (translateY hover), no confirm() dialog - Breadcrumb nav: ← Agent Orchestrator / {session-id} [orchestrator badge] - CSS 8×8px activity dot with pulse animation replaces emoji labels - Merge-ready state: green-bordered banner with checkmark icon - Orchestrator sessions show zone counts strip (merge/respond/review counts) - xterm.js dark theme (#0a0a0f bg, #d4d4d8 fg, full 16-color ANSI palette) - variant prop: "agent" (blue cursor) vs "orchestrator" (violet cursor) - Dynamic height prop instead of fixed 600px; fullscreen toggle with SVG icons Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * refactor(web): strip rainbow stats, clean header, IBM Plex Sans typography - Replace Inter with IBM Plex Sans (technical tool aesthetic, distinctive numerics) - Replace 4-color big-number stats bar with a single compact inline status line in the header: "35 sessions · 1 working · 9 PRs" — no decorative colors - Remove the two-tone "Agent (blue) Orchestrator (white)" title — just "Orchestrator" - Remove ClientTimestamp (useless) — replaced by orchestrator nav link - Zone headers: colored dot only (semantic), neutral uppercase label, plain count — removes the rainbow-colored label text that read as a widget template - Add subtle radial gradient glow at top of page for depth Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(web): kanban layout, amber accent, full-width, bigger stats - Switch accent from blue (#5b7ef8) to amber/gold (#d18616) throughout - Replace grid layout with horizontal Kanban columns for active zones (merge, respond, review, pending, working), Done stays full-width below - Remove max-w-[1100px] constraint — full viewport width - Header stats numbers 20px bold (was 12px), orchestrator link is now a visible bordered button - AttentionZone gains variant="column" for Kanban mode (compact header with count pill, vertical card stack) - Update all hardcoded rgba(91,126,248,...) in SessionCard to amber Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(web): layout, alert sizing, column order, button feel - Kanban column order: working→pending→review→respond→merge (left = in progress, right = ready to ship) - Columns use flex-1 min-w-[200px] to fill available width instead of fixed 260px leaving half the page empty - Alert badges: inline-flex wrapper prevents stretching to full row width when wrapping - Terminal button: add bg-subtle fill so it reads as a button - PR number (#91): remove opaque pill background, now plain amber text link — clearly a hyperlink - Merge PR button: pt-0.5 spacer above the action area Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(web): don't cache rate-limited partial PR data When GitHub rate limits fire, enrichSessionPR was caching the bad partial data (0 additions, CI failing) for 60 seconds, causing the dashboard to show incorrect data for the full TTL window. - Skip cache write when majority of API calls failed - Downgrade console.error → console.warn (this is handled/expected) The next page refresh will retry live API calls, so data recovers as soon as the rate limit window resets. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(web): graceful GitHub API rate limit handling in UI When the GitHub plugin hits rate limits, the dashboard now: - Shows a single amber banner: "GitHub API rate limited — PR data (CI status, review state, sizes) may be stale. Will retry on next refresh." - Hides CI badge, review decision, and size pill on PR cards (they'd show wrong values: +0 -0 XS, CI failing) - Shows a subtle "⚠ PR data rate limited" note on affected cards instead of misleading alert badges - Skips CI/review/conflict-based attention zone classification for rate-limited PRs (prevents sessions moving to Review due to phantom "CI failing" from the fallback value) - Doesn't cache partial rate-limited data so next refresh retries live API calls as soon as the rate limit window resets What still works when rate limited: - Session ID, title, branch, PR number/link - Session activity status (working/spawning/etc.) - Merge button if mergeability was already cached - Restore/terminate/send actions Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(web): dashboard redesign — glassmorphism, Kanban, rate-limit handling, perf fix Design: - Kanban layout: active zones as flex columns (working→pending→review→respond→merge), Done as full-width grid below - GitHub dark color palette (main's tokens) with glassmorphic card surfaces (rgba bg + backdrop-blur) and subtle blue/violet body gradient - Activity state shown as labeled pill (● active / ● idle etc.) instead of bare dot - Session card: title on its own row, larger font, inline-flex alert badges (no stretch) - PR number rendered as plain accent link, not a blue pill badge - Terminal button has background fill to feel like a button - Info circle icon replaces alarming warning triangle for rate-limit indicators - "1 working" → "1 active" in header stats - PR table constrained to max-w-[900px] and centered - Orchestrator session no longer uses purple accent Rate limiting: - isPRRateLimited() helper; getAttentionLevel() skips PR classification when limited - Rate-limited banner in Dashboard; suppressed CI/size/review badges in PRStatus - SessionCard shows subtle "PR data rate limited" indicator; getAlerts() returns [] - serialize.ts: rate-limited enrichment results cached for 5 min (not 60s) to stop retrying 168 failing API calls every minute Performance: - page.tsx: 4s hard timeout on PR enrichment — serves stale data fast instead of blocking SSR for 75s under rate limiting - cache.ts: TTLCache.set() accepts optional ttl override for per-entry control Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: suppress stale size/CI/review in PR table when rate limited PRTableRow now shows "—" for size, CI, and review columns when GitHub API is rate limited, matching the card view which already hides these. Prevents misleading "+0 -0 XS" size and "needs review" labels from the default fallback values. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: 3D card effect with depth shadow and top-edge shine Cards now clearly pop against the dark background: - Solid gradient bg (rgba(28,36,47) → rgba(18,23,31)) instead of near-invisible rgba(22,27,34,0.8) surface - Layered box-shadow: contact shadow + diffuse depth + inset top highlight that simulates light hitting the card's top edge (the "shine") - Hover: card lifts 2px with deeper shadow - Merge-ready: green-tinted bg with green ambient glow + stronger lift on hover Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: restore text legibility inside session cards The darker solid card gradient made muted/secondary text nearly invisible — #484f58 (text-muted) had only ~2:1 contrast on the new card bg. Override the color tokens locally within .session-card to GitHub's established dark-mode legibility values: --color-text-muted: #484f58 → #656d76 (3.8:1 on card bg) --color-text-secondary: #7d8590 → #8b949e (6.2:1 on card bg) --color-text-tertiary: #484f58 → #656d76 Scoped to .session-card so the rest of the UI is unchanged. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: address bugbot comments — fonts, review zone, ActivityDot, orchestrator btn - layout.tsx: add IBM Plex Sans weight 700 (was missing, font-bold falling back to 600) - DirectTerminal.tsx: use "IBM Plex Mono" instead of unloaded "JetBrains Mono" - SessionDetail.tsx: add review zone to OrchestratorStatusStrip (was omitted, sessions with CI failures were invisible in the strip) - ActivityDot.tsx: extract shared component, remove duplicate implementations in SessionCard.tsx and SessionDetail.tsx - Dashboard.tsx: redesign orchestrator button with 3D glass style matching card aesthetic (blue-tinted bg, depth shadow, hover lift) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(web): lint — eqeqeq, duplicate import, unused var - ActivityDot.tsx: != → !== (eqeqeq rule) - PRStatus.tsx: merge duplicate @/lib/types imports into one - SessionCard.tsx: remove unused activityIcon import Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(web): elevate session detail + orchestrator page design - Nav: glass backdrop-blur effect with chevron back link - Header: detail-card 3D treatment with left-border accent keyed to activity color - Meta chips: bordered pill style with subtle bg instead of flat text - Status tag: pill badge for status instead of plain text - PR card: detail-card 3D treatment, border-color reflects PR state - PR merged badge: purple pill instead of gray text - Unresolved count: red pill badge in section header - Blockers section: renamed "Issues" → "Blockers" - Terminal section: colored bar indicator instead of plain label - Orchestrator status strip: total agent count + per-zone colored pills - globals.css: add .nav-glass and .detail-card classes Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(web): fetchZoneCounts parses body.sessions, delayed 2s to avoid contention The /api/sessions endpoint returns `{ sessions: [...] }` not a bare array. fetchZoneCounts was treating the whole response object as an array, so zone counts were always zero on the orchestrator detail page. Also delays the initial fetchZoneCounts call by 2s so it doesn't contend with the session fetch on page load (both hit /api/sessions which is slow when GitHub enrichment is running). Also includes: Playwright kill-Chrome-for-Testing tip in CLAUDE.md, toned-down detail-card shadow in globals.css. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * perf+test(web): cache-first PR enrichment, skip exited sessions, fix component tests Performance improvements: - enrichSessionPR() now accepts cacheOnly option and returns boolean - /api/sessions/[id]: serve from cache immediately, only block on first load - /api/sessions: skip PR enrichment for EXITED sessions (no longer changing) - cache: increase default TTL from 60s to 5 minutes Test fixes (match redesigned SessionCard + AttentionZone): - "restore session" (header) → "restore"; expanded panel still shows "restore session" - "merge PR #N" → "Merge PR #N" (capital M) - "CI status unknown" → "CI unknown" - "ask to fix CI" / "ask to fix CI" → "ask to fix" - "terminate session" → "terminate" - Zone labels: RESPOND/WORKING/DONE → Respond/Working/Done (CSS uppercase is visual only) - "working" zone no longer collapsed by default; collapse tests now use "done" zone Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(core): ActivityDetection with timestamp propagation - Add ActivityDetection interface { state, timestamp? } to types.ts - Agent getActivityState() returns ActivityDetection | null instead of ActivityState | null, allowing timestamp from JSONL mtime to propagate - session-manager updates session.lastActivityAt when detected.timestamp is more recent — fixes "active 22h ago" showing stale timestamps - Update all agent plugins (claude-code, aider, codex, opencode) to return ActivityDetection objects Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(web): dismissible rate limit banner + 60min rate-limit cache TTL - Add X dismiss button to GitHub API rate limit banner in Dashboard.tsx so it can be closed during demos - Extend rate-limited PR cache TTL from 5min to 60min — GitHub GraphQL rate limits reset hourly, no point retrying every 5 minutes Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(web): address Cursor Bugbot review comments on PR #125 - Dashboard StatusLine: active sessions count now uses var(--color-status-working) (blue) instead of neutral text color, matching the design system semantics - SessionCard: isReadyToMerge now guards against rate-limited state — a card with stale cached mergeability data won't show green merge-ready styling - DirectTerminal: add `variant` to useEffect dependency array (was missing, causing stale cursor/selection colors if variant changed after mount) - agent-aider: include `timestamp: chatMtime` in all ActivityDetection returns, matching the pattern used by agent-claude-code (enables accurate lastActivityAt) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(ci): resolve lint, typecheck, and test failures Lint: - Remove unused parseJsonlFile function (superseded by parseJsonlFileTail) - Remove dead lastLogModified stat() call in getSessionInfo (field was removed from AgentSessionInfo but the filesystem read was left behind) Typecheck + Tests (ActivityDetection): - session-manager.test.ts: update mocks to return { state: "active" } / { state: "idle" } instead of bare strings — getActivityState() returns ActivityDetection | null, not ActivityState | null - integration tests (aider, claude-code, codex, opencode): update imports from ActivityState → ActivityDetection, variable types, comparisons (activityState?.state !== "exited"), and assertions (?.state).toBe() Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: parseJsonlFileTail uses readFile for small files; enrich exited sessions with PRs - parseJsonlFileTail now calls stat() then readFile() for files smaller than maxBytes, falling back to open()/handle.read() only for large files. This fixes the test infrastructure (which mocks readFile but not open) and also fixes a scope bug where `offset` was declared inside an inner try block but referenced outside both try blocks. - Math.max(0, NaN) returns NaN not 0, so size must default to 0 when stat returns a mock without a size field: `const { size = 0 } = await stat(...)`. - Update activity-detection.test.ts: getActivityState() now returns ActivityDetection objects, so tests use (await ...)?.state comparisons. - Remove stale lastLogModified test (field was removed from AgentSessionInfo). - Remove EXITED skip guard from api/sessions/route.ts: exited sessions can still have open, merge-ready PRs that need enrichment on the dashboard. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: comprehensive code review fixes — tests, timestamps, UI correctness Address gaps identified in code review of the ActivityDetection PR: Core / Session Manager: - Add `timestamp` to all `{ state: "exited" }` returns in all 4 agent plugins (claude-code, aider, codex, opencode) using consistent `exitedAt = new Date()` pattern - Add 2 new session-manager tests: timestamp propagation when detection timestamp is newer, and no-downgrade when detection timestamp is older - Fix `parseJsonlFileTail` lint error: remove useless `= 0` initializer (value was always overwritten before use; catch block returns early) Web package — tests: - Fix 3 `api-routes.test.ts` failures: `sessionsGET()` needs a Request object since the route reads `request.url` for `?active=true` query param - Fix `serialize.test.ts` rate-limit test: spy on `console.warn` (what the code uses) not `console.error` - Add 5 `ActivityDot` component tests covering all activity states, unknown states, null activity, and dotOnly mode Web package — UI correctness: - Fix `relativeTime()` in SessionDetail to guard against invalid/empty ISO strings - Fix timer Map leak: add `timersRef.current.clear()` in cleanup effect after forEach - Add `encodeURIComponent` to sessionId in message fetch URL Server — race condition fix: - Guard `activeSessions.delete` in pty.onExit, ws.on("close"), and ws.on("error") against stale handlers deleting a newly-registered session with the same ID. Fixes flaky integration test where afterEach's pty.kill() fired asynchronously after the next test had already set up a new session with the same session ID. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(web): narrow PREnrichmentData types to eliminate unsafe casts in serialize PREnrichmentData.ciStatus and .reviewDecision were typed as string, requiring unsafe `as` casts when reading from cache into DashboardPR. Narrow them to the same literal union types used by DashboardPR, making the casts unnecessary. Also narrow ciChecks[].status to match CoreCICheck. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> |
|
|
|
450507193e
|
docs: update port references to reflect configurability (#122)
All docs now mention that the dashboard port (default 3000) is configurable via `port:` in agent-orchestrator.yaml. Fixes incorrect port 9847 references in SETUP.md, adds multi-project port guidance, and documents terminal port auto-detection. Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> |
|
|
|
520010d5a2
|
feat: configurable terminal server ports for multi-dashboard support (#113)
* feat: make terminal server ports configurable to fix multi-dashboard EADDRINUSE When multiple ao dashboards run simultaneously (e.g., ao on port 3000, integrator on port 3002), both try to start terminal WebSocket servers on hardcoded ports 3001/3003, causing EADDRINUSE. Add terminalPort and directTerminalPort to config schema so each instance can use unique ports. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: use optional() instead of default() for terminal port schema Zod .default() always fills in the value, making config.terminalPort never undefined and the env var fallback in buildDashboardEnv dead code. Switch to .optional() so the priority chain works correctly: config value > TERMINAL_PORT env var > hardcoded default. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: move terminal server defaults from 3001/3003 to 14800/14801 The 3000-3009 range is the most contested in dev tooling (Next.js auto-increments, BrowserSync, Grafana, Rails, Express all default to 3000+). Port 14800-14899 has zero IANA registrations, zero known dev tool conflicts, and is safely below OS ephemeral ranges. Updated all hardcoded fallbacks, .env.local.example, docker-compose port mappings, and documentation. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: auto-detect available terminal ports for zero-config multi-dashboard When no terminal ports are configured (no config, no env vars), buildDashboardEnv now probes for an available port pair starting at 14800. The second `ao start` automatically gets 14802/14803 (or the next free pair), eliminating EADDRINUSE without any user configuration. Port detection scans in steps of 2 to keep the pair consecutive. Explicit config/env values bypass auto-detection entirely. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: update onboarding test to use new default terminal port (14801) The onboarding integration test had port 3003 hardcoded for the WebSocket health check. Updated to read from DIRECT_TERMINAL_PORT env var with 14801 as the default, matching the new port defaults. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> |
|
|
|
599710296d
|
fix: migrate to hash-based project isolation architecture
Complete migration to hash-based directory structure for project isolation. All bugbot issues resolved. |
|
|
|
66005c05c5
|
feat: implement comprehensive security audit and secret leak prevention (#67)
* feat: implement comprehensive security audit and secret leak prevention ## Changes ### Security Infrastructure - Add Gitleaks configuration (.gitleaks.toml) for secret scanning - Add pre-commit hook via Husky to block secret commits - Add GitHub Actions security workflow (gitleaks, dependency review, npm audit) - Update .gitignore to exclude secret files and credentials ### Documentation - Create SECURITY.md with security policy and best practices - Create README.md with project overview and security section - Create docs/DEVELOPMENT.md with developer guide - Create docs/SECURITY-AUDIT-SUMMARY.md with full audit report ### Dependencies - Add husky@^9.1.7 for git hooks ## Audit Results - ✅ Current codebase: 0 secrets found (1.47 MB scanned) - ⚠️ Git history: 1 historical secret (OpenClaw token, documented in SECURITY.md) - ✅ All test files use dummy values - ✅ All example configs use environment variables ## Security Features 1. **Pre-commit Hook**: Scans staged files, blocks secrets before commit 2. **CI/CD Pipeline**: Scans full git history on every push/PR 3. **Automated Scanning**: Weekly scheduled scans for new vulnerabilities 4. **Comprehensive Docs**: Security policy, best practices, developer guide ## Testing ```bash # Scan current files gitleaks detect --no-git # Test pre-commit hook echo "token=ghp_fake" > test.txt git add test.txt git commit -m "test" # Should be blocked ``` Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> * fix: make dependency-review job non-blocking The dependency-review action requires GitHub Advanced Security which may not be available on all repositories. Adding continue-on-error to prevent workflow failure when this feature is unavailable. The check will still run and provide useful information when available, but won't block the PR if the repository doesn't have Advanced Security. * feat: add workflow_dispatch trigger to security workflow Allows manual triggering of security scans for testing and re-running. * fix: address Cursor Bugbot security review comments Fixes all high, medium, and low severity issues identified by Cursor Bugbot: **High Severity:** - Redact OpenClaw token from documentation (replace with 1af5c4f...872) - Fix pre-commit hook to FAIL (exit 1) when gitleaks is not installed - Previously silently skipped scanning (exit 0) providing false sense of security - Fix bashism in pre-commit hook: replace &> with > /dev/null 2>&1 (POSIX compliant) **Medium Severity:** - Remove overly broad gitignore patterns (*.sql, *.db, *.sqlite) - These would block legitimate SQL migration files and database schemas - Keep focus on actual credential files only **Low Severity:** - Remove author email (samvit@hotmail.com) from audit documentation All issues now resolved. Pre-commit hook will properly block commits when gitleaks is missing, ensuring consistent secret scanning enforcement. * fix: comment out dependency-review job requiring Dependency graph The dependency-review GitHub Action requires 'Dependency graph' to be enabled in repository settings. Since this feature may not be available or configured on all repositories, commenting out this job to prevent workflow failures. To re-enable: 1. Go to Settings > Code security and analysis 2. Enable 'Dependency graph' 3. Uncomment the dependency-review job in this workflow The npm-audit job provides similar dependency vulnerability scanning and doesn't require special GitHub features. * feat: re-enable dependency-review job after Dependency graph enabled Now that Dependency graph is enabled in repo settings, uncomment the dependency-review job to scan PRs for vulnerable dependencies. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com> |