Skip to content

Feat/dashboard collab and UI upgrades - #113

Merged
MyNameIsEdi merged 7 commits into
mainfrom
feat/dashboard-collab-and-ui-upgrades
May 23, 2026
Merged

Feat/dashboard collab and UI upgrades#113
MyNameIsEdi merged 7 commits into
mainfrom
feat/dashboard-collab-and-ui-upgrades

Conversation

@MyNameIsEdi

@MyNameIsEdi MyNameIsEdi commented May 23, 2026

Copy link
Copy Markdown
Owner

Description

Fixes # (issue number)

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update

Checklist:

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes

Summary by CodeRabbit

  • New Features

    • Multi-agent collaboration now preserves chat history and image attachments across collaboration rounds.
  • Bug Fixes

    • Archive operation success/failure now logged for visibility.
    • Concurrent test runs no longer interfere with each other’s summary results.
    • Archived results display restored correctly when switching between runs.
  • Documentation

    • Docs updated for Gemini/Ollama dual-provider setup and rewritten sections.
    • README features table reformatted and clarified.

Review Change Stack

MyNameIsEdi and others added 5 commits May 23, 2026 22:44
…for every run, UI polish

Three production fixes plus a feature upgrade for the Playwright Dashboard
and the QA Office chat panel:

- **Multi-agent collaboration** in /api/qa-agent: primary → critic → primary
  refine → Edi M synthesis. Auto-triggered when 2+ agents are tagged or the
  manager is mentioned. New SSE turn_start/turn_done/turn_verdict events
  produce a threaded conversation in chat, with colour-coded role pills.
- **Run logs persisted** alongside each archived run; clicking an old run
  re-hydrates the dashboard log panel. archiveRun() now logs success/failure
  to the server console so silent archive failures are visible.
- **Edi M summary now streams to chat for every Run Tests**, not just
  agent-generated dynamic runs. Phase 2 streamSummary() helper shared by
  /api/playwright/run and /api/run-dynamic-test.
- **Dashboard UI/UX polish**: KPI hero with progress ring + verdict, pill
  subtitle row, history-chart hover tooltip + moving-average trend line,
  sticky suite headers with smooth chevron rotation, copy-error button,
  cropped QA Office canvas (no more "blue void" above the office).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- server: drop unnecessary \- escape in runId sanitiser regex
- tests/sv-login: remove unused BASE_URL import
- PlaywrightDashboard: replace ternary-as-statement with explicit if/else
  in the multi-spec picker onChange (no-unused-expressions)
- OfficePage + PlaywrightDashboard: remove orphaned
  `eslint-disable-next-line react-hooks/exhaustive-deps` directives —
  the rule isn't registered in this project's ESLint config so the
  directive itself was reported as an error
- PlaywrightDashboard: drop two unused `// eslint-disable-line`
  trailing comments flagged by no-unused-disable
- README: mention multi-agent collab + persistent run history features
  so the docs-check script sees a docs update alongside the code change

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Auto-format 115 files with Prettier to fix the failing format:check
workflow step. Also removes the temporary PR_BODY.md file.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…, summary snapshot, types)

- CHANGELOG: remove duplicate bullets (two entries appeared under both the
  unreleased ### Changed block and an orphaned second block)
- runCollabTurn: accept and forward history + imageAttachments into
  startChat/sendMessageStream so collaborative turns preserve context and vision
- capturedLog: switch from oldest-first cap to a sliding window (push + shift)
  so archiveRun and AI summaries always see the newest 5 000 lines
- streamSummary: accept runId in SummaryCreds; reads the per-run immutable
  archive instead of the shared RESULTS_PATH to prevent concurrent-run clobbering
- Both route close-handlers now capture archiveRun return value and pass runId
  to streamSummary
- PlaywrightDashboard: define RunRequest and SummaryEvent types; runWithSSE
  typed as (body: RunRequest); evt typed as SummaryEvent | Record<string,unknown>;
  fetchResults always calls setRunLog (clears to [] when not an archived run)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…-and-ui-upgrades

# Conflicts:
#	CHANGELOG.md
#	server/index.ts
#	ui/src/pages/PlaywrightDashboard.tsx
@MyNameIsEdi MyNameIsEdi self-assigned this May 23, 2026
@coderabbitai

coderabbitai Bot commented May 23, 2026

Copy link
Copy Markdown

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: bc856ea6-8108-4262-8e2b-5969446eb1b2

📥 Commits

Reviewing files that changed from the base of the PR and between 2a35981 and 8112a99.

📒 Files selected for processing (2)
  • CHANGELOG.md
  • ui/src/pages/DocsPage.tsx

📝 Walkthrough

Walkthrough

This PR adds per-run result isolation for Playwright/dynamic runs, forwards Gemini multi-agent chat history and images across specialist turns, introduces RunRequest/SummaryEvent typings, and revises docs/README/CHANGELOG content.

Changes

Per-Run Archiving and Gemini Collaboration

Layer / File(s) Summary
Run and SSE type contracts
ui/src/pages/PlaywrightDashboard.tsx, server/index.ts
Introduces RunRequest and SummaryEvent on the UI and extends server SummaryCreds with optional runId so summaries can read per-run archives.
Gemini multi-agent collaboration history & images
server/index.ts
runCollabTurn() now accepts and maps prior history and imageAttachments into Gemini calls; playTurn() and the initial primary turn propagate these values so each collaboration round preserves conversation and vision context.
Per-run archiving and summary resolution
server/index.ts
Playwright and dynamic-test endpoints use a sliding-window for logs, capture the runId returned by archiveRun(), and pass it to streamSummary(); streamSummary() prefers RUNS_DIR/<runId>.json when present, else falls back to shared results.
Client SSE parsing & archived-run hydration
ui/src/pages/PlaywrightDashboard.tsx
Client types request payloads as RunRequest, parses SSE SummaryEvent objects for structured phase-2 events, and restores/clears runLog correctly when viewing archived runs or switching back to latest runs.
Documentation & changelog
ui/src/pages/DocsPage.tsx, README.md, CHANGELOG.md
DocsPage content blocks (architecture, env-vars, running-tests, FAQ, troubleshooting, roadmap) are rewritten; README features table updated (Multi-Agent Collaboration mentions history/image forwarding); CHANGELOG adds DocsPage bullet and clarifies archiveRun() console logging and entry reorganization.

Sequence Diagram

sequenceDiagram
  participant Client
  participant PlayEndpoint as /api/playwright/run
  participant ArchiveRun
  participant StreamSummary
  Client->>PlayEndpoint: POST run request (RunRequest)
  PlayEndpoint->>ArchiveRun: archiveRun(logs, results)
  ArchiveRun-->>PlayEndpoint: runId
  PlayEndpoint->>StreamSummary: streamSummary(creds with runId)
  StreamSummary->>StreamSummary: read RUNS_DIR/runId.json (if exists)
  StreamSummary-->>Client: summary_start/summary_chunk/summary_done SSE
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐰 With per-run archives snug and tidy in store,
Gemini keeps history, images, and more,
SSEs hum summaries clean and bright,
Docs and README now tell the tale right,
Hooray — the rabbit hops, code stitched tight!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description contains only checklist items with no substantive summary, motivation, context, or linked issue number. Add a detailed description explaining what changes were made, why they were needed, and the motivation behind them. Link the related issue number. Provide context about multi-agent collaboration, run log persistence, UI/UX improvements, and bugfixes.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main changes: multi-agent collaboration features and UI/dashboard upgrades are the primary focus across the changeset.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/dashboard-collab-and-ui-upgrades

Comment @coderabbitai help to get the list of available commands and usage tips.

Satisfies the docs-validation CI check that requires README.md to be
updated alongside any server/ or ui/src/ changes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@server/index.ts`:
- Around line 1267-1275: The archive path races because archiveRun() snapshots
the shared RESULTS_PATH (pw-results.json) rather than the per-run output used by
streamSummary; modify archiveRun, and any callers, to accept and archive a
per-run reporter output path derived from runId (e.g., pw-results-{runId}.json)
instead of reading the global RESULTS_PATH, and update streamSummary invocation
sites (where runId is passed) to also pass the same reporter path; ensure
functions/methods named archiveRun, streamSummary and any uses of RESULTS_PATH
are updated to use the per-run path so each run archives its own file
atomically.
- Around line 455-468: playTurn is only passing turnHistory and turnImages into
the initial runCollabTurn call, leaving the critic/refinement/synthesis steps
without chat or image context; update the calls to the downstream functions
(e.g., runCriticTurn, runRefinementTurn, runSynthesisTurn or whatever functions
invoke follow-up turns from playTurn) to accept and forward the same turnHistory
and turnImages parameters so every collaboration turn receives the original chat
history and image attachments; locate the follow-up calls inside playTurn and
add the turnHistory and turnImages arguments (and corresponding parameters on
those functions if needed) so image-based reviews and final synthesis run with
full context.
- Around line 489-490: Guard use of message before calling message.trim(): where
you construct userBlock from message.trim() (the collaboration flow and the
single-agent Ollama/Gemini paths that also call message.trim()), first check
that message is defined and contains non-whitespace (e.g., if (message &&
message.trim().length) ...) and only then build or append userBlock; otherwise
treat it as empty/omit user text so imageAttachments-only requests proceed
without throwing. Update the userBlock construction sites (references:
userBlock, message.trim(), imageAttachments, Ollama, Gemini) to use this guard
and ensure downstream code handles an empty userBlock gracefully.
🪄 Autofix (Beta)

❌ Autofix failed (check again to retry)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 5bd80155-dd57-4608-8750-c627d2297673

📥 Commits

Reviewing files that changed from the base of the PR and between b44ccff and 2a35981.

📒 Files selected for processing (4)
  • CHANGELOG.md
  • README.md
  • server/index.ts
  • ui/src/pages/PlaywrightDashboard.tsx
💤 Files with no reviewable changes (1)
  • CHANGELOG.md

Comment thread server/index.ts
Comment on lines +455 to +468
turnHistory?: HistoryItem[],
turnImages?: ImageAttachment[],
): Promise<string> => {
send({ evt: 'turn_start', agentId: agent.id, agentName: agent.name, role, round, label });
let full = '';
try {
full = await runCollabTurn(apiKey!, model, systemPrompt, userPrompt, (txt) =>
send({ chunk: txt }),
full = await runCollabTurn(
apiKey!,
model,
systemPrompt,
userPrompt,
(txt) => send({ chunk: txt }),
turnHistory,
turnImages,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Forward the original chat context to every collaboration turn.

playTurn can now carry turnHistory and turnImages, but only the initial primary call uses them. The critic, refinement, and synthesis turns still run without the user's prior chat or screenshots, so image-based reviews and the final synthesis are working from incomplete context.

Suggested fix
       const critiqueText = await playTurn(
         critic,
         'critic',
         round,
         `Critique (round ${round})`,
         critic.systemPrompt +
           "\n\nYou are reviewing a peer's draft. Be specific, constructive, and decisive — your goal is to make the final answer the best it can be.",
-        critiquePrompt,
+        critiquePrompt,
+        history,
+        imageAttachments,
       );
@@
       primaryAnswer = await playTurn(
         primary,
         'primary',
         round + 1,
         `Refined response (round ${round + 1})`,
         primary.systemPrompt +
           "\n\nYou are refining your previous draft based on peer feedback. Be focused — incorporate the feedback that's right, push back briefly on anything that's wrong, and produce a stronger answer.",
-        refinePrompt,
+        refinePrompt,
+        history,
+        imageAttachments,
       );
@@
     await playTurn(
       manager,
       'synthesis',
       rounds + 1,
       'Final synthesis',
       manager.systemPrompt +
         "\n\nYou are delivering the team's final answer to the user. Be clear, decisive, and useful.",
-      synthPrompt,
+      synthPrompt,
+      history,
+      imageAttachments,
     );
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@server/index.ts` around lines 455 - 468, playTurn is only passing turnHistory
and turnImages into the initial runCollabTurn call, leaving the
critic/refinement/synthesis steps without chat or image context; update the
calls to the downstream functions (e.g., runCriticTurn, runRefinementTurn,
runSynthesisTurn or whatever functions invoke follow-up turns from playTurn) to
accept and forward the same turnHistory and turnImages parameters so every
collaboration turn receives the original chat history and image attachments;
locate the follow-up calls inside playTurn and add the turnHistory and
turnImages arguments (and corresponding parameters on those functions if needed)
so image-based reviews and final synthesis run with full context.

Comment thread server/index.ts
Comment on lines +489 to +490
history, // forward chat history so prior context is preserved
imageAttachments, // forward image attachments so vision prompts work

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Guard message before trimming in the new image-only flow.

The handler now accepts requests with only imageAttachments, but collaboration still builds userBlock from message.trim() on Line 479, and the single-agent Ollama/Gemini paths do the same on Lines 581 and 664. A screenshot-only prompt will throw before the vision request is sent.

Suggested fix
   const {
     message,
@@
     collaborate = false,
     maxRounds = 2,
   } = req.body as QaAgentBody;
+  const promptText = message?.trim() ?? '';
@@
-  if (!message?.trim() && imageAttachments.length === 0) {
+  if (!promptText && imageAttachments.length === 0) {
     send({ error: 'Body field "message" is required.' });
     res.end();
     return;
   }
@@
-    const userBlock = `# User request\n${message.trim()}\n`;
+    const userBlock = `# User request\n${promptText}\n`;
@@
           content:
-            message.trim() ||
+            promptText ||
             '(image attached — vision not supported by Ollama in this integration)',
@@
-    if (message.trim()) parts.push({ text: message });
+    if (promptText) parts.push({ text: promptText });
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@server/index.ts` around lines 489 - 490, Guard use of message before calling
message.trim(): where you construct userBlock from message.trim() (the
collaboration flow and the single-agent Ollama/Gemini paths that also call
message.trim()), first check that message is defined and contains non-whitespace
(e.g., if (message && message.trim().length) ...) and only then build or append
userBlock; otherwise treat it as empty/omit user text so imageAttachments-only
requests proceed without throwing. Update the userBlock construction sites
(references: userBlock, message.trim(), imageAttachments, Ollama, Gemini) to use
this guard and ensure downstream code handles an empty userBlock gracefully.

Comment thread server/index.ts
Comment on lines +1267 to +1275
await streamSummary(res, {
agentName,
apiKey,
model,
provider,
ollamaBaseUrl,
ollamaModel,
runId: runId ?? undefined,
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical | 🏗️ Heavy lift

runId fixes the read side, but the archive still races on the shared results file.

Both endpoints now pass runId into streamSummary, but archiveRun() still snapshots the single RESULTS_PATH after the child exits. Two overlapping runs can therefore still archive whichever pw-results.json was written last, and the “immutable” summary/history will belong to the wrong run.

Use a per-run reporter output path (or serialize runs) and archive that file directly instead of reading the shared RESULTS_PATH.

Also applies to: 1348-1350, 1604-1612

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@server/index.ts` around lines 1267 - 1275, The archive path races because
archiveRun() snapshots the shared RESULTS_PATH (pw-results.json) rather than the
per-run output used by streamSummary; modify archiveRun, and any callers, to
accept and archive a per-run reporter output path derived from runId (e.g.,
pw-results-{runId}.json) instead of reading the global RESULTS_PATH, and update
streamSummary invocation sites (where runId is passed) to also pass the same
reporter path; ensure functions/methods named archiveRun, streamSummary and any
uses of RESULTS_PATH are updated to use the per-run path so each run archives
its own file atomically.

@coderabbitai

coderabbitai Bot commented May 23, 2026

Copy link
Copy Markdown

Note

Autofix is a beta feature. Expect some limitations and changes as we gather feedback and continue to improve it.

⚠️ Branch updated during autofix.

The branch was updated while autofix was in progress. Please try again.

Rewrote all nine documentation sections in DocsPage to reflect the
current project state. Replaced every Anthropic/Claude reference with
Gemini/Ollama, updated the directory tree, rewrote the env-var section
with dual-provider setup instructions, corrected the tech stack table,
added FAQ entries for provider switching and multi-agent collaboration,
and updated the roadmap to mark completed features as done.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant