feat: Org Chart page (living nodes, status, CRUD, department health)#870
feat: Org Chart page (living nodes, status, CRUD, department health)#870
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (2)
📜 Recent review details⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
🧰 Additional context used📓 Path-based instructions (1)web/src/**/*.{ts,tsx}📄 CodeRabbit inference engine (CLAUDE.md)
Files:
🧠 Learnings (3)📓 Common learnings📚 Learning: 2026-03-20T08:28:32.845ZApplied to files:
📚 Learning: 2026-03-27T14:30:49.093ZApplied to files:
🔇 Additional comments (10)
WalkthroughReplaces the Org Chart placeholder with a full React Flow–based implementation: OrgChartPage (and OrgChartInner) plus a new hook useOrgChartData that builds nodes/edges from store state. Adds node renderers (AgentNode, CeoNode, DepartmentGroupNode, DepartmentStatsBar), UI pieces (OrgChartToolbar, OrgChartSkeleton, NodeContextMenu, HierarchyEdge), layout and graph utilities (applyDagreLayout, buildOrgTree, status-mapping), and enhanced Zustand stores (company, agents) with WebSocket handling and per-agent runtime status. Adds Storybook stories, many Vitest tests, imports XYFlow/React Flow CSS, and updates web/package.json with 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Comment |
Dependency Review✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.Snapshot WarningsEnsure that dependencies are being submitted on PR branches. Re-running this action after a short time may resolve the issue. See the documentation for more information and troubleshooting advice. OpenSSF Scorecard
Scanned Files
|
There was a problem hiding this comment.
Code Review
This pull request implements a comprehensive Org Chart feature using React Flow and Dagre for hierarchical layout. Key additions include specialized node components (Agent, CEO, Department), a custom hook for data management with real-time WebSocket updates, and updated Zustand stores for agent and company data. The implementation is supported by extensive unit tests and Storybook stories. Review feedback suggests improving type safety when accessing node data and replacing magic numbers with named constants in the layout logic to enhance maintainability.
web/src/pages/OrgChartPage.tsx
Outdated
| const handleDelete = useCallback( | ||
| (nodeId: string) => { | ||
| const node = nodes.find((n) => n.id === nodeId) | ||
| const label = node ? String((node.data as { name?: string; displayName?: string }).name ?? (node.data as { displayName?: string }).displayName ?? nodeId) : nodeId |
There was a problem hiding this comment.
The type assertion here is not as safe as it could be. Since node.data is essentially any from React Flow's perspective, you're casting it to a loose shape ({ name?: string; displayName?: string }). This can be brittle if the node data structures change.
A more robust approach would be to use type guards or property checks (e.g., 'name' in node.data) to safely access name or displayName based on the well-defined data types for your nodes (AgentNodeData, DepartmentGroupData). This would improve maintainability and type safety.
web/src/pages/org/layout.ts
Outdated
| } | ||
|
|
||
| const groupX = minX - padding | ||
| const groupY = minY - padding - 40 |
There was a problem hiding this comment.
The magic number 40 is used here and on line 97 to account for the vertical space occupied by the department group node's header. Hardcoding this value makes the layout logic brittle. If the styling of DepartmentGroupNode changes, this value might need to be updated here as well, which is easy to forget.
Consider defining this value as a named constant at the top of the file (e.g., const GROUP_NODE_HEADER_HEIGHT = 40) and using it here. This would improve readability and maintainability.
There was a problem hiding this comment.
Actionable comments posted: 24
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@web/src/__tests__/pages/org/build-org-tree.test.ts`:
- Around line 284-294: The test mutates config.company_name and then passes a
spread with the same value to buildOrgTree, which is redundant; remove the
standalone assignment config.company_name = 'Acme Inc' and keep only the spread
when calling buildOrgTree (refer to makeConfig, config, and buildOrgTree in the
"includes companyName in CEO node data" test) so the test sets company_name
exactly once without mutation.
In `@web/src/__tests__/pages/org/layout.test.ts`:
- Around line 67-80: The test title is misleading: update the it(...)
description in the test that uses makeNode/makeEdge and calls applyDagreLayout
so it accurately reflects the asserted behavior (the department node is returned
with a position rather than being excluded). Change the string from "excludes
department group nodes from dagre layout" to something like "handles department
group nodes separately from dagre layout" or "returns department group nodes
with positions" so the name matches the assertions using result.find(...),
dept.position, and expect(result).toHaveLength(3).
In `@web/src/__tests__/pages/org/NodeContextMenu.test.tsx`:
- Around line 5-11: The shared mock baseProps.onClose in the NodeContextMenu
test suite should be reset before each test to avoid state leakage; inside the
describe('NodeContextMenu') block add a beforeEach that calls vi.resetAllMocks()
or reassigns baseProps.onClose = vi.fn(), ensuring each test starts with a fresh
mock for the onClose handler referenced by baseProps used in the tests.
In `@web/src/__tests__/pages/org/OrgChartToolbar.test.tsx`:
- Around line 6-12: The test currently defines shared mock functions in the
module-scope constant defaultProps which can leak call state between tests;
replace this with a factory or recreate props per test (e.g., implement a
makeDefaultProps() that returns a new object with fresh vi.fn() for
onViewModeChange, onFitView, onZoomIn, onZoomOut) or call vi.resetAllMocks() in
a beforeEach; update references to use the new factory or per-test props instead
of the shared defaultProps constant.
In `@web/src/hooks/useOrgChartData.ts`:
- Around line 45-49: The ESLint disable is referencing a non-existent rule name;
update the hook to either install the missing linter plugin
`eslint-plugin-react-hooks` and change the comment to `//
eslint-disable-next-line react-hooks/exhaustive-deps` or remove the disable
entirely if you want the `useEffect` dependency check; locate the useEffect
where `polling.start()` / `polling.stop()` are called inside `useOrgChartData`
and apply the chosen change (add the plugin to devDependencies and enable it in
ESLint config if keeping the disable, or simply delete the incorrect `//
eslint-disable-next-line `@eslint-react/exhaustive-deps`` line).
In `@web/src/pages/org/AgentNode.stories.tsx`:
- Around line 34-38: The Storybook story meta for AgentNode is missing
accessibility test configuration; update the exported meta object (the const
meta that satisfies Meta<typeof Wrapper>) to include a parameters field with an
a11y.test configuration (e.g., parameters: { a11y: { test: /* desired test
config or presets */ } }) so Storybook runs the accessibility checks for the
Wrapper component/story. Ensure the new parameters.a11y.test key is present
alongside title/component/tags in the meta object.
In `@web/src/pages/org/AgentNode.tsx`:
- Line 27: The AgentNode component currently uses hardcoded pixel width utility
classes ('min-w-[140px] max-w-[180px]')—replace these with the project's
density-aware sizing or standard Tailwind spacing utilities instead; update the
class list in the AgentNode JSX where those tokens appear to use the appropriate
density token (or Tailwind equivalents like min-w-36 / max-w-44) so layout
follows design tokens and responsive/density rules, and verify the node still
renders correctly across breakpoints.
In `@web/src/pages/org/build-org-tree.ts`:
- Around line 100-119: The department node currently defaults missing health to
100%/0 which hides transient API failures; in the nodes.push call that builds
DepartmentGroupData (refer to healthMap.get(dept.name), groupId, and the
nodes.push object), change the health-derived fields so that when health is
undefined you set healthPercent, taskCount and costUsd to null (or leave
undefined) instead of 100/0; preserve agentCount and activeCount logic but
ensure DepartmentGroupData’s healthPercent/taskCount/costUsd remain nullable so
the renderer can show a neutral/loading/error state.
- Around line 96-99: The loop in build-org-tree is currently skipping
departments with no members (the check using deptMembers.length === 0), which
prevents newly created empty departments from rendering; remove that
early-continue so every department in config.departments is processed and
included even when deptAgents.get(dept.name) returns an empty array, ensuring
empty departments are represented (the existing empty-group handling in
web/src/pages/org/layout.ts will take care of rendering them). Locate the for
(const dept of config.departments) block and delete or disable the if
(deptMembers.length === 0) continue guard so deptMembers (possibly []) is still
used to create the department node.
In `@web/src/pages/org/CeoNode.stories.tsx`:
- Around line 34-38: The Storybook story's meta object (const meta) lacks
accessibility test configuration; update the meta for the CeoNode story to
include parameters.a11y.test with the desired a11y rule set (e.g., 'wcag2a' or
your project's configured tests) so Storybook runs automated accessibility
checks — modify the existing meta (satisfies Meta<typeof Wrapper>) to add a
parameters field containing an a11y.test entry referencing the configured tests
for Wrapper/CeoNode.
- Around line 43-69: Add two new Story exports for the missing runtime statuses
by copying the existing Active/Idle pattern: create exports named Error and
Offline that set args.data.runtimeStatus to 'error' and 'offline' respectively
(and adjust other fields if desired). Ensure they follow the same shape as the
existing Active and Idle stories (export const Error: Story = { args: { data: {
... } } } and export const Offline: Story = { ... }) so CeoNode/StatusBadge
renders the error and offline visuals in Storybook.
In `@web/src/pages/org/CeoNode.tsx`:
- Line 23: Update the Tailwind important modifier syntax used in the CeoNode
component: replace the old prefix-style modifiers in the Handle JSX (className
on Handle using "!bg-accent !size-1.5") with Tailwind v4 postfix syntax (e.g.,
"bg-accent! size-1.5!"); locate the Handle element (Handle type="target"
position={Position.Top}) and change its className accordingly so it uses postfix
"!" after each utility.
In `@web/src/pages/org/DepartmentGroupNode.stories.tsx`:
- Around line 35-42: The story meta object for the DepartmentGroupNode story
(the const meta and its relation to Wrapper) is missing the Storybook a11y test
configuration; update the meta to include a parameters property with an
a11y.test key (set to one of the allowed values: 'error' | 'todo' | 'off') so
Storybook will run accessibility tests for this component, e.g. add parameters:
{ a11y: { test: 'error' } } to the existing meta object.
In `@web/src/pages/org/DepartmentStatsBar.tsx`:
- Around line 5-11: The component props (DepartmentStatsBarProps) currently fall
back to EUR when currency is undefined, which conflicts with the costUsd prop
semantics; change the formatting logic in DepartmentStatsBar (where costUsd and
currency are used, e.g., the money formatting call around line ~27) to default
to "USD" when currency is not provided or when costUsd is present (i.e., use
currency ?? "USD" or detect costUsd !== null to force "USD"), and ensure the
Intl.NumberFormat/formatMoney call uses that resolved currency so the displayed
symbol/value correctly reflects USD.
In `@web/src/pages/org/layout.ts`:
- Around line 43-47: The Dagre layout is being computed with fallback sizes
because measured dimensions are not yet available; update applyDagreLayout usage
so layout runs with real node sizes: either (preferred) have useOrgChartData
re-run applyDagreLayout in a useEffect when nodes gain measured dimensions
(watch a measuredAvailable flag or node.measured changes) instead of in a
useMemo, or ensure buildOrgTree supplies stable width/height in node.data and
change the layout code (the loop that calls g.setNode for leaf nodes) to use
those stable dimensions (e.g., node.data.width/height) rather than node.measured
so Dagre computes correct spacing and group bounds.
In `@web/src/pages/org/NodeContextMenu.stories.tsx`:
- Around line 20-36: Add a third story named CeoMenu to mirror AgentMenu and
DepartmentMenu so the NodeContextMenu component's 'ceo' nodeType is covered;
export const CeoMenu: Story = { args: { nodeId: 'ceo-1', nodeType: 'ceo',
position: { x: 100, y: 50 }, onClose: () => {} } } (use the same shape/props as
AgentMenu and DepartmentMenu).
- Around line 4-15: Update the Storybook meta object for NodeContextMenu to
include an accessibility test configuration by adding a parameters.a11y.test
entry; modify the existing meta constant (the object assigned to meta that
"satisfies Meta<typeof NodeContextMenu>") to include a parameters property with
a11y.test set to the desired test flags/configuration so Storybook runs
accessibility checks for the NodeContextMenu story.
In `@web/src/pages/org/NodeContextMenu.tsx`:
- Around line 110-113: The menu buttons in NodeContextMenu (the JSX <button>
rendered for each menu item using key={item.label} and onClick={item.action})
lack an explicit type and can accidentally submit enclosing forms; update the
button element to include type="button" so these menu actions do not trigger
form submission when rendered inside a form context.
- Line 99: The nodeType check in NodeContextMenu.tsx currently maps only
'department' to departmentItems and everything else (including 'ceo') to
agentItems; update the selection logic so 'ceo' does not inherit agent CRUD
actions—either map 'ceo' to departmentItems or a new ceoItems set. Concretely,
change the conditional that assigns items (referencing nodeType,
departmentItems, agentItems) to explicitly handle 'ceo' (e.g., nodeType ===
'department' || nodeType === 'ceo') or introduce and use a distinct ceoItems
array and use that when nodeType === 'ceo'.
In `@web/src/pages/org/OrgChartSkeleton.stories.tsx`:
- Around line 8-14: The decorator currently sets the background via inline style
in the decorators array ((Story) => (<div style={{ height: 400, background:
'var(--background)' }}>...)), so remove the inline background property and leave
only the height styling; rely on Storybook's global backgrounds config or, if
this story needs a custom background, add a story-level parameters.backgrounds
entry instead of an inline style.
In `@web/src/pages/org/OrgChartToolbar.tsx`:
- Around line 33-52: The two toggle Buttons in OrgChartToolbar (the ones using
GitBranch and Network) only indicate active state visually; update each Button
to expose that state to assistive tech by adding an aria-pressed prop set to
true when viewMode matches that button's mode and false otherwise (e.g.,
aria-pressed={viewMode === 'hierarchy'} for the hierarchy Button and
aria-pressed={viewMode === 'force'} for the communication Button), keeping
existing onViewModeChange handlers and aria-labels intact.
In `@web/src/pages/org/status-mapping.ts`:
- Around line 8-18: In mapHrToRuntime the cases 'onboarding' and 'active' both
return 'idle'—combine them into a single fall-through case (e.g., case
'onboarding': case 'active': return 'idle') inside the mapHrToRuntime function
to improve readability while preserving behavior; update the switch in
mapHrToRuntime (types AgentStatus / AgentRuntimeStatus remain unchanged).
In `@web/src/pages/OrgChartPage.tsx`:
- Around line 110-118: handleNodeClick uses a type assertion on node.data to
access name which can throw if data is missing or malformed; update the
handleNodeClick callback to defensively check node.data and that (node.data as
any).name is a string before calling navigate (keep using
encodeURIComponent(name)), and if the guard fails simply return early or log a
warning; locate the handleNodeClick function and replace the direct assertion
with a safe extraction/guard that prevents navigation when name is absent while
keeping behavior for valid agent/ceo nodes (buildOrgTree remains the source of
truth).
In `@web/src/stores/company.ts`:
- Around line 32-45: fetchDepartmentHealths currently calls listDepartments({
limit: 100 }) which only returns the first page and misses departments; update
fetchDepartmentHealths to page through the full list (using listDepartments'
pagination cursor/nextToken or similar) and accumulate all departments before
mapping to getDepartmentHealth, or alternatively drive the health lookups from
config.departments to guarantee alignment with the configured org; ensure you
replace the single listDepartments call in fetchDepartmentHealths with a loop or
helper that collects all pages (referencing listDepartments and
getDepartmentHealth) and then map over the complete array to create
healthPromises.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: acfda971-3933-4a5d-993c-f1fee2224d96
⛔ Files ignored due to path filters (1)
web/package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (35)
CLAUDE.mdweb/package.jsonweb/src/__tests__/pages/org/DepartmentStatsBar.test.tsxweb/src/__tests__/pages/org/NodeContextMenu.test.tsxweb/src/__tests__/pages/org/OrgChartPage.test.tsxweb/src/__tests__/pages/org/OrgChartSkeleton.test.tsxweb/src/__tests__/pages/org/OrgChartToolbar.test.tsxweb/src/__tests__/pages/org/build-org-tree.test.tsweb/src/__tests__/pages/org/layout.test.tsweb/src/__tests__/pages/org/status-mapping.test.tsweb/src/__tests__/stores/agents.test.tsweb/src/__tests__/stores/company.test.tsweb/src/hooks/useOrgChartData.tsweb/src/pages/OrgChartPage.tsxweb/src/pages/org/AgentNode.stories.tsxweb/src/pages/org/AgentNode.tsxweb/src/pages/org/CeoNode.stories.tsxweb/src/pages/org/CeoNode.tsxweb/src/pages/org/DepartmentGroupNode.stories.tsxweb/src/pages/org/DepartmentGroupNode.tsxweb/src/pages/org/DepartmentStatsBar.stories.tsxweb/src/pages/org/DepartmentStatsBar.tsxweb/src/pages/org/HierarchyEdge.tsxweb/src/pages/org/NodeContextMenu.stories.tsxweb/src/pages/org/NodeContextMenu.tsxweb/src/pages/org/OrgChartSkeleton.stories.tsxweb/src/pages/org/OrgChartSkeleton.tsxweb/src/pages/org/OrgChartToolbar.stories.tsxweb/src/pages/org/OrgChartToolbar.tsxweb/src/pages/org/build-org-tree.tsweb/src/pages/org/layout.tsweb/src/pages/org/status-mapping.tsweb/src/stores/agents.tsweb/src/stores/company.tsweb/src/styles/global.css
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
- GitHub Check: Build Web
- GitHub Check: Build Backend
- GitHub Check: Build Sandbox
- GitHub Check: Dashboard Test
- GitHub Check: Dependency Review
- GitHub Check: Analyze (python)
🧰 Additional context used
📓 Path-based instructions (8)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx}: Use TypeScript 6+ withpathsfor module resolution (remove deprecatedbaseUrl);esModuleInteropis always true
In TypeScript,strictdefaults to true andtypesdefaults to[]; do not auto-discover@types/*— must explicitly list needed types
Files:
web/src/__tests__/pages/org/OrgChartToolbar.test.tsxweb/src/pages/org/OrgChartSkeleton.tsxweb/src/__tests__/stores/agents.test.tsweb/src/pages/org/OrgChartToolbar.stories.tsxweb/src/__tests__/pages/org/OrgChartSkeleton.test.tsxweb/src/pages/org/OrgChartSkeleton.stories.tsxweb/src/pages/org/status-mapping.tsweb/src/pages/org/HierarchyEdge.tsxweb/src/pages/org/DepartmentGroupNode.stories.tsxweb/src/__tests__/pages/org/DepartmentStatsBar.test.tsxweb/src/pages/org/CeoNode.tsxweb/src/__tests__/pages/org/OrgChartPage.test.tsxweb/src/__tests__/pages/org/status-mapping.test.tsweb/src/pages/OrgChartPage.tsxweb/src/hooks/useOrgChartData.tsweb/src/__tests__/stores/company.test.tsweb/src/stores/agents.tsweb/src/pages/org/NodeContextMenu.stories.tsxweb/src/pages/org/layout.tsweb/src/pages/org/DepartmentStatsBar.tsxweb/src/pages/org/DepartmentGroupNode.tsxweb/src/pages/org/NodeContextMenu.tsxweb/src/pages/org/OrgChartToolbar.tsxweb/src/__tests__/pages/org/layout.test.tsweb/src/__tests__/pages/org/NodeContextMenu.test.tsxweb/src/pages/org/CeoNode.stories.tsxweb/src/pages/org/AgentNode.tsxweb/src/pages/org/AgentNode.stories.tsxweb/src/__tests__/pages/org/build-org-tree.test.tsweb/src/pages/org/DepartmentStatsBar.stories.tsxweb/src/pages/org/build-org-tree.tsweb/src/stores/company.ts
web/src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
web/src/**/*.{ts,tsx}: Use React 19 with TypeScript 6+ in web dashboard; enforce design tokens (no hardcoded colors, fonts, spacing) and reuse components fromweb/src/components/ui/
Always reuse existing components fromweb/src/components/ui/(StatusBadge, MetricCard, Sparkline, SectionCard, AgentCard, DeptHealthBar, ProgressGauge, StatPill, Avatar, Button, Toast, Skeleton, EmptyState, ErrorBoundary, ConfirmDialog, CommandPalette, InlineEdit, AnimatedPresence, StaggerGroup/StaggerItem) before creating new ones
Use design tokens exclusively in web components: Tailwind semantic classes (text-foreground,bg-card,text-accent,text-success,bg-danger, etc.) or CSS variables (var(--so-accent)); never hardcode hex values or pixel spacing
Usefont-sansorfont-mono(Geist tokens) in web components; never setfontFamilydirectly
Use density-aware spacing tokens in web components (p-card,gap-section-gap,gap-grid-gap) or standard Tailwind spacing; never hardcode pixel values for layout spacing
Use shadow and border token variables in web components (var(--so-shadow-card-hover),border-border,border-bright); never hardcode shadow or border styles
In React components, importcnfrom@/lib/utilsfor conditional class merging; never concatenate class strings directly
Do not recreate status dots inline; use<StatusBadge>component
Do not build card-with-header layouts from scratch; use<SectionCard>component
Do not create metric displays withtext-metric font-bold; use<MetricCard>component
Do not render initials circles manually; use<Avatar>component
Do not create complex (>8 line) JSX inside.map()blocks; extract to a shared component
Files:
web/src/__tests__/pages/org/OrgChartToolbar.test.tsxweb/src/pages/org/OrgChartSkeleton.tsxweb/src/__tests__/stores/agents.test.tsweb/src/pages/org/OrgChartToolbar.stories.tsxweb/src/__tests__/pages/org/OrgChartSkeleton.test.tsxweb/src/pages/org/OrgChartSkeleton.stories.tsxweb/src/pages/org/status-mapping.tsweb/src/pages/org/HierarchyEdge.tsxweb/src/pages/org/DepartmentGroupNode.stories.tsxweb/src/__tests__/pages/org/DepartmentStatsBar.test.tsxweb/src/pages/org/CeoNode.tsxweb/src/__tests__/pages/org/OrgChartPage.test.tsxweb/src/__tests__/pages/org/status-mapping.test.tsweb/src/pages/OrgChartPage.tsxweb/src/hooks/useOrgChartData.tsweb/src/__tests__/stores/company.test.tsweb/src/stores/agents.tsweb/src/pages/org/NodeContextMenu.stories.tsxweb/src/pages/org/layout.tsweb/src/pages/org/DepartmentStatsBar.tsxweb/src/pages/org/DepartmentGroupNode.tsxweb/src/pages/org/NodeContextMenu.tsxweb/src/pages/org/OrgChartToolbar.tsxweb/src/__tests__/pages/org/layout.test.tsweb/src/__tests__/pages/org/NodeContextMenu.test.tsxweb/src/pages/org/CeoNode.stories.tsxweb/src/pages/org/AgentNode.tsxweb/src/pages/org/AgentNode.stories.tsxweb/src/__tests__/pages/org/build-org-tree.test.tsweb/src/pages/org/DepartmentStatsBar.stories.tsxweb/src/pages/org/build-org-tree.tsweb/src/stores/company.ts
web/src/__tests__/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
web/src/__tests__/**/*.{ts,tsx}: Use fast-check for property-based testing in React; usefc.assertandfc.property
Use Vitest for React unit testing with coverage scoped to files changed vs origin/main
Files:
web/src/__tests__/pages/org/OrgChartToolbar.test.tsxweb/src/__tests__/stores/agents.test.tsweb/src/__tests__/pages/org/OrgChartSkeleton.test.tsxweb/src/__tests__/pages/org/DepartmentStatsBar.test.tsxweb/src/__tests__/pages/org/OrgChartPage.test.tsxweb/src/__tests__/pages/org/status-mapping.test.tsweb/src/__tests__/stores/company.test.tsweb/src/__tests__/pages/org/layout.test.tsweb/src/__tests__/pages/org/NodeContextMenu.test.tsxweb/src/__tests__/pages/org/build-org-tree.test.ts
web/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Use ESLint with
@eslint-react/eslint-pluginand eslint-plugin-security in web dashboard
Files:
web/src/__tests__/pages/org/OrgChartToolbar.test.tsxweb/src/pages/org/OrgChartSkeleton.tsxweb/src/__tests__/stores/agents.test.tsweb/src/pages/org/OrgChartToolbar.stories.tsxweb/src/__tests__/pages/org/OrgChartSkeleton.test.tsxweb/src/pages/org/OrgChartSkeleton.stories.tsxweb/src/pages/org/status-mapping.tsweb/src/pages/org/HierarchyEdge.tsxweb/src/pages/org/DepartmentGroupNode.stories.tsxweb/src/__tests__/pages/org/DepartmentStatsBar.test.tsxweb/src/pages/org/CeoNode.tsxweb/src/__tests__/pages/org/OrgChartPage.test.tsxweb/src/__tests__/pages/org/status-mapping.test.tsweb/src/pages/OrgChartPage.tsxweb/src/hooks/useOrgChartData.tsweb/src/__tests__/stores/company.test.tsweb/src/stores/agents.tsweb/src/pages/org/NodeContextMenu.stories.tsxweb/src/pages/org/layout.tsweb/src/pages/org/DepartmentStatsBar.tsxweb/src/pages/org/DepartmentGroupNode.tsxweb/src/pages/org/NodeContextMenu.tsxweb/src/pages/org/OrgChartToolbar.tsxweb/src/__tests__/pages/org/layout.test.tsweb/src/__tests__/pages/org/NodeContextMenu.test.tsxweb/src/pages/org/CeoNode.stories.tsxweb/src/pages/org/AgentNode.tsxweb/src/pages/org/AgentNode.stories.tsxweb/src/__tests__/pages/org/build-org-tree.test.tsweb/src/pages/org/DepartmentStatsBar.stories.tsxweb/src/pages/org/build-org-tree.tsweb/src/stores/company.ts
web/**
📄 CodeRabbit inference engine (CLAUDE.md)
Use Node.js 22+ and npm for web dashboard; all dependencies in
web/package.json(React 19, react-router, shadcn/ui, Radix UI, Tailwind CSS 4, Zustand, Recharts, Framer Motion, Axios, Lucide React, Geist fonts, Storybook 10, Vitest, ESLint, fast-check, etc.)
Files:
web/src/__tests__/pages/org/OrgChartToolbar.test.tsxweb/src/styles/global.cssweb/package.jsonweb/src/pages/org/OrgChartSkeleton.tsxweb/src/__tests__/stores/agents.test.tsweb/src/pages/org/OrgChartToolbar.stories.tsxweb/src/__tests__/pages/org/OrgChartSkeleton.test.tsxweb/src/pages/org/OrgChartSkeleton.stories.tsxweb/src/pages/org/status-mapping.tsweb/src/pages/org/HierarchyEdge.tsxweb/src/pages/org/DepartmentGroupNode.stories.tsxweb/src/__tests__/pages/org/DepartmentStatsBar.test.tsxweb/src/pages/org/CeoNode.tsxweb/src/__tests__/pages/org/OrgChartPage.test.tsxweb/src/__tests__/pages/org/status-mapping.test.tsweb/src/pages/OrgChartPage.tsxweb/src/hooks/useOrgChartData.tsweb/src/__tests__/stores/company.test.tsweb/src/stores/agents.tsweb/src/pages/org/NodeContextMenu.stories.tsxweb/src/pages/org/layout.tsweb/src/pages/org/DepartmentStatsBar.tsxweb/src/pages/org/DepartmentGroupNode.tsxweb/src/pages/org/NodeContextMenu.tsxweb/src/pages/org/OrgChartToolbar.tsxweb/src/__tests__/pages/org/layout.test.tsweb/src/__tests__/pages/org/NodeContextMenu.test.tsxweb/src/pages/org/CeoNode.stories.tsxweb/src/pages/org/AgentNode.tsxweb/src/pages/org/AgentNode.stories.tsxweb/src/__tests__/pages/org/build-org-tree.test.tsweb/src/pages/org/DepartmentStatsBar.stories.tsxweb/src/pages/org/build-org-tree.tsweb/src/stores/company.ts
web/src/pages/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Use React Router with lazy-loaded page components (one per route); place page-scoped sub-components in
pages/<page-name>/subdirectories
Files:
web/src/pages/org/OrgChartSkeleton.tsxweb/src/pages/org/OrgChartToolbar.stories.tsxweb/src/pages/org/OrgChartSkeleton.stories.tsxweb/src/pages/org/status-mapping.tsweb/src/pages/org/HierarchyEdge.tsxweb/src/pages/org/DepartmentGroupNode.stories.tsxweb/src/pages/org/CeoNode.tsxweb/src/pages/OrgChartPage.tsxweb/src/pages/org/NodeContextMenu.stories.tsxweb/src/pages/org/layout.tsweb/src/pages/org/DepartmentStatsBar.tsxweb/src/pages/org/DepartmentGroupNode.tsxweb/src/pages/org/NodeContextMenu.tsxweb/src/pages/org/OrgChartToolbar.tsxweb/src/pages/org/CeoNode.stories.tsxweb/src/pages/org/AgentNode.tsxweb/src/pages/org/AgentNode.stories.tsxweb/src/pages/org/DepartmentStatsBar.stories.tsxweb/src/pages/org/build-org-tree.ts
web/**/*.stories.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
web/**/*.stories.{ts,tsx}: In Storybook, useparameters.backgrounds.options(object keyed by name) andinitialGlobals.backgrounds.valuefor background configuration
In Storybook, useparameters.a11y.test: 'error' | 'todo' | 'off'for a11y testing configuration (replaces old.elementand.manual)
Files:
web/src/pages/org/OrgChartToolbar.stories.tsxweb/src/pages/org/OrgChartSkeleton.stories.tsxweb/src/pages/org/DepartmentGroupNode.stories.tsxweb/src/pages/org/NodeContextMenu.stories.tsxweb/src/pages/org/CeoNode.stories.tsxweb/src/pages/org/AgentNode.stories.tsxweb/src/pages/org/DepartmentStatsBar.stories.tsx
web/src/stores/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Use Zustand stores in web dashboard for state management (auth, WebSocket, toast, analytics, domain shells)
Files:
web/src/stores/agents.tsweb/src/stores/company.ts
🧠 Learnings (28)
📓 Common learnings
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T21:20:09.993Z
Learning: Applies to web/src/components/** : Vue components organized by feature (agents/, approvals/, budget/, common/, dashboard/, layout/, messages/, org-chart/, tasks/).
📚 Learning: 2026-03-27T09:44:40.059Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T09:44:40.059Z
Learning: Applies to web/src/__tests__/**/*.{ts,tsx} : Use Vitest for React unit testing with coverage scoped to files changed vs origin/main
Applied to files:
web/src/__tests__/pages/org/OrgChartToolbar.test.tsxweb/src/__tests__/stores/agents.test.tsweb/src/__tests__/pages/org/OrgChartSkeleton.test.tsxweb/src/__tests__/pages/org/DepartmentStatsBar.test.tsxweb/src/__tests__/pages/org/OrgChartPage.test.tsxweb/src/__tests__/pages/org/status-mapping.test.tsweb/src/__tests__/stores/company.test.tsweb/src/__tests__/pages/org/layout.test.tsweb/src/__tests__/pages/org/NodeContextMenu.test.tsxweb/src/__tests__/pages/org/build-org-tree.test.ts
📚 Learning: 2026-03-20T08:28:32.845Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-20T08:28:32.845Z
Learning: Applies to web/src/__tests__/**/*.{ts,js} : Dashboard testing: Vitest unit tests organized by feature under `web/src/__tests__/`. Use fast-check for property-based testing (`fc.assert` + `fc.property`).
Applied to files:
web/src/__tests__/pages/org/OrgChartToolbar.test.tsxweb/src/__tests__/stores/agents.test.tsweb/src/__tests__/pages/org/OrgChartSkeleton.test.tsxweb/src/__tests__/pages/org/DepartmentStatsBar.test.tsxweb/src/__tests__/pages/org/OrgChartPage.test.tsxweb/src/__tests__/pages/org/status-mapping.test.tsCLAUDE.mdweb/src/__tests__/stores/company.test.tsweb/src/__tests__/pages/org/layout.test.tsweb/src/__tests__/pages/org/NodeContextMenu.test.tsxweb/src/__tests__/pages/org/build-org-tree.test.ts
📚 Learning: 2026-03-27T09:44:40.059Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T09:44:40.059Z
Learning: Applies to web/src/__tests__/**/*.{ts,tsx} : Use fast-check for property-based testing in React; use `fc.assert` and `fc.property`
Applied to files:
web/src/__tests__/pages/org/OrgChartToolbar.test.tsxweb/src/__tests__/pages/org/OrgChartSkeleton.test.tsxweb/src/__tests__/pages/org/DepartmentStatsBar.test.tsxweb/src/__tests__/pages/org/OrgChartPage.test.tsxweb/src/__tests__/stores/company.test.tsweb/src/__tests__/pages/org/layout.test.tsweb/src/__tests__/pages/org/NodeContextMenu.test.tsxweb/src/__tests__/pages/org/build-org-tree.test.ts
📚 Learning: 2026-03-27T09:44:40.059Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T09:44:40.059Z
Learning: Applies to web/src/components/**/*.stories.{ts,tsx} : Use Storybook 10 (ESM-only) for React component documentation; import from `storybook/test`, `storybook/actions`; use `definePreview` from `storybook/react-vite`
Applied to files:
web/src/__tests__/pages/org/OrgChartToolbar.test.tsxweb/package.jsonweb/src/pages/org/OrgChartToolbar.stories.tsxweb/src/pages/org/OrgChartSkeleton.stories.tsxweb/src/pages/org/DepartmentGroupNode.stories.tsxweb/src/__tests__/stores/company.test.tsweb/src/pages/org/NodeContextMenu.stories.tsxweb/src/pages/org/CeoNode.stories.tsxweb/src/pages/org/AgentNode.stories.tsxweb/src/pages/org/DepartmentStatsBar.stories.tsx
📚 Learning: 2026-03-27T09:44:40.059Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T09:44:40.059Z
Learning: Applies to web/**/*.stories.{ts,tsx} : In Storybook, use `parameters.a11y.test: 'error' | 'todo' | 'off'` for a11y testing configuration (replaces old `.element` and `.manual`)
Applied to files:
web/src/__tests__/pages/org/OrgChartToolbar.test.tsxweb/src/pages/org/OrgChartToolbar.stories.tsxweb/src/__tests__/pages/org/OrgChartSkeleton.test.tsxweb/src/pages/org/OrgChartSkeleton.stories.tsxweb/src/pages/org/DepartmentGroupNode.stories.tsxweb/src/pages/org/NodeContextMenu.stories.tsxweb/src/pages/org/CeoNode.stories.tsxweb/src/pages/org/AgentNode.stories.tsxweb/src/pages/org/DepartmentStatsBar.stories.tsx
📚 Learning: 2026-03-27T09:44:40.059Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T09:44:40.059Z
Learning: Applies to web/src/**/*.{ts,tsx} : In React components, import `cn` from `@/lib/utils` for conditional class merging; never concatenate class strings directly
Applied to files:
web/src/styles/global.css
📚 Learning: 2026-03-27T09:44:40.059Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T09:44:40.059Z
Learning: Applies to web/src/**/*.{ts,tsx} : Use React 19 with TypeScript 6+ in web dashboard; enforce design tokens (no hardcoded colors, fonts, spacing) and reuse components from `web/src/components/ui/`
Applied to files:
web/src/styles/global.cssweb/package.jsonweb/src/pages/org/OrgChartSkeleton.tsxweb/src/pages/org/HierarchyEdge.tsxweb/src/pages/org/CeoNode.tsxweb/src/pages/OrgChartPage.tsxCLAUDE.mdweb/src/hooks/useOrgChartData.tsweb/src/pages/org/layout.tsweb/src/pages/org/DepartmentStatsBar.tsxweb/src/pages/org/DepartmentGroupNode.tsxweb/src/pages/org/OrgChartToolbar.tsxweb/src/pages/org/AgentNode.tsxweb/src/pages/org/build-org-tree.ts
📚 Learning: 2026-03-27T09:44:40.059Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T09:44:40.059Z
Learning: Applies to web/src/**/*.{ts,tsx} : Use shadow and border token variables in web components (`var(--so-shadow-card-hover)`, `border-border`, `border-bright`); never hardcode shadow or border styles
Applied to files:
web/src/styles/global.css
📚 Learning: 2026-03-27T09:44:40.059Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T09:44:40.059Z
Learning: Applies to web/src/**/*.{ts,tsx} : Use `font-sans` or `font-mono` (Geist tokens) in web components; never set `fontFamily` directly
Applied to files:
web/src/styles/global.css
📚 Learning: 2026-03-14T15:43:05.601Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T15:43:05.601Z
Learning: Applies to web/package.json : Web dashboard Node.js 20+; dependencies in web/package.json (Vue 3, PrimeVue, Tailwind CSS, Pinia, VueFlow, ECharts, Axios, vue-draggable-plus, Vitest, ESLint, vue-tsc)
Applied to files:
web/package.jsonCLAUDE.md
📚 Learning: 2026-03-27T09:44:40.059Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T09:44:40.059Z
Learning: Applies to web/** : Use Node.js 22+ and npm for web dashboard; all dependencies in `web/package.json` (React 19, react-router, shadcn/ui, Radix UI, Tailwind CSS 4, Zustand, Recharts, Framer Motion, Axios, Lucide React, Geist fonts, Storybook 10, Vitest, ESLint, fast-check, etc.)
Applied to files:
web/package.jsonCLAUDE.md
📚 Learning: 2026-03-15T18:17:43.675Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:17:43.675Z
Learning: Applies to web/** : Web dashboard: Node.js 20+, dependencies in web/package.json (Vue 3, PrimeVue, Tailwind CSS, Pinia, VueFlow, ECharts, Axios, vue-draggable-plus, Vitest, fast-check, ESLint, vue-tsc).
Applied to files:
web/package.jsonCLAUDE.md
📚 Learning: 2026-03-27T09:44:40.059Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T09:44:40.059Z
Learning: Applies to web/.storybook/**/*.{ts,tsx} : In Storybook, use type-safe config with `defineMain` from `storybook/react-vite/node` and `definePreview` from `storybook/react-vite`; include explicit `framework` field
Applied to files:
web/package.jsonweb/src/pages/org/OrgChartToolbar.stories.tsxweb/src/pages/org/OrgChartSkeleton.stories.tsxweb/src/pages/org/DepartmentGroupNode.stories.tsxweb/src/pages/org/NodeContextMenu.stories.tsxweb/src/pages/org/CeoNode.stories.tsxweb/src/pages/org/AgentNode.stories.tsxweb/src/pages/org/DepartmentStatsBar.stories.tsx
📚 Learning: 2026-03-27T09:44:40.059Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T09:44:40.059Z
Learning: Applies to web/src/**/*.{ts,tsx} : Always reuse existing components from `web/src/components/ui/` (StatusBadge, MetricCard, Sparkline, SectionCard, AgentCard, DeptHealthBar, ProgressGauge, StatPill, Avatar, Button, Toast, Skeleton, EmptyState, ErrorBoundary, ConfirmDialog, CommandPalette, InlineEdit, AnimatedPresence, StaggerGroup/StaggerItem) before creating new ones
Applied to files:
web/src/pages/org/OrgChartSkeleton.tsxweb/src/pages/org/HierarchyEdge.tsxweb/src/pages/org/DepartmentGroupNode.stories.tsxweb/src/__tests__/pages/org/DepartmentStatsBar.test.tsxweb/src/pages/org/CeoNode.tsxweb/src/hooks/useOrgChartData.tsweb/src/pages/org/DepartmentStatsBar.tsxweb/src/pages/org/DepartmentGroupNode.tsxweb/src/pages/org/AgentNode.tsxweb/src/pages/org/DepartmentStatsBar.stories.tsx
📚 Learning: 2026-03-27T09:44:40.059Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T09:44:40.059Z
Learning: Applies to web/src/components/ui/**/*.{ts,tsx} : When creating new shared React components, place them in `web/src/components/ui/` with kebab-case filename, create accompanying `.stories.tsx` Storybook file with all states, export TypeScript interface for props, and use design tokens exclusively
Applied to files:
web/src/pages/org/OrgChartSkeleton.tsxweb/src/pages/org/OrgChartToolbar.stories.tsxweb/src/pages/org/OrgChartSkeleton.stories.tsxweb/src/pages/org/DepartmentGroupNode.stories.tsxweb/src/pages/org/CeoNode.tsxCLAUDE.mdweb/src/pages/org/NodeContextMenu.stories.tsxweb/src/pages/org/DepartmentStatsBar.tsxweb/src/pages/org/DepartmentGroupNode.tsxweb/src/pages/org/CeoNode.stories.tsxweb/src/pages/org/AgentNode.stories.tsxweb/src/pages/org/DepartmentStatsBar.stories.tsx
📚 Learning: 2026-03-27T09:44:40.059Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T09:44:40.059Z
Learning: Applies to web/src/**/*.{ts,tsx} : Do not build card-with-header layouts from scratch; use `<SectionCard>` component
Applied to files:
web/src/pages/org/OrgChartSkeleton.tsxweb/src/pages/org/layout.tsweb/src/pages/org/DepartmentGroupNode.tsx
📚 Learning: 2026-03-15T21:20:09.993Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T21:20:09.993Z
Learning: Applies to web/src/components/** : Vue components organized by feature (agents/, approvals/, budget/, common/, dashboard/, layout/, messages/, org-chart/, tasks/).
Applied to files:
web/src/pages/org/OrgChartSkeleton.tsxweb/src/pages/OrgChartPage.tsxCLAUDE.mdweb/src/pages/org/DepartmentStatsBar.tsxweb/src/pages/org/DepartmentStatsBar.stories.tsxweb/src/pages/org/build-org-tree.ts
📚 Learning: 2026-03-27T09:44:40.059Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T09:44:40.059Z
Learning: Applies to web/src/**/*.{ts,tsx} : Do not create complex (>8 line) JSX inside `.map()` blocks; extract to a shared component
Applied to files:
web/src/pages/org/OrgChartSkeleton.tsx
📚 Learning: 2026-03-27T09:44:40.059Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T09:44:40.059Z
Learning: Applies to web/src/stores/**/*.{ts,tsx} : Use Zustand stores in web dashboard for state management (auth, WebSocket, toast, analytics, domain shells)
Applied to files:
web/src/__tests__/stores/agents.test.tsCLAUDE.mdweb/src/__tests__/stores/company.test.tsweb/src/stores/agents.tsweb/src/stores/company.ts
📚 Learning: 2026-03-27T09:44:40.059Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T09:44:40.059Z
Learning: Applies to web/.storybook/preview.tsx : In Storybook, set a11y testing globally in `preview.tsx` with `parameters.a11y.test: 'error'` to enforce WCAG compliance on all stories
Applied to files:
web/src/pages/org/OrgChartToolbar.stories.tsxweb/src/__tests__/pages/org/OrgChartSkeleton.test.tsx
📚 Learning: 2026-03-27T09:44:40.059Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T09:44:40.059Z
Learning: Applies to web/**/*.stories.{ts,tsx} : In Storybook, use `parameters.backgrounds.options` (object keyed by name) and `initialGlobals.backgrounds.value` for background configuration
Applied to files:
web/src/pages/org/OrgChartSkeleton.stories.tsxweb/src/pages/org/DepartmentGroupNode.stories.tsxweb/src/pages/org/NodeContextMenu.stories.tsxweb/src/pages/org/DepartmentStatsBar.stories.tsx
📚 Learning: 2026-03-19T07:13:44.964Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T07:13:44.964Z
Learning: Applies to src/synthorg/hr/**/*.py : HR package (hr/): hiring, firing, onboarding, offboarding, agent registry, performance tracking (task metrics, collaboration scoring, LLM calibration, collaboration overrides, trend detection), promotion/demotion (criteria evaluation, approval strategies, model mapping)
Applied to files:
web/src/pages/org/status-mapping.ts
📚 Learning: 2026-03-27T09:44:40.059Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T09:44:40.059Z
Learning: Applies to web/src/**/*.{ts,tsx} : Do not render initials circles manually; use `<Avatar>` component
Applied to files:
web/src/pages/org/CeoNode.tsx
📚 Learning: 2026-03-19T07:12:14.508Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T07:12:14.508Z
Learning: Applies to src/synthorg/**/*.py : Package structure: src/synthorg/ organized as: api/ (REST+WebSocket, Litestar), auth/ (auth subpackage), backup/ (scheduled/manual backups), budget/ (cost tracking, CFO), cli/ (superseded by Go CLI), communication/ (message bus, meetings), config/ (YAML loading), core/ (domain models, resilience config), engine/ (orchestration, task state, coordination, approval gates, stagnation detection, context budget, compaction), hr/ (hiring, performance, promotion), memory/ (pluggable backend, Mem0, retrieval, consolidation), persistence/ (operational data, SQLite, settings), observability/ (logging, correlation, sinks), providers/ (LLM abstraction, LiteLLM, auth types, presets, runtime CRUD), settings/ (runtime-editable, typed definitions, encryption, config bridge), security/ (SecOps, rule engine, output scanning, progressive trust, autonomy levels), templates/ (company templates, personalities), tools/ (registry, built-in tools, git, sandbox, code_runner, MCP...
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-27T09:44:40.059Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T09:44:40.059Z
Learning: Applies to web/src/pages/**/*.{ts,tsx} : Use React Router with lazy-loaded page components (one per route); place page-scoped sub-components in `pages/<page-name>/` subdirectories
Applied to files:
CLAUDE.mdweb/src/pages/org/layout.ts
📚 Learning: 2026-03-27T09:44:40.059Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T09:44:40.059Z
Learning: Applies to web/src/**/*.{ts,tsx} : Do not recreate status dots inline; use `<StatusBadge>` component
Applied to files:
web/src/pages/org/DepartmentStatsBar.tsxweb/src/pages/org/AgentNode.tsx
📚 Learning: 2026-03-27T09:44:40.059Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T09:44:40.059Z
Learning: Applies to web/src/**/*.{ts,tsx} : Do not create metric displays with `text-metric font-bold`; use `<MetricCard>` component
Applied to files:
web/src/pages/org/DepartmentStatsBar.tsx
🔇 Additional comments (24)
web/src/styles/global.css (1)
7-7: React Flow base stylesheet import is correctly placed.No issues with this addition.
web/src/pages/org/OrgChartSkeleton.tsx (1)
1-30: Good skeleton implementation with accessible loading semantics.Shared UI reuse and status-region attributes are in place.
web/src/pages/org/HierarchyEdge.tsx (1)
1-27: Hierarchy edge renderer looks correct and cohesive with the graph setup.No issues found in this segment.
web/src/pages/org/DepartmentStatsBar.stories.tsx (1)
1-45: Story coverage is solid for key DepartmentStatsBar states.No concerns in this segment.
web/package.json (1)
18-52: No actionable concerns in this dependency diff.web/src/__tests__/pages/org/DepartmentStatsBar.test.tsx (1)
6-40: Solid coverage for core render states.This test suite cleanly covers count rendering, cost conditionality, and test-id presence for the component surface changed in this PR.
web/src/__tests__/pages/org/OrgChartSkeleton.test.tsx (1)
5-20: Nice a11y assertions for loading state.These checks validate status semantics and announcement behavior well for the skeleton component.
CLAUDE.md (1)
127-132: Documentation update is clear and aligned with the implementation.The hooks/stores tree comments now accurately reflect the new org-chart data composition and Zustand domains.
web/src/__tests__/pages/org/status-mapping.test.ts (1)
22-43: Good precedence coverage for runtime-vs-HR conflicts.These cases exercise the critical override semantics and edge conditions clearly.
web/src/pages/org/OrgChartToolbar.stories.tsx (1)
18-22: > Likely an incorrect or invalid review comment.web/src/__tests__/stores/agents.test.ts (1)
1-82: LGTM! Well-structured test coverage for the agents store.The test suite provides comprehensive coverage for both
updateRuntimeStatusandupdateFromWsEvent, including proper validation of edge cases (missing fields, invalid status values, wrong event types). ThebeforeEachreset ensures test isolation.web/src/pages/org/CeoNode.tsx (1)
1-52: Well-implemented CEO node with proper design token usage.The component correctly reuses
AvatarandStatusBadgefrom the shared UI library, uses semantic design tokens throughout, and includes proper accessibility attributes (aria-label,data-testid). The memoization is appropriate for React Flow node performance.web/src/pages/org/DepartmentGroupNode.tsx (1)
1-51: LGTM! Clean implementation with proper design tokens and accessibility.The component correctly uses semantic color tokens for health-based styling, includes
DepartmentStatsBarfor stats display, and provides proper accessibility attributes. The fallback on line 18 is defensive (unreachable givengetHealthColoralways returns a valid key), which is acceptable.web/src/pages/org/AgentNode.stories.tsx (1)
34-66: Good coverage of all runtime status states.The stories provide complete coverage of all
AgentRuntimeStatusvalues (active,idle,error,offline). TheWrapperpattern with disabled interactions is appropriate for static Storybook previews.web/src/__tests__/pages/org/layout.test.ts (1)
1-104: Good test coverage for the layout utility.The test suite covers key layout scenarios including empty input, position assignment, sibling separation, directional layout, department grouping, and edge case handling (missing nodes). The helper functions
makeNodeandmakeEdgekeep tests readable.web/src/pages/org/DepartmentGroupNode.stories.tsx (1)
44-84: LGTM — good coverage of health states.The three stories (
Healthy,Warning,Critical) provide useful visual documentation for different department health scenarios, including thecostUsd: nulledge case inCritical.web/src/__tests__/pages/org/NodeContextMenu.test.tsx (1)
13-60: LGTM — comprehensive menu behavior coverage.Tests cover the key scenarios: conditional rendering based on node type, callback invocation with correct arguments, keyboard accessibility (Escape), and ARIA roles.
web/src/__tests__/pages/org/OrgChartPage.test.tsx (1)
1-143: LGTM — solid page-level test coverage.The test suite effectively covers all major UI states (loading, empty, error, WebSocket disconnect) with proper mock isolation via
beforeEach. The module-level mock state pattern is appropriate for Vitest.web/src/pages/OrgChartPage.tsx (2)
267-286: LGTM — clean page structure with proper error boundaries.The page layout correctly wraps the ReactFlow canvas in
ReactFlowProviderandErrorBoundary, with a clear header section containing navigation.
234-237: No Pro license required forhideAttribution.The
hideAttributionoption inproOptionsis available to all React Flow users under the MIT license and does not require a Pro subscription. While a Pro subscription is appreciated for supporting the project, it is not a prerequisite for hiding the attribution.> Likely an incorrect or invalid review comment.web/src/stores/agents.ts (1)
1-39: LGTM — well-structured store with proper validation.The store correctly validates WebSocket payloads before updating state, and the
VALID_RUNTIME_STATUSESSet matches theAgentRuntimeStatustype definition. Immutable state updates using spread operator are correct.web/src/hooks/useOrgChartData.ts (1)
68-74: LGTM — efficient memoization of derived graph data.The
useMemocorrectly depends onconfig,runtimeStatuses, anddepartmentHealths, ensuring the graph is only rebuilt when source data changes.web/src/__tests__/stores/company.test.ts (1)
1-119: LGTM — comprehensive store test coverage.The test suite properly covers initial state, successful/failed API calls, and WebSocket event handling. The
vi.waitForpattern correctly handles async assertions for the re-fetch behavior.web/src/__tests__/pages/org/build-org-tree.test.ts (1)
66-309: LGTM — thorough coverage of org tree construction logic.The test suite comprehensively validates CEO selection priority, department grouping, hierarchy edges, terminated agent exclusion, health data integration, and edge deduplication. Good use of helper functions for test data setup.
| it('includes companyName in CEO node data', () => { | ||
| const agents = [ | ||
| makeAgent({ id: 'ceo', name: 'Boss', department: 'executive', level: 'c_suite' }), | ||
| ] | ||
| const config = makeConfig(agents) | ||
| config.company_name = 'Acme Inc' | ||
| const result = buildOrgTree({ ...config, company_name: 'Acme Inc' }, {}, []) | ||
|
|
||
| const ceoNode = result.nodes.find((n) => n.type === 'ceo') | ||
| expect(ceoNode!.data.companyName).toBe('Acme Inc') | ||
| }) |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
Remove redundant company_name assignment.
Line 289 assigns config.company_name = 'Acme Inc', then line 290 spreads it with the same value again. The mutation is sufficient.
♻️ Suggested fix
it('includes companyName in CEO node data', () => {
const agents = [
makeAgent({ id: 'ceo', name: 'Boss', department: 'executive', level: 'c_suite' }),
]
const config = makeConfig(agents)
config.company_name = 'Acme Inc'
- const result = buildOrgTree({ ...config, company_name: 'Acme Inc' }, {}, [])
+ const result = buildOrgTree(config, {}, [])
const ceoNode = result.nodes.find((n) => n.type === 'ceo')
expect(ceoNode!.data.companyName).toBe('Acme Inc')
})📝 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.
| it('includes companyName in CEO node data', () => { | |
| const agents = [ | |
| makeAgent({ id: 'ceo', name: 'Boss', department: 'executive', level: 'c_suite' }), | |
| ] | |
| const config = makeConfig(agents) | |
| config.company_name = 'Acme Inc' | |
| const result = buildOrgTree({ ...config, company_name: 'Acme Inc' }, {}, []) | |
| const ceoNode = result.nodes.find((n) => n.type === 'ceo') | |
| expect(ceoNode!.data.companyName).toBe('Acme Inc') | |
| }) | |
| it('includes companyName in CEO node data', () => { | |
| const agents = [ | |
| makeAgent({ id: 'ceo', name: 'Boss', department: 'executive', level: 'c_suite' }), | |
| ] | |
| const config = makeConfig(agents) | |
| config.company_name = 'Acme Inc' | |
| const result = buildOrgTree(config, {}, []) | |
| const ceoNode = result.nodes.find((n) => n.type === 'ceo') | |
| expect(ceoNode!.data.companyName).toBe('Acme Inc') | |
| }) |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@web/src/__tests__/pages/org/build-org-tree.test.ts` around lines 284 - 294,
The test mutates config.company_name and then passes a spread with the same
value to buildOrgTree, which is redundant; remove the standalone assignment
config.company_name = 'Acme Inc' and keep only the spread when calling
buildOrgTree (refer to makeConfig, config, and buildOrgTree in the "includes
companyName in CEO node data" test) so the test sets company_name exactly once
without mutation.
| useEffect(() => { | ||
| polling.start() | ||
| return () => polling.stop() | ||
| // eslint-disable-next-line @eslint-react/exhaustive-deps | ||
| }, []) |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Check which exhaustive-deps rule is configured in the project
rg -n "exhaustive-deps" --type=json --type=js --type=ts -g "*.config.*" -g ".eslintrc*"Repository: Aureliolo/synthorg
Length of output: 44
🏁 Script executed:
#!/bin/bash
# Find ESLint config files
fd -e "eslintrc*" -e "eslint.config.*" . web/
# Also check web/package.json for ESLint plugins
echo "=== ESLint plugins in web/package.json ==="
grep -A 5 -B 5 "eslint" web/package.json | head -50Repository: Aureliolo/synthorg
Length of output: 1235
🏁 Script executed:
#!/bin/bash
# Find ESLint config file
fd -type f "eslint.config.*" . web/
# Also check if there's a legacy .eslintrc
ls -la web/.eslintrc* 2>/dev/null || echo "No legacy .eslintrc found"Repository: Aureliolo/synthorg
Length of output: 275
🌐 Web query:
@eslint-react/eslint-plugin exhaustive-deps rule
💡 Result:
@eslint-react/eslint-plugin is a modern, performant ESLint plugin for React (4-7x faster than alternatives), providing composable rules for React, TypeScript, React 19+, Server Components, and more. It does not have a rule named "exhaustive-deps". The "exhaustive-deps" rule originates from the official eslint-plugin-react-hooks package (from the React team), which validates dependency arrays in hooks like useEffect, useCallback, useMemo to prevent stale closures by ensuring all referenced values are included. It is enabled by default as a warning in the recommended config: "react-hooks/exhaustive-deps": "warn". @eslint-react/eslint-plugin focuses on different rules (e.g., no-missing-key, no-children-prop, jsx-aria, hooks/exhaustive-deps is absent from its rules list). For exhaustive-deps, use eslint-plugin-react-hooks alongside it if needed. Installation for @eslint-react/eslint-plugin: npm install --save-dev typescript-eslint @eslint-react/eslint-plugin Example eslint.config.js: import eslintReact from "@eslint-react/eslint-plugin"; export default [ eslintReact.configs["recommended-typescript"], // rules: { ... } ];
Citations:
- 1: https://www.npmjs.com/package/@eslint-react/eslint-plugin
- 2: https://www.eslint-react.xyz/docs/rules/overview
- 3: https://react.dev/reference/eslint-plugin-react-hooks/lints/exhaustive-deps
- 4: https://github.com/facebook/react/blob/main/packages/eslint-plugin-react-hooks/README.md
- 5: https://react.dev/reference/eslint-plugin-react-hooks
Fix invalid ESLint rule name and missing plugin dependency.
The eslint-disable comment references @eslint-react/exhaustive-deps, but @eslint-react/eslint-plugin does not provide an exhaustive-deps rule. The exhaustive-deps rule comes from eslint-plugin-react-hooks (the official React team plugin), which is not installed in this project.
Either install eslint-plugin-react-hooks and update the disable comment to use the correct rule name react-hooks/exhaustive-deps, or remove the eslint-disable comment if exhaustive-deps checking is not desired. Currently, the comment has no effect since the rule doesn't exist in the configured plugins.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@web/src/hooks/useOrgChartData.ts` around lines 45 - 49, The ESLint disable is
referencing a non-existent rule name; update the hook to either install the
missing linter plugin `eslint-plugin-react-hooks` and change the comment to `//
eslint-disable-next-line react-hooks/exhaustive-deps` or remove the disable
entirely if you want the `useEffect` dependency check; locate the useEffect
where `polling.start()` / `polling.stop()` are called inside `useOrgChartData`
and apply the chosen change (add the plugin to devDependencies and enable it in
ESLint config if keeping the disable, or simply delete the incorrect `//
eslint-disable-next-line `@eslint-react/exhaustive-deps`` line).
There was a problem hiding this comment.
Actionable comments posted: 7
♻️ Duplicate comments (1)
web/src/pages/org/layout.ts (1)
44-48:⚠️ Potential issue | 🟠 MajorDagre never sees real node dimensions here.
useOrgChartData()lays the graph out before React Flow mounts, and nothing passes measured nodes back into this utility, sonode.measuredis effectively alwaysundefinedhere. Dagre therefore spaces the chart with the 160x80 fallbacks on every render, which is why wider CEO/department cards can still overlap or clip.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@web/src/pages/org/layout.ts` around lines 44 - 48, useOrgChartData currently layouts the Dagre graph before React Flow mounts so node.measured is always undefined causing DEFAULT_NODE_WIDTH/HEIGHT to be used; update the layout path to consume real measured sizes: change useOrgChartData (or its caller) to accept a measuredNodes map/prop (or a callback that supplies measured widths/heights) and use those values when setting nodes in the loop that iterates leafNodes (replace reliance on node.measured with the passed-in measurements), so g.setNode(...) uses actual width/height instead of DEFAULT_NODE_WIDTH/DEFAULT_NODE_HEIGHT and the Dagre layout will reflect real card sizes.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@web/src/__tests__/pages/org/NodeContextMenu.test.tsx`:
- Around line 1-2: The test file imports Vitest helpers but omitted beforeEach;
update the import from 'vitest' (where describe, expect, it, vi are imported) to
also import beforeEach so the beforeEach(...) call in NodeContextMenu.test.tsx
resolves at runtime; ensure the import statement that references describe,
expect, it, vi includes beforeEach.
In `@web/src/hooks/useOrgChartData.ts`:
- Around line 31-37: The effect currently calls companyStore.fetchCompanyData()
and companyStore.fetchDepartmentHealths() in parallel causing
fetchDepartmentHealths to early-return when store.config is null; change the
sequencing so fetchDepartmentHealths runs only after config is available — e.g.,
in the useEffect (or inside the Promise chain) await or .then() on
fetchCompanyData() (or observe useCompanyStore.getState().config) and only call
fetchDepartmentHealths() after that promise resolves and config is present;
update the useEffect that uses useCompanyStore.getState(), fetchCompanyData, and
fetchDepartmentHealths to ensure fetchDepartmentHealths is invoked after config
becomes non-null.
In `@web/src/pages/org/build-org-tree.ts`:
- Around line 124-133: teamMemberSet currently overwrites a member's parent if
their name appears in multiple dept.teams; update the loop in build-org-tree to
detect existing entries before setting: when iterating dept.teams and
teamMembers, check teamMemberSet.has(member.id) and either skip setting to avoid
overwrite or log a development-only warning (e.g., using console.warn or the
project logger) indicating the member appears in multiple teams, mentioning the
conflicting team and current teamLead; reference the symbols teamMemberSet,
dept.teams, deptMembers, findHighestSeniority, and team.members when making this
change so the duplicate-membership handling is applied where the map is
populated.
- Around line 226-233: The function findDepartmentHead creates an unnecessary
shallow copy with [...members] when ceo is null; since findHighestSeniority
accepts readonly AgentConfig[] you can pass members directly. Replace the
ternary that builds candidates in findDepartmentHead so it uses members (not
[...members]) when ceo is falsy, keeping the existing filter branch when ceo is
present and returning findHighestSeniority(candidates).
In `@web/src/pages/org/layout.ts`:
- Around line 74-78: The empty-group branch in the positionedGroups mapping
(inside groupNodes.map and the children.length === 0 check that uses
positionedLeafMap) currently sets every empty group to { x: 0, y: 0 }; change it
to compute a distinct layout slot per empty group instead of hard-coding the
origin — e.g., derive position from the group's index or maintain an emptyGroup
counter and place them on a grid (incrementing x/y by a fixed column/row size)
so each empty department gets its own non-overlapping coordinates while
preserving the style assignment.
In `@web/src/pages/OrgChartPage.tsx`:
- Around line 174-185: The handler handleViewModeChange currently calls
setViewMode(mode) for all ViewMode values including the unimplemented 'force';
change it so that when mode === 'force' you only call addToast(...) and return
without calling setViewMode, otherwise call setViewMode(mode); this preserves
the current selected view while still notifying the user (references:
handleViewModeChange, setViewMode, addToast, ViewMode, 'force').
- Around line 297-301: Replace the nested Link->Button pattern with the Button's
asChild composition: remove the outer <Link to={ROUTES.ORG_EDIT}> wrapper and
instead render <Button asChild size="sm" variant="outline"> with a <Link
to={ROUTES.ORG_EDIT}>Edit Organization</Link> as its child so the Button
delegates to the anchor element (preserving ROUTES.ORG_EDIT and Button props)
and avoids interactive element nesting.
---
Duplicate comments:
In `@web/src/pages/org/layout.ts`:
- Around line 44-48: useOrgChartData currently layouts the Dagre graph before
React Flow mounts so node.measured is always undefined causing
DEFAULT_NODE_WIDTH/HEIGHT to be used; update the layout path to consume real
measured sizes: change useOrgChartData (or its caller) to accept a measuredNodes
map/prop (or a callback that supplies measured widths/heights) and use those
values when setting nodes in the loop that iterates leafNodes (replace reliance
on node.measured with the passed-in measurements), so g.setNode(...) uses actual
width/height instead of DEFAULT_NODE_WIDTH/DEFAULT_NODE_HEIGHT and the Dagre
layout will reflect real card sizes.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 05462dce-9131-4f8f-89ff-a96cbdc6181c
📒 Files selected for processing (26)
CLAUDE.mdweb/src/__tests__/pages/org/DepartmentStatsBar.test.tsxweb/src/__tests__/pages/org/NodeContextMenu.test.tsxweb/src/__tests__/pages/org/OrgChartToolbar.test.tsxweb/src/__tests__/pages/org/build-org-tree.test.tsweb/src/__tests__/pages/org/layout.test.tsweb/src/__tests__/stores/company.test.tsweb/src/hooks/useOrgChartData.tsweb/src/pages/OrgChartPage.tsxweb/src/pages/org/AgentNode.stories.tsxweb/src/pages/org/AgentNode.tsxweb/src/pages/org/CeoNode.stories.tsxweb/src/pages/org/CeoNode.tsxweb/src/pages/org/DepartmentGroupNode.stories.tsxweb/src/pages/org/DepartmentGroupNode.tsxweb/src/pages/org/DepartmentStatsBar.stories.tsxweb/src/pages/org/DepartmentStatsBar.tsxweb/src/pages/org/NodeContextMenu.stories.tsxweb/src/pages/org/NodeContextMenu.tsxweb/src/pages/org/OrgChartSkeleton.stories.tsxweb/src/pages/org/OrgChartToolbar.stories.tsxweb/src/pages/org/OrgChartToolbar.tsxweb/src/pages/org/build-org-tree.tsweb/src/pages/org/layout.tsweb/src/pages/org/status-mapping.tsweb/src/stores/company.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
- GitHub Check: Build Backend
- GitHub Check: Build Web
- GitHub Check: Build Sandbox
- GitHub Check: Dashboard Test
- GitHub Check: Dependency Review
- GitHub Check: Analyze (python)
🧰 Additional context used
📓 Path-based instructions (8)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx}: Use TypeScript 6+ withpathsfor module resolution (remove deprecatedbaseUrl);esModuleInteropis always true
In TypeScript,strictdefaults to true andtypesdefaults to[]; do not auto-discover@types/*— must explicitly list needed types
Files:
web/src/pages/org/OrgChartSkeleton.stories.tsxweb/src/pages/org/status-mapping.tsweb/src/__tests__/pages/org/DepartmentStatsBar.test.tsxweb/src/__tests__/pages/org/OrgChartToolbar.test.tsxweb/src/pages/org/DepartmentGroupNode.tsxweb/src/__tests__/pages/org/layout.test.tsweb/src/pages/org/OrgChartToolbar.stories.tsxweb/src/__tests__/pages/org/NodeContextMenu.test.tsxweb/src/pages/org/DepartmentGroupNode.stories.tsxweb/src/pages/org/NodeContextMenu.tsxweb/src/pages/org/AgentNode.tsxweb/src/pages/org/DepartmentStatsBar.tsxweb/src/pages/org/CeoNode.tsxweb/src/pages/org/AgentNode.stories.tsxweb/src/stores/company.tsweb/src/pages/org/DepartmentStatsBar.stories.tsxweb/src/hooks/useOrgChartData.tsweb/src/__tests__/pages/org/build-org-tree.test.tsweb/src/pages/org/OrgChartToolbar.tsxweb/src/pages/org/NodeContextMenu.stories.tsxweb/src/pages/org/build-org-tree.tsweb/src/pages/org/CeoNode.stories.tsxweb/src/__tests__/stores/company.test.tsweb/src/pages/org/layout.tsweb/src/pages/OrgChartPage.tsx
web/src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
web/src/**/*.{ts,tsx}: Use React 19 with TypeScript 6+ in web dashboard; enforce design tokens (no hardcoded colors, fonts, spacing) and reuse components fromweb/src/components/ui/
Always reuse existing components fromweb/src/components/ui/(StatusBadge, MetricCard, Sparkline, SectionCard, AgentCard, DeptHealthBar, ProgressGauge, StatPill, Avatar, Button, Toast, Skeleton, EmptyState, ErrorBoundary, ConfirmDialog, CommandPalette, InlineEdit, AnimatedPresence, StaggerGroup/StaggerItem) before creating new ones
Use design tokens exclusively in web components: Tailwind semantic classes (text-foreground,bg-card,text-accent,text-success,bg-danger, etc.) or CSS variables (var(--so-accent)); never hardcode hex values or pixel spacing
Usefont-sansorfont-mono(Geist tokens) in web components; never setfontFamilydirectly
Use density-aware spacing tokens in web components (p-card,gap-section-gap,gap-grid-gap) or standard Tailwind spacing; never hardcode pixel values for layout spacing
Use shadow and border token variables in web components (var(--so-shadow-card-hover),border-border,border-bright); never hardcode shadow or border styles
In React components, importcnfrom@/lib/utilsfor conditional class merging; never concatenate class strings directly
Do not recreate status dots inline; use<StatusBadge>component
Do not build card-with-header layouts from scratch; use<SectionCard>component
Do not create metric displays withtext-metric font-bold; use<MetricCard>component
Do not render initials circles manually; use<Avatar>component
Do not create complex (>8 line) JSX inside.map()blocks; extract to a shared component
Files:
web/src/pages/org/OrgChartSkeleton.stories.tsxweb/src/pages/org/status-mapping.tsweb/src/__tests__/pages/org/DepartmentStatsBar.test.tsxweb/src/__tests__/pages/org/OrgChartToolbar.test.tsxweb/src/pages/org/DepartmentGroupNode.tsxweb/src/__tests__/pages/org/layout.test.tsweb/src/pages/org/OrgChartToolbar.stories.tsxweb/src/__tests__/pages/org/NodeContextMenu.test.tsxweb/src/pages/org/DepartmentGroupNode.stories.tsxweb/src/pages/org/NodeContextMenu.tsxweb/src/pages/org/AgentNode.tsxweb/src/pages/org/DepartmentStatsBar.tsxweb/src/pages/org/CeoNode.tsxweb/src/pages/org/AgentNode.stories.tsxweb/src/stores/company.tsweb/src/pages/org/DepartmentStatsBar.stories.tsxweb/src/hooks/useOrgChartData.tsweb/src/__tests__/pages/org/build-org-tree.test.tsweb/src/pages/org/OrgChartToolbar.tsxweb/src/pages/org/NodeContextMenu.stories.tsxweb/src/pages/org/build-org-tree.tsweb/src/pages/org/CeoNode.stories.tsxweb/src/__tests__/stores/company.test.tsweb/src/pages/org/layout.tsweb/src/pages/OrgChartPage.tsx
web/src/pages/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Use React Router with lazy-loaded page components (one per route); place page-scoped sub-components in
pages/<page-name>/subdirectories
Files:
web/src/pages/org/OrgChartSkeleton.stories.tsxweb/src/pages/org/status-mapping.tsweb/src/pages/org/DepartmentGroupNode.tsxweb/src/pages/org/OrgChartToolbar.stories.tsxweb/src/pages/org/DepartmentGroupNode.stories.tsxweb/src/pages/org/NodeContextMenu.tsxweb/src/pages/org/AgentNode.tsxweb/src/pages/org/DepartmentStatsBar.tsxweb/src/pages/org/CeoNode.tsxweb/src/pages/org/AgentNode.stories.tsxweb/src/pages/org/DepartmentStatsBar.stories.tsxweb/src/pages/org/OrgChartToolbar.tsxweb/src/pages/org/NodeContextMenu.stories.tsxweb/src/pages/org/build-org-tree.tsweb/src/pages/org/CeoNode.stories.tsxweb/src/pages/org/layout.tsweb/src/pages/OrgChartPage.tsx
web/**/*.stories.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
web/**/*.stories.{ts,tsx}: In Storybook, useparameters.backgrounds.options(object keyed by name) andinitialGlobals.backgrounds.valuefor background configuration
In Storybook, useparameters.a11y.test: 'error' | 'todo' | 'off'for a11y testing configuration (replaces old.elementand.manual)
Files:
web/src/pages/org/OrgChartSkeleton.stories.tsxweb/src/pages/org/OrgChartToolbar.stories.tsxweb/src/pages/org/DepartmentGroupNode.stories.tsxweb/src/pages/org/AgentNode.stories.tsxweb/src/pages/org/DepartmentStatsBar.stories.tsxweb/src/pages/org/NodeContextMenu.stories.tsxweb/src/pages/org/CeoNode.stories.tsx
web/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Use ESLint with
@eslint-react/eslint-pluginand eslint-plugin-security in web dashboard
Files:
web/src/pages/org/OrgChartSkeleton.stories.tsxweb/src/pages/org/status-mapping.tsweb/src/__tests__/pages/org/DepartmentStatsBar.test.tsxweb/src/__tests__/pages/org/OrgChartToolbar.test.tsxweb/src/pages/org/DepartmentGroupNode.tsxweb/src/__tests__/pages/org/layout.test.tsweb/src/pages/org/OrgChartToolbar.stories.tsxweb/src/__tests__/pages/org/NodeContextMenu.test.tsxweb/src/pages/org/DepartmentGroupNode.stories.tsxweb/src/pages/org/NodeContextMenu.tsxweb/src/pages/org/AgentNode.tsxweb/src/pages/org/DepartmentStatsBar.tsxweb/src/pages/org/CeoNode.tsxweb/src/pages/org/AgentNode.stories.tsxweb/src/stores/company.tsweb/src/pages/org/DepartmentStatsBar.stories.tsxweb/src/hooks/useOrgChartData.tsweb/src/__tests__/pages/org/build-org-tree.test.tsweb/src/pages/org/OrgChartToolbar.tsxweb/src/pages/org/NodeContextMenu.stories.tsxweb/src/pages/org/build-org-tree.tsweb/src/pages/org/CeoNode.stories.tsxweb/src/__tests__/stores/company.test.tsweb/src/pages/org/layout.tsweb/src/pages/OrgChartPage.tsx
web/**
📄 CodeRabbit inference engine (CLAUDE.md)
Use Node.js 22+ and npm for web dashboard; all dependencies in
web/package.json(React 19, react-router, shadcn/ui, Radix UI, Tailwind CSS 4, Zustand, Recharts, Framer Motion, Axios, Lucide React, Geist fonts, Storybook 10, Vitest, ESLint, fast-check, etc.)
Files:
web/src/pages/org/OrgChartSkeleton.stories.tsxweb/src/pages/org/status-mapping.tsweb/src/__tests__/pages/org/DepartmentStatsBar.test.tsxweb/src/__tests__/pages/org/OrgChartToolbar.test.tsxweb/src/pages/org/DepartmentGroupNode.tsxweb/src/__tests__/pages/org/layout.test.tsweb/src/pages/org/OrgChartToolbar.stories.tsxweb/src/__tests__/pages/org/NodeContextMenu.test.tsxweb/src/pages/org/DepartmentGroupNode.stories.tsxweb/src/pages/org/NodeContextMenu.tsxweb/src/pages/org/AgentNode.tsxweb/src/pages/org/DepartmentStatsBar.tsxweb/src/pages/org/CeoNode.tsxweb/src/pages/org/AgentNode.stories.tsxweb/src/stores/company.tsweb/src/pages/org/DepartmentStatsBar.stories.tsxweb/src/hooks/useOrgChartData.tsweb/src/__tests__/pages/org/build-org-tree.test.tsweb/src/pages/org/OrgChartToolbar.tsxweb/src/pages/org/NodeContextMenu.stories.tsxweb/src/pages/org/build-org-tree.tsweb/src/pages/org/CeoNode.stories.tsxweb/src/__tests__/stores/company.test.tsweb/src/pages/org/layout.tsweb/src/pages/OrgChartPage.tsx
web/src/__tests__/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
web/src/__tests__/**/*.{ts,tsx}: Use fast-check for property-based testing in React; usefc.assertandfc.property
Use Vitest for React unit testing with coverage scoped to files changed vs origin/main
Files:
web/src/__tests__/pages/org/DepartmentStatsBar.test.tsxweb/src/__tests__/pages/org/OrgChartToolbar.test.tsxweb/src/__tests__/pages/org/layout.test.tsweb/src/__tests__/pages/org/NodeContextMenu.test.tsxweb/src/__tests__/pages/org/build-org-tree.test.tsweb/src/__tests__/stores/company.test.ts
web/src/stores/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Use Zustand stores in web dashboard for state management (auth, WebSocket, toast, analytics, domain shells)
Files:
web/src/stores/company.ts
🧠 Learnings (34)
📓 Common learnings
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T21:20:09.993Z
Learning: Applies to web/src/components/** : Vue components organized by feature (agents/, approvals/, budget/, common/, dashboard/, layout/, messages/, org-chart/, tasks/).
📚 Learning: 2026-03-27T09:44:40.059Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T09:44:40.059Z
Learning: Applies to web/src/components/**/*.stories.{ts,tsx} : Use Storybook 10 (ESM-only) for React component documentation; import from `storybook/test`, `storybook/actions`; use `definePreview` from `storybook/react-vite`
Applied to files:
web/src/pages/org/OrgChartSkeleton.stories.tsxweb/src/__tests__/pages/org/OrgChartToolbar.test.tsxweb/src/pages/org/OrgChartToolbar.stories.tsxweb/src/pages/org/DepartmentGroupNode.stories.tsxweb/src/pages/org/AgentNode.stories.tsxweb/src/pages/org/DepartmentStatsBar.stories.tsxweb/src/pages/org/NodeContextMenu.stories.tsxweb/src/pages/org/CeoNode.stories.tsxweb/src/__tests__/stores/company.test.ts
📚 Learning: 2026-03-27T09:44:40.059Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T09:44:40.059Z
Learning: Applies to web/**/*.stories.{ts,tsx} : In Storybook, use `parameters.a11y.test: 'error' | 'todo' | 'off'` for a11y testing configuration (replaces old `.element` and `.manual`)
Applied to files:
web/src/pages/org/OrgChartSkeleton.stories.tsxweb/src/__tests__/pages/org/OrgChartToolbar.test.tsxweb/src/pages/org/OrgChartToolbar.stories.tsxweb/src/pages/org/DepartmentGroupNode.stories.tsxweb/src/pages/org/AgentNode.stories.tsxweb/src/pages/org/DepartmentStatsBar.stories.tsxweb/src/pages/org/NodeContextMenu.stories.tsxweb/src/pages/org/CeoNode.stories.tsx
📚 Learning: 2026-03-27T09:44:40.059Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T09:44:40.059Z
Learning: Applies to web/src/components/ui/**/*.{ts,tsx} : When creating new shared React components, place them in `web/src/components/ui/` with kebab-case filename, create accompanying `.stories.tsx` Storybook file with all states, export TypeScript interface for props, and use design tokens exclusively
Applied to files:
web/src/pages/org/OrgChartSkeleton.stories.tsxCLAUDE.mdweb/src/pages/org/OrgChartToolbar.stories.tsxweb/src/pages/org/DepartmentGroupNode.stories.tsxweb/src/pages/org/DepartmentStatsBar.tsxweb/src/pages/org/AgentNode.stories.tsxweb/src/pages/org/DepartmentStatsBar.stories.tsxweb/src/pages/org/OrgChartToolbar.tsxweb/src/pages/org/NodeContextMenu.stories.tsxweb/src/pages/org/CeoNode.stories.tsx
📚 Learning: 2026-03-27T09:44:40.059Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T09:44:40.059Z
Learning: Applies to web/**/*.stories.{ts,tsx} : In Storybook, use `parameters.backgrounds.options` (object keyed by name) and `initialGlobals.backgrounds.value` for background configuration
Applied to files:
web/src/pages/org/OrgChartSkeleton.stories.tsxweb/src/pages/org/OrgChartToolbar.stories.tsxweb/src/pages/org/DepartmentGroupNode.stories.tsxweb/src/pages/org/DepartmentStatsBar.stories.tsx
📚 Learning: 2026-03-27T09:44:40.059Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T09:44:40.059Z
Learning: Applies to web/.storybook/**/*.{ts,tsx} : In Storybook, use type-safe config with `defineMain` from `storybook/react-vite/node` and `definePreview` from `storybook/react-vite`; include explicit `framework` field
Applied to files:
web/src/pages/org/OrgChartSkeleton.stories.tsxweb/src/pages/org/OrgChartToolbar.stories.tsxweb/src/pages/org/DepartmentGroupNode.stories.tsxweb/src/pages/org/AgentNode.stories.tsxweb/src/pages/org/DepartmentStatsBar.stories.tsxweb/src/pages/org/NodeContextMenu.stories.tsxweb/src/pages/org/CeoNode.stories.tsx
📚 Learning: 2026-03-27T09:44:40.059Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T09:44:40.059Z
Learning: Applies to web/.storybook/preview.tsx : In Storybook, set a11y testing globally in `preview.tsx` with `parameters.a11y.test: 'error'` to enforce WCAG compliance on all stories
Applied to files:
web/src/pages/org/OrgChartSkeleton.stories.tsxweb/src/pages/org/OrgChartToolbar.stories.tsxweb/src/pages/org/DepartmentGroupNode.stories.tsxweb/src/pages/org/AgentNode.stories.tsxweb/src/pages/org/OrgChartToolbar.tsxweb/src/pages/org/NodeContextMenu.stories.tsxweb/src/pages/org/CeoNode.stories.tsx
📚 Learning: 2026-03-27T09:44:40.059Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T09:44:40.059Z
Learning: Applies to web/src/**/*.{ts,tsx} : Use shadow and border token variables in web components (`var(--so-shadow-card-hover)`, `border-border`, `border-bright`); never hardcode shadow or border styles
Applied to files:
web/src/pages/org/OrgChartSkeleton.stories.tsxweb/src/pages/org/AgentNode.tsxweb/src/pages/org/CeoNode.tsx
📚 Learning: 2026-03-27T09:44:40.059Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T09:44:40.059Z
Learning: Applies to web/src/**/*.{ts,tsx} : Use design tokens exclusively in web components: Tailwind semantic classes (`text-foreground`, `bg-card`, `text-accent`, `text-success`, `bg-danger`, etc.) or CSS variables (`var(--so-accent)`); never hardcode hex values or pixel spacing
Applied to files:
web/src/pages/org/OrgChartSkeleton.stories.tsxweb/src/pages/org/AgentNode.tsxweb/src/pages/org/CeoNode.tsx
📚 Learning: 2026-03-27T09:44:40.059Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T09:44:40.059Z
Learning: Applies to web/src/**/*.{ts,tsx} : Always reuse existing components from `web/src/components/ui/` (StatusBadge, MetricCard, Sparkline, SectionCard, AgentCard, DeptHealthBar, ProgressGauge, StatPill, Avatar, Button, Toast, Skeleton, EmptyState, ErrorBoundary, ConfirmDialog, CommandPalette, InlineEdit, AnimatedPresence, StaggerGroup/StaggerItem) before creating new ones
Applied to files:
web/src/pages/org/OrgChartSkeleton.stories.tsxweb/src/__tests__/pages/org/DepartmentStatsBar.test.tsxweb/src/pages/org/DepartmentGroupNode.tsxweb/src/pages/org/AgentNode.tsxweb/src/pages/org/DepartmentStatsBar.tsxweb/src/pages/org/CeoNode.tsxweb/src/pages/org/DepartmentStatsBar.stories.tsxweb/src/hooks/useOrgChartData.tsweb/src/pages/org/CeoNode.stories.tsxweb/src/pages/OrgChartPage.tsx
📚 Learning: 2026-03-27T09:44:40.059Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T09:44:40.059Z
Learning: Applies to web/src/**/*.{ts,tsx} : Do not recreate status dots inline; use `<StatusBadge>` component
Applied to files:
web/src/pages/org/OrgChartSkeleton.stories.tsxweb/src/pages/org/AgentNode.tsxweb/src/pages/org/DepartmentStatsBar.tsxweb/src/pages/org/CeoNode.stories.tsx
📚 Learning: 2026-03-27T09:44:40.059Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T09:44:40.059Z
Learning: Applies to web/src/**/*.{ts,tsx} : Use React 19 with TypeScript 6+ in web dashboard; enforce design tokens (no hardcoded colors, fonts, spacing) and reuse components from `web/src/components/ui/`
Applied to files:
web/src/pages/org/OrgChartSkeleton.stories.tsxCLAUDE.mdweb/src/pages/org/DepartmentGroupNode.tsxweb/src/pages/org/DepartmentGroupNode.stories.tsxweb/src/pages/org/NodeContextMenu.tsxweb/src/pages/org/AgentNode.tsxweb/src/pages/org/DepartmentStatsBar.tsxweb/src/pages/org/CeoNode.tsxweb/src/hooks/useOrgChartData.tsweb/src/pages/org/OrgChartToolbar.tsxweb/src/pages/org/layout.tsweb/src/pages/OrgChartPage.tsx
📚 Learning: 2026-03-19T07:13:44.964Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T07:13:44.964Z
Learning: Applies to src/synthorg/hr/**/*.py : HR package (hr/): hiring, firing, onboarding, offboarding, agent registry, performance tracking (task metrics, collaboration scoring, LLM calibration, collaboration overrides, trend detection), promotion/demotion (criteria evaluation, approval strategies, model mapping)
Applied to files:
web/src/pages/org/status-mapping.ts
📚 Learning: 2026-03-16T06:24:56.341Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-16T06:24:56.341Z
Learning: Applies to src/synthorg/hr/**/*.py : HR engine must provide: hiring, firing, onboarding, offboarding, agent registry, performance tracking (task metrics, collaboration scoring, trend detection), promotion/demotion
Applied to files:
web/src/pages/org/status-mapping.ts
📚 Learning: 2026-03-27T09:44:40.059Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T09:44:40.059Z
Learning: Applies to web/src/__tests__/**/*.{ts,tsx} : Use Vitest for React unit testing with coverage scoped to files changed vs origin/main
Applied to files:
web/src/__tests__/pages/org/DepartmentStatsBar.test.tsxweb/src/__tests__/pages/org/OrgChartToolbar.test.tsxweb/src/__tests__/pages/org/layout.test.tsweb/src/__tests__/pages/org/NodeContextMenu.test.tsxweb/src/__tests__/pages/org/build-org-tree.test.tsweb/src/__tests__/stores/company.test.ts
📚 Learning: 2026-03-20T08:28:32.845Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-20T08:28:32.845Z
Learning: Applies to web/src/__tests__/**/*.{ts,js} : Dashboard testing: Vitest unit tests organized by feature under `web/src/__tests__/`. Use fast-check for property-based testing (`fc.assert` + `fc.property`).
Applied to files:
web/src/__tests__/pages/org/DepartmentStatsBar.test.tsxCLAUDE.mdweb/src/__tests__/pages/org/OrgChartToolbar.test.tsxweb/src/__tests__/pages/org/layout.test.tsweb/src/__tests__/pages/org/NodeContextMenu.test.tsxweb/src/__tests__/pages/org/build-org-tree.test.tsweb/src/__tests__/stores/company.test.ts
📚 Learning: 2026-03-27T09:44:40.059Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T09:44:40.059Z
Learning: Applies to web/src/__tests__/**/*.{ts,tsx} : Use fast-check for property-based testing in React; use `fc.assert` and `fc.property`
Applied to files:
web/src/__tests__/pages/org/DepartmentStatsBar.test.tsxweb/src/__tests__/pages/org/OrgChartToolbar.test.tsxweb/src/__tests__/pages/org/NodeContextMenu.test.tsxweb/src/__tests__/pages/org/build-org-tree.test.tsweb/src/__tests__/stores/company.test.ts
📚 Learning: 2026-03-27T09:44:40.059Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T09:44:40.059Z
Learning: Applies to web/src/stores/**/*.{ts,tsx} : Use Zustand stores in web dashboard for state management (auth, WebSocket, toast, analytics, domain shells)
Applied to files:
CLAUDE.mdweb/src/stores/company.tsweb/src/__tests__/stores/company.test.ts
📚 Learning: 2026-03-27T09:44:40.059Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T09:44:40.059Z
Learning: Applies to web/** : Use Node.js 22+ and npm for web dashboard; all dependencies in `web/package.json` (React 19, react-router, shadcn/ui, Radix UI, Tailwind CSS 4, Zustand, Recharts, Framer Motion, Axios, Lucide React, Geist fonts, Storybook 10, Vitest, ESLint, fast-check, etc.)
Applied to files:
CLAUDE.mdweb/src/pages/org/DepartmentGroupNode.tsxweb/src/pages/org/CeoNode.tsx
📚 Learning: 2026-03-19T07:12:14.508Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T07:12:14.508Z
Learning: Applies to src/synthorg/**/*.py : Package structure: src/synthorg/ organized as: api/ (REST+WebSocket, Litestar), auth/ (auth subpackage), backup/ (scheduled/manual backups), budget/ (cost tracking, CFO), cli/ (superseded by Go CLI), communication/ (message bus, meetings), config/ (YAML loading), core/ (domain models, resilience config), engine/ (orchestration, task state, coordination, approval gates, stagnation detection, context budget, compaction), hr/ (hiring, performance, promotion), memory/ (pluggable backend, Mem0, retrieval, consolidation), persistence/ (operational data, SQLite, settings), observability/ (logging, correlation, sinks), providers/ (LLM abstraction, LiteLLM, auth types, presets, runtime CRUD), settings/ (runtime-editable, typed definitions, encryption, config bridge), security/ (SecOps, rule engine, output scanning, progressive trust, autonomy levels), templates/ (company templates, personalities), tools/ (registry, built-in tools, git, sandbox, code_runner, MCP...
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-15T21:20:09.993Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T21:20:09.993Z
Learning: Applies to web/src/components/** : Vue components organized by feature (agents/, approvals/, budget/, common/, dashboard/, layout/, messages/, org-chart/, tasks/).
Applied to files:
CLAUDE.mdweb/src/pages/org/DepartmentStatsBar.tsx
📚 Learning: 2026-03-15T18:17:43.675Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:17:43.675Z
Learning: Applies to web/** : Web dashboard: Node.js 20+, dependencies in web/package.json (Vue 3, PrimeVue, Tailwind CSS, Pinia, VueFlow, ECharts, Axios, vue-draggable-plus, Vitest, fast-check, ESLint, vue-tsc).
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-27T09:44:40.059Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T09:44:40.059Z
Learning: Applies to web/src/pages/**/*.{ts,tsx} : Use React Router with lazy-loaded page components (one per route); place page-scoped sub-components in `pages/<page-name>/` subdirectories
Applied to files:
CLAUDE.mdweb/src/pages/org/layout.ts
📚 Learning: 2026-03-14T15:43:05.601Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T15:43:05.601Z
Learning: Applies to web/package.json : Web dashboard Node.js 20+; dependencies in web/package.json (Vue 3, PrimeVue, Tailwind CSS, Pinia, VueFlow, ECharts, Axios, vue-draggable-plus, Vitest, ESLint, vue-tsc)
Applied to files:
CLAUDE.mdweb/src/pages/org/CeoNode.tsx
📚 Learning: 2026-03-21T12:54:22.557Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-21T12:54:22.557Z
Learning: Go 1.26+ required; CLI dependencies in `cli/go.mod` (Cobra, charmbracelet/huh, charmbracelet/lipgloss, sigstore-go, go-containerregistry, go-tuf)
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-15T18:17:43.675Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:17:43.675Z
Learning: Applies to pyproject.toml : Dependencies: all versions use == in pyproject.toml. Groups: test (pytest + plugins, hypothesis), dev (includes test + ruff, mypy, pre-commit, commitizen, pip-audit). Required: mem0ai (Mem0 memory backend — the default and currently only backend). Install: uv sync installs everything (dev group is default).
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-15T18:17:43.675Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:17:43.675Z
Learning: Applies to docker/{Dockerfile*,compose.yml} : Docker: Backend uses 3-stage build (builder → setup → distroless runtime), Chainguard Python, non-root (UID 65532), CIS-hardened. Web uses nginxinc/nginx-unprivileged, Vue 3 SPA with PrimeVue + Tailwind CSS, SPA routing, API/WebSocket proxy to backend.
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-19T11:19:40.044Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T11:19:40.044Z
Learning: Applies to go.mod : Maintain Go 1.26+ requirement. Dependencies: Cobra (CLI framework), charmbracelet/huh and charmbracelet/lipgloss (UI), sigstore-go (code signing), go-containerregistry (container image verification), go-tuf (TUF client for Sigstore).
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-21T14:12:17.848Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-21T14:12:17.848Z
Learning: Applies to cli/go.mod : CLI uses Go 1.26+. Dependencies: Cobra, charmbracelet/huh, charmbracelet/lipgloss, sigstore-go, go-containerregistry, go-tuf
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-15T21:32:02.880Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T21:32:02.880Z
Learning: Applies to cli/**/*.go : Go CLI (Go 1.26+) uses Cobra for commands, charmbracelet/huh for interactive CLI, charmbracelet/lipgloss for styled output. Cross-platform builds (linux/darwin/windows × amd64/arm64). GoReleaser for releases with cosign keyless signing of checksums.txt. SLSA L3 provenance attestations via actions/attest-build-provenance.
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-15T18:17:43.675Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:17:43.675Z
Learning: Applies to cli/** : CLI: Go 1.26+, dependencies in cli/go.mod (Cobra, charmbracelet/huh).
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-27T09:44:40.059Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T09:44:40.059Z
Learning: Applies to web/src/**/*.{ts,tsx} : Use density-aware spacing tokens in web components (`p-card`, `gap-section-gap`, `gap-grid-gap`) or standard Tailwind spacing; never hardcode pixel values for layout spacing
Applied to files:
web/src/pages/org/AgentNode.tsxweb/src/pages/org/CeoNode.tsx
📚 Learning: 2026-03-27T09:44:40.059Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T09:44:40.059Z
Learning: Applies to web/src/**/*.{ts,tsx} : In React components, import `cn` from `@/lib/utils` for conditional class merging; never concatenate class strings directly
Applied to files:
web/src/pages/org/CeoNode.tsx
📚 Learning: 2026-03-27T09:44:40.059Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T09:44:40.059Z
Learning: Applies to web/**/*.{ts,tsx} : Use ESLint with eslint-react/eslint-plugin and eslint-plugin-security in web dashboard
Applied to files:
web/src/hooks/useOrgChartData.ts
🔇 Additional comments (24)
CLAUDE.md (3)
127-127: Good clarification for hooks scope.Including “page data composition” makes the
web/src/hooks/boundary clearer and matches the new Org Chart composition hook work.Based on learnings: “Applies to web/src/**/*.{ts,tsx}: Use React 19 with TypeScript 6+ in web dashboard…”
131-131: Store taxonomy update is accurate and useful.Explicitly listing company/agents/domain stores improves discoverability and matches the Zustand direction for the web dashboard.
Based on learnings: “Applies to web/src/stores/**/*.{ts,tsx}: Use Zustand stores in web dashboard for state management…”
321-321: Dependency list update looks consistent with the feature set.Adding
@dagrejs/dagrein the documented web stack aligns with the new auto-layout implementation and keeps CLAUDE.md in sync.web/src/pages/org/OrgChartSkeleton.stories.tsx (1)
1-23: LGTM!The story is well-structured with proper Storybook 10 typing,
autodocstag, andparameters.a11y.test: 'error'configuration. The previous feedback about inline background styling has been addressed—the decorator now only sets height for layout purposes.web/src/pages/org/status-mapping.ts (1)
1-30: LGTM!Clean utility implementation with exhaustive switch coverage for all
AgentStatusvalues. The previous feedback about combining fall-through cases for'onboarding'and'active'has been addressed (lines 14-16). TheresolveRuntimeStatusfunction correctly prioritizes WebSocket-pushed status over HR-derived defaults using nullish coalescing.web/src/pages/org/NodeContextMenu.tsx (1)
1-139: LGTM!All previous feedback has been addressed:
- CEO nodes now have their own
ceoItemsarray (lines 99-108) with only "View Details", preventing accidental inheritance of agent CRUD actions.- The selection logic (lines 110-111) correctly handles all three node types.
- Buttons include
type="button"(line 124) to prevent accidental form submission.The component properly implements accessibility with
role="menu"androle="menuitem", uses design tokens for styling, and cleans up event listeners on unmount.web/src/pages/org/NodeContextMenu.stories.tsx (1)
1-48: LGTM!All previous feedback has been addressed:
- Accessibility testing is configured with
parameters.a11y.test: 'error'(line 9).- The
CeoMenustory (lines 41-48) has been added for complete coverage of all threenodeTypevariants.The decorator correctly provides relative positioning context for the fixed-position menu component.
web/src/pages/org/AgentNode.tsx (1)
1-60: LGTM!The previous feedback about hardcoded pixel widths has been addressed—the component now uses standard Tailwind spacing classes (
min-w-36 max-w-44on line 27).The implementation properly:
- Reuses
AvatarandStatusBadgefrom@/components/ui/- Uses design tokens for all colors and borders
- Provides accessibility via
aria-labelwith agent context- Covers all
getStatusColoroutputs inSTATUS_RING_CLASSESwith a sensible fallbackweb/src/pages/org/AgentNode.stories.tsx (1)
1-69: LGTM!The previous feedback about missing a11y configuration has been addressed with
parameters.a11y.test: 'error'(lines 38-40).The stories provide complete coverage of all four
AgentRuntimeStatusvalues (active,idle,error,offline) with a well-structuredWrappercomponent that properly initializes the React Flow context needed for node rendering.web/src/__tests__/pages/org/DepartmentStatsBar.test.tsx (1)
1-32: LGTM!The test suite provides good coverage of the
DepartmentStatsBarcomponent:
- Parameterized tests verify all stat values and labels render correctly
- Conditional cost rendering is tested for both provided and null cases
- Component testability is verified via
data-testidThe use of
it.eachwith unique values (5, 3, 8) is a clean approach for testing the stats display.web/src/__tests__/pages/org/OrgChartToolbar.test.tsx (1)
1-52: LGTM!The previous feedback about shared mock instances has been addressed—the
createProps()factory function (lines 6-12) creates freshvi.fn()mocks for each test invocation, preventing state leakage between tests.The test suite provides comprehensive coverage of the toolbar's render states and callback handlers with proper mock isolation.
web/src/pages/org/OrgChartToolbar.stories.tsx (1)
1-30: LGTM!The story correctly uses interactive state management for
viewMode, includes proper a11y testing configuration (parameters.a11y.test: 'error'), and follows Storybook conventions.web/src/__tests__/pages/org/layout.test.ts (1)
1-104: LGTM!Comprehensive test coverage for
applyDagreLayoutincluding edge cases (empty input, invalid edges, department grouping). The test descriptions accurately reflect the assertions.web/src/pages/org/CeoNode.tsx (1)
1-52: LGTM!Clean implementation reusing
AvatarandStatusBadgecomponents. Design tokens are used correctly throughout, and the Tailwind v4 postfix important syntax (bg-accent! size-1.5!) is properly applied. Good accessibility attributes witharia-labelanddata-testid.web/src/pages/org/DepartmentStatsBar.tsx (1)
1-30: LGTM!Clean implementation reusing
StatPillcomponent. Thecurrencydefault correctly aligns withcostUsdsemantics, and the conditional cost rendering handles null values appropriately.web/src/__tests__/pages/org/NodeContextMenu.test.tsx (1)
22-69: Test coverage looks comprehensive.Good coverage of menu rendering by node type, action handler verification, keyboard accessibility (Escape), and ARIA roles.
web/src/pages/org/DepartmentGroupNode.tsx (1)
1-51: LGTM!Well-structured component with proper null handling for health-based styling. The fallback logic for
taskCount(line 42) correctly handles the nullable field, whileactiveCountdoesn't need a fallback since it's a required number per theDepartmentGroupDatainterface. Good use of design tokens and accessibility attributes.web/src/pages/org/DepartmentGroupNode.stories.tsx (1)
1-87: LGTM!Good story coverage across health states (Healthy/Warning/Critical) with appropriate a11y configuration. The
Criticalstory correctly tests thecostUsd: nulledge case.web/src/pages/org/DepartmentStatsBar.stories.tsx (1)
1-48: LGTM!Well-organized stories with good variant coverage (Default, NoCost, ZeroActive). The decorator properly uses Tailwind classes (
max-w-md) for width constraint.web/src/pages/org/build-org-tree.ts (5)
23-32: Health fields are correctly nullable — past issue addressed.The
healthPercent,taskCount, andcostUsdfields are now typed asnumber | null, allowing the renderer to distinguish between "0" and "unknown/loading" states. This addresses the previous review feedback about falsely displaying 100% health when the API is unavailable.
36-49: LGTM!The seniority ranking is comprehensive and correctly ordered. The defensive fallback to
-1handles any hypothetical type widening gracefully.
96-118: Empty departments are now rendered — past issue addressed.The previous review flagged that skipping
deptMembers.length === 0would hide newly created departments. This has been corrected: the loop now processes every configured department regardless of member count, and health fields default tonullrather than falsely-healthy values.
183-196: LGTM!Edge deduplication for CEO→department-head connections is correctly implemented, preventing duplicate edges when the CEO happens to also be connected via the team membership path.
68-78: Clean defensive handling for empty agent list.Early-returning an empty graph when all agents are terminated prevents downstream layout errors and is a sensible guard.
There was a problem hiding this comment.
Actionable comments posted: 5
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@web/src/__tests__/pages/org/NodeContextMenu.test.tsx`:
- Around line 52-57: Add a test alongside the Escape key test in
NodeContextMenu.test.tsx that asserts the menu also closes on an outside click:
render <NodeContextMenu {...baseProps} onClose={onClose} />, then simulate a
document-level outside click (e.g., fireEvent.mouseDown(document, { button: 0 })
or fireEvent.mouseDown(document.body)) and expect the onClose mock to have been
called once; reference the NodeContextMenu component and the onClose mock used
in the existing test to implement this new assertion.
- Around line 22-69: Add a property-based test using fast-check in
NodeContextMenu.test.tsx that asserts an invariant across supported node types
(e.g., 'agent' and 'department'); import fc and use fc.assert(fc.property(...))
to generate nodeType values and render the NodeContextMenu component (using the
existing baseProps and the nodeType prop) and assert invariant DOM properties
such as presence of role="menu" and correct menuitem counts or presence/absence
of specific action labels; update tests referencing NodeContextMenu, baseProps,
and the nodeType prop to run inside the fc.property so the suite covers
randomized inputs per guidelines.
In `@web/src/hooks/useOrgChartData.ts`:
- Around line 31-35: The current useEffect calls fetchDepartmentHealths()
unconditionally in the .then() of fetchCompanyData(), which will run even if
fetchCompanyData recorded an error; change the flow in the useEffect that uses
useCompanyStore.getState() so you await fetchCompanyData() (or inspect its
returned value) and only call companyStore.fetchDepartmentHealths() when the
company load actually succeeded — for example check the store error/success flag
after fetchCompanyData() (or use its boolean result) before invoking
fetchDepartmentHealths(); update the useEffect to use async/await or conditional
.then() logic around fetchCompanyData, referencing useEffect,
useCompanyStore.getState(), fetchCompanyData, and fetchDepartmentHealths.
In `@web/src/pages/org/build-org-tree.ts`:
- Around line 76-78: The early return on agents.length in build-org-tree.ts
prevents department nodes from being emitted when there are no agents; remove or
relax the guard in the code that returns { nodes: [], edges: [] } so
department/group nodes are still created (look for the agents.length === 0 check
in the buildOrgTree logic), and then update applyDagreLayout (the function
responsible for layout/placement) to add a department-only layout branch that
positions empty department/group nodes and prevents them from collapsing
together (ensure it handles cases with nodes but no agent child nodes by
assigning distinct group bounding boxes or fixed positions).
In `@web/src/pages/org/layout.ts`:
- Around line 74-81: The empty-group grid currently seeds at origin causing
overlap; update the empty-group placement inside positionedGroups map (where
emptyGroupIndex is used) to compute start offsets from the maximal laid-out
bounds instead of (0,0): scan positionedLeafMap (and any already-positioned
groups) to compute maxX and maxY (e.g., max position.x + width and position.y +
height) and use those as xOffset/yOffset when computing each empty group's
position (col * 240 + xOffset, row * 140 + yOffset); keep the existing
width/height/style values and increment emptyGroupIndex as before.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 823cc153-930f-4eb2-96c8-03827857c6e2
📒 Files selected for processing (5)
web/src/__tests__/pages/org/NodeContextMenu.test.tsxweb/src/hooks/useOrgChartData.tsweb/src/pages/OrgChartPage.tsxweb/src/pages/org/build-org-tree.tsweb/src/pages/org/layout.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
- GitHub Check: Dashboard Test
- GitHub Check: Build Sandbox
- GitHub Check: Build Web
- GitHub Check: Build Backend
- GitHub Check: Dependency Review
- GitHub Check: Analyze (python)
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx}: Use TypeScript 6+ withpathsfor module resolution (remove deprecatedbaseUrl);esModuleInteropis always true
In TypeScript,strictdefaults to true andtypesdefaults to[]; do not auto-discover@types/*— must explicitly list needed types
Files:
web/src/pages/OrgChartPage.tsxweb/src/hooks/useOrgChartData.tsweb/src/pages/org/layout.tsweb/src/__tests__/pages/org/NodeContextMenu.test.tsxweb/src/pages/org/build-org-tree.ts
web/src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
web/src/**/*.{ts,tsx}: Use React 19 with TypeScript 6+ in web dashboard; enforce design tokens (no hardcoded colors, fonts, spacing) and reuse components fromweb/src/components/ui/
Always reuse existing components fromweb/src/components/ui/(StatusBadge, MetricCard, Sparkline, SectionCard, AgentCard, DeptHealthBar, ProgressGauge, StatPill, Avatar, Button, Toast, Skeleton, EmptyState, ErrorBoundary, ConfirmDialog, CommandPalette, InlineEdit, AnimatedPresence, StaggerGroup/StaggerItem) before creating new ones
Use design tokens exclusively in web components: Tailwind semantic classes (text-foreground,bg-card,text-accent,text-success,bg-danger, etc.) or CSS variables (var(--so-accent)); never hardcode hex values or pixel spacing
Usefont-sansorfont-mono(Geist tokens) in web components; never setfontFamilydirectly
Use density-aware spacing tokens in web components (p-card,gap-section-gap,gap-grid-gap) or standard Tailwind spacing; never hardcode pixel values for layout spacing
Use shadow and border token variables in web components (var(--so-shadow-card-hover),border-border,border-bright); never hardcode shadow or border styles
In React components, importcnfrom@/lib/utilsfor conditional class merging; never concatenate class strings directly
Do not recreate status dots inline; use<StatusBadge>component
Do not build card-with-header layouts from scratch; use<SectionCard>component
Do not create metric displays withtext-metric font-bold; use<MetricCard>component
Do not render initials circles manually; use<Avatar>component
Do not create complex (>8 line) JSX inside.map()blocks; extract to a shared component
Files:
web/src/pages/OrgChartPage.tsxweb/src/hooks/useOrgChartData.tsweb/src/pages/org/layout.tsweb/src/__tests__/pages/org/NodeContextMenu.test.tsxweb/src/pages/org/build-org-tree.ts
web/src/pages/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Use React Router with lazy-loaded page components (one per route); place page-scoped sub-components in
pages/<page-name>/subdirectories
Files:
web/src/pages/OrgChartPage.tsxweb/src/pages/org/layout.tsweb/src/pages/org/build-org-tree.ts
web/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Use ESLint with
@eslint-react/eslint-pluginand eslint-plugin-security in web dashboard
Files:
web/src/pages/OrgChartPage.tsxweb/src/hooks/useOrgChartData.tsweb/src/pages/org/layout.tsweb/src/__tests__/pages/org/NodeContextMenu.test.tsxweb/src/pages/org/build-org-tree.ts
web/**
📄 CodeRabbit inference engine (CLAUDE.md)
Use Node.js 22+ and npm for web dashboard; all dependencies in
web/package.json(React 19, react-router, shadcn/ui, Radix UI, Tailwind CSS 4, Zustand, Recharts, Framer Motion, Axios, Lucide React, Geist fonts, Storybook 10, Vitest, ESLint, fast-check, etc.)
Files:
web/src/pages/OrgChartPage.tsxweb/src/hooks/useOrgChartData.tsweb/src/pages/org/layout.tsweb/src/__tests__/pages/org/NodeContextMenu.test.tsxweb/src/pages/org/build-org-tree.ts
web/src/__tests__/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
web/src/__tests__/**/*.{ts,tsx}: Use fast-check for property-based testing in React; usefc.assertandfc.property
Use Vitest for React unit testing with coverage scoped to files changed vs origin/main
Files:
web/src/__tests__/pages/org/NodeContextMenu.test.tsx
🧠 Learnings (11)
📓 Common learnings
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T21:20:09.993Z
Learning: Applies to web/src/components/** : Vue components organized by feature (agents/, approvals/, budget/, common/, dashboard/, layout/, messages/, org-chart/, tasks/).
📚 Learning: 2026-03-27T09:44:40.059Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T09:44:40.059Z
Learning: Applies to web/src/**/*.{ts,tsx} : Use React 19 with TypeScript 6+ in web dashboard; enforce design tokens (no hardcoded colors, fonts, spacing) and reuse components from `web/src/components/ui/`
Applied to files:
web/src/pages/OrgChartPage.tsxweb/src/hooks/useOrgChartData.tsweb/src/pages/org/layout.ts
📚 Learning: 2026-03-27T09:44:40.059Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T09:44:40.059Z
Learning: Applies to web/src/**/*.{ts,tsx} : Always reuse existing components from `web/src/components/ui/` (StatusBadge, MetricCard, Sparkline, SectionCard, AgentCard, DeptHealthBar, ProgressGauge, StatPill, Avatar, Button, Toast, Skeleton, EmptyState, ErrorBoundary, ConfirmDialog, CommandPalette, InlineEdit, AnimatedPresence, StaggerGroup/StaggerItem) before creating new ones
Applied to files:
web/src/pages/OrgChartPage.tsxweb/src/hooks/useOrgChartData.ts
📚 Learning: 2026-03-27T09:44:40.059Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T09:44:40.059Z
Learning: Applies to web/src/**/*.{ts,tsx} : Do not create complex (>8 line) JSX inside `.map()` blocks; extract to a shared component
Applied to files:
web/src/pages/OrgChartPage.tsx
📚 Learning: 2026-03-27T09:44:40.059Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T09:44:40.059Z
Learning: Applies to web/src/**/*.{ts,tsx} : Do not recreate status dots inline; use `<StatusBadge>` component
Applied to files:
web/src/pages/OrgChartPage.tsx
📚 Learning: 2026-03-27T09:44:40.059Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T09:44:40.059Z
Learning: Applies to web/**/*.{ts,tsx} : Use ESLint with eslint-react/eslint-plugin and eslint-plugin-security in web dashboard
Applied to files:
web/src/hooks/useOrgChartData.ts
📚 Learning: 2026-03-27T09:44:40.059Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T09:44:40.059Z
Learning: Applies to web/src/pages/**/*.{ts,tsx} : Use React Router with lazy-loaded page components (one per route); place page-scoped sub-components in `pages/<page-name>/` subdirectories
Applied to files:
web/src/pages/org/layout.ts
📚 Learning: 2026-03-27T09:44:40.059Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T09:44:40.059Z
Learning: Applies to web/src/__tests__/**/*.{ts,tsx} : Use Vitest for React unit testing with coverage scoped to files changed vs origin/main
Applied to files:
web/src/__tests__/pages/org/NodeContextMenu.test.tsx
📚 Learning: 2026-03-20T08:28:32.845Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-20T08:28:32.845Z
Learning: Applies to web/src/__tests__/**/*.{ts,js} : Dashboard testing: Vitest unit tests organized by feature under `web/src/__tests__/`. Use fast-check for property-based testing (`fc.assert` + `fc.property`).
Applied to files:
web/src/__tests__/pages/org/NodeContextMenu.test.tsx
📚 Learning: 2026-03-27T09:44:40.059Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T09:44:40.059Z
Learning: Applies to web/src/__tests__/**/*.{ts,tsx} : Use fast-check for property-based testing in React; use `fc.assert` and `fc.property`
Applied to files:
web/src/__tests__/pages/org/NodeContextMenu.test.tsx
📚 Learning: 2026-03-27T09:44:40.059Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T09:44:40.059Z
Learning: Applies to web/src/components/**/*.stories.{ts,tsx} : Use Storybook 10 (ESM-only) for React component documentation; import from `storybook/test`, `storybook/actions`; use `definePreview` from `storybook/react-vite`
Applied to files:
web/src/__tests__/pages/org/NodeContextMenu.test.tsx
🔇 Additional comments (3)
web/src/__tests__/pages/org/NodeContextMenu.test.tsx (1)
38-50: Callback argument assertions are correctly scoped tonodeId.Line 42 and Line 49 match the component contract (
onViewDetails(nodeId)/onDelete(nodeId)) and protect against accidental signature drift.web/src/hooks/useOrgChartData.ts (1)
44-48: The eslint-disable still targets a nonexistent rule.
@eslint-react/eslint-plugindoes not expose@eslint-react/exhaustive-deps, so this suppression is inert. Either switch it toreact-hooks/exhaustive-depsafter wiringeslint-plugin-react-hooks, or drop the disable entirely.#!/bin/bash configs="$(fd -t f 'eslint\.config\..*|\.eslintrc.*' .)" printf '%s\n' "$configs" rg -n "@eslint-react/exhaustive-deps|react-hooks/exhaustive-deps|eslint-plugin-react-hooks" web/src/hooks/useOrgChartData.ts web/package.json $configsweb/src/pages/OrgChartPage.tsx (1)
298-300: Good use ofButton asChildhere.This keeps the CTA as a single interactive element and avoids the nested button/link accessibility issue.
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (1)
web/src/hooks/useOrgChartData.ts (1)
31-38:⚠️ Potential issue | 🟡 MinorHealth fetch still runs after failed company load.
The
.then()callback executes regardless of whetherfetchCompanyData()succeeded or recorded an error. While the config check on line 34 prevents callingfetchDepartmentHealths()when config is null, it doesn't distinguish between "not yet loaded" and "load failed with error". This can cause unnecessary API calls when the company endpoint is failing.🛡️ Proposed fix to gate on success
useEffect(() => { - const companyStore = useCompanyStore.getState() - companyStore.fetchCompanyData().then(() => { - if (useCompanyStore.getState().config) { - companyStore.fetchDepartmentHealths() - } - }) + const load = async () => { + const companyStore = useCompanyStore.getState() + await companyStore.fetchCompanyData() + const { config, error } = useCompanyStore.getState() + if (!error && config) { + await companyStore.fetchDepartmentHealths() + } + } + void load() }, [])🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@web/src/hooks/useOrgChartData.ts` around lines 31 - 38, The current useEffect calls useCompanyStore.getState().fetchCompanyData().then(...) which runs the .then callback even when fetchCompanyData failed; change the effect to an async flow and only call fetchDepartmentHealths when the company load succeeded: inside useEffect create an async function that awaits useCompanyStore.getState().fetchCompanyData(), then check a success indicator (e.g. the resolved value or store flags like useCompanyStore.getState().config and absence of useCompanyStore.getState().error) before calling useCompanyStore.getState().fetchDepartmentHealths(); alternatively handle rejection with try/catch and only call fetchDepartmentHealths in the try block after successful await of fetchCompanyData().
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@web/src/pages/org/build-org-tree.ts`:
- Around line 207-220: The CEO selection currently uses a deterministic
"first-in-array wins" tiebreaker but this is implicit; add a clear comment in
findCeo and in findHighestSeniority stating that when multiple agents tie on
level/seniority the function returns the first matching element in array order
(due to using array filter + first element and the '>' comparison in the max
reduction), so maintainers know the intended deterministic behavior and can
change it intentionally if needed; place the comment immediately above the
findCeo and findHighestSeniority function definitions for visibility.
In `@web/src/pages/org/layout.ts`:
- Around line 35-37: The early return that maps all nodes to position {x:0,y:0}
when leafNodes.length === 0 causes overlapping; instead call or reuse the
empty-group positioning logic used later (the code that handles empty department
groups) so each department node gets a computed position rather than all at
(0,0). Replace the nodes.map fallback with a call into that empty-group
positioning routine (or inline the same placement calculation) so nodes are
spaced correctly when there are no leafNodes; update any references to
leafNodes/nodes accordingly.
---
Duplicate comments:
In `@web/src/hooks/useOrgChartData.ts`:
- Around line 31-38: The current useEffect calls
useCompanyStore.getState().fetchCompanyData().then(...) which runs the .then
callback even when fetchCompanyData failed; change the effect to an async flow
and only call fetchDepartmentHealths when the company load succeeded: inside
useEffect create an async function that awaits
useCompanyStore.getState().fetchCompanyData(), then check a success indicator
(e.g. the resolved value or store flags like useCompanyStore.getState().config
and absence of useCompanyStore.getState().error) before calling
useCompanyStore.getState().fetchDepartmentHealths(); alternatively handle
rejection with try/catch and only call fetchDepartmentHealths in the try block
after successful await of fetchCompanyData().
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: ad473a43-79c3-4b14-b3c0-bf442d75cdcf
📒 Files selected for processing (4)
web/src/__tests__/pages/org/NodeContextMenu.test.tsxweb/src/hooks/useOrgChartData.tsweb/src/pages/org/build-org-tree.tsweb/src/pages/org/layout.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
- GitHub Check: Dashboard Test
- GitHub Check: Build Backend
- GitHub Check: Build Sandbox
- GitHub Check: Dependency Review
- GitHub Check: Analyze (python)
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx}: Use TypeScript 6+ withpathsfor module resolution (remove deprecatedbaseUrl);esModuleInteropis always true
In TypeScript,strictdefaults to true andtypesdefaults to[]; do not auto-discover@types/*— must explicitly list needed types
Files:
web/src/__tests__/pages/org/NodeContextMenu.test.tsxweb/src/pages/org/layout.tsweb/src/pages/org/build-org-tree.tsweb/src/hooks/useOrgChartData.ts
web/src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
web/src/**/*.{ts,tsx}: Use React 19 with TypeScript 6+ in web dashboard; enforce design tokens (no hardcoded colors, fonts, spacing) and reuse components fromweb/src/components/ui/
Always reuse existing components fromweb/src/components/ui/(StatusBadge, MetricCard, Sparkline, SectionCard, AgentCard, DeptHealthBar, ProgressGauge, StatPill, Avatar, Button, Toast, Skeleton, EmptyState, ErrorBoundary, ConfirmDialog, CommandPalette, InlineEdit, AnimatedPresence, StaggerGroup/StaggerItem) before creating new ones
Use design tokens exclusively in web components: Tailwind semantic classes (text-foreground,bg-card,text-accent,text-success,bg-danger, etc.) or CSS variables (var(--so-accent)); never hardcode hex values or pixel spacing
Usefont-sansorfont-mono(Geist tokens) in web components; never setfontFamilydirectly
Use density-aware spacing tokens in web components (p-card,gap-section-gap,gap-grid-gap) or standard Tailwind spacing; never hardcode pixel values for layout spacing
Use shadow and border token variables in web components (var(--so-shadow-card-hover),border-border,border-bright); never hardcode shadow or border styles
In React components, importcnfrom@/lib/utilsfor conditional class merging; never concatenate class strings directly
Do not recreate status dots inline; use<StatusBadge>component
Do not build card-with-header layouts from scratch; use<SectionCard>component
Do not create metric displays withtext-metric font-bold; use<MetricCard>component
Do not render initials circles manually; use<Avatar>component
Do not create complex (>8 line) JSX inside.map()blocks; extract to a shared component
Files:
web/src/__tests__/pages/org/NodeContextMenu.test.tsxweb/src/pages/org/layout.tsweb/src/pages/org/build-org-tree.tsweb/src/hooks/useOrgChartData.ts
web/src/__tests__/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
web/src/__tests__/**/*.{ts,tsx}: Use fast-check for property-based testing in React; usefc.assertandfc.property
Use Vitest for React unit testing with coverage scoped to files changed vs origin/main
Files:
web/src/__tests__/pages/org/NodeContextMenu.test.tsx
web/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Use ESLint with
@eslint-react/eslint-pluginand eslint-plugin-security in web dashboard
Files:
web/src/__tests__/pages/org/NodeContextMenu.test.tsxweb/src/pages/org/layout.tsweb/src/pages/org/build-org-tree.tsweb/src/hooks/useOrgChartData.ts
web/**
📄 CodeRabbit inference engine (CLAUDE.md)
Use Node.js 22+ and npm for web dashboard; all dependencies in
web/package.json(React 19, react-router, shadcn/ui, Radix UI, Tailwind CSS 4, Zustand, Recharts, Framer Motion, Axios, Lucide React, Geist fonts, Storybook 10, Vitest, ESLint, fast-check, etc.)
Files:
web/src/__tests__/pages/org/NodeContextMenu.test.tsxweb/src/pages/org/layout.tsweb/src/pages/org/build-org-tree.tsweb/src/hooks/useOrgChartData.ts
web/src/pages/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Use React Router with lazy-loaded page components (one per route); place page-scoped sub-components in
pages/<page-name>/subdirectories
Files:
web/src/pages/org/layout.tsweb/src/pages/org/build-org-tree.ts
🧠 Learnings (11)
📓 Common learnings
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T21:20:09.993Z
Learning: Applies to web/src/components/** : Vue components organized by feature (agents/, approvals/, budget/, common/, dashboard/, layout/, messages/, org-chart/, tasks/).
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T09:44:40.059Z
Learning: Applies to web/** : Use Node.js 22+ and npm for web dashboard; all dependencies in `web/package.json` (React 19, react-router, shadcn/ui, Radix UI, Tailwind CSS 4, Zustand, Recharts, Framer Motion, Axios, Lucide React, Geist fonts, Storybook 10, Vitest, ESLint, fast-check, etc.)
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:17:43.675Z
Learning: Applies to web/** : Web dashboard: Node.js 20+, dependencies in web/package.json (Vue 3, PrimeVue, Tailwind CSS, Pinia, VueFlow, ECharts, Axios, vue-draggable-plus, Vitest, fast-check, ESLint, vue-tsc).
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T09:44:40.059Z
Learning: Applies to web/src/**/*.{ts,tsx} : Always reuse existing components from `web/src/components/ui/` (StatusBadge, MetricCard, Sparkline, SectionCard, AgentCard, DeptHealthBar, ProgressGauge, StatPill, Avatar, Button, Toast, Skeleton, EmptyState, ErrorBoundary, ConfirmDialog, CommandPalette, InlineEdit, AnimatedPresence, StaggerGroup/StaggerItem) before creating new ones
📚 Learning: 2026-03-27T09:44:40.059Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T09:44:40.059Z
Learning: Applies to web/src/__tests__/**/*.{ts,tsx} : Use Vitest for React unit testing with coverage scoped to files changed vs origin/main
Applied to files:
web/src/__tests__/pages/org/NodeContextMenu.test.tsx
📚 Learning: 2026-03-20T08:28:32.845Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-20T08:28:32.845Z
Learning: Applies to web/src/__tests__/**/*.{ts,js} : Dashboard testing: Vitest unit tests organized by feature under `web/src/__tests__/`. Use fast-check for property-based testing (`fc.assert` + `fc.property`).
Applied to files:
web/src/__tests__/pages/org/NodeContextMenu.test.tsx
📚 Learning: 2026-03-27T09:44:40.059Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T09:44:40.059Z
Learning: Applies to web/src/__tests__/**/*.{ts,tsx} : Use fast-check for property-based testing in React; use `fc.assert` and `fc.property`
Applied to files:
web/src/__tests__/pages/org/NodeContextMenu.test.tsx
📚 Learning: 2026-03-27T09:44:40.059Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T09:44:40.059Z
Learning: Applies to web/src/**/*.{ts,tsx} : Use React 19 with TypeScript 6+ in web dashboard; enforce design tokens (no hardcoded colors, fonts, spacing) and reuse components from `web/src/components/ui/`
Applied to files:
web/src/__tests__/pages/org/NodeContextMenu.test.tsxweb/src/pages/org/layout.tsweb/src/pages/org/build-org-tree.tsweb/src/hooks/useOrgChartData.ts
📚 Learning: 2026-03-27T09:44:40.059Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T09:44:40.059Z
Learning: Applies to web/src/components/**/*.stories.{ts,tsx} : Use Storybook 10 (ESM-only) for React component documentation; import from `storybook/test`, `storybook/actions`; use `definePreview` from `storybook/react-vite`
Applied to files:
web/src/__tests__/pages/org/NodeContextMenu.test.tsx
📚 Learning: 2026-03-27T09:44:40.059Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T09:44:40.059Z
Learning: Applies to web/**/*.stories.{ts,tsx} : In Storybook, use `parameters.a11y.test: 'error' | 'todo' | 'off'` for a11y testing configuration (replaces old `.element` and `.manual`)
Applied to files:
web/src/__tests__/pages/org/NodeContextMenu.test.tsx
📚 Learning: 2026-03-27T09:44:40.059Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T09:44:40.059Z
Learning: Applies to web/src/pages/**/*.{ts,tsx} : Use React Router with lazy-loaded page components (one per route); place page-scoped sub-components in `pages/<page-name>/` subdirectories
Applied to files:
web/src/pages/org/layout.ts
📚 Learning: 2026-03-15T21:20:09.993Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T21:20:09.993Z
Learning: Applies to web/src/components/** : Vue components organized by feature (agents/, approvals/, budget/, common/, dashboard/, layout/, messages/, org-chart/, tasks/).
Applied to files:
web/src/pages/org/build-org-tree.ts
📚 Learning: 2026-03-27T09:44:40.059Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T09:44:40.059Z
Learning: Applies to web/src/**/*.{ts,tsx} : Always reuse existing components from `web/src/components/ui/` (StatusBadge, MetricCard, Sparkline, SectionCard, AgentCard, DeptHealthBar, ProgressGauge, StatPill, Avatar, Button, Toast, Skeleton, EmptyState, ErrorBoundary, ConfirmDialog, CommandPalette, InlineEdit, AnimatedPresence, StaggerGroup/StaggerItem) before creating new ones
Applied to files:
web/src/hooks/useOrgChartData.ts
📚 Learning: 2026-03-27T09:44:40.059Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T09:44:40.059Z
Learning: Applies to web/**/*.{ts,tsx} : Use ESLint with eslint-react/eslint-plugin and eslint-plugin-security in web dashboard
Applied to files:
web/src/hooks/useOrgChartData.ts
🔇 Additional comments (17)
web/src/__tests__/pages/org/NodeContextMenu.test.tsx (3)
1-21: LGTM!The test setup correctly addresses previous review feedback: imports are complete (including
beforeEach), and thebeforeEachblock properly resetsbasePropswith a fresh mock for test isolation. Tests that need to assert on callbacks create local mocks, which is the right pattern.
23-86: Good test coverage for core functionality.The tests correctly verify:
- Menu items for different node types (agent: 4 items, department: 3 items)
- Callback wiring (
onViewDetails,onDelete) with correctnodeIdargument- Close behaviors (Escape key, outside click)
- Accessibility roles (
menu,menuitem)One minor gap: there's no explicit test for the
ceonode type menu items (which per the component only shows "View Details"). Theit.eachcovers that it renders something, but not the specific expected content.
88-106: Property-based test complies with guidelines and tests meaningful invariants.The test correctly uses
fc.assertandfc.propertyas required by coding guidelines. The invariants tested (menu role presence, at least one menu item, all items are buttons) are meaningful structural guarantees. Theunmount()call properly cleans up the DOM between iterations.web/src/hooks/useOrgChartData.ts (3)
46-50: Invalid ESLint rule reference remains unfixed.The disable comment references
@eslint-react/exhaustive-deps, but this rule doesn't exist in@eslint-react/eslint-plugin. Theexhaustive-depsrule comes fromeslint-plugin-react-hooks. Sinceeslint-plugin-react-hooksis not installed in this project, this comment has no effect.Either install
eslint-plugin-react-hooksand usereact-hooks/exhaustive-deps, or remove the ineffective comment.
52-63: LGTM!The WebSocket handler correctly dispatches events to both stores. As shown in the store implementations, each store filters for its own event types (
agent.hired/agent.firedfor company,agent.status_changedfor agents), making this dual-dispatch pattern safe and appropriate.
69-75: LGTM!The memoization correctly derives React Flow nodes/edges from store data with appropriate dependencies. The layout computation using fixed fallback dimensions (handled in
applyDagreLayout) provides a stable initial layout before React Flow can measure actual node dimensions.web/src/pages/org/layout.ts (5)
1-16: LGTM!Clean imports and well-documented constants for layout configuration. The type definitions are appropriately scoped.
51-55: LGTM!Good defensive check ensuring edges are only added when both source and target nodes exist in the graph. This handles edge cases like edges referencing missing nodes.
59-80: LGTM!Correct coordinate transformation from dagre's center-based positioning to React Flow's top-left origin. The content bounds computation properly accounts for node dimensions to enable proper empty-group offsetting.
85-93: LGTM!Empty department groups are now correctly offset beyond the content bounds (
xOffset = contentMaxX + padding), preventing overlap with populated content. The 3-column grid layout provides clean organization for multiple empty departments.
115-124: LGTM!Children positions are correctly converted to group-relative coordinates via immutable map updates. This ensures React Flow properly renders children within their parent group nodes.
web/src/pages/org/build-org-tree.ts (6)
1-56: LGTM!Well-structured type definitions and seniority ranking. The index signature
[key: string]: unknownon node data interfaces enables React Flow's type requirements while maintaining type safety for known properties.
73-89: LGTM!Correct filtering of terminated agents and grouping by department. The CEO selection properly falls through the priority chain (executive c_suite → any c_suite → highest seniority).
99-114: LGTM!Department group nodes correctly handle missing health data with nullable fields (
?? null), allowing the UI to render appropriate loading/unknown states rather than falsely showing 100% health.
119-129: LGTM!Team membership assignment correctly prevents overwrites with the
!teamMemberSet.has(member.id)guard, ensuring consistent parent assignment when an agent appears in multiple teams (first team wins).
145-176: LGTM!Node creation correctly assigns
parentIdfor React Flow group containment. Edge creation properly establishes the reporting hierarchy: team members → team lead → department head → CEO, with appropriate deduplication.
222-229: LGTM!
findDepartmentHeadcorrectly excludes the CEO when determining department leadership and properly passes the readonly array directly tofindHighestSeniority.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@web/src/pages/org/layout.ts`:
- Around line 77-98: The empty-group branch in the positionedGroups map replaces
group.style entirely (returning { ...group, position: ..., style: { width: 200,
height: 100 } }) which loses existing style props; change it to merge the
existing style instead (e.g., style: { ...group.style, width: 200, height: 100
}) so it matches the other branches (see positionedGroups, groupNodes,
group.style, DEFAULT_GROUP_PADDING, emptyGroupIndex) and preserves pre-existing
style attributes.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 077bd051-227e-49aa-9261-a67fa5529d8e
📒 Files selected for processing (2)
web/src/pages/org/build-org-tree.tsweb/src/pages/org/layout.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
- GitHub Check: Build Backend
- GitHub Check: Build Web
- GitHub Check: Build Sandbox
- GitHub Check: Dependency Review
- GitHub Check: Analyze (python)
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx}: Use TypeScript 6+ withpathsfor module resolution (remove deprecatedbaseUrl);esModuleInteropis always true
In TypeScript,strictdefaults to true andtypesdefaults to[]; do not auto-discover@types/*— must explicitly list needed types
Files:
web/src/pages/org/layout.tsweb/src/pages/org/build-org-tree.ts
web/src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
web/src/**/*.{ts,tsx}: Use React 19 with TypeScript 6+ in web dashboard; enforce design tokens (no hardcoded colors, fonts, spacing) and reuse components fromweb/src/components/ui/
Always reuse existing components fromweb/src/components/ui/(StatusBadge, MetricCard, Sparkline, SectionCard, AgentCard, DeptHealthBar, ProgressGauge, StatPill, Avatar, Button, Toast, Skeleton, EmptyState, ErrorBoundary, ConfirmDialog, CommandPalette, InlineEdit, AnimatedPresence, StaggerGroup/StaggerItem) before creating new ones
Use design tokens exclusively in web components: Tailwind semantic classes (text-foreground,bg-card,text-accent,text-success,bg-danger, etc.) or CSS variables (var(--so-accent)); never hardcode hex values or pixel spacing
Usefont-sansorfont-mono(Geist tokens) in web components; never setfontFamilydirectly
Use density-aware spacing tokens in web components (p-card,gap-section-gap,gap-grid-gap) or standard Tailwind spacing; never hardcode pixel values for layout spacing
Use shadow and border token variables in web components (var(--so-shadow-card-hover),border-border,border-bright); never hardcode shadow or border styles
In React components, importcnfrom@/lib/utilsfor conditional class merging; never concatenate class strings directly
Do not recreate status dots inline; use<StatusBadge>component
Do not build card-with-header layouts from scratch; use<SectionCard>component
Do not create metric displays withtext-metric font-bold; use<MetricCard>component
Do not render initials circles manually; use<Avatar>component
Do not create complex (>8 line) JSX inside.map()blocks; extract to a shared component
Files:
web/src/pages/org/layout.tsweb/src/pages/org/build-org-tree.ts
web/src/pages/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Use React Router with lazy-loaded page components (one per route); place page-scoped sub-components in
pages/<page-name>/subdirectories
Files:
web/src/pages/org/layout.tsweb/src/pages/org/build-org-tree.ts
web/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Use ESLint with
@eslint-react/eslint-pluginand eslint-plugin-security in web dashboard
Files:
web/src/pages/org/layout.tsweb/src/pages/org/build-org-tree.ts
web/**
📄 CodeRabbit inference engine (CLAUDE.md)
Use Node.js 22+ and npm for web dashboard; all dependencies in
web/package.json(React 19, react-router, shadcn/ui, Radix UI, Tailwind CSS 4, Zustand, Recharts, Framer Motion, Axios, Lucide React, Geist fonts, Storybook 10, Vitest, ESLint, fast-check, etc.)
Files:
web/src/pages/org/layout.tsweb/src/pages/org/build-org-tree.ts
🧠 Learnings (2)
📓 Common learnings
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T21:20:09.993Z
Learning: Applies to web/src/components/** : Vue components organized by feature (agents/, approvals/, budget/, common/, dashboard/, layout/, messages/, org-chart/, tasks/).
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T09:44:40.059Z
Learning: Applies to web/** : Use Node.js 22+ and npm for web dashboard; all dependencies in `web/package.json` (React 19, react-router, shadcn/ui, Radix UI, Tailwind CSS 4, Zustand, Recharts, Framer Motion, Axios, Lucide React, Geist fonts, Storybook 10, Vitest, ESLint, fast-check, etc.)
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:17:43.675Z
Learning: Applies to web/** : Web dashboard: Node.js 20+, dependencies in web/package.json (Vue 3, PrimeVue, Tailwind CSS, Pinia, VueFlow, ECharts, Axios, vue-draggable-plus, Vitest, fast-check, ESLint, vue-tsc).
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T15:43:05.601Z
Learning: Applies to web/package.json : Web dashboard Node.js 20+; dependencies in web/package.json (Vue 3, PrimeVue, Tailwind CSS, Pinia, VueFlow, ECharts, Axios, vue-draggable-plus, Vitest, ESLint, vue-tsc)
📚 Learning: 2026-03-15T21:20:09.993Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T21:20:09.993Z
Learning: Applies to web/src/components/** : Vue components organized by feature (agents/, approvals/, budget/, common/, dashboard/, layout/, messages/, org-chart/, tasks/).
Applied to files:
web/src/pages/org/build-org-tree.ts
🔇 Additional comments (13)
web/src/pages/org/layout.ts (5)
1-16: LGTM!Imports and type definitions are appropriate. Constants for default dimensions and padding are well-chosen defaults for org chart layout.
35-42: Grid fallback for department-only layouts looks correct.When no leaf (agent) nodes exist, placing all nodes on a 3-column grid with preserved styles prevents overlapping. This addresses the prior concern about department-only scenarios.
44-75: Dagre graph construction and coordinate conversion are correct.Leaf nodes are properly separated from department groups, edges are filtered to only include valid node pairs, and dagre center coordinates are correctly converted to React Flow top-left positions.
100-136: Group bounding box calculation and child position adjustment are correct.Padding and header height offsets are properly applied, and child positions are updated immutably via
positionedLeafMap.set().
138-139: Return combines groups and positioned leaves correctly.web/src/pages/org/build-org-tree.ts (8)
1-5: LGTM!Imports are appropriate and use path aliases as expected.
6-32: Well-structured node data interfaces.The interfaces correctly define the data shape for each node type. Using
nullfor optional health/task/cost fields allows the UI to distinguish "unknown/loading" from "zero" values. The[key: string]: unknownindex signature satisfies React Flow's data typing requirements.
34-49: Seniority ranking is well-defined.The SENIORITY_RANK mapping covers the expected levels and
seniorityOfreturns-1for unknown levels, providing safe fallback behavior.
68-97: Agent filtering, grouping, and health integration are correct.Terminated agents are properly excluded. The activeCount calculation correctly uses
resolveRuntimeStatusto determine runtime state. Missing health data correctly defaults tonull(lines 108, 111, 112) rather than falsely healthy values.
119-129: Team membership logic correctly prevents overwrites.The
!teamMemberSet.has(member.id)check at line 125 ensures the first team assignment wins if an agent appears in multiple teams, preventing silent overwrites.
131-177: Agent node creation and edge generation are correct.CEO nodes receive the extended data with
companyName. The edge creation logic properly handles:
- Team members → team lead edges
- Non-team agents → department head edges
- CEO is excluded from self-referential edges
179-193: CEO-to-head edge deduplication is properly handled.The
alreadyConnectedcheck prevents duplicate edges when a department head might already be connected via team structure.
198-231: Helper functions are well-documented and correct.Tiebreaker behavior is clearly documented in the JSDoc comments for both
findHighestSeniorityandfindCeo. ThefindDepartmentHeadfunction correctly passesmembersdirectly (without unnecessary spread) whenceois null, as that array is only read byfindHighestSeniority.
|
All alerts resolved. Learn more about Socket for GitHub. This PR previously contained dependency changes with security issues that have been resolved, removed, or ignored. |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@web/src/pages/org/layout.ts`:
- Around line 35-40: The layout code that maps department group nodes (the
branch using leafNodes.length === 0 and the other empty-group branch) sets
style.height to 100 which conflicts with DepartmentGroupNode.tsx's rendered
min-h-[120px], causing bounds/fitView to be 20px short; update both mapping
branches (the nodes.map that returns { ...n, position: ..., style: { ...n.style,
width: 200, height: 100 } } and the other empty-group mapping) to use the
rendered empty-group height (height: 120 or otherwise derive the min height used
by DepartmentGroupNode) so the Flow measurements match the component's min
height.
- Around line 29-33: The dagre spacing doesn't account for department chrome
(40px side padding and 40px header), so compute effective separators after
detecting group nodes and increase/clamp them: after const groupNodes =
nodes.filter((n) => n.type === 'department') and const leafNodes = ..., if
groupNodes.length > 0 then bump horizontal spacing by the side chrome (e.g.,
nodeSep = Math.max(nodeSep, nodeSep + 80) or more simply nodeSep += 80) and bump
vertical spacing by the header chrome (e.g., rankSep = Math.max(rankSep, rankSep
+ 40) or rankSep += 40) so boxed departments cannot overlap; apply the same
adjustment where separators are set elsewhere noted (the other occurrences
around the file).
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 50c6baf9-1125-4b91-be2b-e392cb19cadb
📒 Files selected for processing (1)
web/src/pages/org/layout.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
- GitHub Check: Build Backend
- GitHub Check: Build Web
- GitHub Check: Build Sandbox
- GitHub Check: Dependency Review
- GitHub Check: Analyze (python)
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx}: Use TypeScript 6+ withpathsfor module resolution (remove deprecatedbaseUrl);esModuleInteropis always true
In TypeScript,strictdefaults to true andtypesdefaults to[]; do not auto-discover@types/*— must explicitly list needed types
Files:
web/src/pages/org/layout.ts
web/src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
web/src/**/*.{ts,tsx}: Use React 19 with TypeScript 6+ in web dashboard; enforce design tokens (no hardcoded colors, fonts, spacing) and reuse components fromweb/src/components/ui/
Always reuse existing components fromweb/src/components/ui/(StatusBadge, MetricCard, Sparkline, SectionCard, AgentCard, DeptHealthBar, ProgressGauge, StatPill, Avatar, Button, Toast, Skeleton, EmptyState, ErrorBoundary, ConfirmDialog, CommandPalette, InlineEdit, AnimatedPresence, StaggerGroup/StaggerItem) before creating new ones
Use design tokens exclusively in web components: Tailwind semantic classes (text-foreground,bg-card,text-accent,text-success,bg-danger, etc.) or CSS variables (var(--so-accent)); never hardcode hex values or pixel spacing
Usefont-sansorfont-mono(Geist tokens) in web components; never setfontFamilydirectly
Use density-aware spacing tokens in web components (p-card,gap-section-gap,gap-grid-gap) or standard Tailwind spacing; never hardcode pixel values for layout spacing
Use shadow and border token variables in web components (var(--so-shadow-card-hover),border-border,border-bright); never hardcode shadow or border styles
In React components, importcnfrom@/lib/utilsfor conditional class merging; never concatenate class strings directly
Do not recreate status dots inline; use<StatusBadge>component
Do not build card-with-header layouts from scratch; use<SectionCard>component
Do not create metric displays withtext-metric font-bold; use<MetricCard>component
Do not render initials circles manually; use<Avatar>component
Do not create complex (>8 line) JSX inside.map()blocks; extract to a shared component
Files:
web/src/pages/org/layout.ts
web/src/pages/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Use React Router with lazy-loaded page components (one per route); place page-scoped sub-components in
pages/<page-name>/subdirectories
Files:
web/src/pages/org/layout.ts
web/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Use ESLint with
@eslint-react/eslint-pluginand eslint-plugin-security in web dashboard
Files:
web/src/pages/org/layout.ts
web/**
📄 CodeRabbit inference engine (CLAUDE.md)
Use Node.js 22+ and npm for web dashboard; all dependencies in
web/package.json(React 19, react-router, shadcn/ui, Radix UI, Tailwind CSS 4, Zustand, Recharts, Framer Motion, Axios, Lucide React, Geist fonts, Storybook 10, Vitest, ESLint, fast-check, etc.)
Files:
web/src/pages/org/layout.ts
🧠 Learnings (1)
📓 Common learnings
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T21:20:09.993Z
Learning: Applies to web/src/components/** : Vue components organized by feature (agents/, approvals/, budget/, common/, dashboard/, layout/, messages/, org-chart/, tasks/).
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T09:44:40.059Z
Learning: Applies to web/** : Use Node.js 22+ and npm for web dashboard; all dependencies in `web/package.json` (React 19, react-router, shadcn/ui, Radix UI, Tailwind CSS 4, Zustand, Recharts, Framer Motion, Axios, Lucide React, Geist fonts, Storybook 10, Vitest, ESLint, fast-check, etc.)
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:17:43.675Z
Learning: Applies to web/** : Web dashboard: Node.js 20+, dependencies in web/package.json (Vue 3, PrimeVue, Tailwind CSS, Pinia, VueFlow, ECharts, Axios, vue-draggable-plus, Vitest, fast-check, ESLint, vue-tsc).
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T15:43:05.601Z
Learning: Applies to web/package.json : Web dashboard Node.js 20+; dependencies in web/package.json (Vue 3, PrimeVue, Tailwind CSS, Pinia, VueFlow, ECharts, Axios, vue-draggable-plus, Vitest, ESLint, vue-tsc)
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@web/src/pages/org/layout.ts`:
- Line 30: The fallback branches ignore the destructured direction variable and
always render a top-to-bottom grid; update the department-only and
empty-department JSX branches to honor direction by using the direction value
when building the grid (e.g., conditionally set gridAutoFlow/gridTemplateColumns
vs gridTemplateRows or swap CSS classes) so applyDagreLayout(..., { direction:
'LR' }) produces a left-to-right layout; locate and update the branches that
render the empty department and department-only grids (referencing the direction
constant) to choose column-oriented styles when direction === 'LR' and
row-oriented styles when direction === 'TB'.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 6358bdf8-9a96-412e-89a8-f8f625cc2590
📒 Files selected for processing (1)
web/src/pages/org/layout.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
- GitHub Check: Dashboard Test
- GitHub Check: Build Web
- GitHub Check: Build Backend
- GitHub Check: Build Sandbox
- GitHub Check: Dependency Review
- GitHub Check: Analyze (python)
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx}: Use TypeScript 6+ withpathsfor module resolution (remove deprecatedbaseUrl);esModuleInteropis always true
In TypeScript,strictdefaults to true andtypesdefaults to[]; do not auto-discover@types/*— must explicitly list needed types
Files:
web/src/pages/org/layout.ts
web/src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
web/src/**/*.{ts,tsx}: Use React 19 with TypeScript 6+ in web dashboard; enforce design tokens (no hardcoded colors, fonts, spacing) and reuse components fromweb/src/components/ui/
Always reuse existing components fromweb/src/components/ui/(StatusBadge, MetricCard, Sparkline, SectionCard, AgentCard, DeptHealthBar, ProgressGauge, StatPill, Avatar, Button, Toast, Skeleton, EmptyState, ErrorBoundary, ConfirmDialog, CommandPalette, InlineEdit, AnimatedPresence, StaggerGroup/StaggerItem) before creating new ones
Use design tokens exclusively in web components: Tailwind semantic classes (text-foreground,bg-card,text-accent,text-success,bg-danger, etc.) or CSS variables (var(--so-accent)); never hardcode hex values or pixel spacing
Usefont-sansorfont-mono(Geist tokens) in web components; never setfontFamilydirectly
Use density-aware spacing tokens in web components (p-card,gap-section-gap,gap-grid-gap) or standard Tailwind spacing; never hardcode pixel values for layout spacing
Use shadow and border token variables in web components (var(--so-shadow-card-hover),border-border,border-bright); never hardcode shadow or border styles
In React components, importcnfrom@/lib/utilsfor conditional class merging; never concatenate class strings directly
Do not recreate status dots inline; use<StatusBadge>component
Do not build card-with-header layouts from scratch; use<SectionCard>component
Do not create metric displays withtext-metric font-bold; use<MetricCard>component
Do not render initials circles manually; use<Avatar>component
Do not create complex (>8 line) JSX inside.map()blocks; extract to a shared component
Files:
web/src/pages/org/layout.ts
web/src/pages/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Use React Router with lazy-loaded page components (one per route); place page-scoped sub-components in
pages/<page-name>/subdirectories
Files:
web/src/pages/org/layout.ts
web/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Use ESLint with
@eslint-react/eslint-pluginand eslint-plugin-security in web dashboard
Files:
web/src/pages/org/layout.ts
web/**
📄 CodeRabbit inference engine (CLAUDE.md)
Use Node.js 22+ and npm for web dashboard; all dependencies in
web/package.json(React 19, react-router, shadcn/ui, Radix UI, Tailwind CSS 4, Zustand, Recharts, Framer Motion, Axios, Lucide React, Geist fonts, Storybook 10, Vitest, ESLint, fast-check, etc.)
Files:
web/src/pages/org/layout.ts
🧠 Learnings (2)
📓 Common learnings
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T21:20:09.993Z
Learning: Applies to web/src/components/** : Vue components organized by feature (agents/, approvals/, budget/, common/, dashboard/, layout/, messages/, org-chart/, tasks/).
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T09:44:40.059Z
Learning: Applies to web/** : Use Node.js 22+ and npm for web dashboard; all dependencies in `web/package.json` (React 19, react-router, shadcn/ui, Radix UI, Tailwind CSS 4, Zustand, Recharts, Framer Motion, Axios, Lucide React, Geist fonts, Storybook 10, Vitest, ESLint, fast-check, etc.)
📚 Learning: 2026-03-27T09:44:40.059Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T09:44:40.059Z
Learning: Applies to web/src/**/*.{ts,tsx} : Use density-aware spacing tokens in web components (`p-card`, `gap-section-gap`, `gap-grid-gap`) or standard Tailwind spacing; never hardcode pixel values for layout spacing
Applied to files:
web/src/pages/org/layout.ts
🔇 Additional comments (1)
web/src/pages/org/layout.ts (1)
16-16: Good alignment between empty-group sizing and dagre spacing.Matching
EMPTY_GROUP_HEIGHTto the rendered department minimum and reserving extra separator budget for group chrome should prevent the earlier clipping/overlap cases.Also applies to: 37-41
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@web/src/pages/org/layout.ts`:
- Around line 101-142: The map callback for positionedGroups mixes pure
computation with a side-effect that mutates positionedLeafMap (see
groupNodes.map and the loop that calls positionedLeafMap.set), harming
readability; refactor by first computing and returning group objects
(groupX/groupY/groupWidth/groupHeight and children list) inside the map without
touching positionedLeafMap, then in a separate pass iterate the computed groups
and adjust child positions (or build a new positionedLeafMap) using the saved
groupX/groupY values so the map remains a pure transformation and mutations are
isolated to a clearly named function or loop.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: ee0ae3f9-35cc-4db7-ab42-ec186db3cb11
📒 Files selected for processing (5)
web/src/__tests__/App.test.tsxweb/src/__tests__/pages/DashboardPage.test.tsxweb/src/__tests__/pages/dashboard/ActivityFeed.test.tsxweb/src/__tests__/utils/errors.property.test.tsweb/src/pages/org/layout.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
- GitHub Check: Build Web
- GitHub Check: Build Backend
- GitHub Check: Dashboard Test
- GitHub Check: Build Sandbox
- GitHub Check: Dependency Review
- GitHub Check: Analyze (go)
- GitHub Check: Analyze (python)
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx}: Use TypeScript 6+ withpathsfor module resolution (remove deprecatedbaseUrl);esModuleInteropis always true
In TypeScript,strictdefaults to true andtypesdefaults to[]; do not auto-discover@types/*— must explicitly list needed types
Files:
web/src/__tests__/App.test.tsxweb/src/__tests__/pages/dashboard/ActivityFeed.test.tsxweb/src/__tests__/pages/DashboardPage.test.tsxweb/src/__tests__/utils/errors.property.test.tsweb/src/pages/org/layout.ts
web/src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
web/src/**/*.{ts,tsx}: Use React 19 with TypeScript 6+ in web dashboard; enforce design tokens (no hardcoded colors, fonts, spacing) and reuse components fromweb/src/components/ui/
Always reuse existing components fromweb/src/components/ui/(StatusBadge, MetricCard, Sparkline, SectionCard, AgentCard, DeptHealthBar, ProgressGauge, StatPill, Avatar, Button, Toast, Skeleton, EmptyState, ErrorBoundary, ConfirmDialog, CommandPalette, InlineEdit, AnimatedPresence, StaggerGroup/StaggerItem) before creating new ones
Use design tokens exclusively in web components: Tailwind semantic classes (text-foreground,bg-card,text-accent,text-success,bg-danger, etc.) or CSS variables (var(--so-accent)); never hardcode hex values or pixel spacing
Usefont-sansorfont-mono(Geist tokens) in web components; never setfontFamilydirectly
Use density-aware spacing tokens in web components (p-card,gap-section-gap,gap-grid-gap) or standard Tailwind spacing; never hardcode pixel values for layout spacing
Use shadow and border token variables in web components (var(--so-shadow-card-hover),border-border,border-bright); never hardcode shadow or border styles
In React components, importcnfrom@/lib/utilsfor conditional class merging; never concatenate class strings directly
Do not recreate status dots inline; use<StatusBadge>component
Do not build card-with-header layouts from scratch; use<SectionCard>component
Do not create metric displays withtext-metric font-bold; use<MetricCard>component
Do not render initials circles manually; use<Avatar>component
Do not create complex (>8 line) JSX inside.map()blocks; extract to a shared component
Files:
web/src/__tests__/App.test.tsxweb/src/__tests__/pages/dashboard/ActivityFeed.test.tsxweb/src/__tests__/pages/DashboardPage.test.tsxweb/src/__tests__/utils/errors.property.test.tsweb/src/pages/org/layout.ts
web/src/__tests__/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
web/src/__tests__/**/*.{ts,tsx}: Use fast-check for property-based testing in React; usefc.assertandfc.property
Use Vitest for React unit testing with coverage scoped to files changed vs origin/main
Files:
web/src/__tests__/App.test.tsxweb/src/__tests__/pages/dashboard/ActivityFeed.test.tsxweb/src/__tests__/pages/DashboardPage.test.tsxweb/src/__tests__/utils/errors.property.test.ts
web/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Use ESLint with
@eslint-react/eslint-pluginand eslint-plugin-security in web dashboard
Files:
web/src/__tests__/App.test.tsxweb/src/__tests__/pages/dashboard/ActivityFeed.test.tsxweb/src/__tests__/pages/DashboardPage.test.tsxweb/src/__tests__/utils/errors.property.test.tsweb/src/pages/org/layout.ts
web/**
📄 CodeRabbit inference engine (CLAUDE.md)
Use Node.js 22+ and npm for web dashboard; all dependencies in
web/package.json(React 19, react-router, shadcn/ui, Radix UI, Tailwind CSS 4, Zustand, Recharts, Framer Motion, Axios, Lucide React, Geist fonts, Storybook 10, Vitest, ESLint, fast-check, etc.)
Files:
web/src/__tests__/App.test.tsxweb/src/__tests__/pages/dashboard/ActivityFeed.test.tsxweb/src/__tests__/pages/DashboardPage.test.tsxweb/src/__tests__/utils/errors.property.test.tsweb/src/pages/org/layout.ts
web/src/pages/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Use React Router with lazy-loaded page components (one per route); place page-scoped sub-components in
pages/<page-name>/subdirectories
Files:
web/src/pages/org/layout.ts
🧠 Learnings (6)
📓 Common learnings
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T21:20:09.993Z
Learning: Applies to web/src/components/** : Vue components organized by feature (agents/, approvals/, budget/, common/, dashboard/, layout/, messages/, org-chart/, tasks/).
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T09:44:40.059Z
Learning: Applies to web/** : Use Node.js 22+ and npm for web dashboard; all dependencies in `web/package.json` (React 19, react-router, shadcn/ui, Radix UI, Tailwind CSS 4, Zustand, Recharts, Framer Motion, Axios, Lucide React, Geist fonts, Storybook 10, Vitest, ESLint, fast-check, etc.)
📚 Learning: 2026-03-27T09:44:40.059Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T09:44:40.059Z
Learning: Applies to web/src/__tests__/**/*.{ts,tsx} : Use Vitest for React unit testing with coverage scoped to files changed vs origin/main
Applied to files:
web/src/__tests__/App.test.tsxweb/src/__tests__/pages/dashboard/ActivityFeed.test.tsxweb/src/__tests__/pages/DashboardPage.test.tsxweb/src/__tests__/utils/errors.property.test.ts
📚 Learning: 2026-03-27T09:44:40.059Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T09:44:40.059Z
Learning: Applies to web/src/__tests__/**/*.{ts,tsx} : Use fast-check for property-based testing in React; use `fc.assert` and `fc.property`
Applied to files:
web/src/__tests__/App.test.tsxweb/src/__tests__/pages/dashboard/ActivityFeed.test.tsxweb/src/__tests__/pages/DashboardPage.test.tsxweb/src/__tests__/utils/errors.property.test.ts
📚 Learning: 2026-03-20T08:28:32.845Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-20T08:28:32.845Z
Learning: Applies to web/src/__tests__/**/*.{ts,js} : Dashboard testing: Vitest unit tests organized by feature under `web/src/__tests__/`. Use fast-check for property-based testing (`fc.assert` + `fc.property`).
Applied to files:
web/src/__tests__/pages/dashboard/ActivityFeed.test.tsxweb/src/__tests__/pages/DashboardPage.test.tsxweb/src/__tests__/utils/errors.property.test.ts
📚 Learning: 2026-03-27T09:44:40.059Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T09:44:40.059Z
Learning: Applies to web/src/**/*.{ts,tsx} : Use React 19 with TypeScript 6+ in web dashboard; enforce design tokens (no hardcoded colors, fonts, spacing) and reuse components from `web/src/components/ui/`
Applied to files:
web/src/__tests__/pages/dashboard/ActivityFeed.test.tsxweb/src/__tests__/pages/DashboardPage.test.tsx
📚 Learning: 2026-03-27T09:44:40.059Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T09:44:40.059Z
Learning: Applies to web/src/**/*.{ts,tsx} : Use density-aware spacing tokens in web components (`p-card`, `gap-section-gap`, `gap-grid-gap`) or standard Tailwind spacing; never hardcode pixel values for layout spacing
Applied to files:
web/src/pages/org/layout.ts
🔇 Additional comments (11)
web/src/__tests__/App.test.tsx (1)
59-84: LGTM!The reformatted test with an explicit 10-second timeout is a sound approach to address flakiness from lazy-loaded modules during concurrent test runs. The test-level timeout (10s) correctly exceeds the
waitFortimeout (5s), ensuring the assertion has room to complete before the test itself times out.web/src/__tests__/pages/DashboardPage.test.tsx (3)
64-73: Clean refactoring from dynamic to static import.The static import after
vi.mockis the correct pattern—Vitest hoists mock declarations, so the mock is applied before the import executes. Removing the async wrapper fromrenderDashboard()simplifies all test cases appropriately.
85-89: Good switch to label-based query.Using
getByLabelText('Loading dashboard')is more specific thangetByRole('status')and produces clearer test failure messages. This also aligns with the pattern established in the new OrgChartPage tests and correctly targets thearia-labelattribute inDashboardSkeleton.
126-132: Correct negative assertion pattern.Using
queryByLabelTextfor the "does not exist" assertion is the right approach—query*methods returnnullinstead of throwing, making them suitable for negative assertions.web/src/__tests__/utils/errors.property.test.ts (3)
2-14: Vitest axios mock setup is solid and deterministic.Using
vi.mock('axios', ...)here is a good fix for async-leak noise, and exposing bothdefault.isAxiosErrorandisAxiosErrorkeeps compatibility with common import styles.As per coding guidelines, “Use Vitest for React unit testing with coverage scoped to files changed vs origin/main.”
16-25:makeFakeAxiosErrorcorrectly mirrors the error shape under test.The helper includes the exact fields consumed by
getErrorMessage, while avoiding dependence on realAxiosErrorinternals in the test environment.
44-44: Property assertion remains strong with the fake error object.Switching to
makeFakeAxiosErrorkeeps the 5xx non-leak invariant intact without weakening the property-based test.As per coding guidelines, “Use fast-check for property-based testing in React; use
fc.assertandfc.property.”web/src/__tests__/pages/dashboard/ActivityFeed.test.tsx (1)
54-54: This change is part of a deliberate CI flakiness fix and is appropriately justified.The
numRuns: 10reduction is intentional, as indicated by the commit message "fix: honor layout direction in fallback branches and fix CI test flakes." For this simple, deterministic property—which verifies ActivityFeed caps items at 10—10 runs provides sufficient coverage of edge cases (count 0, 1–9, 10, 11+, 50) without causing unnecessary test delays.> Likely an incorrect or invalid review comment.web/src/pages/org/layout.ts (3)
1-16: Well-structured constants and type definitions.The constants correctly match the component constraints:
EMPTY_GROUP_HEIGHT = 120aligns withDepartmentGroupNode'smin-h-[120px], andDEFAULT_NODE_WIDTH = 160is appropriately centered within the responsive CSS range (min-w-[140px] max-w-[180px]).
43-53: Direction-aware grid fallback is correctly implemented.The no-leaf-nodes branch now properly respects the
directionoption with theisLRconditional, and preserves existing styles with spread operator.
151-152: Correct node ordering for React Flow containment.Returning groups before leaves ensures proper z-index stacking in React Flow, where parent group nodes must precede their children.
70505b9 to
551b32b
Compare
There was a problem hiding this comment.
Actionable comments posted: 7
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@web/src/__tests__/pages/dashboard/ActivityFeed.test.tsx`:
- Line 54: The test lowered the randomized iteration count by changing the
numRuns value in ActivityFeed.test.tsx, which weakens coverage; restore stronger
coverage by making numRuns environment-aware (e.g., use process.env.CI or a
TEST_RUNS env var) so CI uses 20 while local runs can default to 10, and update
the numRuns reference in the test (the variable used in the ActivityFeed test
block) to read from that env-aware value.
In `@web/src/pages/org/AgentNode.stories.tsx`:
- Line 11: The story contains a div with hardcoded inline style width/height in
AgentNode.stories.tsx; replace that inline style on the container div with the
appropriate Tailwind sizing utility classes (use the nearest standard Tailwind
classes or your design system tokens, e.g., w-*/h-* equivalents) so the
component uses density-aware/tailwind sizing rather than pixel values; update
the JSX div (the container around the story preview) to use className with
Tailwind sizing utilities instead of style={{ width: 400, height: 200 }}.
In `@web/src/pages/org/layout.ts`:
- Around line 60-65: The dagre layout currently uses placeholder sizes
(DEFAULT_NODE_WIDTH/DEFAULT_NODE_HEIGHT) when node.measured is undefined,
yielding an initial layout that mismatches rendered nodes; update the flow so
that after React Flow measures nodes (i.e., when measured.width/height become
available on leafNodes) you recompute the layout and call g.setNode with the
real measured dimensions and re-run the dagre layout pass (or alternatively
enforce fixed dimensions inside the node component), ensuring you trigger the
layout update from the same routine that uses leafNodes and g.setNode so nodes
are laid out with actual sizes instead of placeholders.
In `@web/src/pages/org/NodeContextMenu.tsx`:
- Around line 46-61: The handleClick inside the useEffect uses (e.target as
HTMLElement) when calling menuRef.current.contains, which can be wrong for
non-HTMLElement nodes (SVG, Text, etc.); change the cast to Node (e.g., e.target
as Node) or otherwise ensure the value passed to menuRef.current.contains is
typed as Node | null so contains receives the correct type; update the
handleClick function in NodeContextMenu (referencing useEffect, handleClick,
menuRef, onClose) accordingly.
In `@web/src/pages/org/OrgChartToolbar.stories.tsx`:
- Around line 18-25: The Storybook meta currently sets component:
InteractiveToolbar which causes autodocs to pick up the wrapper instead of the
real component; update the meta to set component: OrgChartToolbar (or keep
InteractiveToolbar but add a render that returns
<InteractiveToolbar><OrgChartToolbar .../></InteractiveToolbar>) so autodocs
reflect OrgChartToolbar's props—modify the meta object (symbol: meta) and the
entries for component/render, referencing InteractiveToolbar and OrgChartToolbar
to ensure the correct API is documented.
In `@web/src/pages/OrgChartPage.tsx`:
- Line 264: Replace the intermediate CSS token with the canonical SynthOrg
token: in the Background component usage (Background color="var(--color-border)"
gap={24} size={1}), change the color prop to use var(--so-border) instead of
var(--color-border) so the component uses the recommended design token directly.
In `@web/src/stores/company.ts`:
- Around line 49-55: The WebSocket handler updateFromWsEvent calls the async
fetchCompanyData via useCompanyStore.getState().fetchCompanyData() without
awaiting or catching errors; change this to either await the call (making
updateFromWsEvent async) or attach a .catch(...) to the returned promise and log
the error (e.g., console.error or your app logger) so fetchCompanyData failures
aren’t silently swallowed; update the invocation accordingly in
updateFromWsEvent to ensure errors are visible.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 0f3c1ae5-ac27-415d-9caf-75e62c4634f4
⛔ Files ignored due to path filters (1)
web/package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (39)
CLAUDE.mdweb/package.jsonweb/src/__tests__/App.test.tsxweb/src/__tests__/pages/DashboardPage.test.tsxweb/src/__tests__/pages/dashboard/ActivityFeed.test.tsxweb/src/__tests__/pages/org/DepartmentStatsBar.test.tsxweb/src/__tests__/pages/org/NodeContextMenu.test.tsxweb/src/__tests__/pages/org/OrgChartPage.test.tsxweb/src/__tests__/pages/org/OrgChartSkeleton.test.tsxweb/src/__tests__/pages/org/OrgChartToolbar.test.tsxweb/src/__tests__/pages/org/build-org-tree.test.tsweb/src/__tests__/pages/org/layout.test.tsweb/src/__tests__/pages/org/status-mapping.test.tsweb/src/__tests__/stores/agents.test.tsweb/src/__tests__/stores/company.test.tsweb/src/__tests__/utils/errors.property.test.tsweb/src/hooks/useOrgChartData.tsweb/src/pages/OrgChartPage.tsxweb/src/pages/org/AgentNode.stories.tsxweb/src/pages/org/AgentNode.tsxweb/src/pages/org/CeoNode.stories.tsxweb/src/pages/org/CeoNode.tsxweb/src/pages/org/DepartmentGroupNode.stories.tsxweb/src/pages/org/DepartmentGroupNode.tsxweb/src/pages/org/DepartmentStatsBar.stories.tsxweb/src/pages/org/DepartmentStatsBar.tsxweb/src/pages/org/HierarchyEdge.tsxweb/src/pages/org/NodeContextMenu.stories.tsxweb/src/pages/org/NodeContextMenu.tsxweb/src/pages/org/OrgChartSkeleton.stories.tsxweb/src/pages/org/OrgChartSkeleton.tsxweb/src/pages/org/OrgChartToolbar.stories.tsxweb/src/pages/org/OrgChartToolbar.tsxweb/src/pages/org/build-org-tree.tsweb/src/pages/org/layout.tsweb/src/pages/org/status-mapping.tsweb/src/stores/agents.tsweb/src/stores/company.tsweb/src/styles/global.css
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
- GitHub Check: Dashboard Test
- GitHub Check: Build Backend
- GitHub Check: Build Web
- GitHub Check: Build Sandbox
- GitHub Check: Dependency Review
- GitHub Check: Analyze (python)
🧰 Additional context used
📓 Path-based instructions (3)
web/src/**/*.{tsx,ts}
📄 CodeRabbit inference engine (CLAUDE.md)
web/src/**/*.{tsx,ts}: Always reuse existing components fromweb/src/components/ui/before creating new ones. Check the required component inventory (StatusBadge, MetricCard, Sparkline, SectionCard, AgentCard, DeptHealthBar, ProgressGauge, StatPill, Avatar, Button, Toast, Skeleton, EmptyState, ErrorBoundary, ConfirmDialog, CommandPalette, InlineEdit, AnimatedPresence, StaggerGroup, TaskStatusIndicator, PriorityBadge)
Use Tailwind semantic classes (text-foreground,bg-card,text-accent,text-success,bg-danger) or CSS variables (var(--so-*)) for colors; never hardcode hex values
Usefont-sansorfont-monofor typography (maps to Geist tokens); never setfontFamilydirectly
Use density-aware spacing tokens (p-card,gap-section-gap,gap-grid-gap) or standard Tailwind spacing; never hardcode pixel values for layout spacing
Use token variables for shadows and borders (var(--so-shadow-card-hover),border-border,border-bright)
Do NOT recreate status dots inline -- use<StatusBadge>; do NOT build card-with-header layouts from scratch -- use<SectionCard>; do NOT create metric displays inline -- use<MetricCard>; do NOT render initials circles manually -- use<Avatar>; do NOT create complex (>8 line) JSX inside.map()-- extract to shared component
TypeScript 6.0: removebaseUrl(deprecated, will stop working in TS 7);esModuleInteropalways true (cannot be set false);typesdefaults to[](must explicitly list needed types);DOM.Iterablemerged intoDOM;moduleResolution: 'classic'and'node10'removed (use'bundler'or'nodenext');strictdefaults to true
Storybook 10 is ESM-only;@storybook/addon-essentials,@storybook/addon-interactions,@storybook/test,@storybook/blocksno longer published (features built into corestorybook);@storybook/addon-docsmust be installed separately if usingtags: ['autodocs']
Files:
web/src/__tests__/App.test.tsxweb/src/__tests__/pages/dashboard/ActivityFeed.test.tsxweb/src/__tests__/pages/org/OrgChartSkeleton.test.tsxweb/src/__tests__/pages/DashboardPage.test.tsxweb/src/__tests__/pages/org/OrgChartToolbar.test.tsxweb/src/__tests__/pages/org/DepartmentStatsBar.test.tsxweb/src/pages/org/OrgChartSkeleton.tsxweb/src/__tests__/pages/org/layout.test.tsweb/src/pages/org/HierarchyEdge.tsxweb/src/pages/org/OrgChartSkeleton.stories.tsxweb/src/pages/org/OrgChartToolbar.stories.tsxweb/src/__tests__/pages/org/status-mapping.test.tsweb/src/__tests__/utils/errors.property.test.tsweb/src/pages/org/DepartmentStatsBar.tsxweb/src/__tests__/stores/agents.test.tsweb/src/stores/agents.tsweb/src/__tests__/pages/org/OrgChartPage.test.tsxweb/src/pages/org/DepartmentGroupNode.tsxweb/src/__tests__/stores/company.test.tsweb/src/pages/org/CeoNode.tsxweb/src/pages/org/DepartmentGroupNode.stories.tsxweb/src/pages/org/OrgChartToolbar.tsxweb/src/pages/org/status-mapping.tsweb/src/pages/org/NodeContextMenu.tsxweb/src/pages/org/AgentNode.tsxweb/src/pages/org/NodeContextMenu.stories.tsxweb/src/pages/org/DepartmentStatsBar.stories.tsxweb/src/pages/org/AgentNode.stories.tsxweb/src/stores/company.tsweb/src/__tests__/pages/org/NodeContextMenu.test.tsxweb/src/hooks/useOrgChartData.tsweb/src/__tests__/pages/org/build-org-tree.test.tsweb/src/pages/OrgChartPage.tsxweb/src/pages/org/build-org-tree.tsweb/src/pages/org/layout.tsweb/src/pages/org/CeoNode.stories.tsx
**/*.md
📄 CodeRabbit inference engine (CLAUDE.md)
Markdown trailing-whitespace removal and end-of-file fixing enforced by pre-commit hooks
Files:
CLAUDE.md
web/src/**/*.stories.tsx
📄 CodeRabbit inference engine (CLAUDE.md)
Storybook 10: use
definePreviewfrom@storybook/react-vitefor type-safe config; import fromstorybook/test(not@storybook/test) andstorybook/actions(not@storybook/addon-actions); useparameters.backgrounds.options(object keyed by name) +initialGlobals.backgrounds.value; useparameters.a11y.test: 'error' | 'todo' | 'off'for accessibility testing
Files:
web/src/pages/org/OrgChartSkeleton.stories.tsxweb/src/pages/org/OrgChartToolbar.stories.tsxweb/src/pages/org/DepartmentGroupNode.stories.tsxweb/src/pages/org/NodeContextMenu.stories.tsxweb/src/pages/org/DepartmentStatsBar.stories.tsxweb/src/pages/org/AgentNode.stories.tsxweb/src/pages/org/CeoNode.stories.tsx
🧠 Learnings (25)
📓 Common learnings
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T21:20:09.993Z
Learning: Applies to web/src/components/** : Vue components organized by feature (agents/, approvals/, budget/, common/, dashboard/, layout/, messages/, org-chart/, tasks/).
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T07:12:14.508Z
Learning: Applies to docs/design/*.md : Design spec pages: 7 pages in `docs/design/` — index, agents, organization, communication, engine, memory, operations
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-16T06:24:56.341Z
Learning: Applies to docs/design/**/*.md : Design specification pages in `docs/design/` must be consulted before implementing features (7 pages: index, agents, organization, communication, engine, memory, operations)
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:17:43.675Z
Learning: Applies to web/** : Web dashboard: Node.js 20+, dependencies in web/package.json (Vue 3, PrimeVue, Tailwind CSS, Pinia, VueFlow, ECharts, Axios, vue-draggable-plus, Vitest, fast-check, ESLint, vue-tsc).
📚 Learning: 2026-03-20T08:28:32.845Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-20T08:28:32.845Z
Learning: Applies to web/src/__tests__/**/*.{ts,js} : Dashboard testing: Vitest unit tests organized by feature under `web/src/__tests__/`. Use fast-check for property-based testing (`fc.assert` + `fc.property`).
Applied to files:
web/src/__tests__/pages/dashboard/ActivityFeed.test.tsxweb/src/__tests__/pages/org/OrgChartSkeleton.test.tsxCLAUDE.mdweb/src/__tests__/pages/DashboardPage.test.tsxweb/src/__tests__/pages/org/OrgChartToolbar.test.tsxweb/src/__tests__/pages/org/DepartmentStatsBar.test.tsxweb/src/__tests__/pages/org/layout.test.tsweb/src/__tests__/pages/org/status-mapping.test.tsweb/src/__tests__/utils/errors.property.test.tsweb/src/__tests__/stores/agents.test.tsweb/src/__tests__/pages/org/OrgChartPage.test.tsxweb/src/__tests__/stores/company.test.tsweb/src/__tests__/pages/org/NodeContextMenu.test.tsxweb/src/__tests__/pages/org/build-org-tree.test.ts
📚 Learning: 2026-03-27T12:41:55.315Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T12:41:55.315Z
Learning: Applies to web/src/**/*.stories.tsx : Storybook 10: use `definePreview` from `storybook/react-vite` for type-safe config; import from `storybook/test` (not `storybook/test`) and `storybook/actions` (not `storybook/addon-actions`); use `parameters.backgrounds.options` (object keyed by name) + `initialGlobals.backgrounds.value`; use `parameters.a11y.test: 'error' | 'todo' | 'off'` for accessibility testing
Applied to files:
web/src/__tests__/pages/org/OrgChartSkeleton.test.tsxweb/src/__tests__/pages/DashboardPage.test.tsxweb/src/__tests__/pages/org/OrgChartToolbar.test.tsxweb/src/pages/org/OrgChartSkeleton.stories.tsxweb/src/pages/org/OrgChartToolbar.stories.tsxweb/src/__tests__/pages/org/OrgChartPage.test.tsxweb/src/__tests__/stores/company.test.tsweb/src/pages/org/DepartmentGroupNode.stories.tsxweb/src/pages/org/NodeContextMenu.stories.tsxweb/src/pages/org/DepartmentStatsBar.stories.tsxweb/src/pages/org/AgentNode.stories.tsxweb/src/__tests__/pages/org/NodeContextMenu.test.tsxweb/src/pages/org/CeoNode.stories.tsx
📚 Learning: 2026-03-15T18:17:43.675Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:17:43.675Z
Learning: Applies to web/** : Web dashboard: Node.js 20+, dependencies in web/package.json (Vue 3, PrimeVue, Tailwind CSS, Pinia, VueFlow, ECharts, Axios, vue-draggable-plus, Vitest, fast-check, ESLint, vue-tsc).
Applied to files:
CLAUDE.mdweb/package.json
📚 Learning: 2026-03-14T15:43:05.601Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T15:43:05.601Z
Learning: Applies to web/package.json : Web dashboard Node.js 20+; dependencies in web/package.json (Vue 3, PrimeVue, Tailwind CSS, Pinia, VueFlow, ECharts, Axios, vue-draggable-plus, Vitest, ESLint, vue-tsc)
Applied to files:
CLAUDE.mdweb/package.jsonweb/src/pages/org/CeoNode.tsx
📚 Learning: 2026-03-19T07:12:14.508Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T07:12:14.508Z
Learning: Applies to src/synthorg/**/*.py : Package structure: src/synthorg/ organized as: api/ (REST+WebSocket, Litestar), auth/ (auth subpackage), backup/ (scheduled/manual backups), budget/ (cost tracking, CFO), cli/ (superseded by Go CLI), communication/ (message bus, meetings), config/ (YAML loading), core/ (domain models, resilience config), engine/ (orchestration, task state, coordination, approval gates, stagnation detection, context budget, compaction), hr/ (hiring, performance, promotion), memory/ (pluggable backend, Mem0, retrieval, consolidation), persistence/ (operational data, SQLite, settings), observability/ (logging, correlation, sinks), providers/ (LLM abstraction, LiteLLM, auth types, presets, runtime CRUD), settings/ (runtime-editable, typed definitions, encryption, config bridge), security/ (SecOps, rule engine, output scanning, progressive trust, autonomy levels), templates/ (company templates, personalities), tools/ (registry, built-in tools, git, sandbox, code_runner, MCP...
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-15T21:20:09.993Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T21:20:09.993Z
Learning: Applies to web/src/components/** : Vue components organized by feature (agents/, approvals/, budget/, common/, dashboard/, layout/, messages/, org-chart/, tasks/).
Applied to files:
CLAUDE.mdweb/src/__tests__/pages/org/DepartmentStatsBar.test.tsxweb/src/pages/org/OrgChartSkeleton.tsxweb/src/pages/OrgChartPage.tsxweb/src/pages/org/build-org-tree.ts
📚 Learning: 2026-03-27T12:41:55.315Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T12:41:55.315Z
Learning: Applies to web/src/components/ui/*.{tsx,ts} : When creating new shared UI components, place in `web/src/components/ui/` with kebab-case filename, create adjacent `.stories.tsx` with all states, export props as TypeScript interface, use design tokens exclusively (no hardcoded colors/fonts/spacing), import `cn` from `@/lib/utils` for conditional class merging
Applied to files:
CLAUDE.mdweb/src/pages/org/OrgChartSkeleton.tsxweb/src/pages/org/OrgChartSkeleton.stories.tsxweb/src/pages/org/OrgChartToolbar.stories.tsxweb/src/pages/org/DepartmentGroupNode.tsxweb/src/pages/org/CeoNode.tsxweb/src/pages/org/DepartmentGroupNode.stories.tsxweb/src/pages/org/OrgChartToolbar.tsxweb/src/pages/org/AgentNode.tsxweb/src/pages/org/NodeContextMenu.stories.tsxweb/src/pages/org/DepartmentStatsBar.stories.tsxweb/src/pages/org/AgentNode.stories.tsxweb/src/pages/org/CeoNode.stories.tsx
📚 Learning: 2026-03-27T12:41:55.315Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T12:41:55.315Z
Learning: Applies to web/src/**/*.{tsx,ts} : Do NOT recreate status dots inline -- use `<StatusBadge>`; do NOT build card-with-header layouts from scratch -- use `<SectionCard>`; do NOT create metric displays inline -- use `<MetricCard>`; do NOT render initials circles manually -- use `<Avatar>`; do NOT create complex (>8 line) JSX inside `.map()` -- extract to shared component
Applied to files:
CLAUDE.mdweb/src/__tests__/pages/DashboardPage.test.tsxweb/src/__tests__/pages/org/OrgChartToolbar.test.tsxweb/src/pages/org/OrgChartSkeleton.tsxweb/src/pages/org/OrgChartSkeleton.stories.tsxweb/src/pages/org/DepartmentStatsBar.tsxweb/src/pages/org/DepartmentGroupNode.tsxweb/src/pages/org/CeoNode.tsxweb/src/pages/org/DepartmentGroupNode.stories.tsxweb/src/pages/org/AgentNode.tsxweb/src/pages/org/DepartmentStatsBar.stories.tsxweb/src/hooks/useOrgChartData.tsweb/src/pages/OrgChartPage.tsxweb/src/pages/org/layout.tsweb/src/pages/org/CeoNode.stories.tsx
📚 Learning: 2026-03-27T12:41:55.315Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T12:41:55.315Z
Learning: Applies to web/src/**/*.{tsx,ts} : Always reuse existing components from `web/src/components/ui/` before creating new ones. Check the required component inventory (StatusBadge, MetricCard, Sparkline, SectionCard, AgentCard, DeptHealthBar, ProgressGauge, StatPill, Avatar, Button, Toast, Skeleton, EmptyState, ErrorBoundary, ConfirmDialog, CommandPalette, InlineEdit, AnimatedPresence, StaggerGroup, TaskStatusIndicator, PriorityBadge)
Applied to files:
CLAUDE.mdweb/src/__tests__/pages/org/OrgChartToolbar.test.tsxweb/src/__tests__/pages/org/DepartmentStatsBar.test.tsxweb/src/pages/org/OrgChartSkeleton.tsxweb/src/pages/org/OrgChartSkeleton.stories.tsxweb/src/pages/org/DepartmentStatsBar.tsxweb/src/pages/org/DepartmentGroupNode.tsxweb/src/pages/org/CeoNode.tsxweb/src/pages/org/AgentNode.tsxweb/src/pages/org/DepartmentStatsBar.stories.tsxweb/src/__tests__/pages/org/NodeContextMenu.test.tsxweb/src/hooks/useOrgChartData.tsweb/src/pages/OrgChartPage.tsxweb/src/pages/org/build-org-tree.ts
📚 Learning: 2026-03-14T15:43:05.601Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T15:43:05.601Z
Learning: Applies to docs/** : Docs source in docs/ (Markdown, built with Zensical); design spec in docs/design/ (7 pages: index, agents, organization, communication, engine, memory, operations)
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-27T12:41:55.315Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T12:41:55.315Z
Learning: Applies to web/src/**/*.{tsx,ts} : Storybook 10 is ESM-only; storybook/addon-essentials, storybook/addon-interactions, storybook/test, storybook/blocks no longer published (features built into core `storybook`); storybook/addon-docs must be installed separately if using `tags: ['autodocs']`
Applied to files:
CLAUDE.mdweb/src/pages/org/OrgChartSkeleton.stories.tsxweb/src/pages/org/OrgChartToolbar.stories.tsxweb/package.jsonweb/src/pages/org/DepartmentGroupNode.stories.tsxweb/src/pages/org/NodeContextMenu.stories.tsxweb/src/pages/org/DepartmentStatsBar.stories.tsxweb/src/pages/org/AgentNode.stories.tsxweb/src/__tests__/pages/org/NodeContextMenu.test.tsxweb/src/pages/org/CeoNode.stories.tsx
📚 Learning: 2026-03-15T18:17:43.675Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:17:43.675Z
Learning: Applies to pyproject.toml : Dependencies: all versions use == in pyproject.toml. Groups: test (pytest + plugins, hypothesis), dev (includes test + ruff, mypy, pre-commit, commitizen, pip-audit). Required: mem0ai (Mem0 memory backend — the default and currently only backend). Install: uv sync installs everything (dev group is default).
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-21T12:54:22.557Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-21T12:54:22.557Z
Learning: Go 1.26+ required; CLI dependencies in `cli/go.mod` (Cobra, charmbracelet/huh, charmbracelet/lipgloss, sigstore-go, go-containerregistry, go-tuf)
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-15T18:17:43.675Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:17:43.675Z
Learning: Applies to docker/{Dockerfile*,compose.yml} : Docker: Backend uses 3-stage build (builder → setup → distroless runtime), Chainguard Python, non-root (UID 65532), CIS-hardened. Web uses nginxinc/nginx-unprivileged, Vue 3 SPA with PrimeVue + Tailwind CSS, SPA routing, API/WebSocket proxy to backend.
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-19T11:19:40.044Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T11:19:40.044Z
Learning: Applies to go.mod : Maintain Go 1.26+ requirement. Dependencies: Cobra (CLI framework), charmbracelet/huh and charmbracelet/lipgloss (UI), sigstore-go (code signing), go-containerregistry (container image verification), go-tuf (TUF client for Sigstore).
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-21T14:12:17.848Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-21T14:12:17.848Z
Learning: Applies to cli/go.mod : CLI uses Go 1.26+. Dependencies: Cobra, charmbracelet/huh, charmbracelet/lipgloss, sigstore-go, go-containerregistry, go-tuf
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-15T21:32:02.880Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T21:32:02.880Z
Learning: Applies to cli/**/*.go : Go CLI (Go 1.26+) uses Cobra for commands, charmbracelet/huh for interactive CLI, charmbracelet/lipgloss for styled output. Cross-platform builds (linux/darwin/windows × amd64/arm64). GoReleaser for releases with cosign keyless signing of checksums.txt. SLSA L3 provenance attestations via actions/attest-build-provenance.
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-15T18:17:43.675Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:17:43.675Z
Learning: Applies to cli/** : CLI: Go 1.26+, dependencies in cli/go.mod (Cobra, charmbracelet/huh).
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-27T12:41:55.315Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T12:41:55.315Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use Tailwind semantic classes (`text-foreground`, `bg-card`, `text-accent`, `text-success`, `bg-danger`) or CSS variables (`var(--so-*)`) for colors; never hardcode hex values
Applied to files:
web/src/pages/org/OrgChartSkeleton.stories.tsxweb/src/styles/global.cssweb/src/pages/org/CeoNode.tsxweb/src/pages/org/AgentNode.tsx
📚 Learning: 2026-03-27T12:41:55.315Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T12:41:55.315Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use token variables for shadows and borders (`var(--so-shadow-card-hover)`, `border-border`, `border-bright`)
Applied to files:
web/src/pages/org/OrgChartSkeleton.stories.tsxweb/src/styles/global.cssweb/src/pages/org/CeoNode.tsxweb/src/pages/org/AgentNode.tsx
📚 Learning: 2026-03-27T12:41:55.315Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T12:41:55.315Z
Learning: Applies to web/src/**/*.{tsx,ts} : TypeScript 6.0: remove `baseUrl` (deprecated, will stop working in TS 7); `esModuleInterop` always true (cannot be set false); `types` defaults to `[]` (must explicitly list needed types); `DOM.Iterable` merged into `DOM`; `moduleResolution: 'classic'` and `'node10'` removed (use `'bundler'` or `'nodenext'`); `strict` defaults to true
Applied to files:
web/package.json
📚 Learning: 2026-03-27T12:41:55.315Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T12:41:55.315Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use density-aware spacing tokens (`p-card`, `gap-section-gap`, `gap-grid-gap`) or standard Tailwind spacing; never hardcode pixel values for layout spacing
Applied to files:
web/src/pages/org/CeoNode.tsxweb/src/pages/org/AgentNode.tsxweb/src/pages/org/layout.ts
📚 Learning: 2026-03-19T07:13:44.964Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T07:13:44.964Z
Learning: Applies to src/synthorg/hr/**/*.py : HR package (hr/): hiring, firing, onboarding, offboarding, agent registry, performance tracking (task metrics, collaboration scoring, LLM calibration, collaboration overrides, trend detection), promotion/demotion (criteria evaluation, approval strategies, model mapping)
Applied to files:
web/src/pages/org/status-mapping.ts
📚 Learning: 2026-03-16T06:24:56.341Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-16T06:24:56.341Z
Learning: Applies to src/synthorg/hr/**/*.py : HR engine must provide: hiring, firing, onboarding, offboarding, agent registry, performance tracking (task metrics, collaboration scoring, trend detection), promotion/demotion
Applied to files:
web/src/pages/org/status-mapping.ts
🔇 Additional comments (47)
web/src/__tests__/App.test.tsx (1)
59-84: Per-test timeout addition is appropriate and scoped.Using a test-level timeout (
10_000) while keepingwaitFortimeout at5000is a solid balance for lazy-loaded authenticated shell rendering under slower concurrent runs.web/src/__tests__/pages/DashboardPage.test.tsx (3)
64-67: Static import + hoisted mock usage is correct.This keeps module loading deterministic while preserving the mocked
useDashboardDatabehavior.
80-83: Sync test conversion is consistent and clean.Dropping unnecessary async flow improves readability without changing test intent.
Also applies to: 91-97, 99-103, 105-108, 110-113, 115-118, 120-124, 134-138, 140-144
85-89: Loading-state assertions now better match accessible UX.Using
getByLabelText/queryByLabelText('Loading dashboard')is a solid improvement for resilient, accessibility-aligned tests.Also applies to: 126-132
web/src/pages/org/HierarchyEdge.tsx (1)
1-27: LGTM!The component is well-structured with proper memoization. The use of
var(--color-border-bright)CSS variable for stroke color correctly follows the design token guidelines.web/src/pages/org/OrgChartSkeleton.tsx (1)
1-30: LGTM!Good implementation with proper accessibility attributes (
role="status",aria-live="polite",aria-label). The component correctly reusesSkeletonCardfrom the UI component library as per coding guidelines.web/src/pages/org/OrgChartSkeleton.stories.tsx (1)
1-23: LGTM!The story is well-configured with proper accessibility testing (
a11y.test: 'error') and the previous review feedback about inline background styling has been addressed.web/src/pages/org/status-mapping.ts (1)
1-30: LGTM!Clean utility functions with proper documentation. The exhaustive switch in
mapHrToRuntimehandles allAgentStatuscases, and the consolidated fall-through foronboarding/active(from previous review feedback) improves readability.web/src/__tests__/utils/errors.property.test.ts (1)
1-49: LGTM!Good approach to avoid the async leak issue from Axios's fetch adapter. The mock properly exposes
isAxiosErrorboth as a default export property and named export. The property-based tests effectively verify security (no body leakage) and robustness (non-empty messages).web/src/__tests__/pages/org/status-mapping.test.ts (1)
1-43: LGTM!Comprehensive test coverage for both functions. The edge case test at lines 39-42 properly documents the scenario where runtime override takes precedence over stale HR status, which is important for understanding the intended behavior.
web/src/pages/org/NodeContextMenu.tsx (1)
113-139: LGTM!The component correctly handles all three node types with appropriate menu items. Previous review feedback has been addressed (explicit
type="button", separateceoItems). Good use of semantic Tailwind classes and ARIA roles.web/src/pages/org/NodeContextMenu.stories.tsx (1)
1-48: LGTM!All three
nodeTypevariants are now covered with stories, and accessibility testing is properly configured. Previous review feedback has been fully addressed.web/src/__tests__/pages/org/NodeContextMenu.test.tsx (1)
88-106: Property-based invariants are well covered.The
fc.assert(fc.property(...))block meaningfully validates menu structure across supportednodeTypevalues and complements deterministic tests.web/src/styles/global.css (1)
7-7: React Flow base stylesheet import is correctly wired.This ensures XYFlow primitives render with expected baseline behavior/styles.
web/package.json (1)
18-18: Dependency additions align with the new graph-layout surface.The added runtime/layout package and typings are consistent with the org-chart dagre integration.
Also applies to: 55-55
web/src/__tests__/pages/org/OrgChartSkeleton.test.tsx (1)
6-19: Good accessibility coverage for loading semantics.These assertions lock in expected ARIA behavior for the skeleton state.
CLAUDE.md (1)
127-127: Documentation updates are consistent with the implemented org-chart architecture.The hook/store and dependency notes now reflect the new page composition and layout stack.
Also applies to: 131-131, 323-323
web/src/__tests__/pages/org/DepartmentStatsBar.test.tsx (1)
17-26: Cost rendering branch coverage is solid.Both present and
nullcost paths are tested, which protects the conditional UI behavior.web/src/pages/org/AgentNode.tsx (1)
35-35: No action required. The important modifier syntax using suffix form (bg-border-bright!,size-1.5!) is correct for Tailwind CSS v4 and matches the official specification. This is the preferred syntax in v4; the prefix form (!bg-red-500) is a v3 pattern that is deprecated.web/src/__tests__/pages/org/OrgChartToolbar.test.tsx (1)
1-52: LGTM! Clean test structure with proper mock isolation.The
createProps()factory pattern correctly addresses the previous review feedback about shared mock instances. Tests cover the essential rendering and interaction behaviors.Consider adding a test for clicking "Hierarchy" when
viewModeis'force'to verify the toggle works in both directions.web/src/__tests__/pages/org/layout.test.ts (1)
1-104: LGTM! Comprehensive layout test coverage.The test suite thoroughly covers
applyDagreLayoutbehavior including edge cases (empty input, missing node references, department grouping). The past review comment about the misleading test description has been addressed.web/src/pages/org/DepartmentStatsBar.tsx (1)
1-30: LGTM! Clean implementation following component reuse guidelines.The component properly reuses
StatPillfrom the UI library, uses semantic Tailwind classes, and correctly defaultscurrencyto'USD'to match thecostUsdprop semantics (addressing the previous review feedback).web/src/pages/org/CeoNode.tsx (1)
1-52: LGTM! Well-structured node component with proper UI reuse.The component correctly reuses
AvatarandStatusBadgefrom the UI library, uses semantic Tailwind classes throughout, includes proper accessibility attributes (aria-label,data-testid), and applies Tailwind v4 postfix important syntax on Handle elements (addressing the previous review).web/src/__tests__/stores/agents.test.ts (1)
1-82: LGTM! Thorough store test coverage.The test suite comprehensively covers
useAgentsStorebehavior including edge cases for WebSocket event handling (missing fields, invalid status values, wrong event types). Proper state isolation viabeforeEachreset.web/src/pages/org/DepartmentStatsBar.stories.tsx (1)
1-48: LGTM! Good story coverage for component states.The stories cover the key variants: default with cost, null cost (testing conditional rendering), and zero values. The decorator constrains width appropriately for visual testing.
web/src/stores/agents.ts (1)
1-39: LGTM! Well-designed store with defensive payload validation.The store implementation is clean and defensive:
VALID_RUNTIME_STATUSESset ensures only known status values are accepted- Type guards properly validate payload fields before processing
- Immutable state updates via spread operator
web/src/__tests__/pages/org/OrgChartPage.test.tsx (1)
1-143: LGTM!The test suite provides good coverage of the
OrgChartPageUI states including loading, empty, error, WebSocket warnings, and the presence of React Flow canvas and toolbar. The mock pattern with module-scoped variables andbeforeEachreset is appropriate for controllinguseOrgChartDatareturn values across tests.web/src/pages/org/DepartmentGroupNode.tsx (2)
1-51: LGTM!The component follows coding guidelines well: uses semantic Tailwind classes (
text-foreground,bg-card/50,border-border), design token-based health colors,font-sans/font-monofor typography, and properly reuses theDepartmentStatsBarcomponent. The memoization and accessibility attributes are appropriate.
35-36: Thetext-microclass is properly defined in your design system (--so-text-micro: 10pxinweb/src/styles/design-tokens.css) and is already used consistently across multiple components. No action needed.web/src/pages/org/DepartmentGroupNode.stories.tsx (1)
1-87: LGTM!The stories follow Storybook 10 patterns with proper
parameters.a11y.test: 'error'configuration. Good coverage of health states (Healthy/Warning/Critical) and thecostUsd: nulledge case in the Critical story.web/src/pages/org/OrgChartToolbar.tsx (1)
1-88: LGTM!The toolbar component is well-implemented with proper accessibility:
aria-pressedon toggle buttons,aria-labelon icon-only buttons, andaria-hiddenon decorative icons. Uses semantic Tailwind classes and reuses theButtoncomponent from@/components/ui/.web/src/pages/org/CeoNode.stories.tsx (1)
1-100: LGTM!The stories provide complete coverage of all four
AgentRuntimeStatusvalues (Active, Idle, Error, Offline) with proper Storybook 10 configuration includingparameters.a11y.test: 'error'.web/src/__tests__/stores/company.test.ts (1)
1-135: LGTM!Solid test coverage for
useCompanyStoreincluding success/failure paths for data fetching, partial failure handling infetchDepartmentHealths, and WebSocket event handling. The use ofvi.waitForfor async assertions and proper mock/state isolation inbeforeEachare good patterns.web/src/hooks/useOrgChartData.ts (2)
1-85: Overall hook structure is sound.The hook properly sequences data fetching (config before department health), sets up polling and WebSocket bindings, and memoizes derived graph data. The pattern of accessing stores via
.getState()in handlers avoids stale closure issues.
46-50: No action required — the ESLint rule is valid.The
@eslint-react/exhaustive-depsrule exists and is actively used throughout the codebase (at least 7 instances). The project uses@eslint-react/eslint-pluginv3, which provides this rule as part of its hooks analysis. The disable comment is correct and has the intended effect.web/src/pages/OrgChartPage.tsx (2)
1-310: Well-structured page implementation.The page correctly addresses all previous review feedback: defensive
getAgentNameguard, early return for unimplemented force view mode, andButton asChildcomposition. Good use of semantic Tailwind classes, existing UI components (ErrorBoundary,EmptyState,ConfirmDialog,Button), and proper accessibility patterns. The viewport persistence logic is robust with validation.
262-262: No action needed. React Flow'shideAttributionoption does not require a paid Pro license and is freely available under the MIT license. The attribution can be removed without any license restrictions.web/src/__tests__/pages/org/build-org-tree.test.ts (3)
288-298: Redundantcompany_namemutation before function call.Line 293 mutates
config.company_name, butmakeConfigalready setscompany_name: 'Test Corp'. The mutation is sufficient on its own. This was flagged in a past review.♻️ Cleaner alternative
it('includes companyName in CEO node data', () => { const agents = [ makeAgent({ id: 'ceo', name: 'Boss', department: 'executive', level: 'c_suite' }), ] - const config = makeConfig(agents) - config.company_name = 'Acme Inc' + const config = { ...makeConfig(agents), company_name: 'Acme Inc' } const result = buildOrgTree(config, {}, []) const ceoNode = result.nodes.find((n) => n.type === 'ceo') expect(ceoNode!.data.companyName).toBe('Acme Inc') })
1-313: LGTM - Comprehensive test coverage for org tree building.The test suite thoroughly covers CEO selection rules, department grouping, edge generation, terminated agent filtering, health data enrichment, runtime status overrides, and edge cases like empty departments. The factory helpers (
makeAgent,makeConfig,makeHealth) provide a clean DSL for constructing test fixtures.
184-187: 🧹 Nitpick | 🔵 TrivialNon-null assertion on array index access.
Line 186 uses
agentNodes[0]!which assumes the filtered array is non-empty. While the test setup guarantees one active agent, using.at(0)with an explicit check orexpect(agentNodes[0]).toBeDefined()first would be more defensive.💡 Safer alternative
const agentNodes = result.nodes.filter((n) => n.type === 'agent' || n.type === 'ceo') expect(agentNodes).toHaveLength(1) - expect(agentNodes[0]!.data.name).toBe('Active') + expect(agentNodes[0]?.data.name).toBe('Active')> Likely an incorrect or invalid review comment.web/src/stores/company.ts (1)
32-47: LGTM!The
fetchDepartmentHealthsimplementation correctly iterates overconfig.departmentsrather than paginating through an API list, addressing the earlier review feedback. The parallel fetching with individual error handling (catching per-department failures and filtering nulls) is a good resilience pattern.web/src/pages/org/build-org-tree.ts (3)
8-32: Index signatures on node data interfaces are appropriate for React Flow compatibility.The
[key: string]: unknownindex signatures onAgentNodeData,CeoNodeData, andDepartmentGroupDataallow these types to satisfy React Flow'sNode<T>constraint whereT extends Record<string, unknown>. This is the correct pattern for React Flow v12.
68-196: LGTM - Well-structured tree-building logic.The
buildOrgTreefunction follows a clear progression: filter terminated agents → group by department → identify CEO → build department nodes with health data → create agent nodes and hierarchy edges → connect CEO to department heads. The deduplication check for CEO-to-head edges (lines 181-191) correctly prevents duplicate edges when team structure already establishes the connection.
200-231: LGTM - Helper functions are well-documented.The tiebreaker behavior ("first wins" by array order) is now documented in comments above
findHighestSeniorityandfindCeo, addressing the earlier review feedback. ThefindDepartmentHeadfunction correctly excludes the CEO from candidates and avoids unnecessary array spread.web/src/pages/org/layout.ts (3)
98-158: LGTM - Clean separation of pure computation and side effects.The refactored two-step approach (Step 1: compute group bounds purely in
groupResults.map(), Step 2: adjust children in a separate loop) addresses the earlier review feedback about mixing concerns. The code is now easier to reason about.
1-161: Well-implemented dagre layout utility.The implementation correctly:
- Separates group nodes from leaf nodes for dagre processing
- Increases spacing to account for department chrome (padding + header)
- Handles the no-leaf-nodes case with a direction-aware grid
- Converts dagre center coordinates to React Flow top-left positions
- Computes group bounds from children and adjusts child positions to be group-relative
- Preserves existing style properties when setting dimensions
100-115: Empty group positioning logic may place nodes off-canvas for LR direction.When
direction === 'LR'and there are populated groups, empty groups are positioned atx = minor * 240(starting from 0) andy = contentMaxY + padding + major * 160. However, ifcontentMaxYis small, this could place empty groups far below the main content. The TB direction usescontentMaxX + paddingfor the X offset, but LR doesn't usecontentMaxXat all for X positioning, which may cause empty groups to overlap with populated content horizontally.
| unmount() | ||
| }), | ||
| { numRuns: 20 }, | ||
| { numRuns: 10 }, |
There was a problem hiding this comment.
Keep stronger property-test coverage or make run count environment-aware.
Line 54 reduces numRuns from 20 to 10, which weakens randomized coverage and lowers confidence in this invariant test. Consider keeping 20 in CI and using a lower value only for local runs.
Suggested adjustment
- { numRuns: 10 },
+ { numRuns: process.env.CI ? 20 : 10 },📝 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.
| { numRuns: 10 }, | |
| { numRuns: process.env.CI ? 20 : 10 }, |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@web/src/__tests__/pages/dashboard/ActivityFeed.test.tsx` at line 54, The test
lowered the randomized iteration count by changing the numRuns value in
ActivityFeed.test.tsx, which weakens coverage; restore stronger coverage by
making numRuns environment-aware (e.g., use process.env.CI or a TEST_RUNS env
var) so CI uses 20 while local runs can default to 10, and update the numRuns
reference in the test (the variable used in the ActivityFeed test block) to read
from that env-aware value.
| function Wrapper({ data }: { data: AgentNodeData }) { | ||
| return ( | ||
| <ReactFlowProvider> | ||
| <div style={{ width: 400, height: 200 }}> |
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major
Replace hardcoded inline dimensions with Tailwind sizing classes.
Line 11 hardcodes pixel dimensions in inline styles. Prefer standard Tailwind sizing utilities for consistency with layout token rules.
♻️ Proposed fix
- <div style={{ width: 400, height: 200 }}>
+ <div className="h-52 w-full max-w-md">As per coding guidelines: Spacing: use density-aware tokens (...) or standard Tailwind spacing. NEVER hardcode pixel values for layout spacing.
📝 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.
| <div style={{ width: 400, height: 200 }}> | |
| <div className="h-52 w-full max-w-md"> |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@web/src/pages/org/AgentNode.stories.tsx` at line 11, The story contains a div
with hardcoded inline style width/height in AgentNode.stories.tsx; replace that
inline style on the container div with the appropriate Tailwind sizing utility
classes (use the nearest standard Tailwind classes or your design system tokens,
e.g., w-*/h-* equivalents) so the component uses density-aware/tailwind sizing
rather than pixel values; update the JSX div (the container around the story
preview) to use className with Tailwind sizing utilities instead of style={{
width: 400, height: 200 }}.
| for (const node of leafNodes) { | ||
| g.setNode(node.id, { | ||
| width: node.measured?.width ?? DEFAULT_NODE_WIDTH, | ||
| height: node.measured?.height ?? DEFAULT_NODE_HEIGHT, | ||
| }) | ||
| } |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
Layout computed with placeholder sizes before React Flow measures nodes.
The dagre layout uses node.measured?.width with DEFAULT_NODE_WIDTH (160) and DEFAULT_NODE_HEIGHT (80) as fallbacks. On initial render, measured is undefined, so all nodes get uniform placeholder sizes. This was noted in past reviews and marked as addressed, but the fundamental issue remains: the initial layout may not match rendered node sizes.
The current approach is pragmatic for an MVP—nodes will be reasonably positioned, and React Flow's built-in pan/zoom allows users to adjust. For production, consider re-running layout after nodes are measured or using fixed dimensions in node components.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@web/src/pages/org/layout.ts` around lines 60 - 65, The dagre layout currently
uses placeholder sizes (DEFAULT_NODE_WIDTH/DEFAULT_NODE_HEIGHT) when
node.measured is undefined, yielding an initial layout that mismatches rendered
nodes; update the flow so that after React Flow measures nodes (i.e., when
measured.width/height become available on leafNodes) you recompute the layout
and call g.setNode with the real measured dimensions and re-run the dagre layout
pass (or alternatively enforce fixed dimensions inside the node component),
ensuring you trigger the layout update from the same routine that uses leafNodes
and g.setNode so nodes are laid out with actual sizes instead of placeholders.
| maxZoom={2} | ||
| proOptions={{ hideAttribution: true }} | ||
| > | ||
| <Background color="var(--color-border)" gap={24} size={1} /> |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Search for --color-border CSS variable definition
rg -n "\-\-color-border" --type=css web/
rg -n "\-\-color-border" web/src/index.css web/src/globals.css 2>/dev/null || echo "No globals.css found"Repository: Aureliolo/synthorg
Length of output: 223
🏁 Script executed:
# Check what --border resolves to and explore the full token structure
rg -n "^\s*--border:" web/src/styles/ -A 1
rg -n "^\s*--so-border" web/src/styles/ -A 1
cat web/src/styles/global.css | head -100Repository: Aureliolo/synthorg
Length of output: 4144
🏁 Script executed:
# Check how Background component is used elsewhere and what color patterns are recommended
rg -n "Background color=" web/src/ --type=tsx --type=ts
rg -n "var(--so-" web/src/styles/ | head -20Repository: Aureliolo/synthorg
Length of output: 153
Use the recommended var(--so-border) token variable instead of the intermediate --color-border variable.
The CSS variable --color-border is defined and functional (--color-border → --border → --so-border → #1e1e2e). However, per the design token pattern, use var(--so-border) directly for consistency with the SynthOrg theme bridge layer, rather than routing through the shadcn intermediate variable.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@web/src/pages/OrgChartPage.tsx` at line 264, Replace the intermediate CSS
token with the canonical SynthOrg token: in the Background component usage
(Background color="var(--color-border)" gap={24} size={1}), change the color
prop to use var(--so-border) instead of var(--color-border) so the component
uses the recommended design token directly.
There was a problem hiding this comment.
Actionable comments posted: 5
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@web/src/pages/org/NodeContextMenu.tsx`:
- Line 117: The NodeContextMenu is positioning the menu at raw client
coordinates (style={{ top: position.y, left: position.x }}) which can overflow
the viewport; add viewport boundary checking by computing a boundedPosition
(e.g., in a useMemo inside NodeContextMenu) that clamps x to
Math.min(position.x, window.innerWidth - menuWidth - margin) and y to
Math.min(position.y, window.innerHeight - menuHeight - margin) using the menu's
expected width/height (use items.length to estimate height) and then use that
boundedPosition for the inline style instead of position.
- Around line 113-120: The context menu returned by the NodeContextMenu
component (the element using menuRef with role="menu" and
data-testid="node-context-menu") is missing an aria-label for screen readers;
update that root div to include a descriptive aria-label (e.g., "Node context
menu" or a localized/prop-driven label) so assistive technology can announce the
menu purpose when role="menu" is used.
In `@web/src/pages/org/OrgChartToolbar.stories.tsx`:
- Around line 5-16: The story wrapper currently hardcodes state and callbacks by
rendering InteractiveToolbar directly, causing Default.args to be ignored;
change the custom render to accept story args and pass them into
InteractiveToolbar (and make InteractiveToolbar accept props from args) so
viewMode, onViewModeChange, onFitView, onZoomIn, and onZoomOut come from args
(falling back to internal state/noop when not provided), and ensure Default.args
is defined and used to initialize the component props so Controls and Docs
reflect the story args for OrgChartToolbar.
In `@web/src/stores/company.ts`:
- Around line 32-47: The fetchDepartmentHealths success path currently updates
departmentHealths but never clears a prior error, so restore/clear error state
when health refresh succeeds: in fetchDepartmentHealths (the async function)
ensure that after computing departmentHealths you call set with both
departmentHealths and error cleared (e.g., set({ departmentHealths, error:
undefined }) or similar), or alternatively clear the error at the start of the
try block before awaiting results; reference fetchDepartmentHealths, set and
getCompanyStore.getState().config when making the change.
- Around line 49-55: The WS event handler updateFromWsEvent currently refetches
company config via useCompanyStore.getState().fetchCompanyData() on
agent.hired/agent.fired but does not refresh department health, leaving
departmentHealths stale; after the fetchCompanyData() call (inside the same
branch) invoke the store method that reloads department health (e.g.,
useCompanyStore.getState().fetchDepartmentHealths()) or, if that method doesn't
exist, add a fetchDepartmentHealths() method to the company store and call it
here so departmentHealths is updated immediately (preserve the existing .catch
handling).
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 86561300-911e-4967-9dd2-9f9cac7a5828
📒 Files selected for processing (3)
web/src/pages/org/NodeContextMenu.tsxweb/src/pages/org/OrgChartToolbar.stories.tsxweb/src/stores/company.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
- GitHub Check: Build Sandbox
- GitHub Check: Build Web
- GitHub Check: Build Backend
- GitHub Check: Dashboard Test
- GitHub Check: Dependency Review
- GitHub Check: Analyze (python)
🧰 Additional context used
📓 Path-based instructions (2)
web/src/**/*.{tsx,ts}
📄 CodeRabbit inference engine (CLAUDE.md)
web/src/**/*.{tsx,ts}: Always reuse existing components fromweb/src/components/ui/before creating new ones. Check the required component inventory (StatusBadge, MetricCard, Sparkline, SectionCard, AgentCard, DeptHealthBar, ProgressGauge, StatPill, Avatar, Button, Toast, Skeleton, EmptyState, ErrorBoundary, ConfirmDialog, CommandPalette, InlineEdit, AnimatedPresence, StaggerGroup, TaskStatusIndicator, PriorityBadge)
Use Tailwind semantic classes (text-foreground,bg-card,text-accent,text-success,bg-danger) or CSS variables (var(--so-*)) for colors; never hardcode hex values
Usefont-sansorfont-monofor typography (maps to Geist tokens); never setfontFamilydirectly
Use density-aware spacing tokens (p-card,gap-section-gap,gap-grid-gap) or standard Tailwind spacing; never hardcode pixel values for layout spacing
Use token variables for shadows and borders (var(--so-shadow-card-hover),border-border,border-bright)
Do NOT recreate status dots inline -- use<StatusBadge>; do NOT build card-with-header layouts from scratch -- use<SectionCard>; do NOT create metric displays inline -- use<MetricCard>; do NOT render initials circles manually -- use<Avatar>; do NOT create complex (>8 line) JSX inside.map()-- extract to shared component
TypeScript 6.0: removebaseUrl(deprecated, will stop working in TS 7);esModuleInteropalways true (cannot be set false);typesdefaults to[](must explicitly list needed types);DOM.Iterablemerged intoDOM;moduleResolution: 'classic'and'node10'removed (use'bundler'or'nodenext');strictdefaults to true
Storybook 10 is ESM-only;@storybook/addon-essentials,@storybook/addon-interactions,@storybook/test,@storybook/blocksno longer published (features built into corestorybook);@storybook/addon-docsmust be installed separately if usingtags: ['autodocs']
Files:
web/src/pages/org/OrgChartToolbar.stories.tsxweb/src/pages/org/NodeContextMenu.tsxweb/src/stores/company.ts
web/src/**/*.stories.tsx
📄 CodeRabbit inference engine (CLAUDE.md)
Storybook 10: use
definePreviewfrom@storybook/react-vitefor type-safe config; import fromstorybook/test(not@storybook/test) andstorybook/actions(not@storybook/addon-actions); useparameters.backgrounds.options(object keyed by name) +initialGlobals.backgrounds.value; useparameters.a11y.test: 'error' | 'todo' | 'off'for accessibility testing
Files:
web/src/pages/org/OrgChartToolbar.stories.tsx
🧠 Learnings (6)
📓 Common learnings
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T21:20:09.993Z
Learning: Applies to web/src/components/** : Vue components organized by feature (agents/, approvals/, budget/, common/, dashboard/, layout/, messages/, org-chart/, tasks/).
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:17:43.675Z
Learning: Applies to web/** : Web dashboard: Node.js 20+, dependencies in web/package.json (Vue 3, PrimeVue, Tailwind CSS, Pinia, VueFlow, ECharts, Axios, vue-draggable-plus, Vitest, fast-check, ESLint, vue-tsc).
📚 Learning: 2026-03-27T12:41:55.315Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T12:41:55.315Z
Learning: Applies to web/src/**/*.{tsx,ts} : Storybook 10 is ESM-only; storybook/addon-essentials, storybook/addon-interactions, storybook/test, storybook/blocks no longer published (features built into core `storybook`); storybook/addon-docs must be installed separately if using `tags: ['autodocs']`
Applied to files:
web/src/pages/org/OrgChartToolbar.stories.tsx
📚 Learning: 2026-03-27T12:41:55.315Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T12:41:55.315Z
Learning: Applies to web/src/**/*.stories.tsx : Storybook 10: use `definePreview` from `storybook/react-vite` for type-safe config; import from `storybook/test` (not `storybook/test`) and `storybook/actions` (not `storybook/addon-actions`); use `parameters.backgrounds.options` (object keyed by name) + `initialGlobals.backgrounds.value`; use `parameters.a11y.test: 'error' | 'todo' | 'off'` for accessibility testing
Applied to files:
web/src/pages/org/OrgChartToolbar.stories.tsx
📚 Learning: 2026-03-27T12:41:55.315Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T12:41:55.315Z
Learning: Applies to web/src/components/ui/*.{tsx,ts} : When creating new shared UI components, place in `web/src/components/ui/` with kebab-case filename, create adjacent `.stories.tsx` with all states, export props as TypeScript interface, use design tokens exclusively (no hardcoded colors/fonts/spacing), import `cn` from `@/lib/utils` for conditional class merging
Applied to files:
web/src/pages/org/OrgChartToolbar.stories.tsx
📚 Learning: 2026-03-27T12:41:55.315Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T12:41:55.315Z
Learning: Applies to web/src/**/*.{tsx,ts} : Do NOT recreate status dots inline -- use `<StatusBadge>`; do NOT build card-with-header layouts from scratch -- use `<SectionCard>`; do NOT create metric displays inline -- use `<MetricCard>`; do NOT render initials circles manually -- use `<Avatar>`; do NOT create complex (>8 line) JSX inside `.map()` -- extract to shared component
Applied to files:
web/src/pages/org/OrgChartToolbar.stories.tsx
📚 Learning: 2026-03-27T12:41:55.315Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T12:41:55.315Z
Learning: Applies to web/src/**/*.{tsx,ts} : Always reuse existing components from `web/src/components/ui/` before creating new ones. Check the required component inventory (StatusBadge, MetricCard, Sparkline, SectionCard, AgentCard, DeptHealthBar, ProgressGauge, StatPill, Avatar, Button, Toast, Skeleton, EmptyState, ErrorBoundary, ConfirmDialog, CommandPalette, InlineEdit, AnimatedPresence, StaggerGroup, TaskStatusIndicator, PriorityBadge)
Applied to files:
web/src/pages/org/OrgChartToolbar.stories.tsx
🔇 Additional comments (5)
web/src/pages/org/OrgChartToolbar.stories.tsx (1)
18-24: Meta configuration looks correct for autodocs and accessibility.Good call setting
component: OrgChartToolbarand enablinga11y.test: 'error'.As per coding guidelines: “use
parameters.a11y.test: 'error' | 'todo' | 'off'for accessibility testing.”web/src/pages/org/NodeContextMenu.tsx (4)
1-4: Imports are appropriate and minimal.Standard React 19 hooks, lucide-react icons for menu visuals, utility function, and toast store for stub action feedback. No issues.
45-61: Event listener setup and cleanup is correct.The outside-click detection using
mousedownand Escape key handling are properly registered and cleaned up on unmount. Theas Nodecast (previously flagged) is correctly applied.
99-111: Node type handling is correctly implemented.The dedicated
ceoItemsarray (previously flagged) now properly limits CEO nodes to "View Details" only, preventing exposure of agent CRUD actions. The selection logic correctly routes all three node types.
121-136: Menu item rendering follows design system conventions.The buttons correctly include
type="button"(previously flagged), use semantic Tailwind classes (text-foreground,text-danger,hover:bg-card-hover), and proper ARIA attributes. Icon sizing withsize-3.5andaria-hidden="true"is appropriate.
| function InteractiveToolbar() { | ||
| const [viewMode, setViewMode] = useState<ViewMode>('hierarchy') | ||
| return ( | ||
| <OrgChartToolbar | ||
| viewMode={viewMode} | ||
| onViewModeChange={setViewMode} | ||
| onFitView={() => {}} | ||
| onZoomIn={() => {}} | ||
| onZoomOut={() => {}} | ||
| /> | ||
| ) | ||
| } |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
Wire story args through the custom render wrapper.
Default.args (Line [31]-Line [38]) are currently ignored because Line [25] renders InteractiveToolbar without args, and the wrapper hardcodes callbacks/state. This weakens Controls/Docs fidelity.
♻️ Proposed refactor
import { useState } from 'react'
import type { Meta, StoryObj } from '@storybook/react'
import { OrgChartToolbar, type ViewMode } from './OrgChartToolbar'
-function InteractiveToolbar() {
- const [viewMode, setViewMode] = useState<ViewMode>('hierarchy')
+type ToolbarProps = React.ComponentProps<typeof OrgChartToolbar>
+
+function InteractiveToolbar(args: ToolbarProps) {
+ const [viewMode, setViewMode] = useState<ViewMode>(args.viewMode)
return (
<OrgChartToolbar
+ {...args}
viewMode={viewMode}
- onViewModeChange={setViewMode}
- onFitView={() => {}}
- onZoomIn={() => {}}
- onZoomOut={() => {}}
+ onViewModeChange={(mode) => {
+ setViewMode(mode)
+ args.onViewModeChange(mode)
+ }}
/>
)
}
@@
- render: () => <InteractiveToolbar />,
+ render: (args) => <InteractiveToolbar {...args} />,
} satisfies Meta<typeof OrgChartToolbar>Also applies to: 25-25, 31-38
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@web/src/pages/org/OrgChartToolbar.stories.tsx` around lines 5 - 16, The story
wrapper currently hardcodes state and callbacks by rendering InteractiveToolbar
directly, causing Default.args to be ignored; change the custom render to accept
story args and pass them into InteractiveToolbar (and make InteractiveToolbar
accept props from args) so viewMode, onViewModeChange, onFitView, onZoomIn, and
onZoomOut come from args (falling back to internal state/noop when not
provided), and ensure Default.args is defined and used to initialize the
component props so Controls and Docs reflect the story args for OrgChartToolbar.
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (1)
web/src/stores/company.ts (1)
32-45:⚠️ Potential issue | 🟡 MinorClear stale
errorafter successful department health refresh.Line 43 updates
departmentHealthsbut leaves any previouserrorintact, so recovered polls can still render an error state.Suggested fix
fetchDepartmentHealths: async () => { try { const config = useCompanyStore.getState().config if (!config) return const healthPromises = config.departments.map((dept) => getDepartmentHealth(dept.name).catch(() => null), ) const healthResults = await Promise.all(healthPromises) const departmentHealths = healthResults.filter( (h): h is DepartmentHealth => h !== null, ) - set({ departmentHealths }) + set({ departmentHealths, error: null }) } catch (err) { set({ error: getErrorMessage(err) }) } },🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@web/src/stores/company.ts` around lines 32 - 45, In fetchDepartmentHealths, after successfully computing departmentHealths call set to also clear any previous error (e.g., set({ departmentHealths, error: null })) so a recovered poll doesn't leave an old error visible; ensure the change is applied in the fetchDepartmentHealths function where set is currently called to update departmentHealths.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@web/src/pages/org/NodeContextMenu.tsx`:
- Line 124: The menuLabel currently uses nodeType === 'department' ? 'Department
actions' : 'Agent actions' and thus labels CEO nodes as "Agent actions"; update
the logic in NodeContextMenu to distinguish 'ceo' explicitly (e.g., nodeType ===
'department' ? 'Department actions' : nodeType === 'ceo' ? 'CEO actions' :
'Agent actions') so CEO nodes get a specific "CEO actions" label and keep
existing behavior for 'agent' and 'department'.
- Around line 119-122: The bounding logic for the context menu only prevents
right/bottom overflow; update the useMemo that computes boundedPosition to clamp
both minimum and maximum bounds (e.g., use Math.max(position.x, margin) and
Math.max(position.y, margin) before Math.min with window.innerWidth - menuWidth
- margin and window.innerHeight - menuHeight - margin) so the menu can't render
off the left/top edges; also include menuWidth, menuHeight, and margin in the
useMemo dependency array so recalculation happens when those change.
---
Duplicate comments:
In `@web/src/stores/company.ts`:
- Around line 32-45: In fetchDepartmentHealths, after successfully computing
departmentHealths call set to also clear any previous error (e.g., set({
departmentHealths, error: null })) so a recovered poll doesn't leave an old
error visible; ensure the change is applied in the fetchDepartmentHealths
function where set is currently called to update departmentHealths.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 0bcfd08f-4de3-4c0d-a6ea-631934beb658
📒 Files selected for processing (2)
web/src/pages/org/NodeContextMenu.tsxweb/src/stores/company.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
- GitHub Check: Dashboard Test
- GitHub Check: Build Web
- GitHub Check: Build Backend
- GitHub Check: Dependency Review
- GitHub Check: Analyze (python)
🧰 Additional context used
📓 Path-based instructions (1)
web/src/**/*.{tsx,ts}
📄 CodeRabbit inference engine (CLAUDE.md)
web/src/**/*.{tsx,ts}: Always reuse existing components fromweb/src/components/ui/before creating new ones. Check the required component inventory (StatusBadge, MetricCard, Sparkline, SectionCard, AgentCard, DeptHealthBar, ProgressGauge, StatPill, Avatar, Button, Toast, Skeleton, EmptyState, ErrorBoundary, ConfirmDialog, CommandPalette, InlineEdit, AnimatedPresence, StaggerGroup, TaskStatusIndicator, PriorityBadge)
Use Tailwind semantic classes (text-foreground,bg-card,text-accent,text-success,bg-danger) or CSS variables (var(--so-*)) for colors; never hardcode hex values
Usefont-sansorfont-monofor typography (maps to Geist tokens); never setfontFamilydirectly
Use density-aware spacing tokens (p-card,gap-section-gap,gap-grid-gap) or standard Tailwind spacing; never hardcode pixel values for layout spacing
Use token variables for shadows and borders (var(--so-shadow-card-hover),border-border,border-bright)
Do NOT recreate status dots inline -- use<StatusBadge>; do NOT build card-with-header layouts from scratch -- use<SectionCard>; do NOT create metric displays inline -- use<MetricCard>; do NOT render initials circles manually -- use<Avatar>; do NOT create complex (>8 line) JSX inside.map()-- extract to shared component
TypeScript 6.0: removebaseUrl(deprecated, will stop working in TS 7);esModuleInteropalways true (cannot be set false);typesdefaults to[](must explicitly list needed types);DOM.Iterablemerged intoDOM;moduleResolution: 'classic'and'node10'removed (use'bundler'or'nodenext');strictdefaults to true
Storybook 10 is ESM-only;@storybook/addon-essentials,@storybook/addon-interactions,@storybook/test,@storybook/blocksno longer published (features built into corestorybook);@storybook/addon-docsmust be installed separately if usingtags: ['autodocs']
Files:
web/src/pages/org/NodeContextMenu.tsxweb/src/stores/company.ts
🧠 Learnings (1)
📓 Common learnings
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T21:20:09.993Z
Learning: Applies to web/src/components/** : Vue components organized by feature (agents/, approvals/, budget/, common/, dashboard/, layout/, messages/, org-chart/, tasks/).
🔇 Additional comments (3)
web/src/stores/company.ts (2)
22-30:fetchCompanyDatastate transitions are clean and deterministic.Good handling of
loading/erroracross both success and failure paths.
49-59: WS lifecycle refresh flow looks correct.Chaining
fetchCompanyData()thenfetchDepartmentHealths()foragent.hired/agent.firedkeeps org structure and health aligned.web/src/pages/org/NodeContextMenu.tsx (1)
1-153: Well-structured context menu implementation.The component correctly:
- Separates menu items by node type with appropriate actions for each
- Handles outside click and Escape dismissal with proper cleanup
- Uses semantic Tailwind classes (
border-border,bg-card,text-foreground,text-danger)- Includes accessibility attributes (
role="menu",role="menuitem",aria-label,aria-hidden)- Clamps position to viewport bounds to prevent overflow
- Uses
type="button"to prevent form submission issuesThe stubbed actions with toast feedback provide clear user communication while backend APIs are pending.
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@web/src/stores/company.ts`:
- Around line 36-43: The code currently converts per-department failures to null
(via healthPromises) so Promise.all never rejects and then always calls set({
departmentHealths, error: null }), which clears any real outage state; change
the logic after awaiting healthResults to detect the "all failed" case (e.g.,
departmentHealths.length === 0 && config.departments.length > 0) and in that
case set an error (or preserve the previous error) instead of clearing it;
otherwise (at least one success) set departmentHealths and clear error as now —
update the block that builds healthPromises/healthResults and the set(...) call
(referencing getDepartmentHealth, departmentHealths, healthPromises,
healthResults, and set) to implement this conditional error handling.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 3d5598db-fc8e-48d1-964d-322f753a386e
📒 Files selected for processing (2)
web/src/pages/org/NodeContextMenu.tsxweb/src/stores/company.ts
📜 Review details
🧰 Additional context used
📓 Path-based instructions (1)
web/src/**/*.{tsx,ts}
📄 CodeRabbit inference engine (CLAUDE.md)
web/src/**/*.{tsx,ts}: Always reuse existing components fromweb/src/components/ui/before creating new ones. Check the required component inventory (StatusBadge, MetricCard, Sparkline, SectionCard, AgentCard, DeptHealthBar, ProgressGauge, StatPill, Avatar, Button, Toast, Skeleton, EmptyState, ErrorBoundary, ConfirmDialog, CommandPalette, InlineEdit, AnimatedPresence, StaggerGroup, TaskStatusIndicator, PriorityBadge)
Use Tailwind semantic classes (text-foreground,bg-card,text-accent,text-success,bg-danger) or CSS variables (var(--so-*)) for colors; never hardcode hex values
Usefont-sansorfont-monofor typography (maps to Geist tokens); never setfontFamilydirectly
Use density-aware spacing tokens (p-card,gap-section-gap,gap-grid-gap) or standard Tailwind spacing; never hardcode pixel values for layout spacing
Use token variables for shadows and borders (var(--so-shadow-card-hover),border-border,border-bright)
Do NOT recreate status dots inline -- use<StatusBadge>; do NOT build card-with-header layouts from scratch -- use<SectionCard>; do NOT create metric displays inline -- use<MetricCard>; do NOT render initials circles manually -- use<Avatar>; do NOT create complex (>8 line) JSX inside.map()-- extract to shared component
TypeScript 6.0: removebaseUrl(deprecated, will stop working in TS 7);esModuleInteropalways true (cannot be set false);typesdefaults to[](must explicitly list needed types);DOM.Iterablemerged intoDOM;moduleResolution: 'classic'and'node10'removed (use'bundler'or'nodenext');strictdefaults to true
Storybook 10 is ESM-only;@storybook/addon-essentials,@storybook/addon-interactions,@storybook/test,@storybook/blocksno longer published (features built into corestorybook);@storybook/addon-docsmust be installed separately if usingtags: ['autodocs']
Files:
web/src/pages/org/NodeContextMenu.tsxweb/src/stores/company.ts
🧠 Learnings (1)
📓 Common learnings
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T21:20:09.993Z
Learning: Applies to web/src/components/** : Vue components organized by feature (agents/, approvals/, budget/, common/, dashboard/, layout/, messages/, org-chart/, tasks/).
🔇 Additional comments (1)
web/src/pages/org/NodeContextMenu.tsx (1)
1-154: Clean implementation with all prior feedback addressed.The component is well-structured with:
- Proper separation of menu item definitions per node type (agent, ceo, department)
- Correct viewport boundary clamping using
Math.max/Math.minfor all edges- Good accessibility:
role="menu",role="menuitem", contextualaria-label,aria-hiddenon icons- Proper cleanup of document event listeners
type="button"on all buttons to prevent form submission issuesThe use of Tailwind semantic classes (
text-foreground,bg-card,border-border,text-danger) aligns with coding guidelines.
Implement the Org Chart page (#778) with real-time organizational visualization using React Flow. The chart shows agent nodes with living status encoding (active/idle/error/offline), department grouping with health overlays, auto-layout via dagre, and CRUD operations via context menus. Key components: - AgentNode/CeoNode: custom React Flow nodes with Avatar + StatusBadge - DepartmentGroupNode: health-colored group with stats bar - HierarchyEdge: styled smooth-step edges - OrgChartToolbar: view toggle, zoom, fit-view controls - NodeContextMenu: right-click context menu with CRUD stubs - OrgChartSkeleton: tree-like loading placeholder Data layer: - useCompanyStore: company config + department health - useAgentsStore: runtime status overlay from WebSocket - useOrgChartData: composite hook (stores + WS + polling) - buildOrgTree: pure function deriving hierarchy from seniority - applyDagreLayout: dagre wrapper for auto-positioning Includes 30 new tests and 7 Storybook story files. Closes #674 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Pre-reviewed by 5 agents, 15 findings addressed: - Replace window.location.href with useNavigate (SPA navigation) - Add onNodeClick handler for click-to-drill agent detail - Add viewMode feedback toast for unimplemented force view - Validate viewport shape from localStorage after JSON.parse - Validate WebSocket payload at runtime before store update - Use SeniorityLevel type instead of string in AgentNodeData - Remove dead if/else branch in layout.ts - Fix in-place array mutation in layout.ts (use Map instead) - Add aria-label to AgentNode, CeoNode, DepartmentGroupNode - Replace raw shadow CSS with Tailwind token in CeoNode - Update CLAUDE.md stores/hooks descriptions - Add store tests for useAgentsStore and useCompanyStore - Add loading-with-nodes and c_suite fallback test cases Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…mini - Type safety: extract getNodeLabel/getAgentName helpers, use Record<SeniorityLevel> instead of Record<string>, add VALID_NODE_TYPES guard, defensive node data access - CEO context menu: separate ceoItems (View Details only) instead of inheriting agent CRUD actions like "Remove Agent" - Empty departments: render in org chart even without agents (supports CRUD flow) - Nullable health: department healthPercent/taskCount are null when API data missing instead of falsely defaulting to 100%/0 - Currency fix: DepartmentStatsBar defaults to 'USD' matching costUsd field semantics - Store fix: fetchDepartmentHealths uses config.departments instead of listDepartments pagination, sets error state on failure instead of console.warn - Tailwind v4: postfix important syntax (bg-accent! not !bg-accent) - Layout: extract GROUP_NODE_HEADER_HEIGHT constant, replace min-w-[140px] with min-w-36 - Accessibility: aria-pressed on toolbar toggle buttons, type="button" on menu items - Stories: add parameters.a11y.test:'error' to all 7 story metas, add CeoNode Error/Offline stories, add CeoMenu story, remove inline background style - Tests: fix mock isolation (beforeEach reset in NodeContextMenu, factory in Toolbar), precise assertion toHaveLength(4), add agent.fired event test, use it.each for stats - Comments: fix inaccurate agentName->teamLeadName, system->agent lifecycle events, memoized->stable reference, add JSDoc explaining active->idle mapping, ESLint suppress justification - Docs: add @dagrejs/dagre to CLAUDE.md dependencies, fix test descriptions Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Fix missing beforeEach import in NodeContextMenu test - Sequence initial data fetch: await fetchCompanyData before fetchDepartmentHealths (health depends on config being loaded) - Skip duplicate team membership in buildOrgTree (first team wins) - Remove unnecessary shallow copy in findDepartmentHead when ceo is null - Place empty department groups on a grid instead of all at (0,0) - Don't set viewMode to 'force' since it's unimplemented (show toast only) - Use Button asChild + Link instead of nested Link > Button (a11y) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add outside-click dismissal test for NodeContextMenu - Add fast-check property-based test for menu structure invariants - Guard fetchDepartmentHealths on config presence after fetchCompanyData - Remove agents.length === 0 early return so department-only orgs render - Offset empty department groups from laid-out content bounds Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add JSDoc to findCeo and findHighestSeniority documenting that ties are broken by array order (first wins) - Fix leafNodes.length === 0 early return in applyDagreLayout to place department-only nodes on a grid instead of all at (0,0) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… chrome spacing - Use EMPTY_GROUP_HEIGHT (120px) matching DepartmentGroupNode's min-h-[120px] - Increase dagre nodeSep/rankSep when department groups exist to prevent overlapping group chrome (padding + header) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- errors.property.test.ts: mock axios to prevent fetch adapter capability detection (creates unresolved ReadableStream promises that leak) - DashboardPage.test.tsx: replace dynamic import with static import to avoid timeout under leak detection overhead, use getByLabelText for skeleton to avoid multiple role="status" match - ActivityFeed.test.tsx: reduce fast-check numRuns from 20 to 10 - App.test.tsx: increase timeout to 10s for lazy-loaded route rendering Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Layout: empty-group and department-only grid branches now respect the direction option (LR swaps axes) - errors.property.test.ts: mock axios to prevent fetch adapter promise leaks - DashboardPage.test.tsx: static import instead of dynamic to avoid timeout under --detect-async-leaks, use getByLabelText for skeleton query - ActivityFeed.test.tsx: reduce fast-check numRuns from 20 to 10 - App.test.tsx: increase timeout for lazy-loaded route rendering Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…layout Split positionedGroups map into two passes: pure computation of group bounds, then isolated child position adjustment. Eliminates side-effect mutation of positionedLeafMap inside a .map() callback. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- NodeContextMenu: cast e.target as Node (not HTMLElement) for contains() - OrgChartToolbar.stories: set component to OrgChartToolbar so autodocs reflect the real props, use render for interactive wrapper - company store: catch fetchCompanyData promise in WS handler to prevent unhandled rejection Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- NodeContextMenu: clamp position to viewport bounds to prevent overflow, add aria-label for screen readers - company store: chain fetchDepartmentHealths after fetchCompanyData in WS handler so health data stays current on agent hire/fire events Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…uccess - NodeContextMenu: distinguish CEO with "CEO actions" aria-label, clamp position to all four viewport edges (not just right/bottom) - company store: clear error on successful health fetch so stale health errors don't persist after recovery Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- company store: detect when all department health fetches fail and set error instead of clearing it with empty array - agents test: fix CoordinationTopology and updated_at type mismatches Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
4203a61 to
fd3ff57
Compare
There was a problem hiding this comment.
Actionable comments posted: 8
♻️ Duplicate comments (4)
web/src/__tests__/pages/dashboard/ActivityFeed.test.tsx (1)
54-54:⚠️ Potential issue | 🟡 MinorRestore stronger property-test coverage or make run count environment-aware.
Reducing
numRunsfrom 20 to 10 cuts randomized coverage by 50%, weakening confidence in the cap-at-10 invariant. Consider keeping 20 runs in CI while allowing 10 for local development.🔧 Proposed fix: environment-aware run count
- { numRuns: 10 }, + { numRuns: process.env.CI ? 20 : 10 },🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@web/src/__tests__/pages/dashboard/ActivityFeed.test.tsx` at line 54, The test reduced randomized coverage by setting the test option { numRuns: 10 } in ActivityFeed.test.tsx; restore stronger coverage by making numRuns environment-aware: replace the hard-coded 10 with a value derived from an env var (e.g., process.env.TEST_RUNS) or use process.env.CI to select 20 for CI and 10 locally, so the unique symbol "numRuns" in ActivityFeed.test.tsx drives the run count dynamically and preserves 20 runs in CI while allowing 10 for local dev.web/src/pages/org/OrgChartToolbar.stories.tsx (1)
5-16: 🧹 Nitpick | 🔵 TrivialStory
argsare defined but not wired through the render function.The
Default.args(Lines 31-38) are ignored becauseInteractiveToolbardoesn't accept any arguments andrender(Line 25) doesn't pass args through. This means Storybook Controls won't affect the rendered component.♻️ Wire args through InteractiveToolbar
-function InteractiveToolbar() { - const [viewMode, setViewMode] = useState<ViewMode>('hierarchy') +type ToolbarProps = React.ComponentProps<typeof OrgChartToolbar> + +function InteractiveToolbar(args: Partial<ToolbarProps>) { + const [viewMode, setViewMode] = useState<ViewMode>(args.viewMode ?? 'hierarchy') return ( <OrgChartToolbar viewMode={viewMode} - onViewModeChange={setViewMode} - onFitView={() => {}} - onZoomIn={() => {}} - onZoomOut={() => {}} + onViewModeChange={(mode) => { + setViewMode(mode) + args.onViewModeChange?.(mode) + }} + onFitView={args.onFitView ?? (() => {})} + onZoomIn={args.onZoomIn ?? (() => {})} + onZoomOut={args.onZoomOut ?? (() => {})} /> ) }And update the render:
- render: () => <InteractiveToolbar />, + render: (args) => <InteractiveToolbar {...args} />,Also applies to: 25-25, 31-38
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@web/src/pages/org/OrgChartToolbar.stories.tsx` around lines 5 - 16, The story's Default.args are not used because InteractiveToolbar is not receiving or forwarding story args; modify InteractiveToolbar to accept props (e.g., args) and spread or pass them into OrgChartToolbar (ensure viewMode and handlers are taken from args or merged with local state as needed), and update the story render function to call InteractiveToolbar with those args (so render: (args) => <InteractiveToolbar {...args} /> or similar). Reference InteractiveToolbar, OrgChartToolbar, Default.args and render when making the change.web/src/hooks/useOrgChartData.ts (1)
46-50:⚠️ Potential issue | 🟡 MinorInvalid ESLint disable comment has no effect.
The comment references
@eslint-react/exhaustive-deps, but this rule doesn't exist in@eslint-react/eslint-plugin. Theexhaustive-depsrule comes fromeslint-plugin-react-hooks.Either:
- Remove the disable comment if exhaustive-deps checking is not enabled, or
- Install
eslint-plugin-react-hooksand change to// eslint-disable-next-line react-hooks/exhaustive-deps♻️ Option 1: Remove ineffective comment
useEffect(() => { polling.start() return () => polling.stop() - // eslint-disable-next-line `@eslint-react/exhaustive-deps` -- mount-only effect; polling.start/stop are stable but reference identity triggers false positive }, [])🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@web/src/hooks/useOrgChartData.ts` around lines 46 - 50, The ESLint disable comment on the useEffect in useOrgChartData.ts is incorrect (refs `@eslint-react/exhaustive-deps`) and has no effect; either remove the disable comment or replace it with the correct rule name. Locate the useEffect that calls polling.start() and returns polling.stop() and either delete the trailing eslint-disable-next-line comment or change it to "// eslint-disable-next-line react-hooks/exhaustive-deps" after ensuring eslint-plugin-react-hooks is configured/installed so the rule will be recognized.web/src/pages/org/AgentNode.stories.tsx (1)
11-11: 🛠️ Refactor suggestion | 🟠 MajorReplace hardcoded inline dimensions with Tailwind sizing classes.
The wrapper uses hardcoded pixel values in inline styles, which violates the coding guidelines.
♻️ Proposed fix
- <div style={{ width: 400, height: 200 }}> + <div className="h-52 w-96">As per coding guidelines:
Use density-aware spacing tokens or standard Tailwind spacing; NEVER hardcode pixel values for layout spacing.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@web/src/pages/org/AgentNode.stories.tsx` at line 11, The story contains a div with inline styles `style={{ width: 400, height: 200 }}`; remove the hardcoded pixel styles and replace them with equivalent Tailwind sizing classes (use appropriate w- and h- classes or project density-aware spacing tokens) in the AgentNode story wrapper so layout uses Tailwind tokens instead of pixels.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@web/src/__tests__/pages/org/build-org-tree.test.ts`:
- Around line 144-174: Add a regression test in build-org-tree.test.ts that
covers equal-seniority peers: create a fixture using makeAgent and makeConfig
with three same-level agents in one department (e.g., CEO, CTO, CFO all level
'c_suite' or two VPs same level), call buildOrgTree(config, {}, []), and assert
the deterministic tie-break behavior by checking result.edges for the expected
sources/targets (use result.edges.filter(e => e.source === 'ceo') or similar and
compare targets with a sorted array to avoid ordering flakiness). This ensures
buildOrgTree's first-wins tie rule is locked down for same-level peers.
In `@web/src/__tests__/pages/org/DepartmentStatsBar.test.tsx`:
- Around line 7-15: The parameterized it.each test repeatedly re-renders
DepartmentStatsBar with identical props; replace the it.each block (the test
titled 'renders %s with label %s') by a single test that renders
<DepartmentStatsBar agentCount={5} activeCount={3} taskCount={8} costUsd={null}
/> once and then asserts all three value/label pairs via multiple
expect(screen.getByText(...)).toBeInTheDocument() calls for '5'/'Agents',
'3'/'Active', and '8'/'Tasks' to keep coverage while avoiding redundant renders.
In `@web/src/__tests__/stores/company.test.ts`:
- Around line 99-124: The tests for useCompanyStore.getState().updateFromWsEvent
currently only assert fetchCompanyData (mockGetCompanyConfig) was called; update
the two agent.hired and agent.fired tests to also assert that
fetchDepartmentHealths triggers getDepartmentHealth by mocking/resolving the
department-health call (e.g., mockGetDepartmentHealth) and using vi.waitFor to
expect mockGetDepartmentHealth toHaveBeenCalled after calling updateFromWsEvent;
reference the functions updateFromWsEvent,
fetchCompanyData/fetchDepartmentHealths and the mocks
mockGetCompanyConfig/mockGetDepartmentHealth to locate and extend the
assertions.
In `@web/src/hooks/useOrgChartData.ts`:
- Around line 40-50: The polling currently starts immediately (polling.start()),
causing fetchDepartmentHealths() to run before fetchCompanyData() completes;
instead, start polling only after the initial fetchCompanyData() has finished.
Move the call to polling.start() out of the mount-only useEffect and invoke it
after await useCompanyStore.getState().fetchCompanyData() (or in the .then
callback) so pollFn/useCompanyStore.getState().fetchDepartmentHealths() runs
only once post-initial-fetch; still ensure polling.stop() is called on unmount
to clean up.
In `@web/src/pages/org/build-org-tree.ts`:
- Around line 168-175: The current fallback creates a hierarchy edge for any
non-team member (using head, agent, edges and id `e-${head.id}-${agent.id}`)
even when head and agent are same seniority; change the condition so you only
push that edge when head has strictly higher seniority/level than agent (e.g.,
check head.level > agent.level or head.seniority > agent.seniority), and skip
creating the manager/subordinate link when levels are equal (leave peers
unparented or handle via explicit business-rule function like
determineReportingRelationship(head, agent) if needed).
In `@web/src/pages/org/DepartmentGroupNode.stories.tsx`:
- Line 11: The wrapper div in DepartmentGroupNode.stories.tsx uses hardcoded
inline pixel styles (width: 500, height: 200); replace those inline styles with
appropriate Tailwind sizing classes on that wrapper (e.g., use density-aware /
standard Tailwind tokens such as w-96 h-48 or the project-specific spacing
tokens) by removing the style={{ width: 500, height: 200 }} and adding a
className with the chosen Tailwind sizes; keep the node's own style prop (the
React Flow node style mentioned in the comment) as-is since React Flow requires
explicit node dimensions.
In `@web/src/pages/OrgChartPage.tsx`:
- Around line 221-231: The error banners in OrgChartPage (the conditional blocks
rendering when error and when !wsConnected && wsSetupError) are not announced to
assistive tech; update those divs in the OrgChartPage component to include
appropriate live-region attributes (e.g., role="alert" or aria-live="assertive"
for the error banner and role="status" or aria-live="polite" for the websocket
warning) so screen readers announce the messages, and ensure any decorative
icons keep aria-hidden="true" (AlertTriangle already has aria-hidden) to avoid
duplicate announcements.
In `@web/src/stores/company.ts`:
- Around line 53-64: The websocket handler updateFromWsEvent triggers concurrent
fetchCompanyData → fetchDepartmentHealths chains; add a fetch-in-progress guard
or debounce in the company store to serialize these calls: introduce a boolean
(e.g., isFetchingCompany) or a simple mutex in the store used by
updateFromWsEvent (obtained via useCompanyStore.getState()) so if a fetch is
already running you either skip starting another fetch or coalesce subsequent
events, and ensure fetchCompanyData awaits completion before calling
fetchDepartmentHealths; update updateFromWsEvent to check/set the guard and to
clear it on success/failure to prevent race conditions and stale overwrites.
---
Duplicate comments:
In `@web/src/__tests__/pages/dashboard/ActivityFeed.test.tsx`:
- Line 54: The test reduced randomized coverage by setting the test option {
numRuns: 10 } in ActivityFeed.test.tsx; restore stronger coverage by making
numRuns environment-aware: replace the hard-coded 10 with a value derived from
an env var (e.g., process.env.TEST_RUNS) or use process.env.CI to select 20 for
CI and 10 locally, so the unique symbol "numRuns" in ActivityFeed.test.tsx
drives the run count dynamically and preserves 20 runs in CI while allowing 10
for local dev.
In `@web/src/hooks/useOrgChartData.ts`:
- Around line 46-50: The ESLint disable comment on the useEffect in
useOrgChartData.ts is incorrect (refs `@eslint-react/exhaustive-deps`) and has no
effect; either remove the disable comment or replace it with the correct rule
name. Locate the useEffect that calls polling.start() and returns polling.stop()
and either delete the trailing eslint-disable-next-line comment or change it to
"// eslint-disable-next-line react-hooks/exhaustive-deps" after ensuring
eslint-plugin-react-hooks is configured/installed so the rule will be
recognized.
In `@web/src/pages/org/AgentNode.stories.tsx`:
- Line 11: The story contains a div with inline styles `style={{ width: 400,
height: 200 }}`; remove the hardcoded pixel styles and replace them with
equivalent Tailwind sizing classes (use appropriate w- and h- classes or project
density-aware spacing tokens) in the AgentNode story wrapper so layout uses
Tailwind tokens instead of pixels.
In `@web/src/pages/org/OrgChartToolbar.stories.tsx`:
- Around line 5-16: The story's Default.args are not used because
InteractiveToolbar is not receiving or forwarding story args; modify
InteractiveToolbar to accept props (e.g., args) and spread or pass them into
OrgChartToolbar (ensure viewMode and handlers are taken from args or merged with
local state as needed), and update the story render function to call
InteractiveToolbar with those args (so render: (args) => <InteractiveToolbar
{...args} /> or similar). Reference InteractiveToolbar, OrgChartToolbar,
Default.args and render when making the change.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: fb1e4d09-7707-4792-9d9d-255d5a86a701
⛔ Files ignored due to path filters (1)
web/package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (39)
CLAUDE.mdweb/package.jsonweb/src/__tests__/App.test.tsxweb/src/__tests__/pages/DashboardPage.test.tsxweb/src/__tests__/pages/dashboard/ActivityFeed.test.tsxweb/src/__tests__/pages/org/DepartmentStatsBar.test.tsxweb/src/__tests__/pages/org/NodeContextMenu.test.tsxweb/src/__tests__/pages/org/OrgChartPage.test.tsxweb/src/__tests__/pages/org/OrgChartSkeleton.test.tsxweb/src/__tests__/pages/org/OrgChartToolbar.test.tsxweb/src/__tests__/pages/org/build-org-tree.test.tsweb/src/__tests__/pages/org/layout.test.tsweb/src/__tests__/pages/org/status-mapping.test.tsweb/src/__tests__/stores/agents.test.tsweb/src/__tests__/stores/company.test.tsweb/src/__tests__/utils/errors.property.test.tsweb/src/hooks/useOrgChartData.tsweb/src/pages/OrgChartPage.tsxweb/src/pages/org/AgentNode.stories.tsxweb/src/pages/org/AgentNode.tsxweb/src/pages/org/CeoNode.stories.tsxweb/src/pages/org/CeoNode.tsxweb/src/pages/org/DepartmentGroupNode.stories.tsxweb/src/pages/org/DepartmentGroupNode.tsxweb/src/pages/org/DepartmentStatsBar.stories.tsxweb/src/pages/org/DepartmentStatsBar.tsxweb/src/pages/org/HierarchyEdge.tsxweb/src/pages/org/NodeContextMenu.stories.tsxweb/src/pages/org/NodeContextMenu.tsxweb/src/pages/org/OrgChartSkeleton.stories.tsxweb/src/pages/org/OrgChartSkeleton.tsxweb/src/pages/org/OrgChartToolbar.stories.tsxweb/src/pages/org/OrgChartToolbar.tsxweb/src/pages/org/build-org-tree.tsweb/src/pages/org/layout.tsweb/src/pages/org/status-mapping.tsweb/src/stores/agents.tsweb/src/stores/company.tsweb/src/styles/global.css
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Build Web
🧰 Additional context used
📓 Path-based instructions (2)
web/src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
web/src/**/*.{ts,tsx}: ALWAYS reuse existing components fromweb/src/components/ui/(StatusBadge, MetricCard, Sparkline, SectionCard, AgentCard, etc.) before creating new ones
Use Tailwind semantic classes (text-foreground,bg-card,text-accent, etc.) or CSS variables (var(--so-*)) for colors; NEVER hardcode hex or rgba values
Usefont-sansorfont-monofor typography; NEVER setfontFamilydirectly in component code
Use density-aware spacing tokens (p-card,gap-section-gap,gap-grid-gap) or standard Tailwind spacing; NEVER hardcode pixel values for layout spacing
Use token variables for shadows and borders (var(--so-shadow-card-hover),border-border,border-bright); NEVER hardcode values
Do NOT recreate status dots inline -- use<StatusBadge>; do NOT build card-with-header layouts from scratch -- use<SectionCard>; do NOT create metric displays with hardcoded styles -- use<MetricCard>
Do NOT create complex (>8 line) JSX inside.map()-- extract to a shared component inweb/src/components/ui/
Use TypeScript 6.0+ strict mode with propertsconfig.jsonconfiguration: remove deprecatedbaseUrl, enablepathsfor imports, explicitly listtypes, usemoduleResolution: 'bundler', keepstrict: true
Setparameters.a11y.test: 'error' | 'todo' | 'off'in Storybook stories to enforce WCAG compliance (set globally inpreview.tsx)
Files:
web/src/__tests__/pages/dashboard/ActivityFeed.test.tsxweb/src/__tests__/pages/DashboardPage.test.tsxweb/src/__tests__/pages/org/OrgChartSkeleton.test.tsxweb/src/__tests__/App.test.tsxweb/src/__tests__/utils/errors.property.test.tsweb/src/pages/org/OrgChartSkeleton.tsxweb/src/__tests__/pages/org/DepartmentStatsBar.test.tsxweb/src/pages/org/HierarchyEdge.tsxweb/src/pages/org/status-mapping.tsweb/src/pages/org/OrgChartSkeleton.stories.tsxweb/src/pages/org/DepartmentStatsBar.tsxweb/src/__tests__/pages/org/status-mapping.test.tsweb/src/__tests__/pages/org/OrgChartPage.test.tsxweb/src/__tests__/pages/org/OrgChartToolbar.test.tsxweb/src/pages/org/OrgChartToolbar.stories.tsxweb/src/stores/agents.tsweb/src/pages/org/CeoNode.tsxweb/src/pages/org/AgentNode.tsxweb/src/hooks/useOrgChartData.tsweb/src/__tests__/pages/org/NodeContextMenu.test.tsxweb/src/__tests__/stores/agents.test.tsweb/src/pages/org/NodeContextMenu.tsxweb/src/pages/org/DepartmentGroupNode.tsxweb/src/pages/org/DepartmentGroupNode.stories.tsxweb/src/__tests__/stores/company.test.tsweb/src/pages/org/NodeContextMenu.stories.tsxweb/src/pages/org/OrgChartToolbar.tsxweb/src/pages/org/AgentNode.stories.tsxweb/src/__tests__/pages/org/build-org-tree.test.tsweb/src/__tests__/pages/org/layout.test.tsweb/src/pages/org/CeoNode.stories.tsxweb/src/stores/company.tsweb/src/pages/org/DepartmentStatsBar.stories.tsxweb/src/pages/org/build-org-tree.tsweb/src/pages/OrgChartPage.tsxweb/src/pages/org/layout.ts
web/src/**/*.stories.tsx
📄 CodeRabbit inference engine (CLAUDE.md)
Storybook stories must cover all component states (default, hover, loading, error, empty) and be created alongside the component in
web/src/components/ui/
Files:
web/src/pages/org/OrgChartSkeleton.stories.tsxweb/src/pages/org/OrgChartToolbar.stories.tsxweb/src/pages/org/DepartmentGroupNode.stories.tsxweb/src/pages/org/NodeContextMenu.stories.tsxweb/src/pages/org/AgentNode.stories.tsxweb/src/pages/org/CeoNode.stories.tsxweb/src/pages/org/DepartmentStatsBar.stories.tsx
🧠 Learnings (28)
📓 Common learnings
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T21:20:09.993Z
Learning: Applies to web/src/components/** : Vue components organized by feature (agents/, approvals/, budget/, common/, dashboard/, layout/, messages/, org-chart/, tasks/).
📚 Learning: 2026-03-20T08:28:32.845Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-20T08:28:32.845Z
Learning: Applies to web/src/__tests__/**/*.{ts,js} : Dashboard testing: Vitest unit tests organized by feature under `web/src/__tests__/`. Use fast-check for property-based testing (`fc.assert` + `fc.property`).
Applied to files:
web/src/__tests__/pages/dashboard/ActivityFeed.test.tsxweb/src/__tests__/pages/DashboardPage.test.tsxweb/src/__tests__/pages/org/OrgChartSkeleton.test.tsxweb/src/__tests__/utils/errors.property.test.tsCLAUDE.mdweb/src/__tests__/pages/org/DepartmentStatsBar.test.tsxweb/src/__tests__/pages/org/status-mapping.test.tsweb/src/__tests__/pages/org/OrgChartPage.test.tsxweb/src/__tests__/pages/org/OrgChartToolbar.test.tsxweb/src/__tests__/pages/org/NodeContextMenu.test.tsxweb/src/__tests__/stores/company.test.tsweb/src/__tests__/pages/org/build-org-tree.test.tsweb/src/__tests__/pages/org/layout.test.ts
📚 Learning: 2026-03-27T14:30:49.093Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T14:30:49.093Z
Learning: Applies to web/src/**/*.{ts,tsx} : Use Tailwind semantic classes (`text-foreground`, `bg-card`, `text-accent`, etc.) or CSS variables (`var(--so-*)`) for colors; NEVER hardcode hex or rgba values
Applied to files:
web/src/styles/global.cssweb/src/pages/org/OrgChartSkeleton.stories.tsxweb/src/pages/org/CeoNode.tsxweb/src/pages/org/AgentNode.tsxweb/src/pages/org/AgentNode.stories.tsxweb/src/pages/OrgChartPage.tsx
📚 Learning: 2026-03-27T14:30:49.093Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T14:30:49.093Z
Learning: Applies to web/src/**/*.{ts,tsx} : Use token variables for shadows and borders (`var(--so-shadow-card-hover)`, `border-border`, `border-bright`); NEVER hardcode values
Applied to files:
web/src/styles/global.cssweb/src/pages/org/OrgChartSkeleton.stories.tsxweb/src/pages/org/CeoNode.tsxweb/src/pages/org/AgentNode.tsxweb/src/pages/org/AgentNode.stories.tsxweb/src/pages/OrgChartPage.tsx
📚 Learning: 2026-03-14T15:43:05.601Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T15:43:05.601Z
Learning: Applies to web/package.json : Web dashboard Node.js 20+; dependencies in web/package.json (Vue 3, PrimeVue, Tailwind CSS, Pinia, VueFlow, ECharts, Axios, vue-draggable-plus, Vitest, ESLint, vue-tsc)
Applied to files:
web/package.jsonCLAUDE.mdweb/src/pages/org/CeoNode.tsx
📚 Learning: 2026-03-15T18:17:43.675Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:17:43.675Z
Learning: Applies to web/** : Web dashboard: Node.js 20+, dependencies in web/package.json (Vue 3, PrimeVue, Tailwind CSS, Pinia, VueFlow, ECharts, Axios, vue-draggable-plus, Vitest, fast-check, ESLint, vue-tsc).
Applied to files:
web/package.jsonCLAUDE.md
📚 Learning: 2026-03-19T07:12:14.508Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T07:12:14.508Z
Learning: Applies to src/synthorg/**/*.py : Package structure: src/synthorg/ organized as: api/ (REST+WebSocket, Litestar), auth/ (auth subpackage), backup/ (scheduled/manual backups), budget/ (cost tracking, CFO), cli/ (superseded by Go CLI), communication/ (message bus, meetings), config/ (YAML loading), core/ (domain models, resilience config), engine/ (orchestration, task state, coordination, approval gates, stagnation detection, context budget, compaction), hr/ (hiring, performance, promotion), memory/ (pluggable backend, Mem0, retrieval, consolidation), persistence/ (operational data, SQLite, settings), observability/ (logging, correlation, sinks), providers/ (LLM abstraction, LiteLLM, auth types, presets, runtime CRUD), settings/ (runtime-editable, typed definitions, encryption, config bridge), security/ (SecOps, rule engine, output scanning, progressive trust, autonomy levels), templates/ (company templates, personalities), tools/ (registry, built-in tools, git, sandbox, code_runner, MCP...
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-15T21:20:09.993Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T21:20:09.993Z
Learning: Applies to web/src/components/** : Vue components organized by feature (agents/, approvals/, budget/, common/, dashboard/, layout/, messages/, org-chart/, tasks/).
Applied to files:
CLAUDE.mdweb/src/pages/org/DepartmentStatsBar.tsxweb/src/pages/org/build-org-tree.ts
📚 Learning: 2026-03-14T15:43:05.601Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T15:43:05.601Z
Learning: Applies to docs/** : Docs source in docs/ (Markdown, built with Zensical); design spec in docs/design/ (7 pages: index, agents, organization, communication, engine, memory, operations)
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-15T18:17:43.675Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:17:43.675Z
Learning: Applies to pyproject.toml : Dependencies: all versions use == in pyproject.toml. Groups: test (pytest + plugins, hypothesis), dev (includes test + ruff, mypy, pre-commit, commitizen, pip-audit). Required: mem0ai (Mem0 memory backend — the default and currently only backend). Install: uv sync installs everything (dev group is default).
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-21T12:54:22.557Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-21T12:54:22.557Z
Learning: Go 1.26+ required; CLI dependencies in `cli/go.mod` (Cobra, charmbracelet/huh, charmbracelet/lipgloss, sigstore-go, go-containerregistry, go-tuf)
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-15T18:17:43.675Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:17:43.675Z
Learning: Applies to docker/{Dockerfile*,compose.yml} : Docker: Backend uses 3-stage build (builder → setup → distroless runtime), Chainguard Python, non-root (UID 65532), CIS-hardened. Web uses nginxinc/nginx-unprivileged, Vue 3 SPA with PrimeVue + Tailwind CSS, SPA routing, API/WebSocket proxy to backend.
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-19T11:19:40.044Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T11:19:40.044Z
Learning: Applies to go.mod : Maintain Go 1.26+ requirement. Dependencies: Cobra (CLI framework), charmbracelet/huh and charmbracelet/lipgloss (UI), sigstore-go (code signing), go-containerregistry (container image verification), go-tuf (TUF client for Sigstore).
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-21T14:12:17.848Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-21T14:12:17.848Z
Learning: Applies to cli/go.mod : CLI uses Go 1.26+. Dependencies: Cobra, charmbracelet/huh, charmbracelet/lipgloss, sigstore-go, go-containerregistry, go-tuf
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-15T21:32:02.880Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T21:32:02.880Z
Learning: Applies to cli/**/*.go : Go CLI (Go 1.26+) uses Cobra for commands, charmbracelet/huh for interactive CLI, charmbracelet/lipgloss for styled output. Cross-platform builds (linux/darwin/windows × amd64/arm64). GoReleaser for releases with cosign keyless signing of checksums.txt. SLSA L3 provenance attestations via actions/attest-build-provenance.
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-15T18:17:43.675Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:17:43.675Z
Learning: Applies to cli/** : CLI: Go 1.26+, dependencies in cli/go.mod (Cobra, charmbracelet/huh).
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-27T14:30:49.093Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T14:30:49.093Z
Learning: Applies to web/src/**/*.{ts,tsx} : Do NOT recreate status dots inline -- use `<StatusBadge>`; do NOT build card-with-header layouts from scratch -- use `<SectionCard>`; do NOT create metric displays with hardcoded styles -- use `<MetricCard>`
Applied to files:
web/src/pages/org/OrgChartSkeleton.tsxweb/src/__tests__/pages/org/DepartmentStatsBar.test.tsxweb/src/pages/org/OrgChartSkeleton.stories.tsxweb/src/pages/org/DepartmentStatsBar.tsxweb/src/pages/org/OrgChartToolbar.stories.tsxweb/src/pages/org/CeoNode.tsxweb/src/pages/org/AgentNode.tsxweb/src/pages/org/DepartmentGroupNode.tsxweb/src/pages/org/DepartmentGroupNode.stories.tsxweb/src/pages/org/AgentNode.stories.tsxweb/src/pages/org/DepartmentStatsBar.stories.tsxweb/src/pages/OrgChartPage.tsxweb/src/pages/org/layout.ts
📚 Learning: 2026-03-19T07:13:44.964Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T07:13:44.964Z
Learning: Applies to src/synthorg/hr/**/*.py : HR package (hr/): hiring, firing, onboarding, offboarding, agent registry, performance tracking (task metrics, collaboration scoring, LLM calibration, collaboration overrides, trend detection), promotion/demotion (criteria evaluation, approval strategies, model mapping)
Applied to files:
web/src/pages/org/status-mapping.ts
📚 Learning: 2026-03-16T06:24:56.341Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-16T06:24:56.341Z
Learning: Applies to src/synthorg/hr/**/*.py : HR engine must provide: hiring, firing, onboarding, offboarding, agent registry, performance tracking (task metrics, collaboration scoring, trend detection), promotion/demotion
Applied to files:
web/src/pages/org/status-mapping.ts
📚 Learning: 2026-03-27T14:30:49.093Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T14:30:49.093Z
Learning: Applies to web/src/**/*.stories.tsx : Storybook stories must cover all component states (default, hover, loading, error, empty) and be created alongside the component in `web/src/components/ui/`
Applied to files:
web/src/pages/org/OrgChartSkeleton.stories.tsxweb/src/pages/org/OrgChartToolbar.stories.tsxweb/src/pages/org/DepartmentGroupNode.stories.tsxweb/src/pages/org/NodeContextMenu.stories.tsxweb/src/pages/org/AgentNode.stories.tsxweb/src/pages/org/CeoNode.stories.tsxweb/src/pages/org/DepartmentStatsBar.stories.tsx
📚 Learning: 2026-03-27T14:30:49.093Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T14:30:49.093Z
Learning: Applies to web/src/components/ui/*.tsx : Create new shared components in `web/src/components/ui/` with a descriptive kebab-case filename, a corresponding `.stories.tsx` Storybook file, and a TypeScript interface for props
Applied to files:
web/src/pages/org/OrgChartSkeleton.stories.tsxweb/src/pages/org/OrgChartToolbar.stories.tsxweb/src/__tests__/pages/org/NodeContextMenu.test.tsxweb/src/pages/org/DepartmentGroupNode.stories.tsxweb/src/pages/org/NodeContextMenu.stories.tsxweb/src/pages/org/AgentNode.stories.tsxweb/src/pages/org/CeoNode.stories.tsxweb/src/pages/org/DepartmentStatsBar.stories.tsx
📚 Learning: 2026-03-27T14:30:49.093Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T14:30:49.093Z
Learning: Applies to web/src/**/*.{ts,tsx} : Set `parameters.a11y.test: 'error' | 'todo' | 'off'` in Storybook stories to enforce WCAG compliance (set globally in `preview.tsx`)
Applied to files:
web/src/pages/org/OrgChartSkeleton.stories.tsxweb/src/__tests__/pages/org/OrgChartToolbar.test.tsxweb/src/pages/org/OrgChartToolbar.stories.tsxweb/src/__tests__/pages/org/NodeContextMenu.test.tsxweb/src/pages/org/DepartmentGroupNode.stories.tsxweb/src/pages/org/NodeContextMenu.stories.tsxweb/src/pages/org/OrgChartToolbar.tsxweb/src/pages/org/AgentNode.stories.tsxweb/src/pages/org/CeoNode.stories.tsxweb/src/pages/org/DepartmentStatsBar.stories.tsx
📚 Learning: 2026-03-27T14:30:49.093Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T14:30:49.093Z
Learning: Applies to web/.storybook/**/*.{ts,tsx} : Use Storybook 10+ API: `defineMain` from `storybook/react-vite/node` for `main.ts`, `definePreview` from `storybook/react-vite` for `preview.tsx`, import from `storybook/*` (not `storybook/*`), use `parameters.backgrounds.options` object + `initialGlobals.backgrounds.value`
Applied to files:
web/src/pages/org/OrgChartSkeleton.stories.tsxweb/src/pages/org/OrgChartToolbar.stories.tsxweb/src/pages/org/DepartmentGroupNode.stories.tsxweb/src/pages/org/NodeContextMenu.stories.tsxweb/src/pages/org/AgentNode.stories.tsxweb/src/pages/org/CeoNode.stories.tsxweb/src/pages/org/DepartmentStatsBar.stories.tsx
📚 Learning: 2026-03-27T14:30:49.093Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T14:30:49.093Z
Learning: Applies to web/src/**/*.{ts,tsx} : ALWAYS reuse existing components from `web/src/components/ui/` (StatusBadge, MetricCard, Sparkline, SectionCard, AgentCard, etc.) before creating new ones
Applied to files:
web/src/pages/org/DepartmentStatsBar.tsxweb/src/pages/org/AgentNode.tsxweb/src/pages/org/AgentNode.stories.tsx
📚 Learning: 2026-03-27T14:30:49.093Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T14:30:49.093Z
Learning: Applies to web/src/**/*.{ts,tsx} : Use density-aware spacing tokens (`p-card`, `gap-section-gap`, `gap-grid-gap`) or standard Tailwind spacing; NEVER hardcode pixel values for layout spacing
Applied to files:
web/src/pages/org/CeoNode.tsxweb/src/pages/org/AgentNode.tsxweb/src/pages/org/AgentNode.stories.tsxweb/src/pages/org/layout.ts
📚 Learning: 2026-03-27T14:30:49.093Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T14:30:49.093Z
Learning: Applies to web/src/components/ui/*.tsx : All new shared components must use design tokens exclusively -- no hardcoded colors, fonts, or spacing -- and import `cn` from `@/lib/utils` for conditional class merging
Applied to files:
web/src/pages/org/CeoNode.tsxweb/src/pages/org/AgentNode.tsxweb/src/pages/org/AgentNode.stories.tsxweb/src/pages/OrgChartPage.tsx
📚 Learning: 2026-03-27T14:30:49.093Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T14:30:49.093Z
Learning: Applies to web/src/**/*.{ts,tsx} : Use TypeScript 6.0+ strict mode with proper `tsconfig.json` configuration: remove deprecated `baseUrl`, enable `paths` for imports, explicitly list `types`, use `moduleResolution: 'bundler'`, keep `strict: true`
Applied to files:
web/src/pages/org/CeoNode.tsx
📚 Learning: 2026-03-27T14:30:49.093Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T14:30:49.093Z
Learning: Applies to web/src/**/*.{ts,tsx} : Do NOT create complex (>8 line) JSX inside `.map()` -- extract to a shared component in `web/src/components/ui/`
Applied to files:
web/src/pages/org/AgentNode.tsxweb/src/pages/org/AgentNode.stories.tsxweb/src/pages/OrgChartPage.tsxweb/src/pages/org/layout.ts
🔇 Additional comments (42)
web/src/__tests__/App.test.tsx (1)
59-84: LGTM!The reformatting and explicit per-test timeout of
10_000ms is a sensible improvement for test stability. The buffer between the innerwaitFortimeout (5s) and the overall test timeout (10s) appropriately accounts for lazy-loaded module resolution overhead in concurrent test runs.web/src/__tests__/pages/DashboardPage.test.tsx (3)
64-73: LGTM!Good refactor. The comment accurately explains Vitest's mock hoisting behavior, and converting
renderDashboardto synchronous is correct since dynamic imports are no longer needed. This simplifies the test code.
85-89: LGTM!Using
getByLabelText('Loading dashboard')is more specific thangetByRole('status')since multiple elements could potentially have the status role. The aria-label uniquely identifies the dashboard skeleton, making the assertion more targeted and resilient.
80-144: LGTM!Consistent removal of
awaitacross all test cases. The tests maintain good coverage of component states (loading, error, WebSocket status) and the synchronous pattern is correctly applied throughout.web/package.json (2)
44-55: LGTM!The
@types/d3-hierarchydev dependency addition is appropriate for providing TypeScript types for hierarchy/tree data structures used in the org chart layout utilities.
18-18: Package version is available. The@dagrejs/dagreversion 3.0.0 exists on npm and is valid for use.CLAUDE.md (2)
131-131: LGTM!Documentation correctly updated to reflect the new
companyandagentsZustand stores added for the org chart feature.
323-323: LGTM!Documentation updated to include
@dagrejs/dagrein the web dashboard dependencies, keeping it in sync with theweb/package.jsonchanges.web/src/__tests__/utils/errors.property.test.ts (2)
5-14: LGTM!The axios mock effectively prevents async leaks from the fetch adapter capability detection. The mock correctly provides
isAxiosErroron the default export, which is whataxios.isAxiosError()resolves to in the actual code.Note: The named
isAxiosErrorexport (lines 12-13) is technically redundant sinceerrors.tsonly callsaxios.isAxiosErrorvia the default import wrapper, but having it doesn't cause harm and provides extra safety if the import pattern changes.
16-25: LGTM!The
makeFakeAxiosErrorhelper cleanly creates AxiosError-shaped objects without importing the real class, avoiding the async leak issues. The property test correctly verifies that 5xx error messages never leak response body content — an important security invariant.Also applies to: 37-49
web/src/pages/org/OrgChartSkeleton.tsx (1)
1-30: LGTM!Well-implemented skeleton component that:
- Correctly reuses
SkeletonCardfrom@/components/ui/skeleton- Provides proper accessibility with
role="status",aria-live="polite", andaria-label- Uses standard Tailwind spacing tokens (
gap-6,gap-8,pt-12)- Visually represents the org chart hierarchy structure
web/src/pages/org/OrgChartSkeleton.stories.tsx (1)
1-23: LGTM!Story follows Storybook 10 conventions correctly:
- Uses
satisfies Meta<typeof OrgChartSkeleton>for type safety- Sets
parameters.a11y.test: 'error'for WCAG compliance enforcement- Decorator provides necessary height for the vertical layout
- Past review comment about inline background style was addressed
For a skeleton component, the "Default" story is appropriate since skeletons represent a single loading state rather than multiple interactive states.
web/src/__tests__/pages/org/OrgChartSkeleton.test.tsx (1)
1-20: LGTM!Focused test suite that verifies the critical accessibility attributes of the skeleton component:
role="status"for live region semanticsaria-live="polite"for non-intrusive screen reader announcements- Accessible label text for context
web/src/pages/org/CeoNode.tsx (1)
1-52: LGTM!Well-structured React Flow node component that:
- Correctly reuses
AvatarandStatusBadgefrom@/components/ui/- Uses Tailwind semantic classes (
text-foreground,bg-card,text-muted-foreground,border-accent/30)- Uses
cn()for class merging- Properly memoized for React Flow performance
- Includes accessibility attributes (
data-testid,aria-label)- Uses Tailwind v4 postfix important syntax (
bg-accent!,size-1.5!) correctlyweb/src/pages/org/DepartmentStatsBar.tsx (1)
1-30: LGTM!Clean implementation that:
- Correctly reuses
StatPillfrom@/components/ui/- Defaults
currencyto'USD'to matchcostUsdfield semantics (past review addressed)- Conditionally renders Cost only when
costUsd !== null- Uses
cn()for className merging- Uses standard Tailwind spacing (
gap-1.5)web/src/pages/org/DepartmentStatsBar.stories.tsx (1)
1-48: LGTM!The stories file properly configures accessibility testing (
a11y.test: 'error') and covers the key component states: default with all props, null cost handling, and zero-value edge case. The decorator constrains width for consistent rendering.web/src/pages/org/CeoNode.stories.tsx (1)
1-100: LGTM!Good coverage of all
AgentRuntimeStatusvalues (active, idle, error, offline) with proper ReactFlow context setup. The a11y test configuration is correctly set to'error'.web/src/stores/company.ts (2)
22-30: LGTM!The
fetchCompanyDataimplementation correctly manages loading state, clears previous errors on start, and properly handles both success and failure paths.
32-51: LGTM!The department health fetch correctly:
- Guards against missing config
- Uses
.catch(() => null)to allow partial success- Filters out failed results
- Sets an appropriate error when all departments fail
web/src/__tests__/stores/company.test.ts (2)
30-47: LGTM!Good test isolation with
beforeEachresetting store state to match the production initial state, andvi.clearAllMocks()ensuring no state leaks between tests.
80-97: LGTM!Good coverage of partial failure handling - verifies that when one department health fetch fails, the successful result is still stored and the failed one is filtered out.
web/src/styles/global.css (1)
7-7: LGTM!Importing React Flow's base styles is required for proper node/edge rendering and is correctly placed in the global stylesheet.
web/src/pages/org/HierarchyEdge.tsx (1)
1-27: LGTM!Clean edge component implementation with proper memoization for React Flow performance. The stroke color correctly uses the CSS variable
var(--color-border-bright)defined inglobal.css, maintaining theme consistency.web/src/__tests__/pages/org/DepartmentStatsBar.test.tsx (1)
17-31: LGTM!Good coverage of conditional rendering for the cost section and the
data-testidattribute for integration testing.web/src/pages/org/status-mapping.ts (1)
1-30: LGTM!Clean utility module with well-documented functions. The switch statement handles all
AgentStatusvariants with appropriate fall-through foronboarding/active, andresolveRuntimeStatuscorrectly prioritizes WebSocket-pushed status over the HR-derived default.web/src/__tests__/pages/org/OrgChartToolbar.test.tsx (1)
1-52: LGTM!The test suite is well-structured with the
createProps()factory function properly creating fresh mock instances per test, avoiding state leakage between tests. Good coverage of toolbar rendering and interaction handlers.web/src/__tests__/pages/org/layout.test.ts (1)
1-104: LGTM!Comprehensive test coverage for
applyDagreLayoutincluding empty inputs, position validation, sibling separation, directional ordering, department node handling, and graceful handling of dangling edges. The test descriptions accurately reflect the assertions.web/src/__tests__/stores/agents.test.ts (1)
416-471: LGTM!Excellent test coverage for the new runtime status functionality. The tests properly validate both the happy path (
updateRuntimeStatus, valid WS events) and defensive cases (missingagent_id, missingstatus, invalid status values, non-status event types). This ensures robust handling of malformed WebSocket payloads.web/src/stores/agents.ts (1)
216-235: LGTM!The runtime status actions are well-implemented with proper defensive validation:
updateRuntimeStatusprovides direct state updatesupdateFromWsEventvalidates event type, checks for required string fields, and validates status against the allowlist before updating stateThe type assertion on Line 232 is safe because the
VALID_RUNTIME_STATUSES.has(status)check guarantees the value is a validAgentRuntimeStatus.web/src/pages/org/NodeContextMenu.stories.tsx (1)
1-48: LGTM!Good story coverage for all three node types (
agent,department,ceo) with proper accessibility testing configuration (a11y.test: 'error'). The decorator provides appropriate container sizing for the context menu positioning.web/src/__tests__/pages/org/status-mapping.test.ts (1)
1-43: LGTM!Comprehensive test coverage for both status mapping functions. The edge case test at Line 39-42 (runtime override precedence over HR
terminatedstatus) is particularly valuable, documenting the expected behavior when WebSocket and HR data conflict.web/src/pages/org/DepartmentGroupNode.tsx (2)
1-51: LGTM!Clean implementation following coding guidelines:
- Uses semantic Tailwind classes (
text-foreground,text-muted-foreground,bg-card/50)- Proper typography classes (
font-sans,font-mono)- Correctly handles nullable
healthPercentandtaskCountfields- Memoized for React Flow performance
The health color mapping and fallback logic is well-structured with the
HEALTH_BG_CLASSESlookup.
35-35:text-microis properly defined in the Tailwind configuration.The class is generated via the
@theme inlinedirective inweb/src/styles/global.css, which declares--font-size-micro: var(--so-text-micro). Tailwind's@thememechanism automatically creates the.text-microutility from this declaration, and it's correctly backed by the design token--so-text-micro: 10pxindesign-tokens.css. No action needed.> Likely an incorrect or invalid review comment.web/src/pages/org/AgentNode.tsx (1)
1-60: LGTM!The component correctly:
- Reuses
StatusBadgeandAvatarfrom shared UI components- Uses semantic Tailwind classes (
text-foreground,bg-card,border-border)- Applies standard Tailwind spacing (
min-w-36,max-w-44,px-3,py-2)- Provides accessible
aria-labelwith agent context- Maps all possible
getStatusColorreturn values inSTATUS_RING_CLASSESThe previous concern about hardcoded pixel widths has been properly addressed.
web/src/__tests__/pages/org/OrgChartPage.test.tsx (1)
1-143: LGTM!The test suite provides solid coverage for
OrgChartPageUI states:
- Loading skeleton display
- Empty state handling
- Error banner rendering
- WebSocket disconnect warnings
- Conditional rendering when nodes exist
- Edge case: skeleton hidden when loading with existing nodes
The mock pattern with module-level variables reset in
beforeEachensures test isolation.web/src/pages/org/AgentNode.stories.tsx (1)
55-69: Good coverage of runtime status variants.The stories appropriately cover all
runtimeStatusstates (active,idle,error,offline) that drive the component's visual behavior (ring color, opacity, pulse animation).web/src/pages/org/OrgChartToolbar.tsx (1)
1-88: LGTM!The toolbar implementation is clean and accessible:
- Proper toggle button pattern with
aria-pressedstate- All buttons have descriptive
aria-labelattributes- Icons marked
aria-hidden="true"- Reuses the shared
Buttoncomponent- Uses semantic Tailwind classes throughout
web/src/hooks/useOrgChartData.ts (1)
69-75: LGTM!The graph derivation is properly memoized with correct dependencies. The computation only reruns when
config,runtimeStatuses, ordepartmentHealthschange.web/src/pages/org/DepartmentGroupNode.stories.tsx (1)
47-87: Good coverage of health status variants.The stories appropriately cover the three health tiers (Healthy at 92%, Warning at 45%, Critical at 15%) and include the edge case where
costUsd: nullsuppresses cost display.web/src/pages/org/NodeContextMenu.tsx (1)
1-154: LGTM!The component addresses all previous review concerns:
- CEO nodes have dedicated menu items (lines 99-108)
- Buttons have explicit
type="button"(line 139)- Type cast uses
Nodeforcontains()check (line 48)- Menu has descriptive
aria-labelbased on node type (line 133)- Position clamping handles all viewport edges with
Math.max/Math.min(lines 120-121)- Menu labels distinguish between agent, CEO, and department
Accessibility is solid with
role="menu",role="menuitem", and properaria-label.web/src/__tests__/pages/org/NodeContextMenu.test.tsx (1)
1-107: LGTM!The test suite provides comprehensive coverage:
- Tests for all node types (
agent,department,ceo)- Callback verification (
onViewDetails,onDelete)- Close behavior (Escape key, outside click)
- ARIA structure validation
- Property-based testing with
fast-checkverifying menu invariants across all node typesPrevious concerns about mock reset,
beforeEachimport, and outside-click testing have all been addressed.web/src/pages/OrgChartPage.tsx (1)
120-129: No changes needed – NodeContextMenu usesposition: fixedwhich correctly aligns with viewport-relative coordinates fromevent.clientX/Y.The menu is already positioned fixed to the viewport, so
clientX/Ycoordinates are appropriate. The implementation also includes viewport-bounds clamping to prevent overflow.> Likely an incorrect or invalid review comment.
| } else if (head && agent.id !== head.id) { | ||
| // Agent reports to department head | ||
| edges.push({ | ||
| id: `e-${head.id}-${agent.id}`, | ||
| source: head.id, | ||
| target: agent.id, | ||
| type: 'hierarchy', | ||
| }) |
There was a problem hiding this comment.
Don't turn equal-seniority peers into manager/subordinate links.
This fallback attaches every non-team member to head, even when head only won a same-level tie by array order. In departments like [CEO, CTO, CFO] or [VP A, VP B], that makes one peer appear to manage another with no supporting data.
🧭 Minimal safeguard
- } else if (head && agent.id !== head.id) {
+ } else if (
+ head &&
+ agent.id !== head.id &&
+ seniorityOf(agent.level) < seniorityOf(head.level)
+ ) {
// Agent reports to department head
edges.push({
id: `e-${head.id}-${agent.id}`,
source: head.id,
target: agent.id,
type: 'hierarchy',
})
}This avoids fabricating peer-to-peer reporting lines. You can then decide separately whether equal-seniority peers should stay unparented or become direct reports via explicit business rules.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@web/src/pages/org/build-org-tree.ts` around lines 168 - 175, The current
fallback creates a hierarchy edge for any non-team member (using head, agent,
edges and id `e-${head.id}-${agent.id}`) even when head and agent are same
seniority; change the condition so you only push that edge when head has
strictly higher seniority/level than agent (e.g., check head.level > agent.level
or head.seniority > agent.seniority), and skip creating the manager/subordinate
link when levels are equal (leave peers unparented or handle via explicit
business-rule function like determineReportingRelationship(head, agent) if
needed).
| function Wrapper({ data }: { data: DepartmentGroupData }) { | ||
| return ( | ||
| <ReactFlowProvider> | ||
| <div style={{ width: 500, height: 200 }}> |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
Replace hardcoded inline dimensions with Tailwind sizing classes.
The wrapper container uses hardcoded pixel values in inline styles.
♻️ Proposed fix
- <div style={{ width: 500, height: 200 }}>
+ <div className="h-52 w-[500px]">Note: The node's style prop (line 19) may need to remain as React Flow uses explicit dimensions for node sizing.
As per coding guidelines: Use density-aware spacing tokens or standard Tailwind spacing; NEVER hardcode pixel values for layout spacing.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@web/src/pages/org/DepartmentGroupNode.stories.tsx` at line 11, The wrapper
div in DepartmentGroupNode.stories.tsx uses hardcoded inline pixel styles
(width: 500, height: 200); replace those inline styles with appropriate Tailwind
sizing classes on that wrapper (e.g., use density-aware / standard Tailwind
tokens such as w-96 h-48 or the project-specific spacing tokens) by removing the
style={{ width: 500, height: 200 }} and adding a className with the chosen
Tailwind sizes; keep the node's own style prop (the React Flow node style
mentioned in the comment) as-is since React Flow requires explicit node
dimensions.
| updateFromWsEvent: (event) => { | ||
| // Handle agent lifecycle events that affect company structure | ||
| if (event.event_type === 'agent.hired' || event.event_type === 'agent.fired') { | ||
| // Re-fetch company config to get updated agent list | ||
| const store = useCompanyStore.getState() | ||
| store.fetchCompanyData() | ||
| .then(() => store.fetchDepartmentHealths()) | ||
| .catch(() => { | ||
| // Errors are set in store state by the respective fetch methods | ||
| }) | ||
| } | ||
| }, |
There was a problem hiding this comment.
Rapid WebSocket events can trigger concurrent fetches causing race conditions.
Per the dispatchEvent implementation in web/src/stores/websocket.ts (lines 93-104), channel handlers are invoked synchronously without throttling. Multiple agent.hired/agent.fired events arriving in quick succession will trigger concurrent fetchCompanyData → fetchDepartmentHealths chains, potentially causing stale responses to overwrite fresher data.
Consider debouncing or adding a fetch-in-progress guard:
🛡️ Proposed fix with in-flight guard
+ _fetchInProgress: false,
+
updateFromWsEvent: (event) => {
// Handle agent lifecycle events that affect company structure
if (event.event_type === 'agent.hired' || event.event_type === 'agent.fired') {
+ if (useCompanyStore.getState()._fetchInProgress) return
+ set({ _fetchInProgress: true })
// Re-fetch company config to get updated agent list
const store = useCompanyStore.getState()
store.fetchCompanyData()
.then(() => store.fetchDepartmentHealths())
- .catch(() => {
+ .finally(() => set({ _fetchInProgress: false }))
+ .catch(() => {
// Errors are set in store state by the respective fetch methods
})
}
},🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@web/src/stores/company.ts` around lines 53 - 64, The websocket handler
updateFromWsEvent triggers concurrent fetchCompanyData → fetchDepartmentHealths
chains; add a fetch-in-progress guard or debounce in the company store to
serialize these calls: introduce a boolean (e.g., isFetchingCompany) or a simple
mutex in the store used by updateFromWsEvent (obtained via
useCompanyStore.getState()) so if a fetch is already running you either skip
starting another fetch or coalesce subsequent events, and ensure
fetchCompanyData awaits completion before calling fetchDepartmentHealths; update
updateFromWsEvent to check/set the guard and to clear it on success/failure to
prevent race conditions and stale overwrites.
…live regions - Add regression test for same-level peer tiebreaker (first-in-array wins) - Consolidate DepartmentStatsBar tests into single render - Assert fetchDepartmentHealths is called after WS agent events - Start health polling only after initial fetchCompanyData completes - Add role="alert" and role="status" aria-live to error/warning banners Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (1)
web/src/pages/OrgChartPage.tsx (1)
264-264: 🧹 Nitpick | 🔵 TrivialUse the canonical
var(--so-border)token.Per coding guidelines, use
var(--so-*)CSS variables directly rather than intermediate variables like--color-border.🎨 Suggested fix
- <Background color="var(--color-border)" gap={24} size={1} /> + <Background color="var(--so-border)" gap={24} size={1} />As per coding guidelines: "Use Tailwind semantic classes (
text-foreground,bg-card,text-accent, etc.) or CSS variables (var(--so-*)) for colors; NEVER hardcode hex or rgba values"🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@web/src/pages/OrgChartPage.tsx` at line 264, The Background component in OrgChartPage.tsx is using the non-canonical CSS variable --color-border; update the prop to use the canonical semantic token var(--so-border) instead (keep the same props gap={24} and size={1}) so the line reads Background color uses var(--so-border) to conform with the so-* token guideline.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@web/src/__tests__/pages/org/DepartmentStatsBar.test.tsx`:
- Around line 17-21: Add a test in DepartmentStatsBar.test.tsx that verifies the
optional currency prop is forwarded to formatCurrency: render
<DepartmentStatsBar agentCount={5} activeCount={3} taskCount={8} costUsd={100}
currency="EUR" /> (or another value), then assert
screen.getByText(formatCurrency(100, 'EUR')) and screen.getByText('Cost') are in
the document; this ensures DepartmentStatsBar and formatCurrency are exercised
with a non-default currency.
In `@web/src/hooks/useOrgChartData.ts`:
- Around line 51-61: The bindings in useOrgChartData are subscribing to
ORG_CHANNELS including the 'system' channel even though
useCompanyStore.updateFromWsEvent and useAgentsStore.updateFromWsEvent only
handle agent-related events; remove the unused subscription by filtering
ORG_CHANNELS to only include the 'agents' channel (or adjust ORG_CHANNELS
definition) before mapping to ChannelBinding so the handler in useOrgChartData
only subscribes to channels that those updateFromWsEvent methods actually
process.
---
Duplicate comments:
In `@web/src/pages/OrgChartPage.tsx`:
- Line 264: The Background component in OrgChartPage.tsx is using the
non-canonical CSS variable --color-border; update the prop to use the canonical
semantic token var(--so-border) instead (keep the same props gap={24} and
size={1}) so the line reads Background color uses var(--so-border) to conform
with the so-* token guideline.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 0a6d3c05-339c-4bb6-81a7-7703012ed6ed
📒 Files selected for processing (5)
web/src/__tests__/pages/org/DepartmentStatsBar.test.tsxweb/src/__tests__/pages/org/build-org-tree.test.tsweb/src/__tests__/stores/company.test.tsweb/src/hooks/useOrgChartData.tsweb/src/pages/OrgChartPage.tsx
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
- GitHub Check: Dashboard Test
- GitHub Check: Build Backend
- GitHub Check: Build Web
- GitHub Check: Build Sandbox
- GitHub Check: Dependency Review
- GitHub Check: Analyze (python)
🧰 Additional context used
📓 Path-based instructions (1)
web/src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
web/src/**/*.{ts,tsx}: ALWAYS reuse existing components fromweb/src/components/ui/(StatusBadge, MetricCard, Sparkline, SectionCard, AgentCard, etc.) before creating new ones
Use Tailwind semantic classes (text-foreground,bg-card,text-accent, etc.) or CSS variables (var(--so-*)) for colors; NEVER hardcode hex or rgba values
Usefont-sansorfont-monofor typography; NEVER setfontFamilydirectly in component code
Use density-aware spacing tokens (p-card,gap-section-gap,gap-grid-gap) or standard Tailwind spacing; NEVER hardcode pixel values for layout spacing
Use token variables for shadows and borders (var(--so-shadow-card-hover),border-border,border-bright); NEVER hardcode values
Do NOT recreate status dots inline -- use<StatusBadge>; do NOT build card-with-header layouts from scratch -- use<SectionCard>; do NOT create metric displays with hardcoded styles -- use<MetricCard>
Do NOT create complex (>8 line) JSX inside.map()-- extract to a shared component inweb/src/components/ui/
Use TypeScript 6.0+ strict mode with propertsconfig.jsonconfiguration: remove deprecatedbaseUrl, enablepathsfor imports, explicitly listtypes, usemoduleResolution: 'bundler', keepstrict: true
Setparameters.a11y.test: 'error' | 'todo' | 'off'in Storybook stories to enforce WCAG compliance (set globally inpreview.tsx)
Files:
web/src/__tests__/pages/org/DepartmentStatsBar.test.tsxweb/src/hooks/useOrgChartData.tsweb/src/pages/OrgChartPage.tsxweb/src/__tests__/pages/org/build-org-tree.test.tsweb/src/__tests__/stores/company.test.ts
🧠 Learnings (10)
📓 Common learnings
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T21:20:09.993Z
Learning: Applies to web/src/components/** : Vue components organized by feature (agents/, approvals/, budget/, common/, dashboard/, layout/, messages/, org-chart/, tasks/).
📚 Learning: 2026-03-20T08:28:32.845Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-20T08:28:32.845Z
Learning: Applies to web/src/__tests__/**/*.{ts,js} : Dashboard testing: Vitest unit tests organized by feature under `web/src/__tests__/`. Use fast-check for property-based testing (`fc.assert` + `fc.property`).
Applied to files:
web/src/__tests__/pages/org/DepartmentStatsBar.test.tsxweb/src/__tests__/pages/org/build-org-tree.test.tsweb/src/__tests__/stores/company.test.ts
📚 Learning: 2026-03-27T14:30:49.093Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T14:30:49.093Z
Learning: Applies to web/src/**/*.{ts,tsx} : Do NOT recreate status dots inline -- use `<StatusBadge>`; do NOT build card-with-header layouts from scratch -- use `<SectionCard>`; do NOT create metric displays with hardcoded styles -- use `<MetricCard>`
Applied to files:
web/src/__tests__/pages/org/DepartmentStatsBar.test.tsxweb/src/pages/OrgChartPage.tsx
📚 Learning: 2026-03-27T14:30:49.093Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T14:30:49.093Z
Learning: Applies to web/src/components/ui/*.tsx : Create new shared components in `web/src/components/ui/` with a descriptive kebab-case filename, a corresponding `.stories.tsx` Storybook file, and a TypeScript interface for props
Applied to files:
web/src/__tests__/pages/org/DepartmentStatsBar.test.tsx
📚 Learning: 2026-03-15T21:20:09.993Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T21:20:09.993Z
Learning: Applies to web/src/components/** : Vue components organized by feature (agents/, approvals/, budget/, common/, dashboard/, layout/, messages/, org-chart/, tasks/).
Applied to files:
web/src/__tests__/pages/org/DepartmentStatsBar.test.tsx
📚 Learning: 2026-03-27T14:30:49.093Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T14:30:49.093Z
Learning: Applies to web/src/**/*.{ts,tsx} : Do NOT create complex (>8 line) JSX inside `.map()` -- extract to a shared component in `web/src/components/ui/`
Applied to files:
web/src/pages/OrgChartPage.tsx
📚 Learning: 2026-03-27T14:30:49.093Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T14:30:49.093Z
Learning: Applies to web/src/**/*.{ts,tsx} : Use token variables for shadows and borders (`var(--so-shadow-card-hover)`, `border-border`, `border-bright`); NEVER hardcode values
Applied to files:
web/src/pages/OrgChartPage.tsx
📚 Learning: 2026-03-27T14:30:49.093Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T14:30:49.093Z
Learning: Applies to web/src/**/*.{ts,tsx} : Use Tailwind semantic classes (`text-foreground`, `bg-card`, `text-accent`, etc.) or CSS variables (`var(--so-*)`) for colors; NEVER hardcode hex or rgba values
Applied to files:
web/src/pages/OrgChartPage.tsx
📚 Learning: 2026-03-27T14:30:49.093Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T14:30:49.093Z
Learning: Applies to web/src/components/ui/*.tsx : All new shared components must use design tokens exclusively -- no hardcoded colors, fonts, or spacing -- and import `cn` from `@/lib/utils` for conditional class merging
Applied to files:
web/src/pages/OrgChartPage.tsx
📚 Learning: 2026-03-27T14:30:49.093Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-27T14:30:49.093Z
Learning: Applies to web/src/**/*.{ts,tsx} : Set `parameters.a11y.test: 'error' | 'todo' | 'off'` in Storybook stories to enforce WCAG compliance (set globally in `preview.tsx`)
Applied to files:
web/src/pages/OrgChartPage.tsx
🔇 Additional comments (11)
web/src/__tests__/pages/org/DepartmentStatsBar.test.tsx (2)
7-15: LGTM! Previous feedback addressed.The consolidated test correctly implements the refactor suggested in the previous review: a single render with multiple assertions for all stat values and labels. This is more efficient than the previous parameterized approach while maintaining full coverage.
1-32: Well-structured test suite.The test suite appropriately covers the component's functionality:
- ✅ All stat pills render with correct values and labels
- ✅ Cost conditional rendering (present when provided, absent when null)
- ✅ Data-testid presence
- ✅ Correct use of
getByTextfor presence andqueryByTextfor absence assertions- ✅ Integration with
formatCurrencyutility matches component implementationweb/src/__tests__/stores/company.test.ts (1)
1-142: LGTM!The test suite provides comprehensive coverage for
useCompanyStore:
- Initial state verification
fetchCompanyDatasuccess and failure pathsfetchDepartmentHealthswith config present, missing, and partial failuresupdateFromWsEventbehavior for agent lifecycle events (now correctly verifying bothgetCompanyConfigandgetDepartmentHealthare called) and unrelated eventsThe previous review comment about verifying the full re-fetch chain has been addressed in lines 99-131.
web/src/__tests__/pages/org/build-org-tree.test.ts (1)
1-332: LGTM!Comprehensive test suite covering all key behaviors of
buildOrgTree:
- CEO identification with multiple fallback strategies
- Department grouping and agent nesting via
parentId- Edge generation for hierarchy relationships
- Filtering of terminated agents
- Health data enrichment and runtime status overrides
- Team-based hierarchy derivation with deduplication
The previous review comments have been addressed:
- Lines 158-175 add the regression test for same-level peer tie-breaking
- Lines 307-317 no longer have the redundant spread assignment
web/src/hooks/useOrgChartData.ts (2)
36-48: Sequencing and polling initialization look correct.The initial fetch correctly:
- Calls
fetchCompanyData()first- Only calls
fetchDepartmentHealths()ifconfigexists (line 41)- Starts polling after initial fetch completes (line 44)
- Stops polling on unmount (line 46)
This addresses the previous review comments about fetch sequencing and polling races.
47-47: The ESLint rule name in the disable comment is correct. The codebase uses@eslint-react/eslint-plugin(as documented inweb/eslint.config.jslines 7-8), noteslint-plugin-react-hooks. The@eslint-react/exhaustive-depsrule is the valid rule name for this configuration and is used consistently across multiple files in the codebase. No change is needed.> Likely an incorrect or invalid review comment.web/src/pages/OrgChartPage.tsx (5)
43-49: Good defensive pattern for extracting agent name.The
getAgentNamehelper correctly validates the node type and checks thatnameis a string before returning, preventing runtime errors from malformed node data. This addresses the previous review comment about adding a runtime guard.
174-187: View mode change handler correctly gates the unimplemented communication view.The handler returns early for
mode === 'force'without callingsetViewMode, keeping the toolbar state consistent with the rendered view. This addresses the previous review comment.
221-232: Accessibility attributes correctly applied to error banners.The error banner uses
role="alert"(line 222) and the WebSocket warning usesrole="status"witharia-live="polite"(line 228), ensuring screen readers announce these async failures. This addresses the previous review comment about announcing failures to assistive tech.
296-301: Correct Button/Link composition usingasChild.The
asChildprop correctly delegates rendering to theLinkchild, avoiding nested interactive elements. This addresses the previous review comment about invalid HTML semantics.
51-53: Stable reference identity for node/edge types.Declaring
nodeTypesandedgeTypesoutside the component prevents unnecessary re-renders of the ReactFlow canvas. This is a React Flow best practice.
…bscription - DepartmentStatsBar: add test for explicit currency prop forwarding - useOrgChartData: remove 'system' from ORG_CHANNELS since neither store handler processes system channel events Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
🤖 I have created a release *beep* *boop* --- #MAJOR CHANGES; We got a somewhat working webui :) ## [0.5.0](v0.4.9...v0.5.0) (2026-03-30) ### Features * add analytics trends and budget forecast API endpoints ([#798](#798)) ([16b61f5](16b61f5)) * add department policies to default templates ([#852](#852)) ([7a41548](7a41548)) * add remaining activity event types (task_started, tool_used, delegation, cost_incurred) ([#832](#832)) ([4252fac](4252fac)) * agent performance, activity, and history API endpoints ([#811](#811)) ([9b75c1d](9b75c1d)) * Agent Profiles and Detail pages (biography, career, performance) ([#874](#874)) ([62d7880](62d7880)) * app shell, Storybook, and CI/CD pipeline ([#819](#819)) ([d4dde90](d4dde90)) * Approvals page with risk grouping, urgency indicators, batch actions ([#889](#889)) ([4e9673d](4e9673d)) * Budget Panel page (P&L dashboard, breakdown charts, forecast) ([#890](#890)) ([b63b0f1](b63b0f1)) * build infrastructure layer (API client, auth, WebSocket) ([#815](#815)) ([9f01d3e](9f01d3e)) * CLI global options infrastructure, UI modes, exit codes, env vars ([#891](#891)) ([fef4fc5](fef4fc5)) * CodeMirror editor and theme preferences toggle ([#905](#905), [#807](#807)) ([#909](#909)) ([41fbedc](41fbedc)) * Company page (department/agent management) ([#888](#888)) ([cfb88b0](cfb88b0)) * comprehensive hint coverage across all CLI commands ([#900](#900)) ([937974e](937974e)) * config system extensions, per-command flags for init/start/stop/status/logs ([#895](#895)) ([32f83fe](32f83fe)) * configurable currency system replacing hardcoded USD ([#854](#854)) ([b372551](b372551)) * Dashboard page (metric cards, activity feed, budget burn) ([#861](#861)) ([7d519d5](7d519d5)) * department health, provider status, and activity feed endpoints ([#818](#818)) ([6d5f196](6d5f196)) * design tokens and core UI components ([#833](#833)) ([ed887f2](ed887f2)) * extend approval, meeting, and budget API responses ([#834](#834)) ([31472bf](31472bf)) * frontend polish -- real-time UX, accessibility, responsive, performance ([#790](#790), [#792](#792), [#791](#791), [#793](#793)) ([#917](#917)) ([f04a537](f04a537)) * implement human roles and access control levels ([#856](#856)) ([d6d8a06](d6d8a06)) * implement semantic conflict detection in workspace merge ([#860](#860)) ([d97283b](d97283b)) * interaction components and animation patterns ([#853](#853)) ([82d4b01](82d4b01)) * Login page + first-run bootstrap + Company page ([#789](#789), [#888](#888)) ([#896](#896)) ([8758e8d](8758e8d)) * Meetings page with timeline viz, token bars, contribution formatting ([#788](#788)) ([#904](#904)) ([b207f46](b207f46)) * Messages page with threading, channel badges, sender indicators ([#787](#787)) ([#903](#903)) ([28293ad](28293ad)) * Org Chart force-directed view and drag-drop reassignment ([#872](#872), [#873](#873)) ([#912](#912)) ([a68a938](a68a938)) * Org Chart page (living nodes, status, CRUD, department health) ([#870](#870)) ([0acbdae](0acbdae)) * per-command flags for remaining commands, auto-behavior wiring, help/discoverability ([#897](#897)) ([3f7afa2](3f7afa2)) * Providers page with backend rework -- health, CRUD, subscription auth ([#893](#893)) ([9f8dd98](9f8dd98)) * scaffold React + Vite + TypeScript + Tailwind project ([#799](#799)) ([bd151aa](bd151aa)) * Settings page with search, dependency indicators, grouped rendering ([#784](#784)) ([#902](#902)) ([a7b9870](a7b9870)) * Setup Wizard rebuild with template comparison, cost estimator, theme customization ([#879](#879)) ([ae8b50b](ae8b50b)) * setup wizard UX -- template filters, card metadata, provider form reuse ([#910](#910)) ([7f04676](7f04676)) * setup wizard UX overhaul -- mode choice, step reorder, provider fixes ([#907](#907)) ([ee964c4](ee964c4)) * structured ModelRequirement in template agent configs ([#795](#795)) ([7433548](7433548)) * Task Board page (rich Kanban, filtering, dependency viz) ([#871](#871)) ([04a19b0](04a19b0)) ### Bug Fixes * align frontend types with backend and debounce WS refetches ([#916](#916)) ([134c11b](134c11b)) * auto-cleanup targets newly pulled images instead of old ones ([#884](#884)) ([50e6591](50e6591)) * correct wipe backup-skip flow and harden error handling ([#808](#808)) ([c05860f](c05860f)) * improve provider setup in wizard, subscription auth, dashboard bugs ([#914](#914)) ([87bf8e6](87bf8e6)) * improve update channel detection and add config get command ([#814](#814)) ([6b137f0](6b137f0)) * resolve all ESLint warnings, add zero-warnings enforcement ([#899](#899)) ([079b46a](079b46a)) * subscription auth uses api_key, base URL optional for cloud providers ([#915](#915)) ([f0098dd](f0098dd)) ### Refactoring * semantic analyzer cleanup -- shared filtering, concurrency, extraction ([#908](#908)) ([81372bf](81372bf)) ### Documentation * brand identity and UX design system from [#765](#765) exploration ([#804](#804)) ([389a9f4](389a9f4)) * page structure and information architecture for v0.5.0 dashboard ([#809](#809)) ([f8d6d4a](f8d6d4a)) * write UX design guidelines with WCAG-verified color system ([#816](#816)) ([4a4594e](4a4594e)) ### Tests * add unit tests for agent hooks and page components ([#875](#875)) ([#901](#901)) ([1d81546](1d81546)) ### CI/CD * bump actions/deploy-pages from 4.0.5 to 5.0.0 in the major group ([#831](#831)) ([01c19de](01c19de)) * bump astral-sh/setup-uv from 7.6.0 to 8.0.0 in /.github/actions/setup-python-uv in the all group ([#920](#920)) ([5f6ba54](5f6ba54)) * bump codecov/codecov-action from 5.5.3 to 6.0.0 in the major group ([#868](#868)) ([f22a181](f22a181)) * bump github/codeql-action from 4.34.1 to 4.35.0 in the all group ([#883](#883)) ([87a4890](87a4890)) * bump sigstore/cosign-installer from 4.1.0 to 4.1.1 in the minor-and-patch group ([#830](#830)) ([7a69050](7a69050)) * bump the all group with 3 updates ([#923](#923)) ([ff27c8e](ff27c8e)) * bump wrangler from 4.76.0 to 4.77.0 in /.github in the minor-and-patch group ([#822](#822)) ([07d43eb](07d43eb)) * bump wrangler from 4.77.0 to 4.78.0 in /.github in the all group ([#882](#882)) ([f84118d](f84118d)) ### Maintenance * add design system enforcement hook and component inventory ([#846](#846)) ([15abc43](15abc43)) * add dev-only auth bypass for frontend testing ([#885](#885)) ([6cdcd8a](6cdcd8a)) * add pre-push rebase check hook ([#855](#855)) ([b637a04](b637a04)) * backend hardening -- eviction/size-caps and model validation ([#911](#911)) ([81253d9](81253d9)) * bump axios from 1.13.6 to 1.14.0 in /web in the all group across 1 directory ([#922](#922)) ([b1b0232](b1b0232)) * bump brace-expansion from 5.0.4 to 5.0.5 in /web ([#862](#862)) ([ba4a565](ba4a565)) * bump eslint-plugin-react-refresh from 0.4.26 to 0.5.2 in /web ([#801](#801)) ([7574bb5](7574bb5)) * bump faker from 40.11.0 to 40.11.1 in the minor-and-patch group ([#803](#803)) ([14d322e](14d322e)) * bump https://github.com/astral-sh/ruff-pre-commit from v0.15.7 to 0.15.8 ([#864](#864)) ([f52901e](f52901e)) * bump nginxinc/nginx-unprivileged from `6582a34` to `f99cc61` in /docker/web in the all group ([#919](#919)) ([df85e4f](df85e4f)) * bump nginxinc/nginx-unprivileged from `ccbac1a` to `6582a34` in /docker/web ([#800](#800)) ([f4e9450](f4e9450)) * bump node from `44bcbf4` to `71be405` in /docker/sandbox ([#827](#827)) ([91bec67](91bec67)) * bump node from `5209bca` to `cf38e1f` in /docker/web ([#863](#863)) ([66d6043](66d6043)) * bump picomatch in /site ([#842](#842)) ([5f20bcc](5f20bcc)) * bump recharts 2->3 and @types/node 22->25 in /web ([#802](#802)) ([a908800](a908800)) * Bump requests from 2.32.5 to 2.33.0 ([#843](#843)) ([41daf69](41daf69)) * bump smol-toml from 1.6.0 to 1.6.1 in /site ([#826](#826)) ([3e5dbe4](3e5dbe4)) * bump the all group with 3 updates ([#921](#921)) ([7bace0b](7bace0b)) * bump the minor-and-patch group across 1 directory with 2 updates ([#829](#829)) ([93e611f](93e611f)) * bump the minor-and-patch group across 1 directory with 3 updates ([#841](#841)) ([7010c8e](7010c8e)) * bump the minor-and-patch group across 1 directory with 3 updates ([#869](#869)) ([548cee5](548cee5)) * bump the minor-and-patch group in /site with 2 updates ([#865](#865)) ([9558101](9558101)) * bump the minor-and-patch group with 2 updates ([#867](#867)) ([4830706](4830706)) * consolidate Dependabot groups to 1 PR per ecosystem ([06d2556](06d2556)) * consolidate Dependabot groups to 1 PR per ecosystem ([#881](#881)) ([06d2556](06d2556)) * improve worktree skill with full dep sync and status enhancements ([#906](#906)) ([772c625](772c625)) * remove Vue remnants and document framework decision ([#851](#851)) ([bf2adf6](bf2adf6)) * update web dependencies and fix brace-expansion CVE ([#880](#880)) ([a7a0ed6](a7a0ed6)) * upgrade to Storybook 10 and TypeScript 6 ([#845](#845)) ([52d95f2](52d95f2)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Summary
@xyflow/reactv12) showing a living organizational diagram with real-time agent status@dagrejs/dagrehierarchical tree layout -- no manual positioning neededuseCompanyStore(company config + department health),useAgentsStore(runtime status from WebSocket)useOrgChartDatacomposite hook followinguseDashboardDatapattern (stores + WS + polling)buildOrgTree(derives hierarchy from seniority + teams),applyDagreLayout,resolveRuntimeStatusPre-reviewed by 5 agents, 15 findings addressed
Test plan
npm --prefix web run type-check-- 0 errorsnpm --prefix web run lint-- 0 errors (1 pre-existing warning)npm --prefix web run test-- 683 tests pass (48 new)npm --prefix web run storybook-- verify AgentNode, CeoNode, DepartmentGroupNode, Toolbar, Skeleton storiesnpm --prefix web run dev-- navigate to/org, verify chart renders with mock/real data/agents/:nameCloses #778
Closes #674
🤖 Generated with Claude Code