Conversation
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #1070. Subsumes #1064.
Replaces the previously closed PR #1074. Same branch, clean single-narrative summary of what actually landed.
Summary
Eight bundled changes that all touch the same frontend files (plus one backend semantics fix for the analytics overview):
Radix UI to Base UI migration.
radix-ui+cmdkfully removed (115 transitive packages);@base-ui/react@1.3.0+cmdk-base@1.0.0installed (8 packages).components.jsonswitches fromradix-novatobase-vega. 14 component files migrated:button.tsx(via a local<Slot>helper over@base-ui/react/merge-props),dialog.tsx,confirm-dialog.tsx,theme-toggle.tsx,command-palette.tsx(nowcmdk-basehosted inside Base UI Dialog for focus trap + escape + portal), six page-level Dialog / AlertDialog files,OrgEditPage.tsxTabs, and both Workflow Menu files. Data attributes rewritten (data-[state=open]todata-[open],data-[state=active]todata-[active], plusdata-[starting-style]/data-[ending-style]for transition lifecycle).CSP nonce activation, end-to-end.
nginx.confgenerates a per-request nonce from$request_idand substitutes it into__CSP_NONCE__viasub_filter.index.htmlexposes the nonce on<meta name="csp-nonce">.web/src/lib/csp.tsreads it (rejecting the un-substituted placeholder and logging warnings when missing/placeholder so production misconfig is visible).App.tsxwraps the tree in<CSPProvider nonce>(Base UI) +<MotionConfig nonce>(Framer Motion).security-headers.confreplacesstyle-src 'self' 'unsafe-inline'with CSP Level 3 split directives:style-src-elem 'self' 'nonce-$csp_nonce'(locks down<style>elements) +style-src-attr 'unsafe-inline'(required by Floating UI positioning, not a practical XSS vector:styleattributes cannot execute JavaScript).Personality trimming WebSocket notification (folded in from feat: WebSocket notification when personality trimming activates #1064):
engine.personality_trimming_notifysetting (BOOLEAN, defaulttrue).WsEventType.PERSONALITY_TRIMMEDenum member.personality_trim_notifiercallback parameter onAgentEngine, invoked best-effort from_prepare_context(re-raisesMemoryError/RecursionError/asyncio.CancelledError; logsprompt.personality.notify_failedand swallows everything else).synthorg.api.app.make_personality_trim_notifierfactory that returns a ready-to-wire async callback bound to the liveChannelsPlugin. External engine runners (CLI workers, K8s jobs) call this factory and pass the result intoAgentEngine.personality.trimmedadded toWsEventType+WS_EVENT_TYPE_VALUES. NewuseGlobalNotificationshook mounted inAppLayoutsubscribes to theagentschannel globally;agentsstore dispatches an info toast withagent_name(length-bounded) +before to aftertokens when the event arrives, and logs a warning on malformed payloads.Org chart page full rebuild.
w-[240px]/h-[90px]so layout centering matches rendered size.minlenapproach was quantized into 50px rank jumps).<HierarchyEdge>SVG L-path replaces React Flow'sgetSmoothStepPath, which had a Z-shape fanout limitation that silently ignoredcenterYon cross-x edges. L-path routes cleanly with a single vertical bend.useLiveEdgeActivityhook subscribes to the messages store and pulses particles along edges that carry traffic in the last 3s. Three modes via segmented control: Flow (always on), Live (traffic-driven, default), Off. SVGanimateMotionwith uniform Manhattan-distance speed so particles don't visually "slow down" on longer edges.useOrgChartPrefs(web/src/stores/org-chart-prefs.ts):particleFlowMode: 'live', add-agent + lead badge + budget bar visible, status dots + minimap hidden.Agent routing by id, not name.
/agents/:agentNameswitched to/agents/:agentId. Names can contain arbitrary characters that broke backend lookup after URL encoding.AgentDetailPageresolves the agent fromuseCompanyStoreby id (falling back to name for legacy config) and passes the resolved name to the data hook. Navigation sites updated:AgentGridView,OrgChartPage,ProjectTeamSection.Dynamic department filter. Department dropdown on the agents page now reads from
useCompanyStore().config.departmentsinstead of the hardcodedDEPARTMENT_NAME_VALUESenum, so it matches the user-configured department list (wizard, packs, manual edits). Usesdisplay_namewhen provided, falls back toformatLabel(name).Coming-soon gates on missing backend CRUD. New shared constant in
web/src/pages/org-edit/coming-soon.tspoints at issue feat: implement backend CRUD endpoints for company, departments, and agents (all 9 write paths are missing) #1081. Nine mutation paths in the org-edit dialogs / drawers surface a banner explaining the limitation instead of hitting 405 responses.Analytics "active agents" runtime semantics.
_resolve_agent_countsinanalytics.pynow computes "active" as agents currently executing a task (task statusIN_PROGRESS,assigned_toin the employed set), not "agents with employment status ACTIVE". The previous semantics conflated HR lifecycle with runtime state and produced the surprising "4 active / 0 idle / 0 tasks" display on the overview dashboard._assemble_overviewnow passesall_tasksinto the helper so the computation reuses the already-fetched task list.Reviewer attention items
Combobox criterion (issue §4a): the issue text says "provider model search (currently a filtered list in
ProviderFormModal)" should use Combobox. That filtered list does not exist in the current repo: the only filter inProviderFormModal.tsxis a static 3-item auth-type filter, not a typeahead. The PR documents the keep-decision inweb/CLAUDE.md-> Base UI Adoption Decisions ("Combobox, Autocomplete: Not adopted: no current typeahead call sites in the dashboard that would benefit. Re-evaluate when filterable selects become a feature requirement.").Bundle size direction: the issue anticipated a net reduction; the actual delta is a 3% increase (
vendor-ui150 kB to 230 kB, total dist 3.4M to 3.5M). The tradeoff is Base UI's more comprehensive primitive surface (Floating UI positioning, focus management, transition tracking) versus the narrow subset shadcn previously pulled from Radix. First-class CSP nonce support, broader component coverage, and active upstream maintenance justify the delta.Personality trimming end-to-end wiring:
AgentEngineis not constructed anywhere undersrc/today (only in tests): it is library code that external runners construct. This PR provides themake_personality_trim_notifierfactory so external runners can wire the callback in one line, but the in-tree API layer does not itself construct engines. The frontend toast path is fully wired and will render when any engine host emits the event. Closing the in-tree wiring gap is a separate architectural decision, out of scope.style-src-attr 'unsafe-inline': retained for Floating UI's transient inline positioning styles (style="position: fixed; top: ...; left: ...").styleattributes cannot execute JavaScript and cannot carry CSP nonces per the CSS spec. This is the narrowest permissive the CSP spec allows. Documented indocs/security.md-> CSP Nonce Infrastructure.Verification
All gates green:
uv run ruff check src/ tests/-- cleanuv run ruff format --check src/ tests/-- 1541 files already formatteduv run mypy src/ tests/-- clean (1541 source files)uv run python -m pytest tests/ -n 8 -k analytics-- 59 passednpm --prefix web run lint-- zero warningsnpm --prefix web run type-check-- cleannpm --prefix web run test-- 2406 passed (203 files)Zero Radix references remain in tracked files.
Non-goals
web/CLAUDE.md).