Skip to content

chore(repo): consolidate committed agent skills under .agents/skills and publish four local skills - #5558

Merged
mmabrouk merged 3 commits into
release/v0.106.1from
chore/skills-repo-sync
Jul 29, 2026
Merged

chore(repo): consolidate committed agent skills under .agents/skills and publish four local skills#5558
mmabrouk merged 3 commits into
release/v0.106.1from
chore/skills-repo-sync

Conversation

@mmabrouk

Copy link
Copy Markdown
Member

Why

The committed agent skills were split across two conventions. Six lived in .agents/skills (the tool-agnostic location that AGENTS.md documents), while five others (add-announcement, create-changelog-announcement, update-api-docs, update-llm-model-list, write-social-announcement) lived only in .claude/skills, so only Claude Code could discover them. sync-model-catalog had no .claude symlink at all. On top of that, the .gitignore allowlist only named 2 of the 11 tracked skills; the other 9 stayed tracked by accident of history, which made git add on them behave confusingly for anyone without the files already in their index.

What changed

  • One convention everywhere: every committed skill now lives in .agents/skills/<name>/ with a symlink at .claude/skills/<name>. The five .claude-native skills moved (git tracks them as 100% renames, history preserved), and sync-model-catalog got its missing symlink.
  • Four previously local-only skills are now committed: write-issue, implement-feature, plan-feature, and style-editing. They were scanned for machine-specific details (IPs, hostnames, credentials) before publishing; each is a single self-contained SKILL.md.
  • The .gitignore allowlist now matches reality: all 15 committed skills are explicitly un-ignored in both directories, so the ignore rules describe exactly what is tracked. Everything else under both skill directories stays local-only by default, as before.

Verification

  • git diff --name-status main..chore/skills-repo-sync contains exactly the 5 renames, 4 new skills, 10 new symlinks, and the .gitignore edit; nothing else.
  • All 15 .claude/skills/<name>/SKILL.md paths resolve through their symlinks on disk.
  • git check-ignore confirms no committed path is ignored and the local-only skills remain ignored.

https://claude.ai/code/session_01KFiHhzfjyGZ95fU7FGw5Mb

mmabrouk added 3 commits July 29, 2026 21:14
…and publish four local skills

Move the five committed .claude-native skills to .agents/skills, publish
write-issue, implement-feature, plan-feature, and style-editing, and make the
.gitignore allowlist match the full tracked set. The .claude symlinks for
these skills land in the follow-up commit.

Claude-Session: https://claude.ai/code/session_01KFiHhzfjyGZ95fU7FGw5Mb
@dosubot dosubot Bot added the size:XL This PR changes 500-999 lines, ignoring generated files. label Jul 29, 2026
@vercel

vercel Bot commented Jul 29, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
agenta-documentation Ready Ready Preview, Comment Jul 29, 2026 7:17pm

Request Review

@coderabbitai

coderabbitai Bot commented Jul 29, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This PR adds agent workflow skills, updates API and runner safeguards, introduces voice and attachment features, adds parked connection interactions, simplifies navigation, migrates table consumers to shared packages, and updates canonical tracing, evaluation, and deployment contracts.

Changes

Agent skills and documentation

Layer / File(s) Summary
Skill specifications and wiring
.agents/skills/*, .claude/skills/*, .gitignore, .gitleaksignore
Adds workflow skill documents, Claude symlinks, expanded ignore exceptions, and scanner suppressions.

Platform and runner

Layer / File(s) Summary
Routing and archive handling
api/entrypoints/routers.py, api/oss/src/middlewares/prefix.py, api/oss/src/core/mounts/service.py
Adds route-aware path normalization, disables automatic slash redirects, and resolves ZIP namespace conflicts and reserved artifacts.
Runner safeguards
services/runner/src/env.ts, services/runner/src/sessions/*, services/runner/src/engines/sandbox_agent/run-limits.ts
Adds bounded numeric environment parsing, timer limits, query timeouts, retry caps, and durable-log drop warnings.
Release configuration
api/pyproject.toml, services/runner/package.json, web/package.json, hosting/kubernetes/helm/Chart.yaml, web/*/package.json
Updates package/chart versions, selected dependencies, CSS declarations, aliases, and type-check scripts.

Navigation and settings

Layer / File(s) Summary
Simplified navigation
web/oss/src/lib/onboarding/*, web/oss/src/state/onboarding/*, web/oss/src/components/Sidebar/*, docs/design/simplify-nav-new-users/*
Adds persisted simplified-navigation defaults and overrides, hides advanced sidebar entries, and documents the two-phase behavior.
Settings and onboarding surfaces
web/oss/src/components/pages/settings/*, web/oss/src/pages/*/settings/index.tsx, web/oss/src/hooks/usePostAuthRedirect.ts, web/oss/src/components/pages/agents/*
Adds scoped settings sections, feature flags, organization controls, first-run query handling, and playground-first agent navigation.

Agent chat and shared UI

Layer / File(s) Summary
Voice, attachments, and drive uploads
web/oss/src/components/AgentChatSlice/*, web/oss/src/components/Drives/*, web/packages/agenta-ui/src/RichChatInput/*
Adds speech input, recording and playback, attachment validation, staged files, local previews, drag-and-drop uploads, and upload progress/retry UI.
Parked connection flow
web/oss/src/components/AgentChatSlice/components/clientTools/*, web/oss/src/components/AgentChatSlice/components/InteractionDock.tsx
Extracts OAuth connection state into useConnectFlow and moves actionable parked interactions into an animated dock.
Shared table and entity contracts
web/oss/src/components/EvalRunDetails/*, web/oss/src/components/EvaluationRunsTablePOC/*, web/oss/src/components/InfiniteVirtualTable/*, web/packages/agenta-entities/*, web/packages/agenta-ui/src/InfiniteVirtualTable/*
Migrates table consumers to @agenta/ui/table, removes the local implementation, and aligns evaluation and tracing types with canonical entity contracts.

Estimated code review effort: 5 (Critical) | ~120 minutes

Possibly related PRs

  • Agenta-AI/agenta#5557 — Overlaps on API route normalization and mount archive namespace handling.
  • Agenta-AI/agenta#5521 — Overlaps on parked connection interactions, InteractionDock, and held queued messages.
  • Agenta-AI/agenta#5471 — Overlaps on migrating InfiniteVirtualTable consumers to shared table exports.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 38.30% which is insufficient. The required threshold is 60.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
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.
Title check ✅ Passed The title accurately summarizes the main changes: consolidating agent skills under .agents/skills and publishing four local skills.
Description check ✅ Passed The description is clearly related and matches the changeset, including skill consolidation, symlinks, new skills, and .gitignore updates.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/skills-repo-sync

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@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: 17

Note

Due to the large number of review comments, Critical, Major severity comments were prioritized as inline comments.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
web/oss/src/components/AgentChatSlice/components/clientTools/ConnectToolWidget.tsx (1)

63-108: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Show manual-retry errors before the settled-result branch.

A manual retry happens after meta.settled is already true, so Line 64 returns the generic “Connection not completed” chip before Line 99 can render errorText. Move the phase === "error" branch above the settled check.

Proposed fix
+    if (phase === "error") {
+        return (
+            <ChipRow icon={<Warning size={13} weight="fill" className="text-colorError" />}>
+                <Text type="danger" className="!text-xs truncate" title={errorText ?? undefined}>
+                    {errorText ?? "Connection failed."}
+                </Text>
+                <RetryButton onClick={() => runConnect(false)} />
+            </ChipRow>
+        )
+    }
+
     if (meta.settled || outcome) {
web/oss/src/components/pages/observability/components/StatusRenderer.tsx (1)

5-18: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Do not render unset statuses as success.

When status is null or undefined, the renderer passes "STATUS_CODE_UNSET", but statusMapper falls through to its success mapping for every non-error value. Add an explicit neutral/unset mapping and reserve success for an actual success status.

Also applies to: 28-34

🟡 Minor comments (9)
.agents/skills/update-api-docs/SKILL.md-68-68 (1)

68-68: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Renumber the verification step.

The workflow jumps from Step 2 to Step 5. Rename this to Step 3 or restore the missing steps so the instructions are sequential.

.agents/skills/create-changelog-announcement/SKILL.md-311-317 (1)

311-317: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Use a Discussion-specific close flow.

githubUrl can point to a GitHub discussion, but gh issue close targets issues/PRs. Add a check for the discussion path and direct CLI users to the GitHub Discussions interface or a GraphQL closeDiscussion call instead.

.agents/skills/write-social-announcement/SKILL.md-14-21 (1)

14-21: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Remove the contradictory “key benefit” wording.

The skill forbids key as an adjective but later requires a “key benefit.” Use “main benefit” or “user benefit” instead.

Also applies to: 137-143

web/oss/src/pages/w/[workspace_id]/p/[project_id]/settings/index.tsx-121-138 (1)

121-138: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Raw --ag-c-* CSS variable literal for the demo badge.

bg-[var(--ag-c-0517290F)] uses a raw --ag-c-* literal instead of a supported theme token. As per coding guidelines, web/**/*.{ts,tsx} files must "Consume theme colors through Ant Design semantic tokens, Tailwind color utilities, or supported var(--ag-color*) variables; do not use raw hex colors or --ag-c-* literals." This also risks not adapting correctly between light/dark themes.

#!/bin/bash
# Check whether --ag-c-0517290F (or similar --ag-c- literals) are used elsewhere / have a sanctioned semantic token equivalent.
rg -n '\-\-ag-c-' --type=ts --type=tsx --type=css -g '!**/theme-variables.css' 2>/dev/null

Source: Coding guidelines

docs/design/simplify-nav-new-users/context.md-89-90 (1)

89-90: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Broken list formatting for criteria 6–8.

Items 6, 7, 8 and the "Phase 2" heading are run together on two lines with no breaks, unlike items 1–5 which are each on their own line. This will render as a run-on paragraph instead of a continued numbered list.

📝 Proposed fix
-**Phase 2** 6. The Settings → Feature flags switch flips the effective mode and survives a
-reload. 7. Toggling the switch updates the sidebar without a full page reload. 8. Phase 1's sidebar behavior is unchanged when no override is set.
+**Phase 2**
+
+6. The Settings → Feature flags switch flips the effective mode and survives a reload.
+7. Toggling the switch updates the sidebar without a full page reload.
+8. Phase 1's sidebar behavior is unchanged when no override is set.
web/oss/src/components/Drives/useDriveDrop.ts-58-87 (1)

58-87: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

dragleave decrements for non-file drags and the spring timer outlives unmount.

Two small asymmetries in this effect:

  • onEnter only counts file drags, but onLeave decrements on every dragleave, so a text drag crossing the window can zero the depth and clear dragging while a file drag is still active.
  • The cleanup removes listeners but never calls clearSpring(), so a pending 700ms spring-load fires onNavigate after unmount.
🛡️ Proposed fix
-        const onLeave = () => {
+        const onLeave = (e: DragEvent) => {
+            if (!has(e)) return
             depth.current = Math.max(0, depth.current - 1)
             if (depth.current === 0) setDragging(false)
         }
@@
         return () => {
             window.removeEventListener("dragenter", onEnter)
             window.removeEventListener("dragleave", onLeave)
             window.removeEventListener("drop", onEnd)
             window.removeEventListener("dragend", onEnd)
+            clearSpring()
         }
web/oss/src/components/AgentChatSlice/components/RecordingBar.tsx-66-88 (1)

66-88: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Live region wraps a per-second clock, so AT re-announces every tick.

role="status" aria-live="polite" on the container includes mmss(seconds), which changes once a second. Keep the live region for state changes only and mark the timer text as aria-hidden (or move aria-live to a dedicated node).

web/oss/src/components/AgentChatSlice/hooks/useAudioRecorder.ts-138-146 (1)

138-146: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Re-entrancy gap while permission is pending.

recRef.current is still null during "requesting", so a second start() before the prompt resolves issues another getUserMedia; the first resolved stream then leaks (only the last one is stored in streamRef). Callers currently disable the button on pending, but the hook shouldn't rely on that.

🛡️ Proposed guard
     const start = useCallback(() => {
-        if (!supported || recRef.current) return
+        if (!supported || recRef.current || startingRef.current) return
+        startingRef.current = true
         setError(null)

Reset startingRef.current = false in both the .then and .catch paths (and in teardown).

web/oss/src/components/Drives/driveFileSource.tsx-42-49 (1)

42-49: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Key local preview state by the selected file. Switching between staged files can reuse state from the prior file: a prior decode error makes the next media file fail immediately, and prior text can render while the next file is loading.

  • web/oss/src/components/Drives/driveFileSource.tsx#L42-L49: store the failed object URL/path rather than a shared boolean, or reset failure state when the local source changes.
  • web/oss/src/components/Drives/driveFileSource.tsx#L72-L85: clear text for a new local source and ignore completions from superseded reads.
🧹 Nitpick comments (11)
web/oss/src/lib/helpers/dynamicEnv.ts (1)

36-48: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Keep these feature-flag comments to one line.

Collapse the UI behavior descriptions into concise constraints; place extended rollout details in documentation. As per coding guidelines, “Keep in-code comments to at most one short line; use longer comments only for genuinely surprising constraints such as bugs, races, or ordering requirements.”

Source: Coding guidelines

web/packages/agenta-shared/package.json (1)

32-32: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

peerDependencies.axios floor not bumped to match the sibling packages.

dependencies.axios was bumped to 1.18.0 here, but peerDependencies.axios (Line 49) is still >=1.13.5 <2.0.0 — unlike agenta-entities and agenta-entity-ui, whose peer floors were both raised to >=1.18.0 in this same change. A consumer could satisfy this package's declared peer contract with a much older, vulnerable axios. The workspace-level pnpm.overrides.axios: "1.18.0" masks the practical impact today, but the manifest is inconsistent with the rest of this bump.

♻️ Proposed fix
     "peerDependencies": {
         "`@tanstack/react-query`": ">=5.0.0",
-        "axios": ">=1.13.5 <2.0.0",
+        "axios": ">=1.18.0 <2.0.0",
         "jotai": ">=2.0.0",

Also applies to: 47-53

web/oss/next.config.ts (1)

139-144: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Add a production regression check for refractor/all.

The fix depends on webpack preserving react-syntax-highlighter’s dynamic refractor/all import. Add a production build/render test for a PrismAsync code block so this IgnorePlugin rule cannot regress silently.

web/oss/src/components/AgentChatSlice/AgentConversation.tsx (1)

1722-1749: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicated attachment-key formula between toUploadFile and uploads.enqueue.

The uid string ${name}-${lastModified}-${size} is built twice; if useAttachmentUploads ever keys items differently, enqueue silently matches nothing. Extract one helper (attachmentUid(file)) used by both.

♻️ Suggested extraction
+const attachmentUid = (file: File) => `${file.name}-${file.lastModified}-${file.size}`
+
 const toUploadFile = (file: File): UploadFile => ({
-        uid: `${file.name}-${file.lastModified}-${file.size}`,
+        uid: attachmentUid(file),
         name: file.name,
         status: "done",
         originFileObj: file as UploadFile["originFileObj"],
     })
@@
-            uploads.enqueue(accepted.map((f) => `${f.name}-${f.lastModified}-${f.size}`))
+            uploads.enqueue(accepted.map(attachmentUid))
web/oss/src/components/Drives/DriveExplorer.tsx (2)

1866-1885: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Index-based staged ids reshuffle on removal.

id: ${i}-${f.name} changes for every item after a removal, so the synthetic tile keys (__staged__/${id}) all change and the surviving tiles remount (losing their fade/scale state). fileKey(f) is already imported and is stable per file.

♻️ Proposed change
             staged.map((f, i) => ({
-                id: `${i}-${f.name}`,
+                id: fileKey(f),
                 name: f.name,

1727-1733: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Double cast hides the shape mismatch.

{path, size} as unknown as MountFile silences the compiler for injected upload nodes. If MountFile has additional required fields, prefer a narrowed helper type (e.g. Pick<MountFile, "path" | "size"> widened at the buildDriveTree boundary) or make those fields optional, so a future field addition surfaces here.

web/oss/src/components/Drives/useDriveDrop.ts (1)

170-194: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

useStageDrop highlight flickers across child elements.

Unlike useDriveDrop, this has no depth counter: onDragLeave fires when the cursor crosses any child of the rail/aside, so dropActive toggles off mid-drag. A depth ref (or checking e.currentTarget.contains(e.relatedTarget as Node)) keeps the tint steady.

web/oss/src/components/AgentChatSlice/components/AudioPlayer.tsx (1)

28-34: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low value

Reset duration/current on src change.

The src effect resets probingRef but leaves the previous clip's duration/current in state, so the timer and progress bar briefly show the old clip's values (and a wrong ratio) until loadedmetadata fires.

♻️ Proposed tweak
         probingRef.current = false
+        setDuration(0)
+        setCurrent(0)
web/oss/src/components/AgentChatSlice/components/RecordingBar.tsx (1)

38-48: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low value

rAF loop for a once-per-second clock.

The frame loop runs ~60×/s to publish a value that changes 1×/s. An interval (e.g. 250 ms) derived from startedAtRef keeps the no-drift property at a fraction of the wakeups.

web/oss/src/components/AgentChatSlice/components/RecordingWaveform.tsx (1)

25-29: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low value

parseRgb assumes an rgb()/rgba() computed color.

If the theme token resolves to a modern color space (oklch(...), color(srgb …)), the digit scan yields nonsense channels or the [0,0,0] fallback — an invisible waveform in dark mode. Consider falling back to currentColor fill with per-stop globalAlpha instead of reconstructing channels.

Also applies to: 53-66

web/packages/agenta-ui/src/RichChatInput/ComposerSendButton.tsx (1)

34-38: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Replace raw hex colors with semantic theme tokens.

The #191a0d and #b8cb3f values will not adapt with the supported theme system. Use Ant semantic tokens, Tailwind semantic utilities, or supported --ag-color* variables instead.

As per coding guidelines, “Consume theme colors through Ant Design semantic tokens, Tailwind color utilities, or supported var(--ag-color*) variables; do not use raw hex colors.”

Source: Coding guidelines


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 03599dc8-8972-4f8a-a39e-60b25ef11bbc

📥 Commits

Reviewing files that changed from the base of the PR and between 56be600 and 1c7e42b.

⛔ Files ignored due to path filters (6)
  • api/uv.lock is excluded by !**/*.lock
  • clients/python/uv.lock is excluded by !**/*.lock
  • sdks/python/uv.lock is excluded by !**/*.lock
  • services/runner/pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
  • services/uv.lock is excluded by !**/*.lock
  • web/pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (246)
  • .agents/skills/add-announcement/SKILL.md
  • .agents/skills/create-changelog-announcement/SKILL.md
  • .agents/skills/implement-feature/SKILL.md
  • .agents/skills/plan-feature/SKILL.md
  • .agents/skills/style-editing/SKILL.md
  • .agents/skills/update-api-docs/SKILL.md
  • .agents/skills/update-llm-model-list/SKILL.md
  • .agents/skills/write-issue/SKILL.md
  • .agents/skills/write-social-announcement/SKILL.md
  • .claude/skills/add-announcement
  • .claude/skills/create-changelog-announcement
  • .claude/skills/implement-feature
  • .claude/skills/plan-feature
  • .claude/skills/style-editing
  • .claude/skills/sync-model-catalog
  • .claude/skills/update-api-docs
  • .claude/skills/update-llm-model-list
  • .claude/skills/write-issue
  • .claude/skills/write-social-announcement
  • .gitignore
  • .gitleaksignore
  • api/entrypoints/routers.py
  • api/oss/src/core/mounts/service.py
  • api/oss/src/middlewares/prefix.py
  • api/oss/tests/pytest/unit/middlewares/test_prefix.py
  • api/oss/tests/pytest/unit/test_mounts_file_ops.py
  • api/pyproject.toml
  • clients/python/pyproject.toml
  • docs/design/simplify-nav-new-users/README.md
  • docs/design/simplify-nav-new-users/context.md
  • docs/design/simplify-nav-new-users/plan.md
  • docs/design/simplify-nav-new-users/research.md
  • docs/design/simplify-nav-new-users/status.md
  • hosting/kubernetes/helm/Chart.yaml
  • sdks/python/pyproject.toml
  • services/pyproject.toml
  • services/runner/package.json
  • services/runner/src/engines/sandbox_agent/run-limits.ts
  • services/runner/src/env.ts
  • services/runner/src/sessions/persist.ts
  • services/runner/src/sessions/records-query.ts
  • services/runner/tests/unit/env-num.test.ts
  • services/runner/tests/unit/run-limits.test.ts
  • services/runner/tests/unit/session-persist.test.ts
  • services/runner/tests/unit/session-records-query.test.ts
  • web/ee/css-modules.d.ts
  • web/ee/package.json
  • web/ee/tsconfig.json
  • web/oss/css-modules.d.ts
  • web/oss/next.config.ts
  • web/oss/package.json
  • web/oss/src/components/AgentChatSlice/AgentConversation.tsx
  • web/oss/src/components/AgentChatSlice/assets/attachments.ts
  • web/oss/src/components/AgentChatSlice/assets/constants.ts
  • web/oss/src/components/AgentChatSlice/assets/markdown.tsx
  • web/oss/src/components/AgentChatSlice/components/AgentMessage.tsx
  • web/oss/src/components/AgentChatSlice/components/AttachmentViewerDrawer.tsx
  • web/oss/src/components/AgentChatSlice/components/AudioPlayer.tsx
  • web/oss/src/components/AgentChatSlice/components/ComposerAttachments.tsx
  • web/oss/src/components/AgentChatSlice/components/ConnectModelBanner.tsx
  • web/oss/src/components/AgentChatSlice/components/Inspector/InspectSessionButton.tsx
  • web/oss/src/components/AgentChatSlice/components/InteractionDock.tsx
  • web/oss/src/components/AgentChatSlice/components/MicPermissionNotice.tsx
  • web/oss/src/components/AgentChatSlice/components/QueuedMessages.tsx
  • web/oss/src/components/AgentChatSlice/components/RecordingBar.tsx
  • web/oss/src/components/AgentChatSlice/components/RecordingWaveform.tsx
  • web/oss/src/components/AgentChatSlice/components/ToolActivity.tsx
  • web/oss/src/components/AgentChatSlice/components/VoiceInputButton.tsx
  • web/oss/src/components/AgentChatSlice/components/clientTools/ConnectToolWidget.tsx
  • web/oss/src/components/AgentChatSlice/components/clientTools/useConnectFlow.ts
  • web/oss/src/components/AgentChatSlice/hooks/useAttachmentUploads.ts
  • web/oss/src/components/AgentChatSlice/hooks/useAudioRecorder.ts
  • web/oss/src/components/AgentChatSlice/hooks/useVoiceInput.ts
  • web/oss/src/components/Drives/ContextRail.tsx
  • web/oss/src/components/Drives/DriveExplorer.tsx
  • web/oss/src/components/Drives/FilesDrawer.tsx
  • web/oss/src/components/Drives/SessionFilesDrawer.tsx
  • web/oss/src/components/Drives/StorageFilesHeader.tsx
  • web/oss/src/components/Drives/StorageSection.tsx
  • web/oss/src/components/Drives/VirtualTileGrid.tsx
  • web/oss/src/components/Drives/configDrive.ts
  • web/oss/src/components/Drives/driveFileSource.tsx
  • web/oss/src/components/Drives/driveMedia.ts
  • web/oss/src/components/Drives/renderers.tsx
  • web/oss/src/components/Drives/useDriveDrop.ts
  • web/oss/src/components/Drives/useImagePreviews.ts
  • web/oss/src/components/Drives/useMountUpload.ts
  • web/oss/src/components/Drives/useSessionDrive.ts
  • web/oss/src/components/EvalRunDetails/Table.tsx
  • web/oss/src/components/EvalRunDetails/atoms/table/run.ts
  • web/oss/src/components/EvalRunDetails/atoms/traces.ts
  • web/oss/src/components/EvalRunDetails/components/CompareRunsMenu.tsx
  • web/oss/src/components/EvalRunDetails/components/EvalTestcaseDrawerAdapter/index.tsx
  • web/oss/src/components/EvalRunDetails/components/FocusDrawerHeader.tsx
  • web/oss/src/components/EvalRunDetails/components/FocusDrawerSidePanel.tsx
  • web/oss/src/components/EvalRunDetails/components/columnVisibility/ColumnVisibilityPopoverContent.tsx
  • web/oss/src/components/EvalRunDetails/components/views/SingleScenarioViewerPOC/ScenarioNavigator.tsx
  • web/oss/src/components/EvalRunDetails/components/views/SingleScenarioViewerPOC/index.tsx
  • web/oss/src/components/EvalRunDetails/evaluationPreviewTableStore.ts
  • web/oss/src/components/EvalRunDetails/hooks/useCellVisibility.ts
  • web/oss/src/components/EvalRunDetails/hooks/usePreviewColumns.tsx
  • web/oss/src/components/EvalRunDetails/utils/buildPreviewColumns.tsx
  • web/oss/src/components/EvaluationRunsTablePOC/atoms/fetchAutoEvaluationRuns.ts
  • web/oss/src/components/EvaluationRunsTablePOC/atoms/tableStore.ts
  • web/oss/src/components/EvaluationRunsTablePOC/components/EvaluationRunsTable/index.tsx
  • web/oss/src/components/EvaluationRunsTablePOC/components/EvaluationRunsTable/types.ts
  • web/oss/src/components/EvaluationRunsTablePOC/components/columnVisibility/ColumnVisibilityPopoverContent.tsx
  • web/oss/src/components/EvaluationRunsTablePOC/components/filters/EvaluationRunsHeaderFilters.tsx
  • web/oss/src/components/EvaluationRunsTablePOC/hooks/useEvaluationRunsColumns/index.tsx
  • web/oss/src/components/EvaluationRunsTablePOC/hooks/useEvaluationRunsColumns/utils.tsx
  • web/oss/src/components/EvaluationRunsTablePOC/hooks/useEvaluatorHeaderReference.ts
  • web/oss/src/components/EvaluationRunsTablePOC/types.ts
  • web/oss/src/components/InfiniteVirtualTable/InfiniteVirtualTable.tsx
  • web/oss/src/components/InfiniteVirtualTable/atoms/columnHiddenKeys.ts
  • web/oss/src/components/InfiniteVirtualTable/atoms/columnVisibility.ts
  • web/oss/src/components/InfiniteVirtualTable/atoms/columnWidths.ts
  • web/oss/src/components/InfiniteVirtualTable/columns/cells.tsx
  • web/oss/src/components/InfiniteVirtualTable/columns/createStandardColumns.tsx
  • web/oss/src/components/InfiniteVirtualTable/columns/createTableColumns.ts
  • web/oss/src/components/InfiniteVirtualTable/columns/types.ts
  • web/oss/src/components/InfiniteVirtualTable/components/ColumnVisibilityHeader.tsx
  • web/oss/src/components/InfiniteVirtualTable/components/ColumnVisibilityTrigger.tsx
  • web/oss/src/components/InfiniteVirtualTable/components/InfiniteVirtualTableInner.tsx
  • web/oss/src/components/InfiniteVirtualTable/components/TableDescription.tsx
  • web/oss/src/components/InfiniteVirtualTable/components/TableShell.tsx
  • web/oss/src/components/InfiniteVirtualTable/components/columnVisibility/ColumnVisibilityMenuTrigger.tsx
  • web/oss/src/components/InfiniteVirtualTable/components/columnVisibility/ColumnVisibilityPopoverContent.tsx
  • web/oss/src/components/InfiniteVirtualTable/components/columnVisibility/TableSettingsDropdown.tsx
  • web/oss/src/components/InfiniteVirtualTable/components/filters/FiltersPopoverTrigger.tsx
  • web/oss/src/components/InfiniteVirtualTable/context/ColumnVisibilityContext.ts
  • web/oss/src/components/InfiniteVirtualTable/context/ColumnVisibilityFlagContext.tsx
  • web/oss/src/components/InfiniteVirtualTable/context/VirtualTableScrollContainerContext.ts
  • web/oss/src/components/InfiniteVirtualTable/createInfiniteDatasetStore.ts
  • web/oss/src/components/InfiniteVirtualTable/createInfiniteTableStore.ts
  • web/oss/src/components/InfiniteVirtualTable/features/InfiniteVirtualTableFeatureShell.tsx
  • web/oss/src/components/InfiniteVirtualTable/features/index.ts
  • web/oss/src/components/InfiniteVirtualTable/features/useInfiniteTableFeaturePagination.ts
  • web/oss/src/components/InfiniteVirtualTable/helpers/createSimpleTableStore.ts
  • web/oss/src/components/InfiniteVirtualTable/helpers/createTableRowHelpers.ts
  • web/oss/src/components/InfiniteVirtualTable/helpers/index.ts
  • web/oss/src/components/InfiniteVirtualTable/hooks/useColumnDomRefs.ts
  • web/oss/src/components/InfiniteVirtualTable/hooks/useColumnVisibility.ts
  • web/oss/src/components/InfiniteVirtualTable/hooks/useColumnVisibilityControls.ts
  • web/oss/src/components/InfiniteVirtualTable/hooks/useContainerResize.ts
  • web/oss/src/components/InfiniteVirtualTable/hooks/useContainerSize.ts
  • web/oss/src/components/InfiniteVirtualTable/hooks/useEditableTable.ts
  • web/oss/src/components/InfiniteVirtualTable/hooks/useExpandableRows.tsx
  • web/oss/src/components/InfiniteVirtualTable/hooks/useHeaderViewportVisibility.ts
  • web/oss/src/components/InfiniteVirtualTable/hooks/useInfiniteScroll.ts
  • web/oss/src/components/InfiniteVirtualTable/hooks/useInfiniteTablePagination.ts
  • web/oss/src/components/InfiniteVirtualTable/hooks/useResizableColumns.ts
  • web/oss/src/components/InfiniteVirtualTable/hooks/useRowHeight.tsx
  • web/oss/src/components/InfiniteVirtualTable/hooks/useScopedColumnVisibility.tsx
  • web/oss/src/components/InfiniteVirtualTable/hooks/useScrollConfig.ts
  • web/oss/src/components/InfiniteVirtualTable/hooks/useScrollContainer.ts
  • web/oss/src/components/InfiniteVirtualTable/hooks/useSmartResizableColumns.ts
  • web/oss/src/components/InfiniteVirtualTable/hooks/useTableActions.tsx
  • web/oss/src/components/InfiniteVirtualTable/hooks/useTableExport.ts
  • web/oss/src/components/InfiniteVirtualTable/hooks/useTableHeaderHeight.ts
  • web/oss/src/components/InfiniteVirtualTable/hooks/useTableKeyboardShortcuts.ts
  • web/oss/src/components/InfiniteVirtualTable/hooks/useTableManager.tsx
  • web/oss/src/components/InfiniteVirtualTable/hooks/useTableRowSelection.ts
  • web/oss/src/components/InfiniteVirtualTable/index.ts
  • web/oss/src/components/InfiniteVirtualTable/providers/ColumnVisibilityProvider.tsx
  • web/oss/src/components/InfiniteVirtualTable/providers/InfiniteVirtualTableStoreProvider.tsx
  • web/oss/src/components/InfiniteVirtualTable/types.ts
  • web/oss/src/components/InfiniteVirtualTable/utils/columnUtils.ts
  • web/oss/src/components/Playground/Components/TestsetDropdown/TestsetPreviewPanelWrapper.tsx
  • web/oss/src/components/SessionInspector/PanelSessionInspectorButton.tsx
  • web/oss/src/components/SharedDrawers/AddToTestsetDrawer/components/PreviewSection.tsx
  • web/oss/src/components/SharedDrawers/SessionDrawer/components/SessionDrawerButton/index.tsx
  • web/oss/src/components/SharedDrawers/SessionDrawer/store/sessionDrawerStore.ts
  • web/oss/src/components/SharedDrawers/SessionDrawer/types.ts
  • web/oss/src/components/SharedDrawers/TraceDrawer/components/TraceContent/components/OverviewTabItem/index.tsx
  • web/oss/src/components/SharedDrawers/TraceDrawer/components/TraceTree/assets/spanVisibility.ts
  • web/oss/src/components/SharedDrawers/TraceDrawer/components/TraceTree/index.tsx
  • web/oss/src/components/SharedDrawers/TraceDrawer/store/traceDrawerStore.ts
  • web/oss/src/components/Sidebar/dynamic/registry.ts
  • web/oss/src/components/Sidebar/hooks/useSidebarConfig/index.tsx
  • web/oss/src/components/Sidebar/scopes/settingsScope.tsx
  • web/oss/src/components/TestcasesTableNew/components/TestcaseHeader.tsx
  • web/oss/src/components/TestcasesTableNew/components/TestcasesTableShell.tsx
  • web/oss/src/components/TestcasesTableNew/index.tsx
  • web/oss/src/components/TestcasesTableNew/state/rowHeight.ts
  • web/oss/src/components/TestsetsTable/TestsetsTable.tsx
  • web/oss/src/components/TestsetsTable/assets/createTestsetsColumns.tsx
  • web/oss/src/components/TestsetsTable/atoms/fetchTestsets.ts
  • web/oss/src/components/TestsetsTable/components/TestsetsHeaderFilters.tsx
  • web/oss/src/components/pages/agent-home/OnboardingEntry.tsx
  • web/oss/src/components/pages/agent-home/hooks/useCreateAgent.ts
  • web/oss/src/components/pages/agents/AgentsPage.tsx
  • web/oss/src/components/pages/agents/store.ts
  • web/oss/src/components/pages/observability/assets/constants.ts
  • web/oss/src/components/pages/observability/assets/exportUtils.ts
  • web/oss/src/components/pages/observability/assets/getObservabilityColumns.tsx
  • web/oss/src/components/pages/observability/components/AvatarTreeContent.tsx
  • web/oss/src/components/pages/observability/components/NodeNameCell.tsx
  • web/oss/src/components/pages/observability/components/SessionsTable/assets/getSessionColumns.tsx
  • web/oss/src/components/pages/observability/components/StatusRenderer.tsx
  • web/oss/src/components/pages/observability/components/TimestampCell.tsx
  • web/oss/src/components/pages/prompts/PromptsPage.tsx
  • web/oss/src/components/pages/settings/FeatureFlags/FeatureFlags.tsx
  • web/oss/src/components/pages/settings/Organization/General.tsx
  • web/oss/src/components/pages/settings/assets/navigation.test.ts
  • web/oss/src/components/pages/settings/assets/navigation.ts
  • web/oss/src/hooks/usePostAuthRedirect.ts
  • web/oss/src/lib/helpers/dynamicEnv.ts
  • web/oss/src/lib/hooks/usePreviewEvaluations/index.ts
  • web/oss/src/lib/hooks/usePreviewEvaluations/types.ts
  • web/oss/src/lib/onboarding/atoms.ts
  • web/oss/src/lib/onboarding/index.ts
  • web/oss/src/pages/w/[workspace_id]/p/[project_id]/apps/[app_id]/index.tsx
  • web/oss/src/pages/w/[workspace_id]/p/[project_id]/settings/index.tsx
  • web/oss/src/services/tracing/types/index.ts
  • web/oss/src/state/app/atoms/fetcher.ts
  • web/oss/src/state/entities/shared/README.md
  • web/oss/src/state/entities/shared/createPaginatedEntityStore.ts
  • web/oss/src/state/entities/testcase/paginatedStore.ts
  • web/oss/src/state/entities/testset/paginatedStore.ts
  • web/oss/src/state/newObservability/atoms/queries.ts
  • web/oss/src/state/onboarding/selectors.ts
  • web/oss/src/state/settings/featureFlags.ts
  • web/oss/tsconfig.json
  • web/package.json
  • web/packages/agenta-api-client/package.json
  • web/packages/agenta-entities/package.json
  • web/packages/agenta-entities/src/evaluationRun/core/schema.ts
  • web/packages/agenta-entities/src/evaluationRun/etl/resolveMappings.ts
  • web/packages/agenta-entities/src/trace/etl/exportMatchingTraces.ts
  • web/packages/agenta-entities/src/workflow/index.ts
  • web/packages/agenta-entities/src/workflow/state/index.ts
  • web/packages/agenta-entities/src/workflow/state/inspectMeta.ts
  • web/packages/agenta-entities/tests/unit/export-matching-traces.test.ts
  • web/packages/agenta-entity-ui/package.json
  • web/packages/agenta-playground/src/index.ts
  • web/packages/agenta-playground/src/state/execution/index.ts
  • web/packages/agenta-playground/src/state/index.ts
  • web/packages/agenta-shared/package.json
  • web/packages/agenta-ui/src/InfiniteVirtualTable/index.ts
  • web/packages/agenta-ui/src/InfiniteVirtualTable/types.ts
  • web/packages/agenta-ui/src/RichChatInput/ComposerSendButton.tsx
  • web/packages/agenta-ui/src/RichChatInput/RichChatInput.tsx
  • web/packages/agenta-ui/src/RichChatInput/index.ts
  • web/packages/agenta-ui/src/RichChatInput/plugins/SendButton.tsx
  • web/packages/agenta-ui/src/RichChatInput/plugins/dictation.ts
  • web/tests/package.json
💤 Files with no reviewable changes (57)
  • web/oss/src/components/InfiniteVirtualTable/hooks/useEditableTable.ts
  • web/oss/src/components/SharedDrawers/SessionDrawer/types.ts
  • web/oss/src/components/InfiniteVirtualTable/features/useInfiniteTableFeaturePagination.ts
  • web/oss/src/components/InfiniteVirtualTable/hooks/useColumnDomRefs.ts
  • web/oss/src/components/InfiniteVirtualTable/columns/cells.tsx
  • web/oss/src/components/InfiniteVirtualTable/hooks/useContainerSize.ts
  • web/oss/src/components/InfiniteVirtualTable/helpers/index.ts
  • web/oss/src/components/InfiniteVirtualTable/hooks/useScopedColumnVisibility.tsx
  • web/oss/src/components/InfiniteVirtualTable/components/TableDescription.tsx
  • web/oss/src/components/InfiniteVirtualTable/columns/types.ts
  • web/oss/src/components/InfiniteVirtualTable/hooks/useTableRowSelection.ts
  • web/oss/src/components/InfiniteVirtualTable/hooks/useContainerResize.ts
  • web/oss/src/components/InfiniteVirtualTable/atoms/columnWidths.ts
  • web/oss/src/components/InfiniteVirtualTable/hooks/useInfiniteScroll.ts
  • web/oss/src/components/InfiniteVirtualTable/components/columnVisibility/TableSettingsDropdown.tsx
  • web/oss/src/components/InfiniteVirtualTable/hooks/useSmartResizableColumns.ts
  • web/oss/src/components/InfiniteVirtualTable/providers/ColumnVisibilityProvider.tsx
  • web/oss/src/components/InfiniteVirtualTable/helpers/createSimpleTableStore.ts
  • web/oss/src/components/InfiniteVirtualTable/components/columnVisibility/ColumnVisibilityMenuTrigger.tsx
  • web/oss/src/components/InfiniteVirtualTable/hooks/useTableKeyboardShortcuts.ts
  • web/oss/src/components/InfiniteVirtualTable/hooks/useTableHeaderHeight.ts
  • web/oss/src/components/InfiniteVirtualTable/hooks/useColumnVisibilityControls.ts
  • web/oss/src/components/InfiniteVirtualTable/helpers/createTableRowHelpers.ts
  • web/oss/src/components/InfiniteVirtualTable/InfiniteVirtualTable.tsx
  • web/oss/src/components/SharedDrawers/SessionDrawer/components/SessionDrawerButton/index.tsx
  • web/oss/src/components/InfiniteVirtualTable/hooks/useTableManager.tsx
  • web/oss/src/components/InfiniteVirtualTable/hooks/useScrollContainer.ts
  • web/oss/src/components/InfiniteVirtualTable/hooks/useHeaderViewportVisibility.ts
  • web/oss/src/components/InfiniteVirtualTable/components/ColumnVisibilityHeader.tsx
  • web/oss/src/components/InfiniteVirtualTable/columns/createTableColumns.ts
  • web/oss/src/components/InfiniteVirtualTable/hooks/useResizableColumns.ts
  • web/oss/src/components/InfiniteVirtualTable/components/TableShell.tsx
  • web/oss/src/components/InfiniteVirtualTable/hooks/useScrollConfig.ts
  • web/oss/src/components/InfiniteVirtualTable/hooks/useTableActions.tsx
  • web/oss/src/components/InfiniteVirtualTable/createInfiniteDatasetStore.ts
  • web/oss/src/components/InfiniteVirtualTable/context/VirtualTableScrollContainerContext.ts
  • web/oss/src/components/InfiniteVirtualTable/atoms/columnHiddenKeys.ts
  • web/oss/src/components/InfiniteVirtualTable/hooks/useInfiniteTablePagination.ts
  • web/oss/src/components/InfiniteVirtualTable/atoms/columnVisibility.ts
  • web/oss/src/components/InfiniteVirtualTable/components/filters/FiltersPopoverTrigger.tsx
  • web/oss/src/components/InfiniteVirtualTable/components/ColumnVisibilityTrigger.tsx
  • web/oss/src/components/InfiniteVirtualTable/hooks/useColumnVisibility.ts
  • web/oss/src/components/InfiniteVirtualTable/hooks/useRowHeight.tsx
  • web/oss/src/components/InfiniteVirtualTable/features/index.ts
  • web/oss/src/components/InfiniteVirtualTable/context/ColumnVisibilityContext.ts
  • web/oss/src/components/InfiniteVirtualTable/utils/columnUtils.ts
  • web/oss/src/components/InfiniteVirtualTable/context/ColumnVisibilityFlagContext.tsx
  • web/oss/src/components/InfiniteVirtualTable/components/InfiniteVirtualTableInner.tsx
  • web/oss/src/components/InfiniteVirtualTable/createInfiniteTableStore.ts
  • web/oss/src/components/InfiniteVirtualTable/columns/createStandardColumns.tsx
  • web/oss/src/components/InfiniteVirtualTable/hooks/useExpandableRows.tsx
  • web/oss/src/components/InfiniteVirtualTable/index.ts
  • web/oss/src/components/InfiniteVirtualTable/hooks/useTableExport.ts
  • web/oss/src/components/InfiniteVirtualTable/components/columnVisibility/ColumnVisibilityPopoverContent.tsx
  • web/oss/src/components/InfiniteVirtualTable/providers/InfiniteVirtualTableStoreProvider.tsx
  • web/oss/src/components/InfiniteVirtualTable/types.ts
  • web/oss/src/components/InfiniteVirtualTable/features/InfiniteVirtualTableFeatureShell.tsx

Comment on lines +178 to +195
## Phase 6: Stacked branch (GitButler)

Put the work on its own lane. This repo runs GitButler, so use `but`, not raw git, and follow
the repo's gotchas.

1. `but oplog snapshot -m "before <feature> branch"` first. The workspace is usually dirty
with other lanes' work, so protect it.
2. `but status` to see the lanes and pick the parent to stack on.
3. `but branch new <type>/<feature> --anchor <parent>` to stack on that parent.
4. Stage only this feature's files to the new lane with `but rub <path> <branch>`, then
`but commit <branch> --only -m "..."`. Never run a bare `but commit`, which sweeps every
unassigned change in the workspace into the lane.
5. Stop there unless the user asks to push. When they do, `but push <branch>` then
`gh pr create --head <branch> --base <parent-or-main>`. Use the PR body drafted in Phase 5
(via the `write-pr-description` skill). Confirm it includes Context, Scope / risk, and the
full How to QA section (prerequisites, steps, expected result, test command, edge cases)
before creating the PR. End commit messages and PR bodies with the session footer the repo
conventions require.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Resolve the contradictory push policy and document verification.

Phase 6 says to stop unless the user explicitly asks to push, but the coordination section says to push a lane whenever a slice is done. Choose one policy, preferably explicit user approval, and add the required local-SHA versus git ls-remote verification after any push.

As per coding guidelines, GitButler pushes must be verified against the remote SHA; silent success is not sufficient.

Also applies to: 215-218

Source: Coding guidelines

Comment on lines +145 to +159
```ts
import { atomWithStorage } from "jotai/utils";

/** null = follow default, true = force simplified, false = force full. Per-user via LS. */
export const navSimplifiedOverrideAtom = atomWithStorage<boolean | null>(
"agenta:onboarding:<userId>:nav-simplified-override",
null,
);

// Phase 2: explicit choice wins; else fall back to the signup-era default.
export const advancedNavHiddenAtom = atom((get) => {
const override = get(navSimplifiedOverrideAtom);
return override ?? get(navSimplifiedDefaultAtom);
});
```

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

navSimplifiedOverrideAtom snippet isn't actually per-user — contradicts its own comment and Slice 1's pattern.

The comment says "Per-user via LS," but the code uses a single atomWithStorage with a literal, non-interpolated key "agenta:onboarding:<userId>:nav-simplified-override". Unlike Slice 1's navSimplifiedDefaultAtomFamily (which wraps atomFamily(userId) + createScopedStorageKey(userId, ...)), this snippet has no per-user family/wrapper — if implemented as written, all users on the same browser would share one override value.

Please verify the actual implementation (in state/onboarding/selectors.ts, not included in this batch) uses proper per-user scoping matching navSimplifiedDefaultAtomFamily, and fix this doc snippet to match if it doesn't.

#!/bin/bash
# Verify whether navSimplifiedOverrideAtom is actually per-user-scoped in the real implementation.
fd -a selectors.ts web/oss/src/state/onboarding
rg -n -A8 'navSimplifiedOverrideAtom' web/oss/src/state/onboarding/selectors.ts web/oss/src/lib/onboarding/atoms.ts 2>/dev/null

Comment on lines +93 to +105
const open = openUid !== null

// Build (and own the object URLs of) the node set only while open, revoking on close/change.
const [nodes, setNodes] = useState<BuiltNodes | null>(null)
useEffect(() => {
if (!open) {
setNodes(null)
return
}
const built = buildNodes(uploads)
setNodes(built)
return () => built.source.forEach((v) => URL.revokeObjectURL(v.objectUrl))
}, [open, uploads])

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🚀 Performance & Scalability | 🟠 Major | ⚡ Quick win

Rebuilds every object URL on any uploads reference change.

buildNodes mints a fresh URL.createObjectURL for every attachment whenever this effect reruns, and it reruns on ANY reference change to uploads — including a progress-percent update on a single in-flight attachment if the composer drives progress through this same list. That thrashes object URLs (revoke+recreate) for every unrelated file while the drawer is open, wasting allocations and risking a preview flicker.

Consider keying URL creation per-file (memoized on file identity, like useImagePreviews) instead of rebuilding the whole node set whenever uploads changes identity.

#!/bin/bash
# Confirm whether the composer's uploads array is re-created on progress ticks
fd ComposerAttachments.tsx web/oss/src/components/AgentChatSlice/components --exec cat -n {}
♻️ Direction for a per-file-memoized fix
-    const [nodes, setNodes] = useState<BuiltNodes | null>(null)
-    useEffect(() => {
-        if (!open) {
-            setNodes(null)
-            return
-        }
-        const built = buildNodes(uploads)
-        setNodes(built)
-        return () => built.source.forEach((v) => URL.revokeObjectURL(v.objectUrl))
-    }, [open, uploads])
+    const urlsRef = useRef(new Map<File, string>())
+    const [nodes, setNodes] = useState<BuiltNodes | null>(null)
+    useEffect(() => {
+        if (!open) {
+            setNodes(null)
+            return
+        }
+        // buildNodes reuses urlsRef entries for files already seen, only minting
+        // URLs for newly-added files and revoking ones no longer present.
+        setNodes(buildNodes(uploads, urlsRef.current))
+    }, [open, uploads])
+    useEffect(() => {
+        return () => {
+            urlsRef.current.forEach((url) => URL.revokeObjectURL(url))
+            urlsRef.current.clear()
+        }
+    }, [])

Comment on lines +149 to +250
const runConnect = useCallback(
async (settleParkedCall: boolean) => {
if (phase === "connecting") return
if (settleParkedCall && (!activeRef.current || settledRef.current || meta.settled))
return
setErrorText(null)
setPhase("connecting")
try {
const result = await handleCreate({slug, name: slug, mode})
if (settleParkedCall && !activeRef.current) return
const redirectUrl =
typeof result.connection?.data?.redirect_url === "string"
? result.connection.data.redirect_url
: undefined

const onSuccess = () => {
if (settleParkedCall && !activeRef.current) return
invalidate()
if (settleParkedCall) finish({connected: true, integration, slug})
else {
setManuallyConnected(true)
setPhase("idle")
}
}

if (!redirectUrl) {
// No OAuth step (e.g. api_key created inline): the connection already exists.
onSuccess()
return
}

const popup = window.open(
redirectUrl,
oauthWindowName,
"width=600,height=700,popup=yes",
)
if (!popup) {
setPhase("error")
setErrorText("Couldn’t open the connection window. Allow popups and retry.")
return
}
popupRef.current = popup

const apiOrigin = agentaApiOrigin()
let succeeded = false

const onMessage = (event: MessageEvent) => {
// HARD requirement: only trust the callback from the Agenta API origin.
if (!apiOrigin || event.origin !== apiOrigin) return
const data = event.data as {
type?: unknown
slug?: unknown
integration?: unknown
} | null
if (!data || data.type !== "tools:oauth:complete") return
// Several connect flows can be live at once (an agent may ask for
// multiple connections in one turn). The callback tags the completion with
// its connection identity, so a flow settles ONLY on its own completion —
// otherwise the first finished flow would mark every open one connected.
// A legacy callback without identity keeps the prior single-flow behavior.
if (typeof data.slug === "string" && data.slug !== slug) return
else if (
typeof data.slug !== "string" &&
typeof data.integration === "string" &&
data.integration !== integration
)
return
succeeded = true
teardown()
onSuccess()
}
window.addEventListener("message", onMessage)

const poll = window.setInterval(() => {
if (!popupRef.current?.closed || succeeded) return
// Abandon: closed without a success message.
teardown()
if (settleParkedCall && !activeRef.current) return
if (settleParkedCall)
finish({connected: false, integration, slug, reason: "cancelled"})
else setPhase("idle")
}, POPUP_POLL_MS)

const timeout = window.setTimeout(() => {
if (succeeded) return
teardown()
if (settleParkedCall && !activeRef.current) return
if (settleParkedCall)
finish({connected: false, integration, slug, reason: "timeout"})
else setPhase("idle")
}, CONNECT_TIMEOUT_MS)

cleanupRef.current = () => {
window.removeEventListener("message", onMessage)
window.clearInterval(poll)
window.clearTimeout(timeout)
try {
popupRef.current?.close()
} catch {
// best effort
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Unmount during handleCreate leaks the listener/poll/timeout (and updates state after unmount).

cleanupRef is only assigned after the awaited handleCreate resolves and the popup opens. If the card unmounts while that request is in flight, the unmount effect runs teardown() with cleanupRef still null; the continuation then registers the message listener, setInterval and setTimeout, which are never torn down — the poll keeps running and its finish/setPhase calls hit an unmounted component. activeRef only guards the settleParkedCall branches, so the retry path (settleParkedCall === false) leaks unconditionally.

Track mount state and bail (plus close the popup) before wiring the watchers.

🛡️ Proposed fix
     const popupRef = useRef<Window | null>(null)
     const cleanupRef = useRef<(() => void) | null>(null)
+    const mountedRef = useRef(true)
+    useEffect(() => () => {
+        mountedRef.current = false
+    }, [])
@@
                 const result = await handleCreate({slug, name: slug, mode})
+                if (!mountedRef.current) return
                 if (settleParkedCall && !activeRef.current) return
@@
                 popupRef.current = popup
+                if (!mountedRef.current) {
+                    try {
+                        popup.close()
+                    } catch {
+                        // best effort
+                    }
+                    return
+                }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const runConnect = useCallback(
async (settleParkedCall: boolean) => {
if (phase === "connecting") return
if (settleParkedCall && (!activeRef.current || settledRef.current || meta.settled))
return
setErrorText(null)
setPhase("connecting")
try {
const result = await handleCreate({slug, name: slug, mode})
if (settleParkedCall && !activeRef.current) return
const redirectUrl =
typeof result.connection?.data?.redirect_url === "string"
? result.connection.data.redirect_url
: undefined
const onSuccess = () => {
if (settleParkedCall && !activeRef.current) return
invalidate()
if (settleParkedCall) finish({connected: true, integration, slug})
else {
setManuallyConnected(true)
setPhase("idle")
}
}
if (!redirectUrl) {
// No OAuth step (e.g. api_key created inline): the connection already exists.
onSuccess()
return
}
const popup = window.open(
redirectUrl,
oauthWindowName,
"width=600,height=700,popup=yes",
)
if (!popup) {
setPhase("error")
setErrorText("Couldn’t open the connection window. Allow popups and retry.")
return
}
popupRef.current = popup
const apiOrigin = agentaApiOrigin()
let succeeded = false
const onMessage = (event: MessageEvent) => {
// HARD requirement: only trust the callback from the Agenta API origin.
if (!apiOrigin || event.origin !== apiOrigin) return
const data = event.data as {
type?: unknown
slug?: unknown
integration?: unknown
} | null
if (!data || data.type !== "tools:oauth:complete") return
// Several connect flows can be live at once (an agent may ask for
// multiple connections in one turn). The callback tags the completion with
// its connection identity, so a flow settles ONLY on its own completion —
// otherwise the first finished flow would mark every open one connected.
// A legacy callback without identity keeps the prior single-flow behavior.
if (typeof data.slug === "string" && data.slug !== slug) return
else if (
typeof data.slug !== "string" &&
typeof data.integration === "string" &&
data.integration !== integration
)
return
succeeded = true
teardown()
onSuccess()
}
window.addEventListener("message", onMessage)
const poll = window.setInterval(() => {
if (!popupRef.current?.closed || succeeded) return
// Abandon: closed without a success message.
teardown()
if (settleParkedCall && !activeRef.current) return
if (settleParkedCall)
finish({connected: false, integration, slug, reason: "cancelled"})
else setPhase("idle")
}, POPUP_POLL_MS)
const timeout = window.setTimeout(() => {
if (succeeded) return
teardown()
if (settleParkedCall && !activeRef.current) return
if (settleParkedCall)
finish({connected: false, integration, slug, reason: "timeout"})
else setPhase("idle")
}, CONNECT_TIMEOUT_MS)
cleanupRef.current = () => {
window.removeEventListener("message", onMessage)
window.clearInterval(poll)
window.clearTimeout(timeout)
try {
popupRef.current?.close()
} catch {
// best effort
}
}
const popupRef = useRef<Window | null>(null)
const cleanupRef = useRef<(() => void) | null>(null)
const mountedRef = useRef(true)
useEffect(
() => () => {
mountedRef.current = false
},
[],
)
const runConnect = useCallback(
async (settleParkedCall: boolean) => {
if (phase === "connecting") return
if (settleParkedCall && (!activeRef.current || settledRef.current || meta.settled))
return
setErrorText(null)
setPhase("connecting")
try {
const result = await handleCreate({slug, name: slug, mode})
if (!mountedRef.current) return
if (settleParkedCall && !activeRef.current) return
const redirectUrl =
typeof result.connection?.data?.redirect_url === "string"
? result.connection.data.redirect_url
: undefined
const onSuccess = () => {
if (settleParkedCall && !activeRef.current) return
invalidate()
if (settleParkedCall) finish({connected: true, integration, slug})
else {
setManuallyConnected(true)
setPhase("idle")
}
}
if (!redirectUrl) {
// No OAuth step (e.g. api_key created inline): the connection already exists.
onSuccess()
return
}
const popup = window.open(
redirectUrl,
oauthWindowName,
"width=600,height=700,popup=yes",
)
if (!popup) {
setPhase("error")
setErrorText("Couldn’t open the connection window. Allow popups and retry.")
return
}
popupRef.current = popup
if (!mountedRef.current) {
try {
popup.close()
} catch {
// best effort
}
return
}
const apiOrigin = agentaApiOrigin()
let succeeded = false
const onMessage = (event: MessageEvent) => {
// HARD requirement: only trust the callback from the Agenta API origin.
if (!apiOrigin || event.origin !== apiOrigin) return
const data = event.data as {
type?: unknown
slug?: unknown
integration?: unknown
} | null
if (!data || data.type !== "tools:oauth:complete") return
// Several connect flows can be live at once (an agent may ask for
// multiple connections in one turn). The callback tags the completion with
// its connection identity, so a flow settles ONLY on its own completion —
// otherwise the first finished flow would mark every open one connected.
// A legacy callback without identity keeps the prior single-flow behavior.
if (typeof data.slug === "string" && data.slug !== slug) return
else if (
typeof data.slug !== "string" &&
typeof data.integration === "string" &&
data.integration !== integration
)
return
succeeded = true
teardown()
onSuccess()
}
window.addEventListener("message", onMessage)
const poll = window.setInterval(() => {
if (!popupRef.current?.closed || succeeded) return
// Abandon: closed without a success message.
teardown()
if (settleParkedCall && !activeRef.current) return
if (settleParkedCall)
finish({connected: false, integration, slug, reason: "cancelled"})
else setPhase("idle")
}, POPUP_POLL_MS)
const timeout = window.setTimeout(() => {
if (succeeded) return
teardown()
if (settleParkedCall && !activeRef.current) return
if (settleParkedCall)
finish({connected: false, integration, slug, reason: "timeout"})
else setPhase("idle")
}, CONNECT_TIMEOUT_MS)
cleanupRef.current = () => {
window.removeEventListener("message", onMessage)
window.clearInterval(poll)
window.clearTimeout(timeout)
try {
popupRef.current?.close()
} catch {
// best effort
}
}

Comment on lines +99 to +119
if (file.status === "error") {
return (
<Tooltip title={typeof file.error === "string" ? file.error : "Upload failed"}>
<div className="absolute inset-0 flex items-center justify-center rounded-lg bg-[var(--ant-color-error-bg)] ring-1 ring-inset ring-colorError">
{onRetry && (
<button
type="button"
aria-label={`Retry ${file.name}`}
onClick={(e) => {
e.stopPropagation()
onRetry(file.uid)
}}
className="flex h-7 w-7 cursor-pointer items-center justify-center rounded-full border-0 bg-colorError text-white"
>
<ArrowClockwise size={14} weight="bold" />
</button>
)}
</div>
</Tooltip>
)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Error overlay swallows clicks on the remove button.

StatusOverlay renders after the tile with absolute inset-0 and, unlike the uploading branch, no pointer-events-none, so a failed attachment can't be removed — only retried (and not even that when onRetry is absent). Scope pointer events to the retry control.

🐛 Proposed fix
-                <div className="absolute inset-0 flex items-center justify-center rounded-lg bg-[var(--ant-color-error-bg)] ring-1 ring-inset ring-colorError">
+                <div className="pointer-events-none absolute inset-0 flex items-center justify-center rounded-lg bg-[var(--ant-color-error-bg)] ring-1 ring-inset ring-colorError">
                     {onRetry && (
                         <button
                             type="button"
+                            className="pointer-events-auto ..."
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (file.status === "error") {
return (
<Tooltip title={typeof file.error === "string" ? file.error : "Upload failed"}>
<div className="absolute inset-0 flex items-center justify-center rounded-lg bg-[var(--ant-color-error-bg)] ring-1 ring-inset ring-colorError">
{onRetry && (
<button
type="button"
aria-label={`Retry ${file.name}`}
onClick={(e) => {
e.stopPropagation()
onRetry(file.uid)
}}
className="flex h-7 w-7 cursor-pointer items-center justify-center rounded-full border-0 bg-colorError text-white"
>
<ArrowClockwise size={14} weight="bold" />
</button>
)}
</div>
</Tooltip>
)
}
if (file.status === "error") {
return (
<Tooltip title={typeof file.error === "string" ? file.error : "Upload failed"}>
<div className="pointer-events-none absolute inset-0 flex items-center justify-center rounded-lg bg-[var(--ant-color-error-bg)] ring-1 ring-inset ring-colorError">
{onRetry && (
<button
type="button"
aria-label={`Retry ${file.name}`}
onClick={(e) => {
e.stopPropagation()
onRetry(file.uid)
}}
className="pointer-events-auto flex h-7 w-7 cursor-pointer items-center justify-center rounded-full border-0 bg-colorError text-white"
>
<ArrowClockwise size={14} weight="bold" />
</button>
)}
</div>
</Tooltip>
)
}

Comment on lines +81 to +85
// Abort in-flight uploads on unmount (session switch / pane close).
useEffect(() => {
const map = controllers.current
return () => map.forEach((c) => c.abort())
}, [])

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Abort uploads when their file leaves the tray.

Cleanup only runs on unmount. If a caller removes a UID from files, its request can still complete and transmit an attachment the user withdrew. Abort and remove controllers absent from the current list.

Suggested fix
+    useEffect(() => {
+        const activeUids = new Set(files.map((file) => file.uid))
+        for (const [uid, controller] of controllers.current) {
+            if (!activeUids.has(uid)) {
+                controller.abort()
+                controllers.current.delete(uid)
+            }
+        }
+    }, [files])
+
     // Abort in-flight uploads on unmount (session switch / pane close).
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Abort in-flight uploads on unmount (session switch / pane close).
useEffect(() => {
const map = controllers.current
return () => map.forEach((c) => c.abort())
}, [])
useEffect(() => {
const activeUids = new Set(files.map((file) => file.uid))
for (const [uid, controller] of controllers.current) {
if (!activeUids.has(uid)) {
controller.abort()
controllers.current.delete(uid)
}
}
}, [files])
// Abort in-flight uploads on unmount (session switch / pane close).
useEffect(() => {
const map = controllers.current
return () => map.forEach((c) => c.abort())
}, [])

Comment on lines +167 to +191
export async function uploadMountFile({
mountId,
destFolder,
file,
projectId,
onProgress,
signal,
}: {
mountId: string
destFolder: string
file: File
projectId?: string | null
onProgress?: (percent: number) => void
signal?: AbortSignal
}): Promise<void> {
const form = new FormData()
form.append("file", file, file.name)
const path = destFolder ? `${destFolder.replace(/\/$/, "")}/${file.name}` : file.name
await axios.post(`${getAgentaApiUrl()}/mounts/${mountId}/files/upload`, form, {
params: {path, project_id: projectId},
signal,
onUploadProgress: (e) => {
if (onProgress && e.total) onProgress(Math.round((e.loaded / e.total) * 100))
},
})

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Use the mount Fern resource accessor for uploads.

Line 185 directly uses Axios, and Line 186 uses Axios-style params. Add or use the per-resource SDK upload accessor and pass query values with {queryParams: {...}}.

As per coding guidelines, “Frontend API code must use per-resource Fern client accessors from @agenta/sdk/resources, never raw axios,” and Fern query parameters must use {queryParams: {...}}.

#!/bin/bash
set -euo pipefail

ast-grep outline web/packages/agenta-sdk/src/resources.ts --items all
rg -n -i -C3 'mount.*upload|upload.*mount' web/packages/agenta-sdk/src web/oss/src

Comment on lines +41 to 47
if (!firstRun || !projectURL) return
void router.replace(`${projectURL}/playground`)
}, [loading, firstRun, projectURL, router])
}, [firstRun, projectURL, router])

// Loading the agents query, or redirecting a first-run user — the shared onboarding loader, so the
// whole flow reads as one continuous "setting up" screen (never the wrong surface, never blank).
if (loading || firstRun) {
// The shared onboarding loader, so the whole flow reads as one continuous "setting up" screen.
if (resolving) {
return <OnboardingLoader />

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Keep first-run onboarding in the loader until the redirect target is ready.

When firstRun is true but projectURL is falsy, the effect returns and the component falls through to <AgentHome /> because only resolving controls the loader. This can leave new users on the wrong surface instead of redirecting them to the playground.

Suggested guard
-    if (resolving) {
+    if (resolving || (firstRun && !projectURL)) {
         return <OnboardingLoader />
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (!firstRun || !projectURL) return
void router.replace(`${projectURL}/playground`)
}, [loading, firstRun, projectURL, router])
}, [firstRun, projectURL, router])
// Loading the agents query, or redirecting a first-run user — the shared onboarding loader, so the
// whole flow reads as one continuous "setting up" screen (never the wrong surface, never blank).
if (loading || firstRun) {
// The shared onboarding loader, so the whole flow reads as one continuous "setting up" screen.
if (resolving) {
return <OnboardingLoader />
if (!firstRun || !projectURL) return
void router.replace(`${projectURL}/playground`)
}, [firstRun, projectURL, router])
// The shared onboarding loader, so the whole flow reads as one continuous "setting up" screen.
if (resolving || (firstRun && !projectURL)) {
return <OnboardingLoader />

Comment on lines +146 to +159
// Latent: GET /organizations list omits default_workspace (details-only field) — typed as-is.
const deletedWorkspaceId =
(selectedOrg as Partial<OrgDetails> | undefined)?.default_workspace?.id || null
clearWorkspaceOrgCache(deletedWorkspaceId)
clearLastUsedProjectId(deletedWorkspaceId)

const remainingOrgs = orgs.filter((org) => org.id !== organizationId)
if (remainingOrgs.length > 0) {
await changeSelectedOrg(remainingOrgs[0].id)
}

resetOrganizationData()
resetProjectData()
await refetch()

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Cache-clearing on org delete is a no-op — self-documented as "Latent."

deletedWorkspaceId is derived from selectedOrg?.default_workspace?.id, but the adjacent comment says the /organizations list response omits default_workspace (it's details-only). That means deletedWorkspaceId will always be null here, so clearWorkspaceOrgCache(null) and clearLastUsedProjectId(null) never actually target the deleted org's cached workspace — the invalidation this code was written to perform silently never happens, potentially leaving stale workspace/project cache entries after deletion.

Consider fetching org details (or otherwise sourcing the real default_workspace.id) before calling deleteOrganization, so the cache-clear call receives the actual workspace id instead of always null.

#!/bin/bash
# Check whether an org-details fetch (with default_workspace) is available/used elsewhere for this purpose.
rg -n 'default_workspace' -C3 web/oss/src/lib/Types.ts web/oss/src/services/organization/api.ts web/oss/src/state/org 2>/dev/null

@@ -108,7 +110,7 @@ export interface ColumnGroup {
/** Stable cache key for this group — useful for grouping in renderers. */
key: string
/** The step.references that drove the grouping (preserved for downstream code). */
refs: Record<string, {id?: string; slug?: string} | null | undefined> | null
refs: Record<string, EvaluationRunStepReference | null | undefined> | null

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Keep ColumnGroup.refs compatible with slug-only references.

EvaluationRunStepReference requires id, but the previous ColumnGroup.refs element type allowed id?. This narrows the contract and can reject valid grouped references or force unsafe casts. Use a group-specific type with optional id, or normalize references before assigning them.

@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.

Caution

Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 17

Note

Due to the large number of review comments, Critical, Major severity comments were prioritized as inline comments.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
web/oss/src/components/AgentChatSlice/components/clientTools/ConnectToolWidget.tsx (1)

63-108: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Show manual-retry errors before the settled-result branch.

A manual retry happens after meta.settled is already true, so Line 64 returns the generic “Connection not completed” chip before Line 99 can render errorText. Move the phase === "error" branch above the settled check.

Proposed fix
+    if (phase === "error") {
+        return (
+            <ChipRow icon={<Warning size={13} weight="fill" className="text-colorError" />}>
+                <Text type="danger" className="!text-xs truncate" title={errorText ?? undefined}>
+                    {errorText ?? "Connection failed."}
+                </Text>
+                <RetryButton onClick={() => runConnect(false)} />
+            </ChipRow>
+        )
+    }
+
     if (meta.settled || outcome) {
web/oss/src/components/pages/observability/components/StatusRenderer.tsx (1)

5-18: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Do not render unset statuses as success.

When status is null or undefined, the renderer passes "STATUS_CODE_UNSET", but statusMapper falls through to its success mapping for every non-error value. Add an explicit neutral/unset mapping and reserve success for an actual success status.

Also applies to: 28-34

🟡 Minor comments (9)
.agents/skills/update-api-docs/SKILL.md-68-68 (1)

68-68: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Renumber the verification step.

The workflow jumps from Step 2 to Step 5. Rename this to Step 3 or restore the missing steps so the instructions are sequential.

.agents/skills/create-changelog-announcement/SKILL.md-311-317 (1)

311-317: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Use a Discussion-specific close flow.

githubUrl can point to a GitHub discussion, but gh issue close targets issues/PRs. Add a check for the discussion path and direct CLI users to the GitHub Discussions interface or a GraphQL closeDiscussion call instead.

.agents/skills/write-social-announcement/SKILL.md-14-21 (1)

14-21: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Remove the contradictory “key benefit” wording.

The skill forbids key as an adjective but later requires a “key benefit.” Use “main benefit” or “user benefit” instead.

Also applies to: 137-143

web/oss/src/pages/w/[workspace_id]/p/[project_id]/settings/index.tsx-121-138 (1)

121-138: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Raw --ag-c-* CSS variable literal for the demo badge.

bg-[var(--ag-c-0517290F)] uses a raw --ag-c-* literal instead of a supported theme token. As per coding guidelines, web/**/*.{ts,tsx} files must "Consume theme colors through Ant Design semantic tokens, Tailwind color utilities, or supported var(--ag-color*) variables; do not use raw hex colors or --ag-c-* literals." This also risks not adapting correctly between light/dark themes.

#!/bin/bash
# Check whether --ag-c-0517290F (or similar --ag-c- literals) are used elsewhere / have a sanctioned semantic token equivalent.
rg -n '\-\-ag-c-' --type=ts --type=tsx --type=css -g '!**/theme-variables.css' 2>/dev/null

Source: Coding guidelines

docs/design/simplify-nav-new-users/context.md-89-90 (1)

89-90: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Broken list formatting for criteria 6–8.

Items 6, 7, 8 and the "Phase 2" heading are run together on two lines with no breaks, unlike items 1–5 which are each on their own line. This will render as a run-on paragraph instead of a continued numbered list.

📝 Proposed fix
-**Phase 2** 6. The Settings → Feature flags switch flips the effective mode and survives a
-reload. 7. Toggling the switch updates the sidebar without a full page reload. 8. Phase 1's sidebar behavior is unchanged when no override is set.
+**Phase 2**
+
+6. The Settings → Feature flags switch flips the effective mode and survives a reload.
+7. Toggling the switch updates the sidebar without a full page reload.
+8. Phase 1's sidebar behavior is unchanged when no override is set.
web/oss/src/components/Drives/useDriveDrop.ts-58-87 (1)

58-87: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

dragleave decrements for non-file drags and the spring timer outlives unmount.

Two small asymmetries in this effect:

  • onEnter only counts file drags, but onLeave decrements on every dragleave, so a text drag crossing the window can zero the depth and clear dragging while a file drag is still active.
  • The cleanup removes listeners but never calls clearSpring(), so a pending 700ms spring-load fires onNavigate after unmount.
🛡️ Proposed fix
-        const onLeave = () => {
+        const onLeave = (e: DragEvent) => {
+            if (!has(e)) return
             depth.current = Math.max(0, depth.current - 1)
             if (depth.current === 0) setDragging(false)
         }
@@
         return () => {
             window.removeEventListener("dragenter", onEnter)
             window.removeEventListener("dragleave", onLeave)
             window.removeEventListener("drop", onEnd)
             window.removeEventListener("dragend", onEnd)
+            clearSpring()
         }
web/oss/src/components/AgentChatSlice/components/RecordingBar.tsx-66-88 (1)

66-88: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Live region wraps a per-second clock, so AT re-announces every tick.

role="status" aria-live="polite" on the container includes mmss(seconds), which changes once a second. Keep the live region for state changes only and mark the timer text as aria-hidden (or move aria-live to a dedicated node).

web/oss/src/components/AgentChatSlice/hooks/useAudioRecorder.ts-138-146 (1)

138-146: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Re-entrancy gap while permission is pending.

recRef.current is still null during "requesting", so a second start() before the prompt resolves issues another getUserMedia; the first resolved stream then leaks (only the last one is stored in streamRef). Callers currently disable the button on pending, but the hook shouldn't rely on that.

🛡️ Proposed guard
     const start = useCallback(() => {
-        if (!supported || recRef.current) return
+        if (!supported || recRef.current || startingRef.current) return
+        startingRef.current = true
         setError(null)

Reset startingRef.current = false in both the .then and .catch paths (and in teardown).

web/oss/src/components/Drives/driveFileSource.tsx-42-49 (1)

42-49: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Key local preview state by the selected file. Switching between staged files can reuse state from the prior file: a prior decode error makes the next media file fail immediately, and prior text can render while the next file is loading.

  • web/oss/src/components/Drives/driveFileSource.tsx#L42-L49: store the failed object URL/path rather than a shared boolean, or reset failure state when the local source changes.
  • web/oss/src/components/Drives/driveFileSource.tsx#L72-L85: clear text for a new local source and ignore completions from superseded reads.
🧹 Nitpick comments (11)
web/oss/src/lib/helpers/dynamicEnv.ts (1)

36-48: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Keep these feature-flag comments to one line.

Collapse the UI behavior descriptions into concise constraints; place extended rollout details in documentation. As per coding guidelines, “Keep in-code comments to at most one short line; use longer comments only for genuinely surprising constraints such as bugs, races, or ordering requirements.”

Source: Coding guidelines

web/packages/agenta-shared/package.json (1)

32-32: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

peerDependencies.axios floor not bumped to match the sibling packages.

dependencies.axios was bumped to 1.18.0 here, but peerDependencies.axios (Line 49) is still >=1.13.5 <2.0.0 — unlike agenta-entities and agenta-entity-ui, whose peer floors were both raised to >=1.18.0 in this same change. A consumer could satisfy this package's declared peer contract with a much older, vulnerable axios. The workspace-level pnpm.overrides.axios: "1.18.0" masks the practical impact today, but the manifest is inconsistent with the rest of this bump.

♻️ Proposed fix
     "peerDependencies": {
         "`@tanstack/react-query`": ">=5.0.0",
-        "axios": ">=1.13.5 <2.0.0",
+        "axios": ">=1.18.0 <2.0.0",
         "jotai": ">=2.0.0",

Also applies to: 47-53

web/oss/next.config.ts (1)

139-144: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Add a production regression check for refractor/all.

The fix depends on webpack preserving react-syntax-highlighter’s dynamic refractor/all import. Add a production build/render test for a PrismAsync code block so this IgnorePlugin rule cannot regress silently.

web/oss/src/components/AgentChatSlice/AgentConversation.tsx (1)

1722-1749: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicated attachment-key formula between toUploadFile and uploads.enqueue.

The uid string ${name}-${lastModified}-${size} is built twice; if useAttachmentUploads ever keys items differently, enqueue silently matches nothing. Extract one helper (attachmentUid(file)) used by both.

♻️ Suggested extraction
+const attachmentUid = (file: File) => `${file.name}-${file.lastModified}-${file.size}`
+
 const toUploadFile = (file: File): UploadFile => ({
-        uid: `${file.name}-${file.lastModified}-${file.size}`,
+        uid: attachmentUid(file),
         name: file.name,
         status: "done",
         originFileObj: file as UploadFile["originFileObj"],
     })
@@
-            uploads.enqueue(accepted.map((f) => `${f.name}-${f.lastModified}-${f.size}`))
+            uploads.enqueue(accepted.map(attachmentUid))
web/oss/src/components/Drives/DriveExplorer.tsx (2)

1866-1885: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Index-based staged ids reshuffle on removal.

id: ${i}-${f.name} changes for every item after a removal, so the synthetic tile keys (__staged__/${id}) all change and the surviving tiles remount (losing their fade/scale state). fileKey(f) is already imported and is stable per file.

♻️ Proposed change
             staged.map((f, i) => ({
-                id: `${i}-${f.name}`,
+                id: fileKey(f),
                 name: f.name,

1727-1733: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Double cast hides the shape mismatch.

{path, size} as unknown as MountFile silences the compiler for injected upload nodes. If MountFile has additional required fields, prefer a narrowed helper type (e.g. Pick<MountFile, "path" | "size"> widened at the buildDriveTree boundary) or make those fields optional, so a future field addition surfaces here.

web/oss/src/components/Drives/useDriveDrop.ts (1)

170-194: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

useStageDrop highlight flickers across child elements.

Unlike useDriveDrop, this has no depth counter: onDragLeave fires when the cursor crosses any child of the rail/aside, so dropActive toggles off mid-drag. A depth ref (or checking e.currentTarget.contains(e.relatedTarget as Node)) keeps the tint steady.

web/oss/src/components/AgentChatSlice/components/AudioPlayer.tsx (1)

28-34: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low value

Reset duration/current on src change.

The src effect resets probingRef but leaves the previous clip's duration/current in state, so the timer and progress bar briefly show the old clip's values (and a wrong ratio) until loadedmetadata fires.

♻️ Proposed tweak
         probingRef.current = false
+        setDuration(0)
+        setCurrent(0)
web/oss/src/components/AgentChatSlice/components/RecordingBar.tsx (1)

38-48: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low value

rAF loop for a once-per-second clock.

The frame loop runs ~60×/s to publish a value that changes 1×/s. An interval (e.g. 250 ms) derived from startedAtRef keeps the no-drift property at a fraction of the wakeups.

web/oss/src/components/AgentChatSlice/components/RecordingWaveform.tsx (1)

25-29: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low value

parseRgb assumes an rgb()/rgba() computed color.

If the theme token resolves to a modern color space (oklch(...), color(srgb …)), the digit scan yields nonsense channels or the [0,0,0] fallback — an invisible waveform in dark mode. Consider falling back to currentColor fill with per-stop globalAlpha instead of reconstructing channels.

Also applies to: 53-66

web/packages/agenta-ui/src/RichChatInput/ComposerSendButton.tsx (1)

34-38: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Replace raw hex colors with semantic theme tokens.

The #191a0d and #b8cb3f values will not adapt with the supported theme system. Use Ant semantic tokens, Tailwind semantic utilities, or supported --ag-color* variables instead.

As per coding guidelines, “Consume theme colors through Ant Design semantic tokens, Tailwind color utilities, or supported var(--ag-color*) variables; do not use raw hex colors.”

Source: Coding guidelines


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 03599dc8-8972-4f8a-a39e-60b25ef11bbc

📥 Commits

Reviewing files that changed from the base of the PR and between 56be600 and 1c7e42b.

⛔ Files ignored due to path filters (6)
  • api/uv.lock is excluded by !**/*.lock
  • clients/python/uv.lock is excluded by !**/*.lock
  • sdks/python/uv.lock is excluded by !**/*.lock
  • services/runner/pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
  • services/uv.lock is excluded by !**/*.lock
  • web/pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (246)
  • .agents/skills/add-announcement/SKILL.md
  • .agents/skills/create-changelog-announcement/SKILL.md
  • .agents/skills/implement-feature/SKILL.md
  • .agents/skills/plan-feature/SKILL.md
  • .agents/skills/style-editing/SKILL.md
  • .agents/skills/update-api-docs/SKILL.md
  • .agents/skills/update-llm-model-list/SKILL.md
  • .agents/skills/write-issue/SKILL.md
  • .agents/skills/write-social-announcement/SKILL.md
  • .claude/skills/add-announcement
  • .claude/skills/create-changelog-announcement
  • .claude/skills/implement-feature
  • .claude/skills/plan-feature
  • .claude/skills/style-editing
  • .claude/skills/sync-model-catalog
  • .claude/skills/update-api-docs
  • .claude/skills/update-llm-model-list
  • .claude/skills/write-issue
  • .claude/skills/write-social-announcement
  • .gitignore
  • .gitleaksignore
  • api/entrypoints/routers.py
  • api/oss/src/core/mounts/service.py
  • api/oss/src/middlewares/prefix.py
  • api/oss/tests/pytest/unit/middlewares/test_prefix.py
  • api/oss/tests/pytest/unit/test_mounts_file_ops.py
  • api/pyproject.toml
  • clients/python/pyproject.toml
  • docs/design/simplify-nav-new-users/README.md
  • docs/design/simplify-nav-new-users/context.md
  • docs/design/simplify-nav-new-users/plan.md
  • docs/design/simplify-nav-new-users/research.md
  • docs/design/simplify-nav-new-users/status.md
  • hosting/kubernetes/helm/Chart.yaml
  • sdks/python/pyproject.toml
  • services/pyproject.toml
  • services/runner/package.json
  • services/runner/src/engines/sandbox_agent/run-limits.ts
  • services/runner/src/env.ts
  • services/runner/src/sessions/persist.ts
  • services/runner/src/sessions/records-query.ts
  • services/runner/tests/unit/env-num.test.ts
  • services/runner/tests/unit/run-limits.test.ts
  • services/runner/tests/unit/session-persist.test.ts
  • services/runner/tests/unit/session-records-query.test.ts
  • web/ee/css-modules.d.ts
  • web/ee/package.json
  • web/ee/tsconfig.json
  • web/oss/css-modules.d.ts
  • web/oss/next.config.ts
  • web/oss/package.json
  • web/oss/src/components/AgentChatSlice/AgentConversation.tsx
  • web/oss/src/components/AgentChatSlice/assets/attachments.ts
  • web/oss/src/components/AgentChatSlice/assets/constants.ts
  • web/oss/src/components/AgentChatSlice/assets/markdown.tsx
  • web/oss/src/components/AgentChatSlice/components/AgentMessage.tsx
  • web/oss/src/components/AgentChatSlice/components/AttachmentViewerDrawer.tsx
  • web/oss/src/components/AgentChatSlice/components/AudioPlayer.tsx
  • web/oss/src/components/AgentChatSlice/components/ComposerAttachments.tsx
  • web/oss/src/components/AgentChatSlice/components/ConnectModelBanner.tsx
  • web/oss/src/components/AgentChatSlice/components/Inspector/InspectSessionButton.tsx
  • web/oss/src/components/AgentChatSlice/components/InteractionDock.tsx
  • web/oss/src/components/AgentChatSlice/components/MicPermissionNotice.tsx
  • web/oss/src/components/AgentChatSlice/components/QueuedMessages.tsx
  • web/oss/src/components/AgentChatSlice/components/RecordingBar.tsx
  • web/oss/src/components/AgentChatSlice/components/RecordingWaveform.tsx
  • web/oss/src/components/AgentChatSlice/components/ToolActivity.tsx
  • web/oss/src/components/AgentChatSlice/components/VoiceInputButton.tsx
  • web/oss/src/components/AgentChatSlice/components/clientTools/ConnectToolWidget.tsx
  • web/oss/src/components/AgentChatSlice/components/clientTools/useConnectFlow.ts
  • web/oss/src/components/AgentChatSlice/hooks/useAttachmentUploads.ts
  • web/oss/src/components/AgentChatSlice/hooks/useAudioRecorder.ts
  • web/oss/src/components/AgentChatSlice/hooks/useVoiceInput.ts
  • web/oss/src/components/Drives/ContextRail.tsx
  • web/oss/src/components/Drives/DriveExplorer.tsx
  • web/oss/src/components/Drives/FilesDrawer.tsx
  • web/oss/src/components/Drives/SessionFilesDrawer.tsx
  • web/oss/src/components/Drives/StorageFilesHeader.tsx
  • web/oss/src/components/Drives/StorageSection.tsx
  • web/oss/src/components/Drives/VirtualTileGrid.tsx
  • web/oss/src/components/Drives/configDrive.ts
  • web/oss/src/components/Drives/driveFileSource.tsx
  • web/oss/src/components/Drives/driveMedia.ts
  • web/oss/src/components/Drives/renderers.tsx
  • web/oss/src/components/Drives/useDriveDrop.ts
  • web/oss/src/components/Drives/useImagePreviews.ts
  • web/oss/src/components/Drives/useMountUpload.ts
  • web/oss/src/components/Drives/useSessionDrive.ts
  • web/oss/src/components/EvalRunDetails/Table.tsx
  • web/oss/src/components/EvalRunDetails/atoms/table/run.ts
  • web/oss/src/components/EvalRunDetails/atoms/traces.ts
  • web/oss/src/components/EvalRunDetails/components/CompareRunsMenu.tsx
  • web/oss/src/components/EvalRunDetails/components/EvalTestcaseDrawerAdapter/index.tsx
  • web/oss/src/components/EvalRunDetails/components/FocusDrawerHeader.tsx
  • web/oss/src/components/EvalRunDetails/components/FocusDrawerSidePanel.tsx
  • web/oss/src/components/EvalRunDetails/components/columnVisibility/ColumnVisibilityPopoverContent.tsx
  • web/oss/src/components/EvalRunDetails/components/views/SingleScenarioViewerPOC/ScenarioNavigator.tsx
  • web/oss/src/components/EvalRunDetails/components/views/SingleScenarioViewerPOC/index.tsx
  • web/oss/src/components/EvalRunDetails/evaluationPreviewTableStore.ts
  • web/oss/src/components/EvalRunDetails/hooks/useCellVisibility.ts
  • web/oss/src/components/EvalRunDetails/hooks/usePreviewColumns.tsx
  • web/oss/src/components/EvalRunDetails/utils/buildPreviewColumns.tsx
  • web/oss/src/components/EvaluationRunsTablePOC/atoms/fetchAutoEvaluationRuns.ts
  • web/oss/src/components/EvaluationRunsTablePOC/atoms/tableStore.ts
  • web/oss/src/components/EvaluationRunsTablePOC/components/EvaluationRunsTable/index.tsx
  • web/oss/src/components/EvaluationRunsTablePOC/components/EvaluationRunsTable/types.ts
  • web/oss/src/components/EvaluationRunsTablePOC/components/columnVisibility/ColumnVisibilityPopoverContent.tsx
  • web/oss/src/components/EvaluationRunsTablePOC/components/filters/EvaluationRunsHeaderFilters.tsx
  • web/oss/src/components/EvaluationRunsTablePOC/hooks/useEvaluationRunsColumns/index.tsx
  • web/oss/src/components/EvaluationRunsTablePOC/hooks/useEvaluationRunsColumns/utils.tsx
  • web/oss/src/components/EvaluationRunsTablePOC/hooks/useEvaluatorHeaderReference.ts
  • web/oss/src/components/EvaluationRunsTablePOC/types.ts
  • web/oss/src/components/InfiniteVirtualTable/InfiniteVirtualTable.tsx
  • web/oss/src/components/InfiniteVirtualTable/atoms/columnHiddenKeys.ts
  • web/oss/src/components/InfiniteVirtualTable/atoms/columnVisibility.ts
  • web/oss/src/components/InfiniteVirtualTable/atoms/columnWidths.ts
  • web/oss/src/components/InfiniteVirtualTable/columns/cells.tsx
  • web/oss/src/components/InfiniteVirtualTable/columns/createStandardColumns.tsx
  • web/oss/src/components/InfiniteVirtualTable/columns/createTableColumns.ts
  • web/oss/src/components/InfiniteVirtualTable/columns/types.ts
  • web/oss/src/components/InfiniteVirtualTable/components/ColumnVisibilityHeader.tsx
  • web/oss/src/components/InfiniteVirtualTable/components/ColumnVisibilityTrigger.tsx
  • web/oss/src/components/InfiniteVirtualTable/components/InfiniteVirtualTableInner.tsx
  • web/oss/src/components/InfiniteVirtualTable/components/TableDescription.tsx
  • web/oss/src/components/InfiniteVirtualTable/components/TableShell.tsx
  • web/oss/src/components/InfiniteVirtualTable/components/columnVisibility/ColumnVisibilityMenuTrigger.tsx
  • web/oss/src/components/InfiniteVirtualTable/components/columnVisibility/ColumnVisibilityPopoverContent.tsx
  • web/oss/src/components/InfiniteVirtualTable/components/columnVisibility/TableSettingsDropdown.tsx
  • web/oss/src/components/InfiniteVirtualTable/components/filters/FiltersPopoverTrigger.tsx
  • web/oss/src/components/InfiniteVirtualTable/context/ColumnVisibilityContext.ts
  • web/oss/src/components/InfiniteVirtualTable/context/ColumnVisibilityFlagContext.tsx
  • web/oss/src/components/InfiniteVirtualTable/context/VirtualTableScrollContainerContext.ts
  • web/oss/src/components/InfiniteVirtualTable/createInfiniteDatasetStore.ts
  • web/oss/src/components/InfiniteVirtualTable/createInfiniteTableStore.ts
  • web/oss/src/components/InfiniteVirtualTable/features/InfiniteVirtualTableFeatureShell.tsx
  • web/oss/src/components/InfiniteVirtualTable/features/index.ts
  • web/oss/src/components/InfiniteVirtualTable/features/useInfiniteTableFeaturePagination.ts
  • web/oss/src/components/InfiniteVirtualTable/helpers/createSimpleTableStore.ts
  • web/oss/src/components/InfiniteVirtualTable/helpers/createTableRowHelpers.ts
  • web/oss/src/components/InfiniteVirtualTable/helpers/index.ts
  • web/oss/src/components/InfiniteVirtualTable/hooks/useColumnDomRefs.ts
  • web/oss/src/components/InfiniteVirtualTable/hooks/useColumnVisibility.ts
  • web/oss/src/components/InfiniteVirtualTable/hooks/useColumnVisibilityControls.ts
  • web/oss/src/components/InfiniteVirtualTable/hooks/useContainerResize.ts
  • web/oss/src/components/InfiniteVirtualTable/hooks/useContainerSize.ts
  • web/oss/src/components/InfiniteVirtualTable/hooks/useEditableTable.ts
  • web/oss/src/components/InfiniteVirtualTable/hooks/useExpandableRows.tsx
  • web/oss/src/components/InfiniteVirtualTable/hooks/useHeaderViewportVisibility.ts
  • web/oss/src/components/InfiniteVirtualTable/hooks/useInfiniteScroll.ts
  • web/oss/src/components/InfiniteVirtualTable/hooks/useInfiniteTablePagination.ts
  • web/oss/src/components/InfiniteVirtualTable/hooks/useResizableColumns.ts
  • web/oss/src/components/InfiniteVirtualTable/hooks/useRowHeight.tsx
  • web/oss/src/components/InfiniteVirtualTable/hooks/useScopedColumnVisibility.tsx
  • web/oss/src/components/InfiniteVirtualTable/hooks/useScrollConfig.ts
  • web/oss/src/components/InfiniteVirtualTable/hooks/useScrollContainer.ts
  • web/oss/src/components/InfiniteVirtualTable/hooks/useSmartResizableColumns.ts
  • web/oss/src/components/InfiniteVirtualTable/hooks/useTableActions.tsx
  • web/oss/src/components/InfiniteVirtualTable/hooks/useTableExport.ts
  • web/oss/src/components/InfiniteVirtualTable/hooks/useTableHeaderHeight.ts
  • web/oss/src/components/InfiniteVirtualTable/hooks/useTableKeyboardShortcuts.ts
  • web/oss/src/components/InfiniteVirtualTable/hooks/useTableManager.tsx
  • web/oss/src/components/InfiniteVirtualTable/hooks/useTableRowSelection.ts
  • web/oss/src/components/InfiniteVirtualTable/index.ts
  • web/oss/src/components/InfiniteVirtualTable/providers/ColumnVisibilityProvider.tsx
  • web/oss/src/components/InfiniteVirtualTable/providers/InfiniteVirtualTableStoreProvider.tsx
  • web/oss/src/components/InfiniteVirtualTable/types.ts
  • web/oss/src/components/InfiniteVirtualTable/utils/columnUtils.ts
  • web/oss/src/components/Playground/Components/TestsetDropdown/TestsetPreviewPanelWrapper.tsx
  • web/oss/src/components/SessionInspector/PanelSessionInspectorButton.tsx
  • web/oss/src/components/SharedDrawers/AddToTestsetDrawer/components/PreviewSection.tsx
  • web/oss/src/components/SharedDrawers/SessionDrawer/components/SessionDrawerButton/index.tsx
  • web/oss/src/components/SharedDrawers/SessionDrawer/store/sessionDrawerStore.ts
  • web/oss/src/components/SharedDrawers/SessionDrawer/types.ts
  • web/oss/src/components/SharedDrawers/TraceDrawer/components/TraceContent/components/OverviewTabItem/index.tsx
  • web/oss/src/components/SharedDrawers/TraceDrawer/components/TraceTree/assets/spanVisibility.ts
  • web/oss/src/components/SharedDrawers/TraceDrawer/components/TraceTree/index.tsx
  • web/oss/src/components/SharedDrawers/TraceDrawer/store/traceDrawerStore.ts
  • web/oss/src/components/Sidebar/dynamic/registry.ts
  • web/oss/src/components/Sidebar/hooks/useSidebarConfig/index.tsx
  • web/oss/src/components/Sidebar/scopes/settingsScope.tsx
  • web/oss/src/components/TestcasesTableNew/components/TestcaseHeader.tsx
  • web/oss/src/components/TestcasesTableNew/components/TestcasesTableShell.tsx
  • web/oss/src/components/TestcasesTableNew/index.tsx
  • web/oss/src/components/TestcasesTableNew/state/rowHeight.ts
  • web/oss/src/components/TestsetsTable/TestsetsTable.tsx
  • web/oss/src/components/TestsetsTable/assets/createTestsetsColumns.tsx
  • web/oss/src/components/TestsetsTable/atoms/fetchTestsets.ts
  • web/oss/src/components/TestsetsTable/components/TestsetsHeaderFilters.tsx
  • web/oss/src/components/pages/agent-home/OnboardingEntry.tsx
  • web/oss/src/components/pages/agent-home/hooks/useCreateAgent.ts
  • web/oss/src/components/pages/agents/AgentsPage.tsx
  • web/oss/src/components/pages/agents/store.ts
  • web/oss/src/components/pages/observability/assets/constants.ts
  • web/oss/src/components/pages/observability/assets/exportUtils.ts
  • web/oss/src/components/pages/observability/assets/getObservabilityColumns.tsx
  • web/oss/src/components/pages/observability/components/AvatarTreeContent.tsx
  • web/oss/src/components/pages/observability/components/NodeNameCell.tsx
  • web/oss/src/components/pages/observability/components/SessionsTable/assets/getSessionColumns.tsx
  • web/oss/src/components/pages/observability/components/StatusRenderer.tsx
  • web/oss/src/components/pages/observability/components/TimestampCell.tsx
  • web/oss/src/components/pages/prompts/PromptsPage.tsx
  • web/oss/src/components/pages/settings/FeatureFlags/FeatureFlags.tsx
  • web/oss/src/components/pages/settings/Organization/General.tsx
  • web/oss/src/components/pages/settings/assets/navigation.test.ts
  • web/oss/src/components/pages/settings/assets/navigation.ts
  • web/oss/src/hooks/usePostAuthRedirect.ts
  • web/oss/src/lib/helpers/dynamicEnv.ts
  • web/oss/src/lib/hooks/usePreviewEvaluations/index.ts
  • web/oss/src/lib/hooks/usePreviewEvaluations/types.ts
  • web/oss/src/lib/onboarding/atoms.ts
  • web/oss/src/lib/onboarding/index.ts
  • web/oss/src/pages/w/[workspace_id]/p/[project_id]/apps/[app_id]/index.tsx
  • web/oss/src/pages/w/[workspace_id]/p/[project_id]/settings/index.tsx
  • web/oss/src/services/tracing/types/index.ts
  • web/oss/src/state/app/atoms/fetcher.ts
  • web/oss/src/state/entities/shared/README.md
  • web/oss/src/state/entities/shared/createPaginatedEntityStore.ts
  • web/oss/src/state/entities/testcase/paginatedStore.ts
  • web/oss/src/state/entities/testset/paginatedStore.ts
  • web/oss/src/state/newObservability/atoms/queries.ts
  • web/oss/src/state/onboarding/selectors.ts
  • web/oss/src/state/settings/featureFlags.ts
  • web/oss/tsconfig.json
  • web/package.json
  • web/packages/agenta-api-client/package.json
  • web/packages/agenta-entities/package.json
  • web/packages/agenta-entities/src/evaluationRun/core/schema.ts
  • web/packages/agenta-entities/src/evaluationRun/etl/resolveMappings.ts
  • web/packages/agenta-entities/src/trace/etl/exportMatchingTraces.ts
  • web/packages/agenta-entities/src/workflow/index.ts
  • web/packages/agenta-entities/src/workflow/state/index.ts
  • web/packages/agenta-entities/src/workflow/state/inspectMeta.ts
  • web/packages/agenta-entities/tests/unit/export-matching-traces.test.ts
  • web/packages/agenta-entity-ui/package.json
  • web/packages/agenta-playground/src/index.ts
  • web/packages/agenta-playground/src/state/execution/index.ts
  • web/packages/agenta-playground/src/state/index.ts
  • web/packages/agenta-shared/package.json
  • web/packages/agenta-ui/src/InfiniteVirtualTable/index.ts
  • web/packages/agenta-ui/src/InfiniteVirtualTable/types.ts
  • web/packages/agenta-ui/src/RichChatInput/ComposerSendButton.tsx
  • web/packages/agenta-ui/src/RichChatInput/RichChatInput.tsx
  • web/packages/agenta-ui/src/RichChatInput/index.ts
  • web/packages/agenta-ui/src/RichChatInput/plugins/SendButton.tsx
  • web/packages/agenta-ui/src/RichChatInput/plugins/dictation.ts
  • web/tests/package.json
💤 Files with no reviewable changes (57)
  • web/oss/src/components/InfiniteVirtualTable/hooks/useEditableTable.ts
  • web/oss/src/components/SharedDrawers/SessionDrawer/types.ts
  • web/oss/src/components/InfiniteVirtualTable/features/useInfiniteTableFeaturePagination.ts
  • web/oss/src/components/InfiniteVirtualTable/hooks/useColumnDomRefs.ts
  • web/oss/src/components/InfiniteVirtualTable/columns/cells.tsx
  • web/oss/src/components/InfiniteVirtualTable/hooks/useContainerSize.ts
  • web/oss/src/components/InfiniteVirtualTable/helpers/index.ts
  • web/oss/src/components/InfiniteVirtualTable/hooks/useScopedColumnVisibility.tsx
  • web/oss/src/components/InfiniteVirtualTable/components/TableDescription.tsx
  • web/oss/src/components/InfiniteVirtualTable/columns/types.ts
  • web/oss/src/components/InfiniteVirtualTable/hooks/useTableRowSelection.ts
  • web/oss/src/components/InfiniteVirtualTable/hooks/useContainerResize.ts
  • web/oss/src/components/InfiniteVirtualTable/atoms/columnWidths.ts
  • web/oss/src/components/InfiniteVirtualTable/hooks/useInfiniteScroll.ts
  • web/oss/src/components/InfiniteVirtualTable/components/columnVisibility/TableSettingsDropdown.tsx
  • web/oss/src/components/InfiniteVirtualTable/hooks/useSmartResizableColumns.ts
  • web/oss/src/components/InfiniteVirtualTable/providers/ColumnVisibilityProvider.tsx
  • web/oss/src/components/InfiniteVirtualTable/helpers/createSimpleTableStore.ts
  • web/oss/src/components/InfiniteVirtualTable/components/columnVisibility/ColumnVisibilityMenuTrigger.tsx
  • web/oss/src/components/InfiniteVirtualTable/hooks/useTableKeyboardShortcuts.ts
  • web/oss/src/components/InfiniteVirtualTable/hooks/useTableHeaderHeight.ts
  • web/oss/src/components/InfiniteVirtualTable/hooks/useColumnVisibilityControls.ts
  • web/oss/src/components/InfiniteVirtualTable/helpers/createTableRowHelpers.ts
  • web/oss/src/components/InfiniteVirtualTable/InfiniteVirtualTable.tsx
  • web/oss/src/components/SharedDrawers/SessionDrawer/components/SessionDrawerButton/index.tsx
  • web/oss/src/components/InfiniteVirtualTable/hooks/useTableManager.tsx
  • web/oss/src/components/InfiniteVirtualTable/hooks/useScrollContainer.ts
  • web/oss/src/components/InfiniteVirtualTable/hooks/useHeaderViewportVisibility.ts
  • web/oss/src/components/InfiniteVirtualTable/components/ColumnVisibilityHeader.tsx
  • web/oss/src/components/InfiniteVirtualTable/columns/createTableColumns.ts
  • web/oss/src/components/InfiniteVirtualTable/hooks/useResizableColumns.ts
  • web/oss/src/components/InfiniteVirtualTable/components/TableShell.tsx
  • web/oss/src/components/InfiniteVirtualTable/hooks/useScrollConfig.ts
  • web/oss/src/components/InfiniteVirtualTable/hooks/useTableActions.tsx
  • web/oss/src/components/InfiniteVirtualTable/createInfiniteDatasetStore.ts
  • web/oss/src/components/InfiniteVirtualTable/context/VirtualTableScrollContainerContext.ts
  • web/oss/src/components/InfiniteVirtualTable/atoms/columnHiddenKeys.ts
  • web/oss/src/components/InfiniteVirtualTable/hooks/useInfiniteTablePagination.ts
  • web/oss/src/components/InfiniteVirtualTable/atoms/columnVisibility.ts
  • web/oss/src/components/InfiniteVirtualTable/components/filters/FiltersPopoverTrigger.tsx
  • web/oss/src/components/InfiniteVirtualTable/components/ColumnVisibilityTrigger.tsx
  • web/oss/src/components/InfiniteVirtualTable/hooks/useColumnVisibility.ts
  • web/oss/src/components/InfiniteVirtualTable/hooks/useRowHeight.tsx
  • web/oss/src/components/InfiniteVirtualTable/features/index.ts
  • web/oss/src/components/InfiniteVirtualTable/context/ColumnVisibilityContext.ts
  • web/oss/src/components/InfiniteVirtualTable/utils/columnUtils.ts
  • web/oss/src/components/InfiniteVirtualTable/context/ColumnVisibilityFlagContext.tsx
  • web/oss/src/components/InfiniteVirtualTable/components/InfiniteVirtualTableInner.tsx
  • web/oss/src/components/InfiniteVirtualTable/createInfiniteTableStore.ts
  • web/oss/src/components/InfiniteVirtualTable/columns/createStandardColumns.tsx
  • web/oss/src/components/InfiniteVirtualTable/hooks/useExpandableRows.tsx
  • web/oss/src/components/InfiniteVirtualTable/index.ts
  • web/oss/src/components/InfiniteVirtualTable/hooks/useTableExport.ts
  • web/oss/src/components/InfiniteVirtualTable/components/columnVisibility/ColumnVisibilityPopoverContent.tsx
  • web/oss/src/components/InfiniteVirtualTable/providers/InfiniteVirtualTableStoreProvider.tsx
  • web/oss/src/components/InfiniteVirtualTable/types.ts
  • web/oss/src/components/InfiniteVirtualTable/features/InfiniteVirtualTableFeatureShell.tsx
🛑 Comments failed to post (5)
.agents/skills/add-announcement/SKILL.md (1)

219-222: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Use GitButler commands in the example workflow.

Raw git add/git commit can commit unassigned changes from another lane. Replace them with lane-scoped but rub and but commit <lane> --only commands.

As per coding guidelines, when GitButler workspace mode is active, use the but CLI instead of raw git commit.

Source: Coding guidelines

.agents/skills/create-changelog-announcement/SKILL.md (2)

272-285: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Keep the sidebar example valid JSON.

The fenced block is labeled json but contains // ... existing entries, which makes changelog.json invalid. Remove the comment or use a valid JSON example.


370-386: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Include the required summary structure in the canonical example.

The detailed-entry example starts directly with ## Overview and omits both <Summary>...</Summary> and {/* truncate */}, despite the earlier instructions making them required. Copying this example can produce an incomplete changelog index entry.

.agents/skills/update-llm-model-list/SKILL.md (2)

35-46: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Make the “no local install needed” checker executable.

uvx --with litellm provides LiteLLM, but the script imports agenta.sdk.utils.assets from /tmp. In a clean checkout, the Agenta package is neither installed nor on sys.path, so the command fails before checking any model. Install the local package explicitly, set the required source path and dependencies, or make the script consume a serialized model list.

Also applies to: 70-70


50-53: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Restrict prefix stripping to the documented providers.

exists() strips any prefix containing /, so a gemini/invalid-name entry can pass if invalid-name exists in LiteLLM. Only strip the Anthropic and Cohere prefixes described in the rules; otherwise require the exact provider-prefixed key.

Suggested fix
 def exists(m):
     if m in mc: return True
-    if "/" in m and m.split("/", 1)[1] in mc: return True
+    if m.startswith(("anthropic/", "cohere/")):
+        return m.split("/", 1)[1] in mc
     return False
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

def exists(m):
    if m in mc: return True
    if m.startswith(("anthropic/", "cohere/")):
        return m.split("/", 1)[1] in mc
    return False

@mmabrouk
mmabrouk changed the base branch from main to release/v0.106.1 July 29, 2026 19:55
@mmabrouk
mmabrouk merged commit 0638af8 into release/v0.106.1 Jul 29, 2026
44 of 45 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XL This PR changes 500-999 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant