E2E findings: 40 fixes across routing, services, MCP, UI#20
Merged
Conversation
Addresses 24 bugs from docs/testing/2026-05-10-e2e-findings.md spanning
routing, APIs, services, and MCP tools. Breakdown:
P0:
- F-001: add /research-projects/[uuid]/page.tsx redirecting to dashboard
- F-002: map InvalidTransitionError to 400 in experiment PATCH route
- F-021: preserve agent-written project_synthesis across refresh
- F-022: dispatch comment_added notifications directly from
commentService.createComment (move out of activity listener to avoid
duplicate + race)
P1:
- F-003/F-005: reject non-realtime autonomousLoopAgentUuid at the
research-project service layer with a typed 400
- F-004: PATCH /api/research-projects/[uuid] returns full GET-shaped
payload (counts, autonomousLoop*, github*, activities)
- F-007/F-029: hide sshKeyName/sshKeySource via compute.service
serializer when managedKeyAvailable; expose keyManagedByServer flag
- F-015: add GET /api/compute-nodes for flat company-scoped listing
- F-023/F-024: plumb createdBy* and assignedBy/assignedAt through
createExperiment + synapse_propose_experiment
- F-028: honor explicit mentions[] array on /api/comments and mention
service (dedupe with content-parsed tokens)
- F-030: synapse_delete_project_group refuses non-empty groups unless
force=true cascades child-project deletes
- F-031: synapse_create_research_project accepts projectGroupUuid
(canonical) in addition to legacy groupUuid
- F-032: synapse_create_research_question accepts optional parentUuid
- F-033: synapse_create_baseline metrics accept number | string |
nested record
- F-034: synapse_compare_results accepts per-metric maps per experiment
- F-035: research-question MCP status enum aligned with platform
vocabulary (open/in_progress/to_verify/done/closed) while keeping
legacy aliases
- F-046: content-equality short-circuit in refreshProjectSynthesis
P2:
- F-020: tighten researchQuestionUuid with z.string().uuid()
- F-036: synapse_update_experiment_plan accepts plan alias for description
- F-038: deep research reports stored as document type 'deep_research'
- F-041: synapse_list_baselines returns {baselines:[...]} wrapper
Test updates:
- experiments-route + research-projects-route: align mocks with new
shapes and use valid-format UUIDs
- comment.service + notification-listener: reflect moved dispatch
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Addresses a second batch of 15 findings from docs/testing/2026-05-10-e2e-findings.md on top of 9a8b29f. P1: - F-006: createAgent now resolves color to a deterministic palette entry derived from the agent name when no explicit color is supplied, so openclaw agents like Haru get a consistent pill on the board - F-008: new Autonomous Loop and Auto Search cards in Project Settings with realtime-only agent picker, enable switch, and loop mode select. 20 new i18n keys in en + zh. - F-009: locale-context calls router.refresh() after writing the locale cookie so Server Components re-render with the new locale - F-010: experiments board reacts to ?selected=<uuid> URL changes and strips the param from the URL when the detail Sheet closes - F-025: read_paper_brief / read_paper_head fall back to arXiv Atom export when DeepXiv responds not-found (auth/5xx still surface) - F-037: remove synapse_verify_reproducibility MCP tool; underlying service kept for legacy /api/experiment-runs route - F-039: confirmed synapse_search references already cleaned from CLAUDE.md + agent-working-guide (nothing to do) P2: - F-017: notification/realtime SSE contexts guard against reconnect race on unmount via isUnmounting flag; onerror comments clarify aborts-during-teardown are expected native network-layer messages - F-026: listComments attaches a resolved mentions[] summary per comment; mention-renderer rewrites plain-text @handle tokens into canonical @[Name](type:uuid) markup before chip rendering, so API-created comments render the same as UI-typeahead comments - F-027: autonomous-loop wake prompt and get_project_full_context hint enumerate one-independent-run-per-card and split sweeps/ablations/ repeated-trials/comparisons into separate cards - F-040: rename stale synapse_pi_* comment stubs in pi.ts to the registered tool names - F-042: synapse_create_project_group returns projects: [] and synapse_update_project_group re-fetches via getProjectGroup so all three group tools return the same shape - F-044: experiment-designs POST error messages now name the missing or invalid field and echo the bad value - F-045: confirmed project-group service already selects only minimal project fields (nothing to do) Confirmed as already fixed in earlier commits (no new code): - F-011: onboarding honors ?force=1 (fixed in 862a999) - F-018: route loading.tsx renders DashboardRouteSkeleton with board placeholders (fixed in c253064); residual "Loading..." is from the dashboard layout's session gate, outside board scope - F-019: agent-activity service already filters experiment counts by researchProjectUuid Test updates: - paper-search: added 4 F-025 fallback tests - agent.service: updated createAgent default-color assertion + added explicit-color-preservation test + fixed pre-existing listAgentSummaries mock-vs-select drift - comment.service: added prisma.mention.findMany mock + default Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…nfigured End-to-end retest on synapse-test exposed that DeepXiv returns 401 for unauthenticated requests, not 404 as assumed. The anonymous "1000 req/day" path requires a token too. Agent J's original condition only covered 404 and error payloads matching "not found", so the fallback never fired on deployments without a DeepXiv token. Tightened deepxivIsNotFound to also accept 401/403 (and token-required payloads) when no token is configured, while still surfacing real auth failures when a token IS configured (misconfiguration remains visible). deepxivGet now returns whether the request was authenticated; the two consumers pass that through to the classifier. Tests: split the 401 assertion into "falls back when unauthenticated" and "does not fall back when a token is configured". Both pass. Added env stub reset in beforeEach/afterEach to prevent cross-test pollution. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes 40 findings from the 2026-05-10 E2E test pass (
docs/testing/2026-05-10-e2e-findings.md). Three commits, organized by round and code domain:9a8b29fa— Round 1: backend correctness (routing, PATCH, synthesis preservation, comment notifications, MCP schemas, compute SSH key leak)f83ff195— Round 2: UI, locale, MCP cleanup, paper-search fallback, E2E-confirmed "already-fixed" verifications0c5d919a— F-025 hotfix found in end-to-end retest (unauth 401 now triggers fallback)Findings fixed
P0
/research-projects/{uuid}now redirects to./dashboardinstead of 404refreshProjectSynthesisno longer clobbers agent-written synthesis whencompletedIdeasis empty — preserves the document andlatestSynthesis*summary fields/api/commentsnow dispatchescomment_addednotifications for the target assignee and creator (moved out of the activity listener to avoid double-delivery and races)synapse_delete_project_grouprefuses non-empty groups unlessforce=truecascade-deletes childrenP1
updateResearchProjectrejectsautonomousLoopAgentUuidpointing at a non-realtime (poll) agent with a typed 400PATCH /api/research-projects/[uuid]returns the full GET-shaped payload (counts, autonomousLoop*, github*, activities)createAgentassigns a deterministic palette color when none is provided; null colors fall back at render timesshKeyName/sshKeySourcewhenmanagedKeyAvailable=trueand exposeskeyManagedByServerfor UIrouter.refresh()after cookie write so Server Components re-render with the new locale?selected=<uuid>URL changes and strips the param on Sheet closeGET /api/compute-nodesreturns a flat company-scoped list (was 405)synapse_propose_experimentnow stampscreatedBy*andassignedAt/assignedByon auto-proposed experimentsread_paper_brief/read_paper_headfall back to the public arXiv Atom API when DeepXiv cannot answer (not-found, or unauthenticated 401/403 without a token); real auth misconfig still surfacessynapse_create_research_projectacceptsprojectGroupUuid(canonical) in addition togroupUuid(alias)synapse_create_research_questionaccepts optionalparentUuidso agents can build hierarchiesmetricsaccept mixed number / string / nested recordsynapse_compare_resultsacceptsRecord<exp, Record<metric, number>>; returns per-metric deltasopen/in_progress/to_verify/done/closed) with legacy aliasessynapse_verify_reproducibilityMCP tool removed (legacy ExperimentRegistry flow; underlying service kept for legacy REST route)P2
isUnmounting; comments clarify that nativenet::ERR_ABORTEDis unsuppressable from JSresearchQuestionUuidon experiments POST/PATCH tightened toz.string().uuid()listCommentsattaches a resolvedmentions[]summary per comment;mention-rendererrewrites plain-text@handletokens into canonical chips so API-written comments match UI-typeahead onesget_project_full_contexthint explicitly enumerate "one independent run per card; split sweeps/ablations/repeated trials/comparisons"synapse_update_experiment_planacceptsplanas an alias fordescriptiondeep_research(new writes; existing rows keep their prior type)synapse_pi_*comment stubs inpi.tsrenamed to registered tool namessynapse_list_baselinesreturns{baselines: [...]}wrappercreate_project_groupreturnsprojects: [];update_project_groupre-fetches viagetProjectGroupso all three tools return the same shapeVerified already-fixed on branch (no new code)
/onboarding?force=1is honored (commit862a9999)loading.tsxalready rendersDashboardRouteSkeletonresearchProjectUuidsynapse_searchreferences already cleaned from CLAUDE.md / agent-working-guideproject-group.servicealready selects only minimal project fieldsOut of scope (not in this PR)
F-012/F-013/F-014 OpenClaw external machine config, F-016 onboarding RSC abort chain, F-043 hypothesis-formulation MCP surface (large new tool family), F-046 hash-based debounce.
Test plan
pnpm exec tsc --noEmit— 2 pre-existing errors only (unrelated to this PR)pnpm test— 1299 pass / 6 fail; fails are pre-existing mock/select drift inuuid-resolver,research-project.service,agent.servicetests (confirmed unchanged vs.mainbaseline)synapse-test— docker image rebuilt, 25 findings verified via API / MCP / Playwright browser?selected=deep link opens detail Sheet; zh locale switch renders Chinese Server Components on first navigationArtifacts
Retest screenshots under
docs/testing/2026-05-10-e2e-screenshots/retest-*.png(Settings Loop card, deep-link detail panel).