Skip to content

feat: Login page + first-run bootstrap + Company page (#789, #888)#896

Merged
Aureliolo merged 9 commits intomainfrom
feat/first-run-flow
Mar 28, 2026
Merged

feat: Login page + first-run bootstrap + Company page (#789, #888)#896
Aureliolo merged 9 commits intomainfrom
feat/first-run-flow

Conversation

@Aureliolo
Copy link
Copy Markdown
Owner

Summary

Test plan

  • 10933 Python tests pass (8 new: bootstrap unit tests, _maybe_bootstrap_agents tests, provider reload test, integration test)
  • 1467 Vitest tests pass (1 new pristine-save test, 1 App.test fix)
  • mypy strict -- no issues in 1230 files
  • TypeScript type-check clean
  • ESLint clean (0 errors)
  • ruff lint + format clean
  • Pre-commit + pre-push hooks pass
  • Integration test: full first-run flow (admin create -> login -> company -> agent -> complete -> agents registered)
  • Visual verification at http://localhost:5173/login and /org/edit

Review coverage

Pre-reviewed by 16 agents (code-reviewer, python-reviewer, logging-audit, resilience-audit, conventions-enforcer, silent-failure-hunter, async-concurrency-reviewer, comment-analyzer, type-design-analyzer, security-reviewer, frontend-reviewer, api-contract-drift, docs-consistency, pr-test-analyzer, test-quality-reviewer, issue-resolution-verifier). 30 findings identified and addressed in review fixes commit.

Closes #789
Closes #888

Generated with Claude Code

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 28, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 3c26eee4-c47c-4c48-b0f9-de71dbb99321

📥 Commits

Reviewing files that changed from the base of the PR and between dad9ef7 and 9783fd0.

📒 Files selected for processing (2)
  • web/src/pages/LoginPage.stories.tsx
  • web/src/pages/LoginPage.tsx
📜 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). (3)
  • GitHub Check: Dashboard Test
  • GitHub Check: Test (Python 3.14)
  • GitHub Check: Build Backend
🧰 Additional context used
📓 Path-based instructions (5)
{src,tests,web/src,cli}/**/*.{py,ts,tsx,go}

📄 CodeRabbit inference engine (CLAUDE.md)

Never use real vendor names (Anthropic, OpenAI, Claude, GPT, etc.) in project-owned code, docstrings, comments, tests, or config examples; use generic names (example-provider, example-large-001, large/medium/small)

Files:

  • web/src/pages/LoginPage.stories.tsx
  • web/src/pages/LoginPage.tsx
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

TypeScript files must use baseUrl in tsconfig relative to tsconfig directory (deprecated in TS 6, removed in TS 7); prefer paths entries

Files:

  • web/src/pages/LoginPage.stories.tsx
  • web/src/pages/LoginPage.tsx
web/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

web/src/**/*.{ts,tsx}: ALWAYS reuse existing components from web/src/components/ui/ before creating new ones (StatusBadge, MetricCard, Sparkline, SectionCard, AgentCard, DeptHealthBar, ProgressGauge, StatPill, Avatar, Button, Toast, Skeleton variants, EmptyState, ErrorBoundary, ConfirmDialog, CommandPalette, InlineEdit, AnimatedPresence, StaggerGroup, Drawer, InputField, SelectField, SliderField, ToggleField, TaskStatusIndicator, PriorityBadge, ProviderHealthBadge)
Use Tailwind semantic classes (text-foreground, bg-card, text-accent, text-success, bg-danger, etc.) or CSS variables (var(--so-accent)); NEVER hardcode hex values in .tsx/.ts files
Use font-sans or font-mono for typography (maps to Geist tokens); NEVER set fontFamily directly
Use density-aware design tokens for spacing (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 shadow or border 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 text-metric font-bold -- use <MetricCard>
Do NOT render initials circles manually -- use <Avatar>
Do NOT create complex (>8 line) JSX inside .map() -- extract to a shared component
Do NOT use rgba() with hardcoded values -- use design token variables

Files:

  • web/src/pages/LoginPage.stories.tsx
  • web/src/pages/LoginPage.tsx
{docs/design/operations.md,web/src/**,src/synthorg/providers/presets.py,src/synthorg/**/*.{py,ts,tsx},cli/**}

📄 CodeRabbit inference engine (CLAUDE.md)

Vendor names (Anthropic, OpenAI, Claude, GPT) may only appear in: (1) docs/design/operations.md, (2) .claude/ skill/agent files, (3) third-party import paths/module names, (4) provider presets (src/synthorg/providers/presets.py)

Files:

  • web/src/pages/LoginPage.stories.tsx
  • web/src/pages/LoginPage.tsx
web/src/**/*.stories.tsx

📄 CodeRabbit inference engine (CLAUDE.md)

web/src/**/*.stories.tsx: Storybook 10+ is ESM-only; remove all CJS support from stories
Storybook 10+ essential addons (backgrounds, controls, viewport, actions, toolbars, measure, outline) and interactions are built into core storybook; do NOT import from removed packages
Use storybook/test imports (not @storybook/test), storybook/actions (not @storybook/addon-actions) in Storybook 10+ stories
Use parameters.backgrounds.options (object keyed by name) + initialGlobals.backgrounds.value in Storybook 10+ (replaces old default + values array)
Use parameters.a11y.test: 'error' | 'todo' | 'off' for a11y testing in Storybook 10+ (replaces old .element and .manual); set globally in preview.tsx to enforce WCAG compliance on all stories

Files:

  • web/src/pages/LoginPage.stories.tsx
🧠 Learnings (8)
📓 Common learnings
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-26T15:18:16.848Z
Learning: Applies to src/synthorg/api/**/*.py : Litestar API must include setup wizard, auth/, auto-wiring, and lifecycle management
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...
📚 Learning: 2026-03-28T11:47:10.822Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T11:47:10.822Z
Learning: Applies to web/src/**/*.stories.tsx : Storybook 10+ essential addons (backgrounds, controls, viewport, actions, toolbars, measure, outline) and interactions are built into core `storybook`; do NOT import from removed packages

Applied to files:

  • web/src/pages/LoginPage.stories.tsx
📚 Learning: 2026-03-28T11:47:10.822Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T11:47:10.822Z
Learning: Applies to web/src/**/*.stories.tsx : Use `storybook/test` imports (not `storybook/test`), `storybook/actions` (not `storybook/addon-actions`) in Storybook 10+ stories

Applied to files:

  • web/src/pages/LoginPage.stories.tsx
📚 Learning: 2026-03-28T11:47:10.822Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T11:47:10.822Z
Learning: Applies to web/src/**/*.stories.tsx : Storybook 10+ is ESM-only; remove all CJS support from stories

Applied to files:

  • web/src/pages/LoginPage.stories.tsx
📚 Learning: 2026-03-28T11:47:10.822Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T11:47:10.822Z
Learning: Applies to web/src/**/*.stories.tsx : Use `parameters.backgrounds.options` (object keyed by name) + `initialGlobals.backgrounds.value` in Storybook 10+ (replaces old `default` + `values` array)

Applied to files:

  • web/src/pages/LoginPage.stories.tsx
📚 Learning: 2026-03-28T11:47:10.822Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T11:47:10.822Z
Learning: Applies to web/src/components/ui/**/*.{ts,tsx} : When creating new shared components: place in `web/src/components/ui/`, create `.stories.tsx` file with all states, export props as TypeScript interface, use design tokens exclusively, import `cn` from `@/lib/utils` for class merging

Applied to files:

  • web/src/pages/LoginPage.stories.tsx
📚 Learning: 2026-03-28T11:47:10.822Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T11:47:10.822Z
Learning: Applies to web/src/**/*.stories.tsx : Use `parameters.a11y.test: 'error' | 'todo' | 'off'` for a11y testing in Storybook 10+ (replaces old `.element` and `.manual`); set globally in `preview.tsx` to enforce WCAG compliance on all stories

Applied to files:

  • web/src/pages/LoginPage.stories.tsx
📚 Learning: 2026-03-28T11:47:10.822Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T11:47:10.822Z
Learning: Applies to .storybook/{main.ts,preview.tsx} : Use `defineMain` from `storybook/react-vite/node` and `definePreview` from `storybook/react-vite` with explicit `framework` field in Storybook 10+ config

Applied to files:

  • web/src/pages/LoginPage.stories.tsx
🪛 GitHub Check: Dashboard Lint
web/src/pages/LoginPage.tsx

[warning] 79-79:
Potential timing attack, left side: true

🔇 Additional comments (9)
web/src/pages/LoginPage.tsx (6)

75-82: The timing attack warning is a false positive for client-side form validation.

The static analysis tool flagged password !== confirmPassword as a potential timing attack. This concern applies to server-side comparisons of secrets (e.g., comparing user input against stored password hashes or tokens), where an attacker could measure response time differences to infer information.

Here, both values are user-provided inputs being compared in the browser before submission — no secret is involved, and no timing information leaks to an attacker. This is safe to ignore.


1-9: LGTM!

Imports are well-organized, correctly pulling from existing UI components (InputField, Button) and utility hooks.


25-42: LGTM!

Clean implementation of the setup status detection with proper cleanup pattern using cancelled flag to prevent state updates on unmounted component. Falls back gracefully to login mode on network errors.


44-67: LGTM!

Login handler properly validates inputs, enforces lockout protection via checkAndClearLockout(), and uses trimmed username for the API call. Error handling correctly distinguishes between lockout messages and general errors.


108-109: LGTM!

Lockout is correctly scoped to login mode only, ensuring the admin setup flow remains interactive even if prior login attempts triggered a lockout.


111-206: LGTM!

The JSX uses semantic Tailwind classes (bg-background, text-foreground, bg-card, border-border, text-accent, text-danger, text-warning, etc.), design token variables for colors, and font-sans for typography — all compliant with coding guidelines. The lockout warning is correctly conditioned on locked && isLoginMode. Accessibility is addressed with role="alert" on error and warning elements.

web/src/pages/LoginPage.stories.tsx (3)

17-28: LGTM!

Meta configuration is correct for Storybook 10+ with proper ESM imports, fullscreen layout, and single MemoryRouter decorator at the meta level.


86-88: LGTM!

The AdminCreation story correctly uses a render function to mount AdminCreationGate, which handles the setup-before-render pattern. The cleanup in AdminCreationGate properly restores the original function on unmount.


45-78: 🧹 Nitpick | 🔵 Trivial

Consider migrating to static mock data or MSW in future refactors for cleaner API mocking strategy.

The ESM module patching approach works in Vite's dev environment and is intentionally used here to mock getSetupStatus before LoginPage renders. However, other stories in the codebase use static mock data objects (e.g., DashboardPage.stories.tsx). For consistency and to reduce reliance on dynamic module mutation, consider:

  • Using static mock data if the setup state is fixed per story variant
  • Migrating to MSW (Mock Service Worker) when available, which is the standard approach for API mocking in Storybook

This is not blocking—the current pattern works for visual testing—but would align with the codebase's established mocking conventions.

⛔ Skipped due to learnings
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T11:47:10.822Z
Learning: Applies to web/src/**/*.stories.tsx : Storybook 10+ is ESM-only; remove all CJS support from stories
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T11:47:10.822Z
Learning: Applies to web/src/**/*.stories.tsx : Use `storybook/test` imports (not `storybook/test`), `storybook/actions` (not `storybook/addon-actions`) in Storybook 10+ stories
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T11:47:10.822Z
Learning: Applies to web/src/**/*.stories.tsx : Use `parameters.a11y.test: 'error' | 'todo' | 'off'` for a11y testing in Storybook 10+ (replaces old `.element` and `.manual`); set globally in `preview.tsx` to enforce WCAG compliance on all stories
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T11:47:10.822Z
Learning: Applies to web/src/**/*.stories.tsx : Storybook 10+ essential addons (backgrounds, controls, viewport, actions, toolbars, measure, outline) and interactions are built into core `storybook`; do NOT import from removed packages
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T11:47:10.822Z
Learning: Applies to .storybook/{main.ts,preview.tsx} : Use `defineMain` from `storybook/react-vite/node` and `definePreview` from `storybook/react-vite` with explicit `framework` field in Storybook 10+ config
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T11:47:10.822Z
Learning: Applies to web/src/**/*.stories.tsx : Use `parameters.backgrounds.options` (object keyed by name) + `initialGlobals.backgrounds.value` in Storybook 10+ (replaces old `default` + `values` array)

Walkthrough

Adds runtime agent bootstrapping from persisted configuration and integrates it into startup and setup-completion flows. Introduces a new synthorg.api.bootstrap module with bootstrap_agents(...), a _maybe_bootstrap_agents startup helper, and wiring to invoke bootstrap during app startup and after POST /setup/complete reinitialization. Adds observability event constants, template-variable metadata across templates and API models, stricter request validation, OpenAPI nullable-union flattening improvements, many frontend/login and org-edit UI changes, and extensive new unit and integration tests covering bootstrap and first-run setup behavior.

Suggested labels

autorelease: tagged

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The PR title 'feat: Login page + first-run bootstrap + Company page (#789, #888)' clearly and specifically summarizes the three main features added in this changeset.
Description check ✅ Passed The PR description provides a comprehensive overview covering all major changes including the login page, agent bootstrap module, engine re-init, company page, and API contract fix, with clear test coverage and validation results.
Docstring Coverage ✅ Passed Docstring coverage is 66.00% which is sufficient. The required threshold is 40.00%.

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


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

@Aureliolo Aureliolo temporarily deployed to cloudflare-preview March 28, 2026 10:46 — with GitHub Actions Inactive
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request implements agent bootstrapping from persisted configuration, ensuring agents are registered in the runtime registry during application startup and after the setup process is finalized. It also enhances the first-run experience by adding administrator account creation to the login page and improving template variable handling. A critical issue was identified across several files where multiple exceptions are caught using legacy Python 2 syntax (e.g., except Exception, e), which will result in a SyntaxError in Python 3.

Comment on lines +225 to +226
except MemoryError, RecursionError:
raise
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

critical

The except Exception, e syntax is from Python 2 and is a SyntaxError in Python 3. To catch multiple exceptions, they should be enclosed in a tuple.

    except (MemoryError, RecursionError):
        raise

Comment on lines +245 to +246
except MemoryError, RecursionError:
raise
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

critical

This except block uses Python 2 syntax, which will not work in Python 3. Please update it to use a tuple for multiple exceptions.

    except (MemoryError, RecursionError):
        raise

Comment on lines +104 to +105
except MemoryError, RecursionError:
raise
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

critical

The syntax for catching multiple exceptions has changed in Python 3. The exceptions should be wrapped in a tuple to avoid a SyntaxError.

        except (MemoryError, RecursionError):
            raise

Comment on lines +125 to +126
except MemoryError, RecursionError:
raise
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

critical

This is another instance of Python 2 except syntax. It needs to be updated for Python 3 compatibility by using a tuple for the exception types.

        except (MemoryError, RecursionError):
            raise

Comment on lines +777 to +778
except MemoryError, RecursionError:
raise
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

critical

This except statement uses Python 2 syntax. For Python 3 compatibility, please wrap the exception classes in a tuple.

    except (MemoryError, RecursionError):
        raise

Comment on lines +795 to +796
except MemoryError, RecursionError:
raise
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

critical

The except syntax here is invalid in Python 3. To catch multiple exceptions, they must be passed as a tuple.

        except (MemoryError, RecursionError):
            raise

Comment on lines +810 to +811
except MemoryError, RecursionError:
raise
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

critical

This except block uses legacy Python 2 syntax. It should be updated to the Python 3 tuple-based syntax to avoid a SyntaxError.

    except (MemoryError, RecursionError):
        raise

Comment on lines 1169 to 1170
except MemoryError, RecursionError:
raise
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

critical

This is another occurrence of Python 2 except syntax. Please update it to the correct Python 3 syntax by using a tuple for the exceptions.

    except (MemoryError, RecursionError):
        raise

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 28, 2026

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Snapshot Warnings

⚠️: No snapshots were found for the head SHA 9783fd0.
Ensure 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.

Scanned Files

None

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@web/src/__tests__/pages/org-edit/GeneralTab.test.tsx`:
- Around line 64-68: Add a property-based test in GeneralTab.test.tsx using
fast-check to cover the pristine/dirty × saving matrix for the GeneralTab
component: use fc.assert + fc.property(fc.boolean(), fc.boolean(), (dirty,
saving) => { render(<GeneralTab config={makeCompanyConfig()}
onUpdate={mockOnUpdate} saving={saving} />); if (dirty) use userEvent.type or
fireEvent.change on a visible input (e.g., querySelector('input') or a known
field) to make the form dirty; then get the Save Settings button via
screen.getByText('Save Settings').closest('button') and assert that its disabled
state equals expectedDisabled where expectedDisabled = (!dirty) || saving;
return true for the property. Ensure imports for fast-check (fc) and user-event
are added and the test follows the existing Vitest pattern.
- Line 9: The test calls vi.resetAllMocks() which wipes the async implementation
on mockOnUpdate so handleSave’s awaited onUpdate call no longer returns a
Promise; replace vi.resetAllMocks() with vi.clearAllMocks() in the test (keeping
the Promise-returning implementation assigned to mockOnUpdate) so call history
is cleared but the async mock implementation used by
GeneralTab.handleSave/onUpdate is preserved.

In `@web/src/pages/LoginPage.stories.tsx`:
- Around line 58-72: The decorator currently defers restoration with
setTimeout(restore, 100) which is fragile; replace that timing workaround with a
React effect cleanup that calls the restore function when the decorator wrapper
unmounts: inside the decorators slot wrap Story in a small functional component
(e.g., RestoreWrapper) that reads const restore = (context.loaded as {
restoreSetup?: () => void })?.restoreSetup and uses useEffect(() => { return ()
=> { if (restore) restore() } }, [restore]) to perform restoration on cleanup,
and render
<MemoryRouter><RestoreWrapper><Story/></RestoreWrapper></MemoryRouter> (or
similarly call restore in the cleanup of the component that returns <Story />),
removing the setTimeout call and keeping restoreSetup, Story, context and
MemoryRouter identifiers.
🪄 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: c2050b01-9c87-48b4-949e-9b82de38755f

📥 Commits

Reviewing files that changed from the base of the PR and between 32f83fe and e3cec39.

📒 Files selected for processing (27)
  • CLAUDE.md
  • docs/design/brand-and-ux.md
  • src/synthorg/api/app.py
  • src/synthorg/api/bootstrap.py
  • src/synthorg/api/controllers/setup.py
  • src/synthorg/api/controllers/setup_models.py
  • src/synthorg/observability/events/setup.py
  • src/synthorg/templates/loader.py
  • tests/integration/api/test_first_run_flow.py
  • tests/unit/api/controllers/test_setup.py
  • tests/unit/api/test_bootstrap.py
  • web/src/__tests__/App.test.tsx
  • web/src/__tests__/pages/LoginPage.test.tsx
  • web/src/__tests__/pages/org-edit/AgentCreateDialog.test.tsx
  • web/src/__tests__/pages/org-edit/AgentEditDrawer.test.tsx
  • web/src/__tests__/pages/org-edit/AgentsTab.test.tsx
  • web/src/__tests__/pages/org-edit/DepartmentCreateDialog.test.tsx
  • web/src/__tests__/pages/org-edit/DepartmentEditDrawer.test.tsx
  • web/src/__tests__/pages/org-edit/DepartmentsTab.test.tsx
  • web/src/__tests__/pages/org-edit/GeneralTab.test.tsx
  • web/src/__tests__/pages/org-edit/YamlEditorPanel.test.tsx
  • web/src/api/endpoints/setup.ts
  • web/src/pages/LoginPage.stories.tsx
  • web/src/pages/LoginPage.tsx
  • web/src/pages/OrgEditPage.tsx
  • web/src/pages/org-edit/GeneralTab.tsx
  • web/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). (7)
  • GitHub Check: Test (Python 3.14)
  • GitHub Check: Dashboard Test
  • GitHub Check: Build Sandbox
  • GitHub Check: Build Backend
  • GitHub Check: Build Web
  • GitHub Check: Dependency Review
  • GitHub Check: Analyze (python)
🧰 Additional context used
📓 Path-based instructions (10)
**/*.{py,ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Line length: 88 characters (ruff enforced).

Files:

  • web/src/__tests__/pages/org-edit/AgentEditDrawer.test.tsx
  • web/src/__tests__/App.test.tsx
  • web/src/__tests__/pages/org-edit/DepartmentsTab.test.tsx
  • web/src/__tests__/pages/org-edit/DepartmentCreateDialog.test.tsx
  • web/src/__tests__/pages/org-edit/YamlEditorPanel.test.tsx
  • web/src/__tests__/pages/org-edit/AgentCreateDialog.test.tsx
  • web/src/__tests__/pages/org-edit/DepartmentEditDrawer.test.tsx
  • web/src/pages/org-edit/GeneralTab.tsx
  • web/src/pages/OrgEditPage.tsx
  • web/src/__tests__/pages/org-edit/AgentsTab.test.tsx
  • web/src/stores/company.ts
  • web/src/api/endpoints/setup.ts
  • web/src/__tests__/pages/org-edit/GeneralTab.test.tsx
  • src/synthorg/templates/loader.py
  • src/synthorg/observability/events/setup.py
  • web/src/pages/LoginPage.tsx
  • web/src/pages/LoginPage.stories.tsx
  • src/synthorg/api/app.py
  • src/synthorg/api/controllers/setup.py
  • tests/unit/api/controllers/test_setup.py
  • tests/unit/api/test_bootstrap.py
  • web/src/__tests__/pages/LoginPage.test.tsx
  • src/synthorg/api/bootstrap.py
  • src/synthorg/api/controllers/setup_models.py
  • tests/integration/api/test_first_run_flow.py
web/src/**/*.{tsx,ts}

📄 CodeRabbit inference engine (CLAUDE.md)

web/src/**/*.{tsx,ts}: Use Tailwind semantic classes (text-foreground, bg-card, text-accent, etc.) or CSS variables (var(--so-accent)). NEVER hardcode hex values in .tsx/.ts files. Use design token variables for colors, typography, spacing, shadows, borders.
Import cn from @/lib/utils for conditional class merging in React components.
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 a shared component.
Use StatusBadge for agent/task/system status indicators (colored dot + optional built-in label toggle).
Use MetricCard for numeric KPIs with sparkline, change badge, progress bar.
Use SectionCard for titled card wrapper with icon and action slot.
Use AgentCard for agent display: avatar, name, role, status, current task.
Use DeptHealthBar for department health: animated fill bar + health (required) + agentCount/taskCount (required).
Use ProgressGauge for circular gauge for budget/utilization (max? defaults to 100).
Use Avatar for circular initials avatar with optional borderColor? prop.
Use Toast / ToastContainer for success/error/warning/info notifications with auto-dismiss queue. Mount ToastContainer once in AppLayout.
Use Skeleton / SkeletonCard / SkeletonMetric / SkeletonTable / SkeletonText for loading placeholders matching component shapes (shimmer animation, respects prefers-reduced-motion).
Use ErrorBoundary React error boundary with retry -- level prop: page / section / component.
Use ConfirmDialog for confirmation modal (Radix AlertDialog) with default / destructive variants and loading state.
Use CommandPalette for global Cmd+K search (cmdk + React Router) -- mount once in AppLayout, register commands via `useComma...

Files:

  • web/src/__tests__/pages/org-edit/AgentEditDrawer.test.tsx
  • web/src/__tests__/App.test.tsx
  • web/src/__tests__/pages/org-edit/DepartmentsTab.test.tsx
  • web/src/__tests__/pages/org-edit/DepartmentCreateDialog.test.tsx
  • web/src/__tests__/pages/org-edit/YamlEditorPanel.test.tsx
  • web/src/__tests__/pages/org-edit/AgentCreateDialog.test.tsx
  • web/src/__tests__/pages/org-edit/DepartmentEditDrawer.test.tsx
  • web/src/pages/org-edit/GeneralTab.tsx
  • web/src/pages/OrgEditPage.tsx
  • web/src/__tests__/pages/org-edit/AgentsTab.test.tsx
  • web/src/stores/company.ts
  • web/src/api/endpoints/setup.ts
  • web/src/__tests__/pages/org-edit/GeneralTab.test.tsx
  • web/src/pages/LoginPage.tsx
  • web/src/pages/LoginPage.stories.tsx
  • web/src/__tests__/pages/LoginPage.test.tsx
web/src/__tests__/**/*.test.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Web dashboard: test with Vitest unit + property tests (fast-check). Mirror src/ structure in __tests__/. Property tests use fc.assert + fc.property.

Files:

  • web/src/__tests__/pages/org-edit/AgentEditDrawer.test.tsx
  • web/src/__tests__/App.test.tsx
  • web/src/__tests__/pages/org-edit/DepartmentsTab.test.tsx
  • web/src/__tests__/pages/org-edit/DepartmentCreateDialog.test.tsx
  • web/src/__tests__/pages/org-edit/YamlEditorPanel.test.tsx
  • web/src/__tests__/pages/org-edit/AgentCreateDialog.test.tsx
  • web/src/__tests__/pages/org-edit/DepartmentEditDrawer.test.tsx
  • web/src/__tests__/pages/org-edit/AgentsTab.test.tsx
  • web/src/__tests__/pages/org-edit/GeneralTab.test.tsx
  • web/src/__tests__/pages/LoginPage.test.tsx
web/src/stores/**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

React: use Zustand stores for global state (auth, WebSocket, toast, analytics, setup wizard, company, agents, budget, tasks, settings, providers). Create per-domain stores for page data.

Files:

  • web/src/stores/company.ts
**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.py: No from __future__ import annotations -- Python 3.14 has PEP 649 native lazy annotations.
Use PEP 758 except syntax: except A, B: (no parentheses) -- ruff enforces this on Python 3.14.

Files:

  • src/synthorg/templates/loader.py
  • src/synthorg/observability/events/setup.py
  • src/synthorg/api/app.py
  • src/synthorg/api/controllers/setup.py
  • tests/unit/api/controllers/test_setup.py
  • tests/unit/api/test_bootstrap.py
  • src/synthorg/api/bootstrap.py
  • src/synthorg/api/controllers/setup_models.py
  • tests/integration/api/test_first_run_flow.py
src/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

src/**/*.py: All public functions require type hints. Enforce mypy strict mode.
Google-style docstrings required on all public classes and functions. Enforced by ruff D rules.
Never mutate existing objects. Create new objects instead. For non-Pydantic internal collections (registries, BaseTool), use copy.deepcopy() at construction + MappingProxyType wrapping for read-only enforcement.
For dict/list fields in frozen Pydantic models, use copy.deepcopy() at system boundaries (tool execution, LLM provider serialization, inter-agent delegation, serializing for persistence).
Use frozen Pydantic models for config/identity; use separate mutable-via-copy models (using model_copy(update=...)) for runtime state that evolves. Never mix static config fields with mutable runtime fields in one model.
Use Pydantic v2 conventions: BaseModel, model_validator, computed_field, ConfigDict. Use @computed_field for derived values instead of storing redundant fields. Use NotBlankStr for all identifier/name fields.
Prefer asyncio.TaskGroup for fan-out/fan-in parallel operations in new code. Prefer structured concurrency over bare create_task.
Functions must be < 50 lines, files < 800 lines.
Never use real vendor names (Anthropic, OpenAI, Claude, GPT, etc.) in project-owned code, docstrings, comments, tests, or config examples. Use generic names: example-provider, example-large-001, test-provider, test-small-001.

Files:

  • src/synthorg/templates/loader.py
  • src/synthorg/observability/events/setup.py
  • src/synthorg/api/app.py
  • src/synthorg/api/controllers/setup.py
  • src/synthorg/api/bootstrap.py
  • src/synthorg/api/controllers/setup_models.py
src/**/*.{py,ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

src/**/*.{py,ts,tsx}: Handle errors explicitly. Never silently swallow exceptions.
Validate at system boundaries (user input, external APIs, config files).

Files:

  • src/synthorg/templates/loader.py
  • src/synthorg/observability/events/setup.py
  • src/synthorg/api/app.py
  • src/synthorg/api/controllers/setup.py
  • src/synthorg/api/bootstrap.py
  • src/synthorg/api/controllers/setup_models.py
src/synthorg/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

src/synthorg/**/*.py: Every module with business logic must have: from synthorg.observability import get_logger then logger = get_logger(__name__). Never use import logging / logging.getLogger() / print() in application code.
Always use structured logging: logger.info(EVENT, key=value). Never use format strings like logger.info("msg %s", val).
Use event name constants from domain-specific modules under synthorg.observability.events (e.g., API_REQUEST_STARTED from events.api). Import directly: from synthorg.observability.events.<domain> import EVENT_CONSTANT.
All error paths must log at WARNING or ERROR with context before raising. All state transitions must log at INFO. DEBUG for object creation, internal flow, entry/exit of key functions.

Files:

  • src/synthorg/templates/loader.py
  • src/synthorg/observability/events/setup.py
  • src/synthorg/api/app.py
  • src/synthorg/api/controllers/setup.py
  • src/synthorg/api/bootstrap.py
  • src/synthorg/api/controllers/setup_models.py
web/src/**/*.stories.tsx

📄 CodeRabbit inference engine (CLAUDE.md)

Post-Training Reference: Storybook 10 - ESM-only; @storybook/addon-docs is separate; import from storybook/test and storybook/actions; use defineMain and definePreview; backgrounds API uses parameters.backgrounds.options (object) + initialGlobals.backgrounds.value; a11y uses parameters.a11y.test; minimum versions: Node 20.19+, Vite 5+, Vitest 3+, TypeScript 4.9+.

Files:

  • web/src/pages/LoginPage.stories.tsx
tests/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

tests/**/*.py: Test markers: @pytest.mark.unit, @pytest.mark.integration, @pytest.mark.e2e, @pytest.mark.slow.
80% minimum code coverage (enforced in CI). Never skip, dismiss, or ignore flaky tests -- fix them fully and fundamentally.
Async tests: asyncio_mode = "auto" -- no manual @pytest.mark.asyncio needed. Default timeout: 30 seconds per test. Always run pytest with -n auto for parallelism (never sequentially).
Prefer @pytest.mark.parametrize for testing similar cases.
For timing-sensitive tests, mock time.monotonic() and asyncio.sleep() to make them deterministic. For tasks that must block indefinitely, use asyncio.Event().wait() instead of asyncio.sleep(large_number).
Property-based testing: use Hypothesis with @given + @settings. Run dev profile (1000 examples) with HYPOTHESIS_PROFILE=dev.

Files:

  • tests/unit/api/controllers/test_setup.py
  • tests/unit/api/test_bootstrap.py
  • tests/integration/api/test_first_run_flow.py
🧠 Learnings (51)
📚 Learning: 2026-03-28T10:20:33.391Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T10:20:33.391Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use `AgentCard` for agent display: avatar, name, role, status, current task.

Applied to files:

  • web/src/__tests__/pages/org-edit/AgentEditDrawer.test.tsx
  • web/src/__tests__/pages/org-edit/AgentCreateDialog.test.tsx
  • web/src/__tests__/pages/org-edit/AgentsTab.test.tsx
  • docs/design/brand-and-ux.md
  • CLAUDE.md
📚 Learning: 2026-03-28T10:20:33.391Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T10:20:33.391Z
Learning: Applies to web/src/__tests__/**/*.test.{ts,tsx} : Web dashboard: test with Vitest unit + property tests (`fast-check`). Mirror `src/` structure in `__tests__/`. Property tests use `fc.assert` + `fc.property`.

Applied to files:

  • web/src/__tests__/pages/org-edit/AgentEditDrawer.test.tsx
  • web/src/__tests__/App.test.tsx
  • web/src/__tests__/pages/org-edit/DepartmentsTab.test.tsx
  • web/src/__tests__/pages/org-edit/DepartmentCreateDialog.test.tsx
  • web/src/__tests__/pages/org-edit/YamlEditorPanel.test.tsx
  • web/src/__tests__/pages/org-edit/AgentCreateDialog.test.tsx
  • web/src/__tests__/pages/org-edit/DepartmentEditDrawer.test.tsx
  • web/src/__tests__/pages/org-edit/AgentsTab.test.tsx
  • web/src/__tests__/pages/org-edit/GeneralTab.test.tsx
  • web/src/__tests__/pages/LoginPage.test.tsx
📚 Learning: 2026-03-28T10:20:33.391Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T10:20:33.391Z
Learning: Applies to web/src/**/*.stories.tsx : Post-Training Reference: Storybook 10 - ESM-only; `storybook/addon-docs` is separate; import from `storybook/test` and `storybook/actions`; use `defineMain` and `definePreview`; backgrounds API uses `parameters.backgrounds.options` (object) + `initialGlobals.backgrounds.value`; a11y uses `parameters.a11y.test`; minimum versions: Node 20.19+, Vite 5+, Vitest 3+, TypeScript 4.9+.

Applied to files:

  • web/src/__tests__/App.test.tsx
  • web/src/__tests__/pages/org-edit/DepartmentsTab.test.tsx
  • web/src/__tests__/pages/org-edit/YamlEditorPanel.test.tsx
  • web/src/__tests__/pages/org-edit/AgentsTab.test.tsx
  • web/src/pages/LoginPage.stories.tsx
  • web/src/__tests__/pages/LoginPage.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__/App.test.tsx
  • web/src/__tests__/pages/org-edit/DepartmentsTab.test.tsx
  • web/src/__tests__/pages/org-edit/DepartmentCreateDialog.test.tsx
  • web/src/__tests__/pages/org-edit/AgentCreateDialog.test.tsx
  • web/src/__tests__/pages/org-edit/DepartmentEditDrawer.test.tsx
  • web/src/__tests__/pages/org-edit/AgentsTab.test.tsx
  • web/src/__tests__/pages/org-edit/GeneralTab.test.tsx
  • web/src/__tests__/pages/LoginPage.test.tsx
📚 Learning: 2026-03-28T10:20:33.391Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T10:20:33.391Z
Learning: Applies to web/src/**/*.{tsx,ts} : React: use Linting (ESLint) and type-checking (TypeScript). Run tests with `npm --prefix web run test` (Vitest, coverage scoped to changed files vs origin/main).

Applied to files:

  • web/src/__tests__/pages/org-edit/DepartmentsTab.test.tsx
  • web/src/__tests__/pages/org-edit/AgentsTab.test.tsx
  • web/src/__tests__/pages/LoginPage.test.tsx
📚 Learning: 2026-03-28T10:20:33.391Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T10:20:33.391Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use `Drawer` for right-side slide-in panel with overlay, spring animation, focus trap, Escape-to-close.

Applied to files:

  • web/src/__tests__/pages/org-edit/DepartmentEditDrawer.test.tsx
📚 Learning: 2026-03-28T10:20:33.391Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T10:20:33.391Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use `InlineEdit` for click-to-edit text with Enter/Escape, validation, optimistic save with rollback.

Applied to files:

  • web/src/pages/org-edit/GeneralTab.tsx
  • web/src/pages/OrgEditPage.tsx
📚 Learning: 2026-03-28T10:20:33.391Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T10:20:33.391Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use `StatusBadge` for agent/task/system status indicators (colored dot + optional built-in label toggle).

Applied to files:

  • web/src/pages/OrgEditPage.tsx
  • docs/design/brand-and-ux.md
  • CLAUDE.md
📚 Learning: 2026-03-28T10:20:33.391Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T10:20:33.391Z
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 a shared component.

Applied to files:

  • web/src/pages/OrgEditPage.tsx
  • docs/design/brand-and-ux.md
  • CLAUDE.md
  • web/src/pages/LoginPage.tsx
📚 Learning: 2026-03-28T10:20:33.391Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T10:20:33.391Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use `ProviderHealthBadge` for provider health status indicator (up/degraded/down colored dot + optional label).

Applied to files:

  • web/src/pages/OrgEditPage.tsx
  • docs/design/brand-and-ux.md
  • CLAUDE.md
📚 Learning: 2026-03-28T10:20:33.391Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T10:20:33.391Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use `Toast` / `ToastContainer` for success/error/warning/info notifications with auto-dismiss queue. Mount `ToastContainer` once in AppLayout.

Applied to files:

  • web/src/pages/OrgEditPage.tsx
📚 Learning: 2026-03-28T10:20:33.391Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T10:20:33.391Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use `ConfirmDialog` for confirmation modal (Radix AlertDialog) with `default` / `destructive` variants and `loading` state.

Applied to files:

  • web/src/pages/OrgEditPage.tsx
📚 Learning: 2026-03-28T10:20:33.391Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T10:20:33.391Z
Learning: Applies to web/src/stores/**/*.ts : React: use Zustand stores for global state (auth, WebSocket, toast, analytics, setup wizard, company, agents, budget, tasks, settings, providers). Create per-domain stores for page data.

Applied to files:

  • web/src/stores/company.ts
📚 Learning: 2026-03-28T10:20:33.391Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T10:20:33.391Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use `DeptHealthBar` for department health: animated fill bar + `health` (required) + `agentCount`/`taskCount` (required).

Applied to files:

  • docs/design/brand-and-ux.md
  • CLAUDE.md
📚 Learning: 2026-03-28T10:20:33.391Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T10:20:33.391Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use `MetricCard` for numeric KPIs with sparkline, change badge, progress bar.

Applied to files:

  • docs/design/brand-and-ux.md
  • CLAUDE.md
📚 Learning: 2026-03-28T10:20:33.391Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T10:20:33.391Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use `SectionCard` for titled card wrapper with icon and action slot.

Applied to files:

  • docs/design/brand-and-ux.md
  • CLAUDE.md
📚 Learning: 2026-03-28T10:20:33.391Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T10:20:33.391Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use `Skeleton` / `SkeletonCard` / `SkeletonMetric` / `SkeletonTable` / `SkeletonText` for loading placeholders matching component shapes (shimmer animation, respects `prefers-reduced-motion`).

Applied to files:

  • docs/design/brand-and-ux.md
📚 Learning: 2026-03-28T10:20:33.391Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T10:20:33.391Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use `ProgressGauge` for circular gauge for budget/utilization (`max?` defaults to 100).

Applied to files:

  • docs/design/brand-and-ux.md
  • 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:

  • docs/design/brand-and-ux.md
  • CLAUDE.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
  • src/synthorg/api/bootstrap.py
📚 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 docs/design/*.md : Design spec pages: 7 pages in `docs/design/` — index, agents, organization, communication, engine, memory, operations

Applied to files:

  • CLAUDE.md
📚 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-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 docs/design/**/*.md : Design specification pages in `docs/design/` must be consulted before implementing features (7 pages: index, agents, organization, communication, engine, memory, operations)

Applied to files:

  • CLAUDE.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/api/**/*.py : API package (api/): Litestar REST + WebSocket with controllers, guards, channels, JWT + API key + WS ticket auth, approval gate integration, coordination endpoint, collaboration endpoint, settings endpoint, provider management endpoint (CRUD + test + presets), backup endpoint, RFC 9457 structured errors, AppState hot-reload slots, service auto-wiring (Phase 1 at construction, Phase 2 on startup), lifecycle helpers

Applied to files:

  • CLAUDE.md
  • src/synthorg/api/app.py
  • src/synthorg/api/controllers/setup.py
📚 Learning: 2026-03-26T15:18:16.848Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-26T15:18:16.848Z
Learning: Applies to src/synthorg/api/**/*.py : Litestar API must include setup wizard, auth/, auto-wiring, and lifecycle management

Applied to files:

  • CLAUDE.md
  • src/synthorg/api/app.py
  • src/synthorg/api/controllers/setup.py
  • src/synthorg/api/bootstrap.py
  • tests/integration/api/test_first_run_flow.py
📚 Learning: 2026-03-17T06:30:14.180Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T06:30:14.180Z
Learning: Applies to src/synthorg/api/**/*.py : Use Litestar for REST + WebSocket API. Controllers, guards, channels, JWT + API key + WS ticket auth, RFC 9457 structured errors.

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-03-17T22:08:13.456Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T22:08:13.456Z
Learning: Applies to src/synthorg/api/**/*.py : REST API: Litestar framework, controllers with guards, channels for WebSocket, JWT + API key + WS ticket auth, approval gate integration, coordination endpoint, collaboration endpoint, settings endpoint. RFC 9457 structured errors (ErrorCategory, ErrorCode, ErrorDetail, ProblemDetail, CATEGORY_TITLES, category_title, category_type_uri, content negotiation).

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-03-20T11:18:48.128Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-20T11:18:48.128Z
Learning: Applies to src/synthorg/api/**/*.py : Use Litestar for REST API and WebSocket API with JWT + API key + WS ticket authentication, RFC 9457 structured errors, and content negotiation.

Applied to files:

  • CLAUDE.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/engine/**/*.py : Engine package (engine/): agent orchestration, parallel execution, task decomposition, routing, TaskEngine (centralized single-writer), task lifecycle/recovery/shutdown, workspace isolation, coordination (4 dispatchers: SAS/centralized/decentralized/context-dependent, wave execution), approval gates (escalation detection, context parking/resume), stagnation detection (ToolRepetitionDetector, corrective prompt injection), AgentRuntimeState (execution status), context budget management, conversation compaction (oldest-turns summarizer)

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-03-17T06:30:14.180Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T06:30:14.180Z
Learning: Applies to src/synthorg/security/**/*.py : Security module includes SecOps agent, rule engine (soft-allow/hard-deny), audit log, output scanner, risk classifier, autonomy levels (4 strategies), timeout policies.

Applied to files:

  • CLAUDE.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/security/**/*.py : Security package (security/): SecOps agent, rule engine (soft-allow/hard-deny, fail-closed), audit log, output scanner, output scan response policies (redact/withhold/log-only/autonomy-tiered), risk classifier, risk tier classifier, action type registry, ToolInvoker security integration, progressive trust (4 strategies), autonomy levels (presets, resolver, change strategy), timeout policies (park/resume)

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-03-17T22:08:13.456Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T22:08:13.456Z
Learning: Documentation source in `docs/` (Markdown, built with Zensical). Design spec in `docs/design/` (7 pages: index, agents, organization, communication, engine, memory, operations). Architecture in `docs/architecture/` (overview, tech-stack, decision log). Roadmap in `docs/roadmap/`. Security in `docs/security.md`. Licensing in `docs/licensing.md`. Reference in `docs/reference/`. REST API reference in `docs/rest-api.md`. Library reference in `docs/api/` (auto-generated from docstrings). Custom templates in `docs/overrides/`. Config in `mkdocs.yml`.

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-03-28T10:20:33.391Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T10:20:33.391Z
Learning: Applies to web/src/components/ui/*.tsx : When creating new shared React components: place in `web/src/components/ui/` with descriptive kebab-case filename. Create `.stories.tsx` file with all states. Export props as TypeScript interface. Use design tokens exclusively -- no hardcoded colors, fonts, or spacing.

Applied to files:

  • CLAUDE.md
  • web/src/pages/LoginPage.stories.tsx
  • web/src/__tests__/pages/LoginPage.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 src/synthorg/templates/**/*.py : Templates: pre-built company templates, personality presets, and builder.

Applied to files:

  • src/synthorg/templates/loader.py
  • src/synthorg/api/controllers/setup.py
  • src/synthorg/api/controllers/setup_models.py
📚 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/observability/**/*.py : Observability package (observability/): structured logging, correlation tracking, log sinks; event constants organized by domain under observability/events/ (e.g., events.api, events.tool, events.git, events.context_budget, events.backup)

Applied to files:

  • src/synthorg/observability/events/setup.py
  • src/synthorg/api/controllers/setup.py
📚 Learning: 2026-03-15T19:14:27.144Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T19:14:27.144Z
Learning: Applies to src/synthorg/**/*.py : Use event name constants from synthorg.observability.events domain-specific modules (e.g., PROVIDER_CALL_START from events.provider). Import directly: from synthorg.observability.events.<domain> import EVENT_CONSTANT.

Applied to files:

  • src/synthorg/observability/events/setup.py
📚 Learning: 2026-03-19T11:33:01.580Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T11:33:01.580Z
Learning: Applies to src/synthorg/**/*.py : Use event constants from `synthorg.observability.events.<domain>` (e.g., `API_REQUEST_STARTED` from `events.api`); import directly and log with structured kwargs: `logger.info(EVENT, key=value)`, never interpolated strings

Applied to files:

  • src/synthorg/observability/events/setup.py
  • src/synthorg/api/controllers/setup.py
📚 Learning: 2026-03-28T10:20:33.390Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T10:20:33.390Z
Learning: Applies to src/synthorg/**/*.py : Use event name constants from domain-specific modules under `synthorg.observability.events` (e.g., `API_REQUEST_STARTED` from `events.api`). Import directly: `from synthorg.observability.events.<domain> import EVENT_CONSTANT`.

Applied to files:

  • src/synthorg/observability/events/setup.py
📚 Learning: 2026-03-15T18:28:13.207Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:28:13.207Z
Learning: Applies to src/synthorg/**/*.py : Event names: always use constants from domain-specific modules under synthorg.observability.events (e.g., PROVIDER_CALL_START from events.provider, BUDGET_RECORD_ADDED from events.budget, etc.). Import directly: `from synthorg.observability.events.<domain> import EVENT_CONSTANT`.

Applied to files:

  • src/synthorg/observability/events/setup.py
📚 Learning: 2026-03-20T11:18:48.128Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-20T11:18:48.128Z
Learning: Applies to src/synthorg/**/*.py : Use event name constants from domain-specific modules under `synthorg.observability.events` (e.g., `API_REQUEST_STARTED` from `events.api`, `TOOL_INVOKE_START` from `events.tool`). Import directly: `from synthorg.observability.events.<domain> import EVENT_CONSTANT`.

Applied to files:

  • src/synthorg/observability/events/setup.py
📚 Learning: 2026-03-15T18:38:44.202Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:38:44.202Z
Learning: Applies to src/synthorg/**/*.py : Always use event name constants from domain-specific modules under `synthorg.observability.events` (e.g., `PROVIDER_CALL_START` from `events.provider`); import directly: `from synthorg.observability.events.<domain> import EVENT_CONSTANT`

Applied to files:

  • src/synthorg/observability/events/setup.py
📚 Learning: 2026-03-14T16:18:57.267Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T16:18:57.267Z
Learning: Applies to src/ai_company/!(observability)/**/*.py : Use event name constants from domain-specific modules under `ai_company.observability.events` (e.g., `PROVIDER_CALL_START` from `events.provider`). Import directly: `from ai_company.observability.events.<domain> import EVENT_CONSTANT`.

Applied to files:

  • src/synthorg/observability/events/setup.py
📚 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/**/*.py : Always use event name constants from the domain-specific module under `synthorg.observability.events` in logging calls

Applied to files:

  • src/synthorg/observability/events/setup.py
📚 Learning: 2026-03-18T21:23:23.586Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-18T21:23:23.586Z
Learning: Applies to src/synthorg/**/*.py : Event names: always use constants from the domain-specific module under synthorg.observability.events (e.g., API_REQUEST_STARTED from events.api, TOOL_INVOKE_START from events.tool). Import directly from synthorg.observability.events.<domain>.

Applied to files:

  • src/synthorg/observability/events/setup.py
📚 Learning: 2026-03-28T10:20:33.391Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T10:20:33.391Z
Learning: Applies to web/src/router/**/*.{ts,tsx} : React: use React Router for routing. Lazy-load page components (one per route). Use route guards for auth and setup.

Applied to files:

  • web/src/pages/LoginPage.tsx
  • web/src/pages/LoginPage.stories.tsx
  • web/src/__tests__/pages/LoginPage.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 src/synthorg/providers/**/*.py : Providers: LLM provider abstraction (LiteLLM adapter), auth types (api_key/oauth/custom_header/none), presets (PROVIDER_PRESETS), runtime CRUD (ProviderManagementService with asyncio.Lock serialization), hot-reload via AppState swap.

Applied to files:

  • src/synthorg/api/controllers/setup.py
📚 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 src/synthorg/**/*.py : `RetryConfig` and `RateLimiterConfig` are set per-provider in `ProviderConfig`. Retryable errors: `RateLimitError`, `ProviderTimeoutError`, `ProviderConnectionError`, `ProviderInternalError`. Non-retryable errors raise immediately.

Applied to files:

  • src/synthorg/api/controllers/setup.py
📚 Learning: 2026-03-20T21:44:04.528Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-20T21:44:04.528Z
Learning: Applies to src/synthorg/**/*.py : Use frozen Pydantic models for config/identity; use separate mutable-via-copy models (via `model_copy(update=...)`) for runtime state that evolves

Applied to files:

  • src/synthorg/api/controllers/setup_models.py
📚 Learning: 2026-03-15T18:38:44.202Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:38:44.202Z
Learning: Applies to src/synthorg/**/*.py : Use frozen Pydantic models for config/identity; separate mutable-via-copy models (using `model_copy(update=...)`) for runtime state

Applied to files:

  • src/synthorg/api/controllers/setup_models.py
📚 Learning: 2026-03-15T19:14:27.144Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T19:14:27.144Z
Learning: Applies to src/synthorg/**/*.py : Use frozen Pydantic models for config/identity; use separate mutable-via-copy models (using model_copy(update=...)) for runtime state that evolves. Never mix static config fields with mutable runtime fields in one model.

Applied to files:

  • src/synthorg/api/controllers/setup_models.py
📚 Learning: 2026-03-20T21:44:04.528Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-20T21:44:04.528Z
Learning: Applies to tests/**/*.py : Fix flaky tests completely and fundamentally; for timing-sensitive tests, mock `time.monotonic()` and `asyncio.sleep()` to make them deterministic instead of widening timing margins

Applied to files:

  • tests/integration/api/test_first_run_flow.py
🪛 GitHub Check: Dashboard Lint
web/src/pages/LoginPage.tsx

[warning] 78-78:
Potential timing attack, left side: true

🔇 Additional comments (50)
web/src/pages/OrgEditPage.tsx (1)

108-108: Good accessibility improvement with alert semantics.

Adding role="alert" to these banners is the right change for screen-reader announcement of important state messages.

Also applies to: 135-135, 143-143

web/src/stores/company.ts (1)

105-105: LGTM! Error formatting consistency improved.

Formatting the error with getErrorMessage(err) aligns with the error handling pattern used throughout this store (lines 71, 93, 118, 134, 150, 165, 176, 192, 208, 223, 245) and provides cleaner, more consistent observability logs.

web/src/__tests__/pages/org-edit/DepartmentCreateDialog.test.tsx (1)

19-19: Good mock isolation update.

Using vi.resetAllMocks() in setup improves per-test isolation for this suite.

web/src/__tests__/pages/org-edit/DepartmentsTab.test.tsx (1)

27-27: Looks good.

vi.resetAllMocks() is a solid choice for preventing cross-test mock leakage.

web/src/__tests__/pages/org-edit/AgentCreateDialog.test.tsx (1)

21-21: Approved.

Resetting mocks in beforeEach helps keep this dialog suite deterministic.

web/src/__tests__/pages/org-edit/YamlEditorPanel.test.tsx (1)

8-8: Nice consistency improvement.

This mock reset pattern is appropriate for isolating tests in the panel suite.

web/src/__tests__/pages/org-edit/AgentEditDrawer.test.tsx (1)

26-26: Good change.

Using full mock resets in setup keeps drawer tests isolated and predictable.

web/src/__tests__/pages/org-edit/AgentsTab.test.tsx (1)

38-38: Approved.

vi.resetAllMocks() is appropriate here for per-test isolation in AgentsTab tests.

web/src/__tests__/pages/org-edit/DepartmentEditDrawer.test.tsx (1)

29-29: Looks good.

This reset strategy is a solid fit for keeping drawer test cases independent.

web/src/pages/org-edit/GeneralTab.tsx (1)

127-127: Good UX guard on Save button.

Disabling Save when the form is pristine (and while saving) avoids unnecessary update calls.

web/src/__tests__/pages/org-edit/GeneralTab.test.tsx (1)

51-53: Good fix: the test now makes the form dirty before asserting save payload.

This change correctly aligns the test with the new “pristine form cannot save” behavior and validates the updated company_name value.

Also applies to: 57-57

web/src/__tests__/App.test.tsx (1)

54-56: LGTM!

The test assertion correctly reflects the updated LoginPage heading ("Sign In" instead of "Login"), aligning with the UI changes described in the PR summary.

docs/design/brand-and-ux.md (1)

203-203: LGTM!

The documentation correctly reflects the updated DeptHealthBar prop optionality: health? (null-safe with "N/A" fallback) and taskCount?, while agentCount remains required. This aligns with the corresponding update in CLAUDE.md.

CLAUDE.md (3)

173-173: LGTM!

The API package documentation correctly reflects the new bootstrap.py module for agent registry initialization from persisted config at startup.


223-223: LGTM!

The DeptHealthBar component inventory correctly documents the updated prop optionality (health?, taskCount?) with the null-safe "N/A" rendering behavior.


517-520: LGTM!

Minor comment cleanup in the logging bootstrap section.

src/synthorg/templates/loader.py (2)

44-44: LGTM!

The TemplateVariable import and new variables field on TemplateInfo correctly extend template metadata to expose user-configurable variables. The frozen dataclass with tuple field maintains immutability.

Also applies to: 85-85


129-129: LGTM!

Both list_templates() and _collect_user_templates() correctly populate the new variables field from loaded.template.variables, enabling the API to return template variable metadata.

Also applies to: 157-157

src/synthorg/observability/events/setup.py (1)

99-110: LGTM!

The new event constants follow the established setup.<entity>.<action> naming convention and are properly typed as Final[str]. The comments clearly document each event's purpose in the agent bootstrap flow.

src/synthorg/api/controllers/setup_models.py (3)

36-54: LGTM!

The new TemplateVariableResponse model correctly mirrors the TemplateVariable schema fields (name, description, var_type, default, required) and uses a frozen config for immutability.


84-87: LGTM!

The variables field correctly uses tuple[TemplateVariableResponse, ...] for immutability and provides a sensible default of ().


99-99: Good addition of extra="forbid" to request models.

This strengthens the API contract by rejecting requests with unknown fields, preventing silent data loss and catching client-side typos early. The existing tests confirm no regressions.

Also applies to: 174-174

web/src/api/endpoints/setup.ts (1)

99-101: LGTM!

Tightening the return type to { setup_complete: true } accurately reflects the API contract: success always returns true, while failures throw exceptions. This improves type safety without affecting runtime behavior. The context snippets confirm callers handle errors via try/catch, not by checking for false.

src/synthorg/api/app.py (2)

205-257: Well-implemented conditional bootstrap with appropriate resilience.

The _maybe_bootstrap_agents function correctly:

  • Guards against missing services before attempting bootstrap
  • Checks setup_complete setting before loading agents
  • Uses non-fatal error handling to avoid blocking startup on bootstrap failures
  • Re-raises MemoryError/RecursionError per project convention
  • Uses deferred import to reduce startup coupling

Consider adding an explicit return type annotation for consistency with project conventions:

♻️ Suggested improvement
-async def _maybe_bootstrap_agents(app_state: AppState) -> None:
+async def _maybe_bootstrap_agents(app_state: AppState) -> None:

(The diff shows no change because the function already has the annotation — my scratchpad analysis was incorrect on re-inspection. LGTM!)


359-359: LGTM!

Agent bootstrap is correctly wired into the startup sequence after Phase 2 auto-wiring completes (ensuring SettingsService is available) and before the background ticket cleanup task starts.

web/src/pages/LoginPage.tsx (5)

78-81: Static analysis warning is a false positive here.

The timing attack warning on password !== confirmPassword is a false positive. This comparison is for client-side UX validation (ensuring the user typed the same password twice), not for security-sensitive authentication. Timing attacks apply to server-side credential verification, not client-side form validation.


26-42: LGTM! Setup status detection with proper cleanup.

The effect correctly:

  1. Uses a cancellation flag to prevent state updates after unmount
  2. Falls back to login mode on network errors (safe default)
  3. Applies server-provided min_password_length with a fallback constant

44-66: LGTM! Login handler with proper lockout integration.

The handler correctly:

  1. Validates inputs before network call
  2. Checks lockout status with checkAndClearLockout()
  3. Resets on success, records failures for rate limiting
  4. Surfaces either lockout message or API error to user

68-91: LGTM! Setup handler with appropriate validation.

The handler correctly validates inputs in sensible order (username → length → match) before calling setup(). Note that lockout is intentionally not used for admin account creation, which is appropriate since this is a one-time first-run operation.


171-189: Good accessibility implementation with role="alert" on error messages.

Both the error message (Line 174) and lockout warning (Line 184) correctly use role="alert" for screen reader announcement, ensuring users with assistive technology are notified of form state changes.

src/synthorg/api/controllers/setup.py (5)

213-222: LGTM! Template variables mapping looks correct.

The variables tuple comprehension properly transforms TemplateInfo.variables into TemplateVariableResponse objects with all required fields mapped correctly.


758-803: LGTM! Non-fatal reinitialization logic is well-structured.

The function correctly:

  1. Guards on has_config_resolver before proceeding
  2. Handles provider reload failures gracefully with logging
  3. Guards on has_agent_registry before bootstrap attempt
  4. Logs warnings with context on failures while allowing setup to succeed

805-819: LGTM! Fail-open error handling is appropriate for setup status detection.

The function correctly uses fail-open semantics (returning True on error) which ensures the setup wizard is shown when the system state is uncertain.


1154-1180: LGTM! Updated docstring accurately reflects the exception propagation behavior.

The function properly distinguishes between:

  • SettingNotFoundError: Returns False (setup not complete)
  • Unexpected exceptions: Logs at ERROR level and propagates

749-751: LGTM! Post-setup reinitialization is correctly integrated.

The reinit call is properly placed after the setup_complete flag is set, ensuring that even if reinit fails, the setup completion persists and users can restart the server to pick up changes.

web/src/pages/LoginPage.stories.tsx (1)

15-32: LGTM! Storybook meta configuration is well-structured.

The meta correctly configures layout: 'fullscreen' and wraps stories with MemoryRouter for routing context.

tests/unit/api/controllers/test_setup.py (3)

513-551: LGTM! Comprehensive test for agent bootstrapping during setup completion.

The test correctly:

  1. Seeds required prerequisites (company_name, agents, provider_registry)
  2. Verifies the endpoint succeeds
  3. Asserts agents are registered in the runtime registry
  4. Properly cleans up state in the finally block

553-587: LGTM! Good test for non-fatal bootstrap failure handling.

This test validates the critical requirement that setup completion succeeds even when agent bootstrap fails, ensuring users aren't blocked by transient errors during first-run.


589-648: LGTM! Effective test for provider registry reload verification.

The test uses a controlled fake _post_setup_reinit to verify:

  1. The function is invoked during setup completion
  2. The provider registry swap mechanism works correctly
web/src/__tests__/pages/LoginPage.test.tsx (3)

7-33: LGTM! Well-structured mock setup with proper isolation.

The mocks for useAuthStore, getSetupStatus, and useLoginLockout are correctly configured with:

  • Separate mock functions for login and setup
  • Controllable lockout state via mockLockout object
  • Proper hook pattern simulation via selectors

168-186: LGTM! Good validation test for password mismatch in admin creation.

The test correctly:

  1. Sets up admin mode via mock
  2. Fills form with mismatched passwords
  3. Verifies the error message appears
  4. Confirms mockSetup was not called (validation blocked submission)

250-261: LGTM! Lockout state test verifies both UI elements.

The test correctly validates that when locked:

  1. The submit button is disabled
  2. The lockout warning message is displayed
tests/unit/api/test_bootstrap.py (3)

84-109: Good documentation of the re-call behavior.

The test correctly documents that repeated bootstrap_agents calls with fresh AgentConfig objects (new UUIDs) will register additional agents rather than being truly idempotent. This is important for understanding the function's behavior at startup vs. post-setup-complete.


111-132: LGTM! Good resilience test for invalid configs.

The test verifies that one broken config doesn't abort the entire bootstrap process—valid configs continue to register while invalid ones are skipped with a warning.


256-283: LGTM! Good test for bootstrap invocation with correct arguments.

The test verifies that when setup_complete == "true", bootstrap_agents is called with the correct keyword arguments (config_resolver and agent_registry from app_state).

src/synthorg/api/bootstrap.py (3)

35-44: LGTM! Good fallback handling for missing model configuration.

The function correctly logs a warning with context (agent_name, reason) when falling back to unknown provider/model, making debugging easier.


47-72: LGTM! Complete field mapping from AgentConfig to AgentIdentity.

The function correctly:

  1. Maps all required fields (name, role, department, level, model)
  2. Handles optional config dicts with sensible defaults
  3. Sets hiring_date to current UTC date
  4. Preserves autonomy_level from config

75-141: LGTM! Resilient bootstrap loop with proper error categorization.

The function demonstrates good practices:

  1. Resilience: Invalid configs are skipped with warnings, not aborted
  2. Idempotency: Already-registered agents are logged at DEBUG level (not warnings)
  3. Observability: Final log includes both count (successes) and total_configs for monitoring
  4. Safety: MemoryError/RecursionError are re-raised per PEP 758 pattern
tests/integration/api/test_first_run_flow.py (2)

56-108: LGTM! Well-structured integration test fixture.

The fixture correctly:

  1. Creates isolated fake persistence and message bus
  2. Configures real services (AuthService, SettingsService, AgentRegistryService)
  3. Provides a stub provider registry for completion validation
  4. Patches provider management for model validation during agent creation

115-198: LGTM! Comprehensive end-to-end test for the first-run wizard.

The test exercises the complete happy path:

  1. Status check confirms first-run state
  2. Admin creation and login
  3. Template discovery
  4. Company and agent creation
  5. Setup completion
  6. Runtime registry verification

This provides confidence that all the new bootstrap/reinit logic integrates correctly.


beforeEach(() => {
vi.clearAllMocks()
vi.resetAllMocks()
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify whether GeneralTab treats onUpdate asynchronously and whether this suite
# depends on mockResolvedValue behavior.
rg -nP --type=tsx -C3 '\bonUpdate\b|await\s+onUpdate|onUpdate\s*\(' web/src/pages/org-edit/GeneralTab.tsx
rg -nP --type=tsx -C3 'mockResolvedValue|resetAllMocks|clearAllMocks' web/src/__tests__/pages/org-edit/GeneralTab.test.tsx

Repository: Aureliolo/synthorg

Length of output: 117


🏁 Script executed:

# Check the test file directly - corrected without tsx file type
cat -n web/src/__tests__/pages/org-edit/GeneralTab.test.tsx | head -80

Repository: Aureliolo/synthorg

Length of output: 3648


🏁 Script executed:

# Also check the component being tested
cat -n web/src/pages/org-edit/GeneralTab.tsx | head -100

Repository: Aureliolo/synthorg

Length of output: 4211


Avoid vi.resetAllMocks() here; it drops the async mock implementation.

At Line 9, vi.resetAllMocks() resets mockOnUpdate back to a bare mock, losing the Promise-returning behavior from Line 6. The component's handleSave (Lines 68-81 in GeneralTab.tsx) explicitly calls await onUpdate(...), so the mock must return a resolved Promise. Use vi.clearAllMocks() instead to preserve the implementation while clearing call history.

🔧 Proposed fix
 beforeEach(() => {
-  vi.resetAllMocks()
+  vi.clearAllMocks()
 })
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@web/src/__tests__/pages/org-edit/GeneralTab.test.tsx` at line 9, The test
calls vi.resetAllMocks() which wipes the async implementation on mockOnUpdate so
handleSave’s awaited onUpdate call no longer returns a Promise; replace
vi.resetAllMocks() with vi.clearAllMocks() in the test (keeping the
Promise-returning implementation assigned to mockOnUpdate) so call history is
cleared but the async mock implementation used by GeneralTab.handleSave/onUpdate
is preserved.

@codecov
Copy link
Copy Markdown

codecov bot commented Mar 28, 2026

Codecov Report

❌ Patch coverage is 75.22124% with 28 lines in your changes missing coverage. Please review.
✅ Project coverage is 92.10%. Comparing base (9f8dd98) to head (9783fd0).
⚠️ Report is 7 commits behind head on main.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
src/synthorg/api/controllers/setup.py 41.37% 14 Missing and 3 partials ⚠️
src/synthorg/api/bootstrap.py 82.50% 7 Missing ⚠️
src/synthorg/api/app.py 91.66% 2 Missing ⚠️
src/synthorg/api/openapi.py 71.42% 1 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #896      +/-   ##
==========================================
- Coverage   92.16%   92.10%   -0.06%     
==========================================
  Files         592      593       +1     
  Lines       31216    31324     +108     
  Branches     3031     3041      +10     
==========================================
+ Hits        28770    28851      +81     
- Misses       1932     1955      +23     
- Partials      514      518       +4     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

Caution

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

⚠️ Outside diff range comments (1)
src/synthorg/api/controllers/setup.py (1)

806-821: ⚠️ Potential issue | 🟡 Minor

QueryError is caught implicitly via the generic Exception handler, not propagating as stated.

The function will fail-open (return True) if QueryError is raised from count_by_role() because the except Exception as exc: clause catches it. However, per coding guidelines requiring explicit error handling, QueryError should be named explicitly in the exception handler to clarify intent. Other call sites show inconsistent patterns: users.py explicitly catches QueryError with custom logic, while auth/controller.py doesn't catch it at all. Update the exception handler to explicitly catch QueryError alongside other exceptions:

except (QueryError, Exception) as exc:

Alternatively, if QueryError should propagate to surface database issues, remove it from the generic handler and document why the fail-open behavior applies only to non-query exceptions.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/synthorg/api/controllers/setup.py` around lines 806 - 821, The
_check_needs_admin function currently swallows QueryError via the broad except
Exception handler; update the exception handling around the await
persistence.users.count_by_role(HumanRole.CEO) call so QueryError is named
explicitly (e.g., change the handler to catch QueryError alongside Exception) so
the intent is clear and QueryError handling is not implicit—adjust the except
clause in _check_needs_admin to explicitly include QueryError (or remove it if
you intend QueryError to propagate) and keep the existing logging/return
behavior for the remaining exceptions.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@tests/integration/api/test_first_run_flow.py`:
- Around line 42-55: The fixture fake_message_bus starts the FakeMessageBus but
never stops it; change it to yield the bus and perform cleanup after yield by
calling the appropriate shutdown method (e.g., await bus.stop() or await
bus.shutdown()) so resources are released; locate the fake_message_bus fixture
and replace the current return with a yield pattern and ensure the stop/shutdown
method on FakeMessageBus is awaited in the teardown.
- Around line 200-203: The test uses deprecated asyncio.get_event_loop() to run
the coroutine for agent_count; replace that usage by calling
asyncio.run(app_state.agent_registry.agent_count()) (or create a new event loop
via asyncio.new_event_loop() and set it if you need explicit control) and assign
the result to agent_count, ensuring you remove the
get_event_loop()/run_until_complete pattern around
app_state.agent_registry.agent_count().

In `@tests/unit/api/controllers/test_setup.py`:
- Around line 549-553: The test uses asyncio.get_event_loop() (in
tests/unit/api/controllers/test_setup.py around the agent_count check and
similarly at the other occurrence) which is deprecated; replace it by creating
an explicit loop with asyncio.new_event_loop(), set it as the current loop with
asyncio.set_event_loop(loop) before running
loop.run_until_complete(app_state.agent_registry.agent_count()), and then close
the loop with loop.close() after the assertion (or alternatively switch the test
to a pytest-asyncio async test and await app_state.agent_registry.agent_count()
directly); update both occurrences referenced in the comment.

In `@web/src/pages/org-edit/GeneralTab.tsx`:
- Line 33: The line initializing budgetFormatter in GeneralTab.tsx exceeds the
88-char limit; refactor the statement so the Intl.NumberFormat constructor
arguments and options are wrapped across multiple lines (e.g., place the locale
argument and the options object on separate lines) to reduce line length while
preserving the same settings (style: 'decimal', maximumFractionDigits: 0);
ensure the identifier budgetFormatter and its configuration remain unchanged
other than formatting.

---

Outside diff comments:
In `@src/synthorg/api/controllers/setup.py`:
- Around line 806-821: The _check_needs_admin function currently swallows
QueryError via the broad except Exception handler; update the exception handling
around the await persistence.users.count_by_role(HumanRole.CEO) call so
QueryError is named explicitly (e.g., change the handler to catch QueryError
alongside Exception) so the intent is clear and QueryError handling is not
implicit—adjust the except clause in _check_needs_admin to explicitly include
QueryError (or remove it if you intend QueryError to propagate) and keep the
existing logging/return behavior for the remaining exceptions.
🪄 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: f6015745-c26d-421e-afd1-df3197ad6d89

📥 Commits

Reviewing files that changed from the base of the PR and between e3cec39 and c768b12.

📒 Files selected for processing (27)
  • CLAUDE.md
  • docs/design/brand-and-ux.md
  • src/synthorg/api/app.py
  • src/synthorg/api/bootstrap.py
  • src/synthorg/api/controllers/setup.py
  • src/synthorg/api/controllers/setup_models.py
  • src/synthorg/observability/events/setup.py
  • src/synthorg/templates/loader.py
  • tests/integration/api/test_first_run_flow.py
  • tests/unit/api/controllers/test_setup.py
  • tests/unit/api/test_bootstrap.py
  • web/src/__tests__/App.test.tsx
  • web/src/__tests__/pages/LoginPage.test.tsx
  • web/src/__tests__/pages/org-edit/AgentCreateDialog.test.tsx
  • web/src/__tests__/pages/org-edit/AgentEditDrawer.test.tsx
  • web/src/__tests__/pages/org-edit/AgentsTab.test.tsx
  • web/src/__tests__/pages/org-edit/DepartmentCreateDialog.test.tsx
  • web/src/__tests__/pages/org-edit/DepartmentEditDrawer.test.tsx
  • web/src/__tests__/pages/org-edit/DepartmentsTab.test.tsx
  • web/src/__tests__/pages/org-edit/GeneralTab.test.tsx
  • web/src/__tests__/pages/org-edit/YamlEditorPanel.test.tsx
  • web/src/api/endpoints/setup.ts
  • web/src/pages/LoginPage.stories.tsx
  • web/src/pages/LoginPage.tsx
  • web/src/pages/OrgEditPage.tsx
  • web/src/pages/org-edit/GeneralTab.tsx
  • web/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). (7)
  • GitHub Check: Test (Python 3.14)
  • 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 (10)
**/*.{py,ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Line length: 88 characters (ruff enforced).

Files:

  • web/src/__tests__/pages/org-edit/AgentCreateDialog.test.tsx
  • web/src/__tests__/pages/org-edit/AgentEditDrawer.test.tsx
  • web/src/__tests__/pages/org-edit/YamlEditorPanel.test.tsx
  • web/src/__tests__/App.test.tsx
  • web/src/__tests__/pages/org-edit/DepartmentCreateDialog.test.tsx
  • web/src/__tests__/pages/org-edit/DepartmentsTab.test.tsx
  • web/src/stores/company.ts
  • web/src/__tests__/pages/org-edit/AgentsTab.test.tsx
  • web/src/__tests__/pages/org-edit/DepartmentEditDrawer.test.tsx
  • web/src/pages/OrgEditPage.tsx
  • web/src/pages/org-edit/GeneralTab.tsx
  • src/synthorg/templates/loader.py
  • web/src/api/endpoints/setup.ts
  • src/synthorg/api/app.py
  • web/src/pages/LoginPage.stories.tsx
  • src/synthorg/observability/events/setup.py
  • web/src/pages/LoginPage.tsx
  • tests/unit/api/test_bootstrap.py
  • src/synthorg/api/bootstrap.py
  • web/src/__tests__/pages/org-edit/GeneralTab.test.tsx
  • tests/integration/api/test_first_run_flow.py
  • web/src/__tests__/pages/LoginPage.test.tsx
  • src/synthorg/api/controllers/setup_models.py
  • tests/unit/api/controllers/test_setup.py
  • src/synthorg/api/controllers/setup.py
web/src/**/*.{tsx,ts}

📄 CodeRabbit inference engine (CLAUDE.md)

web/src/**/*.{tsx,ts}: Use Tailwind semantic classes (text-foreground, bg-card, text-accent, etc.) or CSS variables (var(--so-accent)). NEVER hardcode hex values in .tsx/.ts files. Use design token variables for colors, typography, spacing, shadows, borders.
Import cn from @/lib/utils for conditional class merging in React components.
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 a shared component.
Use StatusBadge for agent/task/system status indicators (colored dot + optional built-in label toggle).
Use MetricCard for numeric KPIs with sparkline, change badge, progress bar.
Use SectionCard for titled card wrapper with icon and action slot.
Use AgentCard for agent display: avatar, name, role, status, current task.
Use DeptHealthBar for department health: animated fill bar + health (required) + agentCount/taskCount (required).
Use ProgressGauge for circular gauge for budget/utilization (max? defaults to 100).
Use Avatar for circular initials avatar with optional borderColor? prop.
Use Toast / ToastContainer for success/error/warning/info notifications with auto-dismiss queue. Mount ToastContainer once in AppLayout.
Use Skeleton / SkeletonCard / SkeletonMetric / SkeletonTable / SkeletonText for loading placeholders matching component shapes (shimmer animation, respects prefers-reduced-motion).
Use ErrorBoundary React error boundary with retry -- level prop: page / section / component.
Use ConfirmDialog for confirmation modal (Radix AlertDialog) with default / destructive variants and loading state.
Use CommandPalette for global Cmd+K search (cmdk + React Router) -- mount once in AppLayout, register commands via `useComma...

Files:

  • web/src/__tests__/pages/org-edit/AgentCreateDialog.test.tsx
  • web/src/__tests__/pages/org-edit/AgentEditDrawer.test.tsx
  • web/src/__tests__/pages/org-edit/YamlEditorPanel.test.tsx
  • web/src/__tests__/App.test.tsx
  • web/src/__tests__/pages/org-edit/DepartmentCreateDialog.test.tsx
  • web/src/__tests__/pages/org-edit/DepartmentsTab.test.tsx
  • web/src/stores/company.ts
  • web/src/__tests__/pages/org-edit/AgentsTab.test.tsx
  • web/src/__tests__/pages/org-edit/DepartmentEditDrawer.test.tsx
  • web/src/pages/OrgEditPage.tsx
  • web/src/pages/org-edit/GeneralTab.tsx
  • web/src/api/endpoints/setup.ts
  • web/src/pages/LoginPage.stories.tsx
  • web/src/pages/LoginPage.tsx
  • web/src/__tests__/pages/org-edit/GeneralTab.test.tsx
  • web/src/__tests__/pages/LoginPage.test.tsx
web/src/__tests__/**/*.test.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Web dashboard: test with Vitest unit + property tests (fast-check). Mirror src/ structure in __tests__/. Property tests use fc.assert + fc.property.

Files:

  • web/src/__tests__/pages/org-edit/AgentCreateDialog.test.tsx
  • web/src/__tests__/pages/org-edit/AgentEditDrawer.test.tsx
  • web/src/__tests__/pages/org-edit/YamlEditorPanel.test.tsx
  • web/src/__tests__/App.test.tsx
  • web/src/__tests__/pages/org-edit/DepartmentCreateDialog.test.tsx
  • web/src/__tests__/pages/org-edit/DepartmentsTab.test.tsx
  • web/src/__tests__/pages/org-edit/AgentsTab.test.tsx
  • web/src/__tests__/pages/org-edit/DepartmentEditDrawer.test.tsx
  • web/src/__tests__/pages/org-edit/GeneralTab.test.tsx
  • web/src/__tests__/pages/LoginPage.test.tsx
web/src/stores/**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

React: use Zustand stores for global state (auth, WebSocket, toast, analytics, setup wizard, company, agents, budget, tasks, settings, providers). Create per-domain stores for page data.

Files:

  • web/src/stores/company.ts
**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.py: No from __future__ import annotations -- Python 3.14 has PEP 649 native lazy annotations.
Use PEP 758 except syntax: except A, B: (no parentheses) -- ruff enforces this on Python 3.14.

Files:

  • src/synthorg/templates/loader.py
  • src/synthorg/api/app.py
  • src/synthorg/observability/events/setup.py
  • tests/unit/api/test_bootstrap.py
  • src/synthorg/api/bootstrap.py
  • tests/integration/api/test_first_run_flow.py
  • src/synthorg/api/controllers/setup_models.py
  • tests/unit/api/controllers/test_setup.py
  • src/synthorg/api/controllers/setup.py
src/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

src/**/*.py: All public functions require type hints. Enforce mypy strict mode.
Google-style docstrings required on all public classes and functions. Enforced by ruff D rules.
Never mutate existing objects. Create new objects instead. For non-Pydantic internal collections (registries, BaseTool), use copy.deepcopy() at construction + MappingProxyType wrapping for read-only enforcement.
For dict/list fields in frozen Pydantic models, use copy.deepcopy() at system boundaries (tool execution, LLM provider serialization, inter-agent delegation, serializing for persistence).
Use frozen Pydantic models for config/identity; use separate mutable-via-copy models (using model_copy(update=...)) for runtime state that evolves. Never mix static config fields with mutable runtime fields in one model.
Use Pydantic v2 conventions: BaseModel, model_validator, computed_field, ConfigDict. Use @computed_field for derived values instead of storing redundant fields. Use NotBlankStr for all identifier/name fields.
Prefer asyncio.TaskGroup for fan-out/fan-in parallel operations in new code. Prefer structured concurrency over bare create_task.
Functions must be < 50 lines, files < 800 lines.
Never use real vendor names (Anthropic, OpenAI, Claude, GPT, etc.) in project-owned code, docstrings, comments, tests, or config examples. Use generic names: example-provider, example-large-001, test-provider, test-small-001.

Files:

  • src/synthorg/templates/loader.py
  • src/synthorg/api/app.py
  • src/synthorg/observability/events/setup.py
  • src/synthorg/api/bootstrap.py
  • src/synthorg/api/controllers/setup_models.py
  • src/synthorg/api/controllers/setup.py
src/**/*.{py,ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

src/**/*.{py,ts,tsx}: Handle errors explicitly. Never silently swallow exceptions.
Validate at system boundaries (user input, external APIs, config files).

Files:

  • src/synthorg/templates/loader.py
  • src/synthorg/api/app.py
  • src/synthorg/observability/events/setup.py
  • src/synthorg/api/bootstrap.py
  • src/synthorg/api/controllers/setup_models.py
  • src/synthorg/api/controllers/setup.py
src/synthorg/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

src/synthorg/**/*.py: Every module with business logic must have: from synthorg.observability import get_logger then logger = get_logger(__name__). Never use import logging / logging.getLogger() / print() in application code.
Always use structured logging: logger.info(EVENT, key=value). Never use format strings like logger.info("msg %s", val).
Use event name constants from domain-specific modules under synthorg.observability.events (e.g., API_REQUEST_STARTED from events.api). Import directly: from synthorg.observability.events.<domain> import EVENT_CONSTANT.
All error paths must log at WARNING or ERROR with context before raising. All state transitions must log at INFO. DEBUG for object creation, internal flow, entry/exit of key functions.

Files:

  • src/synthorg/templates/loader.py
  • src/synthorg/api/app.py
  • src/synthorg/observability/events/setup.py
  • src/synthorg/api/bootstrap.py
  • src/synthorg/api/controllers/setup_models.py
  • src/synthorg/api/controllers/setup.py
web/src/**/*.stories.tsx

📄 CodeRabbit inference engine (CLAUDE.md)

Post-Training Reference: Storybook 10 - ESM-only; @storybook/addon-docs is separate; import from storybook/test and storybook/actions; use defineMain and definePreview; backgrounds API uses parameters.backgrounds.options (object) + initialGlobals.backgrounds.value; a11y uses parameters.a11y.test; minimum versions: Node 20.19+, Vite 5+, Vitest 3+, TypeScript 4.9+.

Files:

  • web/src/pages/LoginPage.stories.tsx
tests/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

tests/**/*.py: Test markers: @pytest.mark.unit, @pytest.mark.integration, @pytest.mark.e2e, @pytest.mark.slow.
80% minimum code coverage (enforced in CI). Never skip, dismiss, or ignore flaky tests -- fix them fully and fundamentally.
Async tests: asyncio_mode = "auto" -- no manual @pytest.mark.asyncio needed. Default timeout: 30 seconds per test. Always run pytest with -n auto for parallelism (never sequentially).
Prefer @pytest.mark.parametrize for testing similar cases.
For timing-sensitive tests, mock time.monotonic() and asyncio.sleep() to make them deterministic. For tasks that must block indefinitely, use asyncio.Event().wait() instead of asyncio.sleep(large_number).
Property-based testing: use Hypothesis with @given + @settings. Run dev profile (1000 examples) with HYPOTHESIS_PROFILE=dev.

Files:

  • tests/unit/api/test_bootstrap.py
  • tests/integration/api/test_first_run_flow.py
  • tests/unit/api/controllers/test_setup.py
🧠 Learnings (64)
📓 Common learnings
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-26T15:18:16.848Z
Learning: Applies to src/synthorg/api/**/*.py : Litestar API must include setup wizard, auth/, auto-wiring, and lifecycle management
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/api/**/*.py : API package (api/): Litestar REST + WebSocket with controllers, guards, channels, JWT + API key + WS ticket auth, approval gate integration, coordination endpoint, collaboration endpoint, settings endpoint, provider management endpoint (CRUD + test + presets), backup endpoint, RFC 9457 structured errors, AppState hot-reload slots, service auto-wiring (Phase 1 at construction, Phase 2 on startup), lifecycle helpers
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...
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
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-20T08:28:32.845Z
Learning: Applies to src/synthorg/providers/**/*.py : Providers: LLM provider abstraction (LiteLLM adapter), auth types (api_key/oauth/custom_header/none), presets (PROVIDER_PRESETS), runtime CRUD (ProviderManagementService with asyncio.Lock serialization), hot-reload via AppState swap.
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)
📚 Learning: 2026-03-28T10:20:33.391Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T10:20:33.391Z
Learning: Applies to web/src/__tests__/**/*.test.{ts,tsx} : Web dashboard: test with Vitest unit + property tests (`fast-check`). Mirror `src/` structure in `__tests__/`. Property tests use `fc.assert` + `fc.property`.

Applied to files:

  • web/src/__tests__/pages/org-edit/AgentCreateDialog.test.tsx
  • web/src/__tests__/pages/org-edit/AgentEditDrawer.test.tsx
  • web/src/__tests__/pages/org-edit/YamlEditorPanel.test.tsx
  • web/src/__tests__/App.test.tsx
  • web/src/__tests__/pages/org-edit/DepartmentCreateDialog.test.tsx
  • web/src/__tests__/pages/org-edit/DepartmentsTab.test.tsx
  • web/src/__tests__/pages/org-edit/AgentsTab.test.tsx
  • web/src/__tests__/pages/org-edit/DepartmentEditDrawer.test.tsx
  • web/src/__tests__/pages/org-edit/GeneralTab.test.tsx
  • web/src/__tests__/pages/LoginPage.test.tsx
📚 Learning: 2026-03-28T10:20:33.391Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T10:20:33.391Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use `AgentCard` for agent display: avatar, name, role, status, current task.

Applied to files:

  • web/src/__tests__/pages/org-edit/AgentCreateDialog.test.tsx
  • web/src/__tests__/pages/org-edit/AgentEditDrawer.test.tsx
  • web/src/__tests__/pages/org-edit/AgentsTab.test.tsx
  • CLAUDE.md
  • docs/design/brand-and-ux.md
📚 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-edit/AgentCreateDialog.test.tsx
  • web/src/__tests__/pages/org-edit/DepartmentCreateDialog.test.tsx
  • web/src/__tests__/pages/org-edit/DepartmentsTab.test.tsx
  • web/src/__tests__/pages/org-edit/AgentsTab.test.tsx
  • web/src/__tests__/pages/org-edit/DepartmentEditDrawer.test.tsx
  • web/src/__tests__/pages/org-edit/GeneralTab.test.tsx
  • web/src/__tests__/pages/LoginPage.test.tsx
📚 Learning: 2026-03-28T10:20:33.391Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T10:20:33.391Z
Learning: Applies to web/src/**/*.stories.tsx : Post-Training Reference: Storybook 10 - ESM-only; `storybook/addon-docs` is separate; import from `storybook/test` and `storybook/actions`; use `defineMain` and `definePreview`; backgrounds API uses `parameters.backgrounds.options` (object) + `initialGlobals.backgrounds.value`; a11y uses `parameters.a11y.test`; minimum versions: Node 20.19+, Vite 5+, Vitest 3+, TypeScript 4.9+.

Applied to files:

  • web/src/__tests__/pages/org-edit/YamlEditorPanel.test.tsx
  • web/src/__tests__/App.test.tsx
  • web/src/__tests__/pages/org-edit/AgentsTab.test.tsx
  • web/src/pages/LoginPage.stories.tsx
  • web/src/__tests__/pages/LoginPage.test.tsx
📚 Learning: 2026-03-28T10:20:33.391Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T10:20:33.391Z
Learning: Applies to web/src/**/*.{tsx,ts} : React: use Linting (ESLint) and type-checking (TypeScript). Run tests with `npm --prefix web run test` (Vitest, coverage scoped to changed files vs origin/main).

Applied to files:

  • web/src/__tests__/pages/org-edit/DepartmentsTab.test.tsx
  • web/src/__tests__/pages/org-edit/AgentsTab.test.tsx
  • web/src/__tests__/pages/org-edit/GeneralTab.test.tsx
📚 Learning: 2026-03-28T10:20:33.391Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T10:20:33.391Z
Learning: Applies to web/src/stores/**/*.ts : React: use Zustand stores for global state (auth, WebSocket, toast, analytics, setup wizard, company, agents, budget, tasks, settings, providers). Create per-domain stores for page data.

Applied to files:

  • web/src/stores/company.ts
  • web/src/pages/LoginPage.tsx
📚 Learning: 2026-03-28T10:20:33.391Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T10:20:33.391Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use `DeptHealthBar` for department health: animated fill bar + `health` (required) + `agentCount`/`taskCount` (required).

Applied to files:

  • CLAUDE.md
  • docs/design/brand-and-ux.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
  • src/synthorg/api/app.py
  • src/synthorg/api/bootstrap.py
  • src/synthorg/api/controllers/setup.py
📚 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 docs/design/*.md : Design spec pages: 7 pages in `docs/design/` — index, agents, organization, communication, engine, memory, operations

Applied to files:

  • CLAUDE.md
📚 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-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 docs/design/**/*.md : Design specification pages in `docs/design/` must be consulted before implementing features (7 pages: index, agents, organization, communication, engine, memory, operations)

Applied to files:

  • CLAUDE.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/api/**/*.py : API package (api/): Litestar REST + WebSocket with controllers, guards, channels, JWT + API key + WS ticket auth, approval gate integration, coordination endpoint, collaboration endpoint, settings endpoint, provider management endpoint (CRUD + test + presets), backup endpoint, RFC 9457 structured errors, AppState hot-reload slots, service auto-wiring (Phase 1 at construction, Phase 2 on startup), lifecycle helpers

Applied to files:

  • CLAUDE.md
  • src/synthorg/api/app.py
  • src/synthorg/api/controllers/setup.py
📚 Learning: 2026-03-26T15:18:16.848Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-26T15:18:16.848Z
Learning: Applies to src/synthorg/api/**/*.py : Litestar API must include setup wizard, auth/, auto-wiring, and lifecycle management

Applied to files:

  • CLAUDE.md
  • src/synthorg/api/app.py
  • src/synthorg/api/bootstrap.py
  • tests/integration/api/test_first_run_flow.py
  • src/synthorg/api/controllers/setup.py
📚 Learning: 2026-03-17T06:30:14.180Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T06:30:14.180Z
Learning: Applies to src/synthorg/api/**/*.py : Use Litestar for REST + WebSocket API. Controllers, guards, channels, JWT + API key + WS ticket auth, RFC 9457 structured errors.

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-03-17T22:08:13.456Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T22:08:13.456Z
Learning: Applies to src/synthorg/api/**/*.py : REST API: Litestar framework, controllers with guards, channels for WebSocket, JWT + API key + WS ticket auth, approval gate integration, coordination endpoint, collaboration endpoint, settings endpoint. RFC 9457 structured errors (ErrorCategory, ErrorCode, ErrorDetail, ProblemDetail, CATEGORY_TITLES, category_title, category_type_uri, content negotiation).

Applied to files:

  • CLAUDE.md
  • src/synthorg/api/app.py
📚 Learning: 2026-03-20T11:18:48.128Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-20T11:18:48.128Z
Learning: Applies to src/synthorg/api/**/*.py : Use Litestar for REST API and WebSocket API with JWT + API key + WS ticket authentication, RFC 9457 structured errors, and content negotiation.

Applied to files:

  • CLAUDE.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/engine/**/*.py : Engine package (engine/): agent orchestration, parallel execution, task decomposition, routing, TaskEngine (centralized single-writer), task lifecycle/recovery/shutdown, workspace isolation, coordination (4 dispatchers: SAS/centralized/decentralized/context-dependent, wave execution), approval gates (escalation detection, context parking/resume), stagnation detection (ToolRepetitionDetector, corrective prompt injection), AgentRuntimeState (execution status), context budget management, conversation compaction (oldest-turns summarizer)

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-03-17T06:30:14.180Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T06:30:14.180Z
Learning: Applies to src/synthorg/security/**/*.py : Security module includes SecOps agent, rule engine (soft-allow/hard-deny), audit log, output scanner, risk classifier, autonomy levels (4 strategies), timeout policies.

Applied to files:

  • CLAUDE.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/security/**/*.py : Security package (security/): SecOps agent, rule engine (soft-allow/hard-deny, fail-closed), audit log, output scanner, output scan response policies (redact/withhold/log-only/autonomy-tiered), risk classifier, risk tier classifier, action type registry, ToolInvoker security integration, progressive trust (4 strategies), autonomy levels (presets, resolver, change strategy), timeout policies (park/resume)

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-03-17T22:08:13.456Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T22:08:13.456Z
Learning: Documentation source in `docs/` (Markdown, built with Zensical). Design spec in `docs/design/` (7 pages: index, agents, organization, communication, engine, memory, operations). Architecture in `docs/architecture/` (overview, tech-stack, decision log). Roadmap in `docs/roadmap/`. Security in `docs/security.md`. Licensing in `docs/licensing.md`. Reference in `docs/reference/`. REST API reference in `docs/rest-api.md`. Library reference in `docs/api/` (auto-generated from docstrings). Custom templates in `docs/overrides/`. Config in `mkdocs.yml`.

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-03-28T10:20:33.391Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T10:20:33.391Z
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 a shared component.

Applied to files:

  • CLAUDE.md
  • web/src/pages/OrgEditPage.tsx
  • docs/design/brand-and-ux.md
  • web/src/pages/LoginPage.stories.tsx
  • web/src/pages/LoginPage.tsx
📚 Learning: 2026-03-28T10:20:33.391Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T10:20:33.391Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use `MetricCard` for numeric KPIs with sparkline, change badge, progress bar.

Applied to files:

  • CLAUDE.md
  • docs/design/brand-and-ux.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.md
  • docs/design/brand-and-ux.md
📚 Learning: 2026-03-28T10:20:33.391Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T10:20:33.391Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use `ProviderHealthBadge` for provider health status indicator (up/degraded/down colored dot + optional label).

Applied to files:

  • CLAUDE.md
  • web/src/pages/OrgEditPage.tsx
  • docs/design/brand-and-ux.md
📚 Learning: 2026-03-28T10:20:33.391Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T10:20:33.391Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use `SectionCard` for titled card wrapper with icon and action slot.

Applied to files:

  • CLAUDE.md
  • docs/design/brand-and-ux.md
📚 Learning: 2026-03-28T10:20:33.391Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T10:20:33.391Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use `StatusBadge` for agent/task/system status indicators (colored dot + optional built-in label toggle).

Applied to files:

  • CLAUDE.md
  • web/src/pages/OrgEditPage.tsx
  • docs/design/brand-and-ux.md
📚 Learning: 2026-03-28T10:20:33.391Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T10:20:33.391Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use `ProgressGauge` for circular gauge for budget/utilization (`max?` defaults to 100).

Applied to files:

  • CLAUDE.md
  • docs/design/brand-and-ux.md
📚 Learning: 2026-03-28T10:20:33.391Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T10:20:33.391Z
Learning: Applies to web/src/components/ui/*.tsx : When creating new shared React components: place in `web/src/components/ui/` with descriptive kebab-case filename. Create `.stories.tsx` file with all states. Export props as TypeScript interface. Use design tokens exclusively -- no hardcoded colors, fonts, or spacing.

Applied to files:

  • CLAUDE.md
  • web/src/pages/LoginPage.stories.tsx
📚 Learning: 2026-03-28T10:20:33.391Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T10:20:33.391Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use `InlineEdit` for click-to-edit text with Enter/Escape, validation, optimistic save with rollback.

Applied to files:

  • web/src/pages/OrgEditPage.tsx
  • web/src/pages/org-edit/GeneralTab.tsx
  • web/src/__tests__/pages/org-edit/GeneralTab.test.tsx
📚 Learning: 2026-03-28T10:20:33.391Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T10:20:33.391Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use `Toast` / `ToastContainer` for success/error/warning/info notifications with auto-dismiss queue. Mount `ToastContainer` once in AppLayout.

Applied to files:

  • web/src/pages/OrgEditPage.tsx
📚 Learning: 2026-03-28T10:20:33.391Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T10:20:33.391Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use `ConfirmDialog` for confirmation modal (Radix AlertDialog) with `default` / `destructive` variants and `loading` state.

Applied to files:

  • web/src/pages/OrgEditPage.tsx
📚 Learning: 2026-03-28T10:20:33.391Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T10:20:33.391Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use `Skeleton` / `SkeletonCard` / `SkeletonMetric` / `SkeletonTable` / `SkeletonText` for loading placeholders matching component shapes (shimmer animation, respects `prefers-reduced-motion`).

Applied to files:

  • docs/design/brand-and-ux.md
📚 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 src/synthorg/templates/**/*.py : Templates: pre-built company templates, personality presets, and builder.

Applied to files:

  • src/synthorg/templates/loader.py
  • src/synthorg/api/controllers/setup_models.py
  • src/synthorg/api/controllers/setup.py
📚 Learning: 2026-03-20T21:44:04.528Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-20T21:44:04.528Z
Learning: Applies to **/*.py : Use `except A, B:` syntax (without parentheses) per PEP 758 for exception handling in Python 3.14

Applied to files:

  • src/synthorg/api/app.py
  • src/synthorg/api/bootstrap.py
  • src/synthorg/api/controllers/setup.py
📚 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 **/*.py : Handle errors explicitly, never silently swallow exceptions

Applied to files:

  • src/synthorg/api/app.py
  • src/synthorg/api/bootstrap.py
  • src/synthorg/api/controllers/setup.py
📚 Learning: 2026-03-16T07:22:28.134Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-16T07:22:28.134Z
Learning: Applies to **/*.py : Handle errors explicitly; never silently swallow exceptions

Applied to files:

  • src/synthorg/api/app.py
  • src/synthorg/api/bootstrap.py
  • src/synthorg/api/controllers/setup.py
📚 Learning: 2026-03-16T07:22:28.134Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-16T07:22:28.134Z
Learning: Applies to **/*.py : Use `except A, B:` syntax (no parentheses) for exception handling — PEP 758 exception syntax enforced by ruff on Python 3.14

Applied to files:

  • src/synthorg/api/app.py
  • src/synthorg/api/bootstrap.py
  • src/synthorg/api/controllers/setup.py
📚 Learning: 2026-03-14T16:18:57.267Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T16:18:57.267Z
Learning: Applies to **/*.py : Use PEP 758 except syntax with `except A, B:` (no parentheses) for multiple exceptions—ruff enforces this on Python 3.14.

Applied to files:

  • src/synthorg/api/app.py
  • src/synthorg/api/bootstrap.py
  • src/synthorg/api/controllers/setup.py
📚 Learning: 2026-03-14T16:18:57.267Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T16:18:57.267Z
Learning: Applies to **/*.py : Handle errors explicitly—never silently swallow exceptions.

Applied to files:

  • src/synthorg/api/app.py
  • src/synthorg/api/bootstrap.py
  • src/synthorg/api/controllers/setup.py
📚 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 **/*.py : Use PEP 758 except syntax: `except A, B:` (no parentheses) — enforced by ruff on Python 3.14

Applied to files:

  • src/synthorg/api/app.py
  • src/synthorg/api/bootstrap.py
  • src/synthorg/api/controllers/setup.py
📚 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/observability/**/*.py : Observability package (observability/): structured logging, correlation tracking, log sinks; event constants organized by domain under observability/events/ (e.g., events.api, events.tool, events.git, events.context_budget, events.backup)

Applied to files:

  • src/synthorg/api/app.py
  • src/synthorg/observability/events/setup.py
  • src/synthorg/api/controllers/setup.py
📚 Learning: 2026-03-15T19:14:27.144Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T19:14:27.144Z
Learning: Applies to src/synthorg/**/*.py : Use event name constants from synthorg.observability.events domain-specific modules (e.g., PROVIDER_CALL_START from events.provider). Import directly: from synthorg.observability.events.<domain> import EVENT_CONSTANT.

Applied to files:

  • src/synthorg/api/app.py
  • src/synthorg/observability/events/setup.py
📚 Learning: 2026-03-18T21:23:23.586Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-18T21:23:23.586Z
Learning: Applies to src/synthorg/**/*.py : Event names: always use constants from the domain-specific module under synthorg.observability.events (e.g., API_REQUEST_STARTED from events.api, TOOL_INVOKE_START from events.tool). Import directly from synthorg.observability.events.<domain>.

Applied to files:

  • src/synthorg/api/app.py
  • src/synthorg/observability/events/setup.py
📚 Learning: 2026-03-28T10:20:33.390Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T10:20:33.390Z
Learning: Applies to src/synthorg/**/*.py : Use event name constants from domain-specific modules under `synthorg.observability.events` (e.g., `API_REQUEST_STARTED` from `events.api`). Import directly: `from synthorg.observability.events.<domain> import EVENT_CONSTANT`.

Applied to files:

  • src/synthorg/api/app.py
  • src/synthorg/observability/events/setup.py
📚 Learning: 2026-03-19T11:33:01.580Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T11:33:01.580Z
Learning: Applies to src/synthorg/**/*.py : Use event constants from `synthorg.observability.events.<domain>` (e.g., `API_REQUEST_STARTED` from `events.api`); import directly and log with structured kwargs: `logger.info(EVENT, key=value)`, never interpolated strings

Applied to files:

  • src/synthorg/api/app.py
  • src/synthorg/api/controllers/setup.py
📚 Learning: 2026-03-20T11:18:48.128Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-20T11:18:48.128Z
Learning: Applies to src/synthorg/**/*.py : Use event name constants from domain-specific modules under `synthorg.observability.events` (e.g., `API_REQUEST_STARTED` from `events.api`, `TOOL_INVOKE_START` from `events.tool`). Import directly: `from synthorg.observability.events.<domain> import EVENT_CONSTANT`.

Applied to files:

  • src/synthorg/api/app.py
  • src/synthorg/observability/events/setup.py
📚 Learning: 2026-03-20T21:44:04.528Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-20T21:44:04.528Z
Learning: Applies to src/synthorg/**/*.py : Always use event name constants from domain-specific modules under `synthorg.observability.events` (e.g., `API_REQUEST_STARTED` from `events.api`, `TOOL_INVOKE_START` from `events.tool`); import directly rather than using string literals

Applied to files:

  • src/synthorg/api/app.py
  • src/synthorg/observability/events/setup.py
📚 Learning: 2026-03-28T10:20:33.391Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T10:20:33.391Z
Learning: Applies to web/src/router/**/*.{ts,tsx} : React: use React Router for routing. Lazy-load page components (one per route). Use route guards for auth and setup.

Applied to files:

  • web/src/pages/LoginPage.stories.tsx
  • web/src/pages/LoginPage.tsx
  • web/src/__tests__/pages/LoginPage.test.tsx
📚 Learning: 2026-03-14T16:18:57.267Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T16:18:57.267Z
Learning: Applies to src/ai_company/!(observability)/**/*.py : Use event name constants from domain-specific modules under `ai_company.observability.events` (e.g., `PROVIDER_CALL_START` from `events.provider`). Import directly: `from ai_company.observability.events.<domain> import EVENT_CONSTANT`.

Applied to files:

  • src/synthorg/observability/events/setup.py
📚 Learning: 2026-03-15T18:38:44.202Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:38:44.202Z
Learning: Applies to src/synthorg/**/*.py : Always use event name constants from domain-specific modules under `synthorg.observability.events` (e.g., `PROVIDER_CALL_START` from `events.provider`); import directly: `from synthorg.observability.events.<domain> import EVENT_CONSTANT`

Applied to files:

  • src/synthorg/observability/events/setup.py
📚 Learning: 2026-03-15T18:28:13.207Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:28:13.207Z
Learning: Applies to src/synthorg/**/*.py : Event names: always use constants from domain-specific modules under synthorg.observability.events (e.g., PROVIDER_CALL_START from events.provider, BUDGET_RECORD_ADDED from events.budget, etc.). Import directly: `from synthorg.observability.events.<domain> import EVENT_CONSTANT`.

Applied to files:

  • src/synthorg/observability/events/setup.py
📚 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 src/**/*.py : Use event name constants from domain-specific modules under ai_company.observability.events (e.g., PROVIDER_CALL_START from events.provider, BUDGET_RECORD_ADDED from events.budget, etc.) — import directly

Applied to files:

  • src/synthorg/observability/events/setup.py
📚 Learning: 2026-03-20T21:44:04.528Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-20T21:44:04.528Z
Learning: Applies to tests/**/*.py : Fix flaky tests completely and fundamentally; for timing-sensitive tests, mock `time.monotonic()` and `asyncio.sleep()` to make them deterministic instead of widening timing margins

Applied to files:

  • tests/unit/api/test_bootstrap.py
📚 Learning: 2026-03-20T21:44:04.528Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-20T21:44:04.528Z
Learning: Applies to src/synthorg/**/*.py : Use frozen Pydantic models for config/identity; use separate mutable-via-copy models (via `model_copy(update=...)`) for runtime state that evolves

Applied to files:

  • src/synthorg/api/bootstrap.py
  • src/synthorg/api/controllers/setup_models.py
📚 Learning: 2026-03-15T16:55:07.730Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T16:55:07.730Z
Learning: Applies to **/*.py : Use PEP 758 except syntax: use `except A, B:` (no parentheses) — ruff enforces this on Python 3.14.

Applied to files:

  • src/synthorg/api/bootstrap.py
📚 Learning: 2026-03-19T21:11:37.538Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T21:11:37.538Z
Learning: Applies to **/*.py : Errors: handle explicitly, never silently swallow.

Applied to files:

  • src/synthorg/api/bootstrap.py
📚 Learning: 2026-03-28T10:20:33.390Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T10:20:33.390Z
Learning: Applies to **/*.py : Use PEP 758 except syntax: `except A, B:` (no parentheses) -- ruff enforces this on Python 3.14.

Applied to files:

  • src/synthorg/api/bootstrap.py
📚 Learning: 2026-03-15T18:38:44.202Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:38:44.202Z
Learning: Applies to src/synthorg/**/*.py : Use frozen Pydantic models for config/identity; separate mutable-via-copy models (using `model_copy(update=...)`) for runtime state

Applied to files:

  • src/synthorg/api/controllers/setup_models.py
📚 Learning: 2026-03-15T19:14:27.144Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T19:14:27.144Z
Learning: Applies to src/synthorg/**/*.py : Use frozen Pydantic models for config/identity; use separate mutable-via-copy models (using model_copy(update=...)) for runtime state that evolves. Never mix static config fields with mutable runtime fields in one model.

Applied to files:

  • src/synthorg/api/controllers/setup_models.py
📚 Learning: 2026-03-28T10:20:33.391Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T10:20:33.391Z
Learning: Applies to tests/**/*.py : For timing-sensitive tests, mock `time.monotonic()` and `asyncio.sleep()` to make them deterministic. For tasks that must block indefinitely, use `asyncio.Event().wait()` instead of `asyncio.sleep(large_number)`.

Applied to files:

  • tests/unit/api/controllers/test_setup.py
📚 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/settings/**/*.py : Settings package (settings/): runtime-editable settings persistence (DB > env > YAML > code defaults), typed definitions (9 namespaces), Fernet encryption for sensitive values, config bridge (JSON serialization for Pydantic/collections), ConfigResolver (typed accessors), validation, registry, change notifications via message bus, SettingsSubscriber protocol, SettingsChangeDispatcher (polls `#settings` channel, routes to subscribers, restart_required filtering)

Applied to files:

  • src/synthorg/api/controllers/setup.py
📚 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 src/synthorg/providers/**/*.py : Providers: LLM provider abstraction (LiteLLM adapter), auth types (api_key/oauth/custom_header/none), presets (PROVIDER_PRESETS), runtime CRUD (ProviderManagementService with asyncio.Lock serialization), hot-reload via AppState swap.

Applied to files:

  • src/synthorg/api/controllers/setup.py
📚 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 src/synthorg/**/*.py : `RetryConfig` and `RateLimiterConfig` are set per-provider in `ProviderConfig`. Retryable errors: `RateLimitError`, `ProviderTimeoutError`, `ProviderConnectionError`, `ProviderInternalError`. Non-retryable errors raise immediately.

Applied to files:

  • src/synthorg/api/controllers/setup.py
🪛 GitHub Check: Dashboard Lint
web/src/pages/LoginPage.tsx

[warning] 78-78:
Potential timing attack, left side: true

Aureliolo and others added 7 commits March 28, 2026 12:49
Branded login page with first-run detection (admin creation vs sign in),
lockout protection, and proper error handling. Agent bootstrap routine
loads persisted configs into the runtime registry on startup and after
setup completion. Engine re-init reloads provider registry atomically.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… tests

Pre-reviewed by 16 agents, 30 findings addressed:

- Add MemoryError/RecursionError guard + logging in _maybe_bootstrap_agents
- Broaden exception catches in bootstrap loop (ValidationError -> Exception)
- Add logging for unknown provider fallback in _identity_from_config
- Use dedicated event constants for post-setup reinit failures
- Broaden _check_needs_admin exception catch and type persistence param
- Fix _is_setup_complete docstring (re-raises on error, not returns False)
- Add TemplateVariableResponse to backend, closing frontend/backend drift
- Add extra="forbid" to SetupCompanyRequest and SetupAgentRequest
- Add role="alert" to OrgEditPage error/warning banners (a11y)
- Disable GeneralTab Save when form is pristine
- Replace vi.clearAllMocks with vi.resetAllMocks in org-edit tests
- Strengthen completeSetup() return type to Literal[true]
- Sanitize console.error in company store (getErrorMessage)
- Update CLAUDE.md: DeptHealthBar optional props, bootstrap in api/
- Update brand-and-ux.md: DeptHealthBar props table
- Move @pytest.mark.unit to class level in TestBootstrapAgents
- Add tests for _maybe_bootstrap_agents, provider reload, empty model
- Add integration test for full first-run flow (#789 deliverable)
- Fix App.test.tsx heading assertion (Sign In, not Login)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Backend:
- Elevate _maybe_bootstrap_agents settings-read log from DEBUG to WARNING
- Move SETUP_AGENT_BOOTSTRAP_FAILED import to top-level (remove deferred)
- Add DEBUG logs for bootstrap skip reasons (services missing, setup incomplete)
- Change _build_model_config to raise ValueError instead of phantom "unknown" agent
- Add hiring_date explanatory comment in bootstrap.py
- Bind exception in _check_needs_admin for structured logging (error= field)
- Add cascading-failure comment in _post_setup_reinit
- Tighten TemplateVariableResponse: var_type to Literal, default to bounded union
- Fix docstring "USD" -> "base currency" in SetupAgentRequest

Frontend:
- Guard LoginPage form submit during loading mode
- Add role="alert" to GeneralTab submitError element
- Use browser-default locale for budgetFormatter (remove hardcoded en-US)
- Replace setTimeout with useEffect cleanup in LoginPage stories

Tests:
- Replace private _agents access with public agent_count() in 2 test files
- Revert GeneralTab.test resetAllMocks -> clearAllMocks (preserve mock impl)
- Replace closest('button') with getByRole('button') in GeneralTab tests
- Add property-based test for save-button disabled state (fast-check)
- Add password-required and setup-mode username-required LoginPage tests
- Add TemplateVariableResponse variables assertion in template listing test
- Add provider-reload-failure isolation test for _post_setup_reinit
- Fix integration fixture: add teardown for fake_persistence
- Update test_empty_model to expect skip instead of unknown fallback

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The LoginPage now calls getSetupStatus() on mount via useEffect,
adding an async step after the lazy-load Suspense resolve.  The
default 1s waitFor timeout is insufficient in CI under load.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add teardown to fake_message_bus fixture (yield + stop)
- Replace deprecated asyncio.get_event_loop() with new_event_loop()
  in 3 sync test methods (integration + 2 unit)
- Wrap budgetFormatter across multiple lines (line length)
- Make _check_needs_admin explicitly catch QueryError before Exception

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
_flatten_nullable now handles oneOf unions with multiple primitive
branches plus null (e.g. str | int | float | bool | None) by
collapsing them into a compact type array.  Previously only
two-branch T | None unions were flattened.

Fixes the test_no_oneof_with_null_after_processing CI failure
caused by the new TemplateVariableResponse.default field.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The test previously asserted multi-branch primitive unions stay as
oneOf.  Updated to match the new behavior where all-primitive
nullable unions are collapsed to a type array.  Added a test for
mixed ($ref + primitive + null) unions that should NOT be flattened.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

Caution

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

⚠️ Outside diff range comments (1)
src/synthorg/templates/loader.py (1)

65-86: ⚠️ Potential issue | 🟡 Minor

Update TemplateInfo docstring to include variables.

TemplateInfo now exposes a public variables field, but the class attribute docs still list the pre-change fields only. This leaves API docs stale.

As per coding guidelines, "Docstrings must use Google style and are required on all public classes and functions; enforced by ruff D rules."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/synthorg/templates/loader.py` around lines 65 - 86, Update the
TemplateInfo class docstring to document the new public variables field in
Google style: add a "variables" entry under Attributes describing that it's a
tuple of TemplateVariable instances representing template variables and their
metadata, and mention TemplateVariable in the description to help readers find
the type; keep the existing attribute descriptions for name, display_name,
description, source, tags, and skill_patterns unchanged.
♻️ Duplicate comments (2)
web/src/__tests__/pages/org-edit/DepartmentEditDrawer.test.tsx (1)

29-29: ⚠️ Potential issue | 🟠 Major

Preserve async mock behavior in beforeEach.

At Line 29, vi.resetAllMocks() wipes the mockResolvedValue(...) implementations set at Lines 10-11, so save/delete tests can stop exercising the intended async path. Prefer vi.clearAllMocks() here (or re-apply implementations in beforeEach).

🔧 Proposed fix
-beforeEach(() => vi.resetAllMocks())
+beforeEach(() => vi.clearAllMocks())
#!/bin/bash
set -euo pipefail

# Verify the test's mock setup/reset behavior
cat -n web/src/__tests__/pages/org-edit/DepartmentEditDrawer.test.tsx | sed -n '1,45p'

# Verify whether DepartmentEditDrawer awaits onUpdate/onDelete (async path expectation)
rg -nP --type=tsx -C3 '\bonUpdate\b|\bonDelete\b|await\s+onUpdate|await\s+onDelete' web/src/pages/org-edit/DepartmentEditDrawer.tsx
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@web/src/__tests__/pages/org-edit/DepartmentEditDrawer.test.tsx` at line 29,
The beforeEach currently calls vi.resetAllMocks(), which clears
mockResolvedValue implementations set earlier and breaks async save/delete test
paths; change the reset to vi.clearAllMocks() (or alternatively re-apply the
mockResolvedValue implementations inside beforeEach) so the async mocks for
onUpdate/onDelete (and other mockResolvedValue calls created at the top of the
test file) are preserved across tests and the DepartmentEditDrawer tests
exercise the intended async behavior.
web/src/pages/LoginPage.stories.tsx (1)

20-25: ⚠️ Potential issue | 🟠 Major

Remove MemoryRouter from the story decorator — it's already provided at the meta level.

The AdminCreation story decorator wraps with <MemoryRouter> at lines 67–69, but the meta-level decorator (lines 20–25) already wraps all stories with <MemoryRouter>. This creates a nested router setup that React Router explicitly rejects with the error: "You cannot render a inside another . You should never have more than one in your app."

The story decorator should return <Story /> directly rather than wrapping it again.

🔧 Proposed fix
   decorators: [
     (Story, context) => {
       const restore = (context.loaded as { restoreSetup?: () => void })?.restoreSetup
       // Restore on unmount via useEffect cleanup instead of setTimeout.
       useEffect(() => {
         return () => { if (restore) restore() }
       }, [restore])
-      return (
-        <MemoryRouter>
-          <Story />
-        </MemoryRouter>
-      )
+      return <Story />
     },
   ],

Also applies to: 67-69

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@web/src/pages/LoginPage.stories.tsx` around lines 20 - 25, The AdminCreation
story decorator is redundantly wrapping stories with <MemoryRouter> even though
the meta-level decorators array already provides a MemoryRouter; remove the
extra router by changing the AdminCreation decorator to return Story directly
(i.e., return <Story />) so you don't render a Router inside another
Router—update the decorator function referenced as the AdminCreation story
decorator and the Story parameter accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@tests/unit/api/controllers/test_setup.py`:
- Around line 563-597: The test test_complete_succeeds_even_if_bootstrap_fails
injects failing_bootstrap via monkeypatch for
synthorg.api.bootstrap.bootstrap_agents but never asserts it was invoked; update
the test to assert the AsyncMock was awaited (e.g.,
failing_bootstrap.assert_awaited_once() or failing_bootstrap.assert_awaited())
after the POST so the failing path is actually verified, and make the analogous
change in the other failure-mode test around lines 690-714 to assert its
injected AsyncMock was awaited as well.

In `@tests/unit/api/test_openapi_nullable.py`:
- Around line 170-181: The test test_multi_branch_mixed_union_not_flattened
should also assert that the schema was not flattened to a type array: after
calling _normalize_nullable_unions(schema) ensure that there is no "type" key
(or no "type" array) in result in addition to asserting an "anyOf" or "oneOf" is
present; update the assertions in that test to include a negative check like
assert "type" not in result (or assert not isinstance(result.get("type"), list))
so regressions that leave a type-array alongside anyOf/oneOf fail.

In `@web/src/pages/LoginPage.stories.tsx`:
- Around line 44-57: The current approach tries to assign to the ESM namespace
(setupApi.getSetupStatus) which is read-only and thus fails, and the
AdminCreation story decorator wraps a second MemoryRouter causing nested Router
errors; fix by removing the MemoryRouter wrapper from the AdminCreation
decorator (leave the meta-level MemoryRouter intact) and replace the module
patching of setupApi.getSetupStatus with a proper mock: either provide a story
decorator or provider that injects a mocked getSetupStatus implementation into
the component via props/context (or use Storybook's mocking loader/Mock Service
Worker) so LoginPage receives the mocked response instead of attempting to
reassign the ESM export.

In `@web/src/pages/LoginPage.tsx`:
- Around line 106-107: The current disabled flag (const disabled = submitting ||
locked) applies lockout to both admin setup and normal login; change it so
locked only affects the login flow by gating it with the login-mode check (e.g.,
const disabled = submitting || (locked && isLoginMode) or equivalent using the
component's mode/route state), and apply the same conditional fix to the other
occurrence that uses lockout (the block referenced around lines 183-190). Update
any uses of the disabled variable or duplicate lockout logic in LoginPage to
ensure admin/setup mode remains interactive while preserving lockout for regular
login attempts.

---

Outside diff comments:
In `@src/synthorg/templates/loader.py`:
- Around line 65-86: Update the TemplateInfo class docstring to document the new
public variables field in Google style: add a "variables" entry under Attributes
describing that it's a tuple of TemplateVariable instances representing template
variables and their metadata, and mention TemplateVariable in the description to
help readers find the type; keep the existing attribute descriptions for name,
display_name, description, source, tags, and skill_patterns unchanged.

---

Duplicate comments:
In `@web/src/__tests__/pages/org-edit/DepartmentEditDrawer.test.tsx`:
- Line 29: The beforeEach currently calls vi.resetAllMocks(), which clears
mockResolvedValue implementations set earlier and breaks async save/delete test
paths; change the reset to vi.clearAllMocks() (or alternatively re-apply the
mockResolvedValue implementations inside beforeEach) so the async mocks for
onUpdate/onDelete (and other mockResolvedValue calls created at the top of the
test file) are preserved across tests and the DepartmentEditDrawer tests
exercise the intended async behavior.

In `@web/src/pages/LoginPage.stories.tsx`:
- Around line 20-25: The AdminCreation story decorator is redundantly wrapping
stories with <MemoryRouter> even though the meta-level decorators array already
provides a MemoryRouter; remove the extra router by changing the AdminCreation
decorator to return Story directly (i.e., return <Story />) so you don't render
a Router inside another Router—update the decorator function referenced as the
AdminCreation story decorator and the Story parameter accordingly.
🪄 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: 9d296069-e6f0-4467-a559-fb883916d5ce

📥 Commits

Reviewing files that changed from the base of the PR and between cbc8ece and c678769.

📒 Files selected for processing (29)
  • CLAUDE.md
  • docs/design/brand-and-ux.md
  • src/synthorg/api/app.py
  • src/synthorg/api/bootstrap.py
  • src/synthorg/api/controllers/setup.py
  • src/synthorg/api/controllers/setup_models.py
  • src/synthorg/api/openapi.py
  • src/synthorg/observability/events/setup.py
  • src/synthorg/templates/loader.py
  • tests/integration/api/test_first_run_flow.py
  • tests/unit/api/controllers/test_setup.py
  • tests/unit/api/test_bootstrap.py
  • tests/unit/api/test_openapi_nullable.py
  • web/src/__tests__/App.test.tsx
  • web/src/__tests__/pages/LoginPage.test.tsx
  • web/src/__tests__/pages/org-edit/AgentCreateDialog.test.tsx
  • web/src/__tests__/pages/org-edit/AgentEditDrawer.test.tsx
  • web/src/__tests__/pages/org-edit/AgentsTab.test.tsx
  • web/src/__tests__/pages/org-edit/DepartmentCreateDialog.test.tsx
  • web/src/__tests__/pages/org-edit/DepartmentEditDrawer.test.tsx
  • web/src/__tests__/pages/org-edit/DepartmentsTab.test.tsx
  • web/src/__tests__/pages/org-edit/GeneralTab.test.tsx
  • web/src/__tests__/pages/org-edit/YamlEditorPanel.test.tsx
  • web/src/api/endpoints/setup.ts
  • web/src/pages/LoginPage.stories.tsx
  • web/src/pages/LoginPage.tsx
  • web/src/pages/OrgEditPage.tsx
  • web/src/pages/org-edit/GeneralTab.tsx
  • web/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). (1)
  • GitHub Check: Test (Python 3.14)
🧰 Additional context used
📓 Path-based instructions (9)
{src,tests,web/src,cli}/**/*.{py,ts,tsx,go}

📄 CodeRabbit inference engine (CLAUDE.md)

Never use real vendor names (Anthropic, OpenAI, Claude, GPT, etc.) in project-owned code, docstrings, comments, tests, or config examples; use generic names (example-provider, example-large-001, large/medium/small)

Files:

  • web/src/__tests__/pages/org-edit/AgentEditDrawer.test.tsx
  • web/src/__tests__/App.test.tsx
  • web/src/__tests__/pages/org-edit/DepartmentCreateDialog.test.tsx
  • web/src/stores/company.ts
  • web/src/__tests__/pages/org-edit/AgentsTab.test.tsx
  • web/src/__tests__/pages/org-edit/YamlEditorPanel.test.tsx
  • web/src/__tests__/pages/org-edit/DepartmentsTab.test.tsx
  • web/src/__tests__/pages/org-edit/AgentCreateDialog.test.tsx
  • web/src/pages/OrgEditPage.tsx
  • web/src/__tests__/pages/org-edit/DepartmentEditDrawer.test.tsx
  • tests/unit/api/test_openapi_nullable.py
  • src/synthorg/templates/loader.py
  • web/src/__tests__/pages/org-edit/GeneralTab.test.tsx
  • src/synthorg/api/openapi.py
  • web/src/pages/org-edit/GeneralTab.tsx
  • tests/unit/api/controllers/test_setup.py
  • web/src/pages/LoginPage.stories.tsx
  • src/synthorg/observability/events/setup.py
  • src/synthorg/api/app.py
  • web/src/pages/LoginPage.tsx
  • tests/unit/api/test_bootstrap.py
  • web/src/__tests__/pages/LoginPage.test.tsx
  • src/synthorg/api/controllers/setup.py
  • tests/integration/api/test_first_run_flow.py
  • web/src/api/endpoints/setup.ts
  • src/synthorg/api/bootstrap.py
  • src/synthorg/api/controllers/setup_models.py
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

TypeScript files must use baseUrl in tsconfig relative to tsconfig directory (deprecated in TS 6, removed in TS 7); prefer paths entries

Files:

  • web/src/__tests__/pages/org-edit/AgentEditDrawer.test.tsx
  • web/src/__tests__/App.test.tsx
  • web/src/__tests__/pages/org-edit/DepartmentCreateDialog.test.tsx
  • web/src/stores/company.ts
  • web/src/__tests__/pages/org-edit/AgentsTab.test.tsx
  • web/src/__tests__/pages/org-edit/YamlEditorPanel.test.tsx
  • web/src/__tests__/pages/org-edit/DepartmentsTab.test.tsx
  • web/src/__tests__/pages/org-edit/AgentCreateDialog.test.tsx
  • web/src/pages/OrgEditPage.tsx
  • web/src/__tests__/pages/org-edit/DepartmentEditDrawer.test.tsx
  • web/src/__tests__/pages/org-edit/GeneralTab.test.tsx
  • web/src/pages/org-edit/GeneralTab.tsx
  • web/src/pages/LoginPage.stories.tsx
  • web/src/pages/LoginPage.tsx
  • web/src/__tests__/pages/LoginPage.test.tsx
  • web/src/api/endpoints/setup.ts
web/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

web/src/**/*.{ts,tsx}: ALWAYS reuse existing components from web/src/components/ui/ before creating new ones (StatusBadge, MetricCard, Sparkline, SectionCard, AgentCard, DeptHealthBar, ProgressGauge, StatPill, Avatar, Button, Toast, Skeleton variants, EmptyState, ErrorBoundary, ConfirmDialog, CommandPalette, InlineEdit, AnimatedPresence, StaggerGroup, Drawer, InputField, SelectField, SliderField, ToggleField, TaskStatusIndicator, PriorityBadge, ProviderHealthBadge)
Use Tailwind semantic classes (text-foreground, bg-card, text-accent, text-success, bg-danger, etc.) or CSS variables (var(--so-accent)); NEVER hardcode hex values in .tsx/.ts files
Use font-sans or font-mono for typography (maps to Geist tokens); NEVER set fontFamily directly
Use density-aware design tokens for spacing (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 shadow or border 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 text-metric font-bold -- use <MetricCard>
Do NOT render initials circles manually -- use <Avatar>
Do NOT create complex (>8 line) JSX inside .map() -- extract to a shared component
Do NOT use rgba() with hardcoded values -- use design token variables

Files:

  • web/src/__tests__/pages/org-edit/AgentEditDrawer.test.tsx
  • web/src/__tests__/App.test.tsx
  • web/src/__tests__/pages/org-edit/DepartmentCreateDialog.test.tsx
  • web/src/stores/company.ts
  • web/src/__tests__/pages/org-edit/AgentsTab.test.tsx
  • web/src/__tests__/pages/org-edit/YamlEditorPanel.test.tsx
  • web/src/__tests__/pages/org-edit/DepartmentsTab.test.tsx
  • web/src/__tests__/pages/org-edit/AgentCreateDialog.test.tsx
  • web/src/pages/OrgEditPage.tsx
  • web/src/__tests__/pages/org-edit/DepartmentEditDrawer.test.tsx
  • web/src/__tests__/pages/org-edit/GeneralTab.test.tsx
  • web/src/pages/org-edit/GeneralTab.tsx
  • web/src/pages/LoginPage.stories.tsx
  • web/src/pages/LoginPage.tsx
  • web/src/__tests__/pages/LoginPage.test.tsx
  • web/src/api/endpoints/setup.ts
web/src/**/__tests__/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Use property-based testing with fast-check in React: fc.assert + fc.property for Vitest unit tests

Files:

  • web/src/__tests__/pages/org-edit/AgentEditDrawer.test.tsx
  • web/src/__tests__/App.test.tsx
  • web/src/__tests__/pages/org-edit/DepartmentCreateDialog.test.tsx
  • web/src/__tests__/pages/org-edit/AgentsTab.test.tsx
  • web/src/__tests__/pages/org-edit/YamlEditorPanel.test.tsx
  • web/src/__tests__/pages/org-edit/DepartmentsTab.test.tsx
  • web/src/__tests__/pages/org-edit/AgentCreateDialog.test.tsx
  • web/src/__tests__/pages/org-edit/DepartmentEditDrawer.test.tsx
  • web/src/__tests__/pages/org-edit/GeneralTab.test.tsx
  • web/src/__tests__/pages/LoginPage.test.tsx
{docs/design/operations.md,web/src/**,src/synthorg/providers/presets.py,src/synthorg/**/*.{py,ts,tsx},cli/**}

📄 CodeRabbit inference engine (CLAUDE.md)

Vendor names (Anthropic, OpenAI, Claude, GPT) may only appear in: (1) docs/design/operations.md, (2) .claude/ skill/agent files, (3) third-party import paths/module names, (4) provider presets (src/synthorg/providers/presets.py)

Files:

  • web/src/__tests__/pages/org-edit/AgentEditDrawer.test.tsx
  • web/src/__tests__/App.test.tsx
  • web/src/__tests__/pages/org-edit/DepartmentCreateDialog.test.tsx
  • web/src/stores/company.ts
  • web/src/__tests__/pages/org-edit/AgentsTab.test.tsx
  • web/src/__tests__/pages/org-edit/YamlEditorPanel.test.tsx
  • web/src/__tests__/pages/org-edit/DepartmentsTab.test.tsx
  • web/src/__tests__/pages/org-edit/AgentCreateDialog.test.tsx
  • web/src/pages/OrgEditPage.tsx
  • web/src/__tests__/pages/org-edit/DepartmentEditDrawer.test.tsx
  • src/synthorg/templates/loader.py
  • web/src/__tests__/pages/org-edit/GeneralTab.test.tsx
  • src/synthorg/api/openapi.py
  • web/src/pages/org-edit/GeneralTab.tsx
  • web/src/pages/LoginPage.stories.tsx
  • src/synthorg/observability/events/setup.py
  • src/synthorg/api/app.py
  • web/src/pages/LoginPage.tsx
  • web/src/__tests__/pages/LoginPage.test.tsx
  • src/synthorg/api/controllers/setup.py
  • web/src/api/endpoints/setup.ts
  • src/synthorg/api/bootstrap.py
  • src/synthorg/api/controllers/setup_models.py
**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.py: Do NOT use from __future__ import annotations -- Python 3.14 has PEP 649 native lazy annotations
Use except A, B: syntax (no parentheses) for multiple exception handling -- PEP 758 except syntax for Python 3.14
All public functions must have type hints; enforce with mypy strict mode
Docstrings must use Google style and are required on all public classes and functions; enforced by ruff D rules
Create new objects instead of mutating existing ones; use copy.deepcopy() for non-Pydantic internal collections and wrap with MappingProxyType for read-only enforcement
Use frozen Pydantic models for config/identity; use separate mutable-via-copy models for runtime state that evolves
Use Pydantic v2 conventions: @computed_field for derived values, NotBlankStr for identifier/name fields (including optional and tuple variants) instead of manual whitespace validators
Prefer asyncio.TaskGroup for fan-out/fan-in parallel operations in new code (e.g. multiple tool invocations, parallel agent calls)
Line length must not exceed 88 characters; enforced by ruff
Functions must be shorter than 50 lines; files must be shorter than 800 lines

Files:

  • tests/unit/api/test_openapi_nullable.py
  • src/synthorg/templates/loader.py
  • src/synthorg/api/openapi.py
  • tests/unit/api/controllers/test_setup.py
  • src/synthorg/observability/events/setup.py
  • src/synthorg/api/app.py
  • tests/unit/api/test_bootstrap.py
  • src/synthorg/api/controllers/setup.py
  • tests/integration/api/test_first_run_flow.py
  • src/synthorg/api/bootstrap.py
  • src/synthorg/api/controllers/setup_models.py
tests/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

tests/**/*.py: Use @pytest.mark.unit, @pytest.mark.integration, @pytest.mark.e2e, @pytest.mark.slow for test markers
Maintain 80% minimum test coverage; enforced in CI
Use asyncio_mode = 'auto' for async tests -- no manual @pytest.mark.asyncio needed
Global test timeout is 30 seconds per test; non-default overrides are allowed but should be minimal
Prefer @pytest.mark.parametrize for testing similar cases in Python tests
Use test-provider and test-small-001 in tests instead of vendor names
Use Hypothesis for Python property-based testing with @given and @settings decorators; use HYPOTHESIS_PROFILE env var to control example counts (ci=50, dev=1000)
For timing-sensitive Python tests, mock time.monotonic() and asyncio.sleep() to make them deterministic; use asyncio.Event().wait() for indefinite blocking instead of asyncio.sleep(large_number)
Use @given and @settings for Hypothesis property-based testing in Python

Files:

  • tests/unit/api/test_openapi_nullable.py
  • tests/unit/api/controllers/test_setup.py
  • tests/unit/api/test_bootstrap.py
  • tests/integration/api/test_first_run_flow.py
src/synthorg/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

src/synthorg/**/*.py: Every module with business logic MUST import from synthorg.observability import get_logger and assign logger = get_logger(__name__)
Never use import logging / logging.getLogger() / print() in application code; only observability/setup.py and observability/sinks.py may use stdlib logging for bootstrap
Variable name must always be logger (not _logger, not log)
Use event name constants from synthorg.observability.events (e.g., API_REQUEST_STARTED from events.api). Import directly and use as logger.info(EVENT_CONSTANT, key=value)
Use structured kwargs in logging: logger.info(EVENT, key=value) -- never logger.info('msg %s', val)
All error paths must log at WARNING or ERROR with context before raising
All state transitions must log at INFO level
DEBUG logging should be used for object creation, internal flow, and entry/exit of key functions

Files:

  • src/synthorg/templates/loader.py
  • src/synthorg/api/openapi.py
  • src/synthorg/observability/events/setup.py
  • src/synthorg/api/app.py
  • src/synthorg/api/controllers/setup.py
  • src/synthorg/api/bootstrap.py
  • src/synthorg/api/controllers/setup_models.py
web/src/**/*.stories.tsx

📄 CodeRabbit inference engine (CLAUDE.md)

web/src/**/*.stories.tsx: Storybook 10+ is ESM-only; remove all CJS support from stories
Storybook 10+ essential addons (backgrounds, controls, viewport, actions, toolbars, measure, outline) and interactions are built into core storybook; do NOT import from removed packages
Use storybook/test imports (not @storybook/test), storybook/actions (not @storybook/addon-actions) in Storybook 10+ stories
Use parameters.backgrounds.options (object keyed by name) + initialGlobals.backgrounds.value in Storybook 10+ (replaces old default + values array)
Use parameters.a11y.test: 'error' | 'todo' | 'off' for a11y testing in Storybook 10+ (replaces old .element and .manual); set globally in preview.tsx to enforce WCAG compliance on all stories

Files:

  • web/src/pages/LoginPage.stories.tsx
🧠 Learnings (62)
📓 Common learnings
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-26T15:18:16.848Z
Learning: Applies to src/synthorg/api/**/*.py : Litestar API must include setup wizard, auth/, auto-wiring, and lifecycle management
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...
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/api/**/*.py : API package (api/): Litestar REST + WebSocket with controllers, guards, channels, JWT + API key + WS ticket auth, approval gate integration, coordination endpoint, collaboration endpoint, settings endpoint, provider management endpoint (CRUD + test + presets), backup endpoint, RFC 9457 structured errors, AppState hot-reload slots, service auto-wiring (Phase 1 at construction, Phase 2 on startup), lifecycle helpers
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
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-20T08:28:32.845Z
Learning: Applies to src/synthorg/providers/**/*.py : Providers: LLM provider abstraction (LiteLLM adapter), auth types (api_key/oauth/custom_header/none), presets (PROVIDER_PRESETS), runtime CRUD (ProviderManagementService with asyncio.Lock serialization), hot-reload via AppState swap.
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)
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T06:30:14.180Z
Learning: Applies to src/synthorg/security/**/*.py : Security module includes SecOps agent, rule engine (soft-allow/hard-deny), audit log, output scanner, risk classifier, autonomy levels (4 strategies), timeout policies.
📚 Learning: 2026-03-28T11:47:10.822Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T11:47:10.822Z
Learning: Applies to web/src/**/*.stories.tsx : Use `storybook/test` imports (not `storybook/test`), `storybook/actions` (not `storybook/addon-actions`) in Storybook 10+ stories

Applied to files:

  • web/src/__tests__/App.test.tsx
  • web/src/__tests__/pages/org-edit/DepartmentCreateDialog.test.tsx
  • web/src/__tests__/pages/org-edit/AgentsTab.test.tsx
  • web/src/__tests__/pages/org-edit/YamlEditorPanel.test.tsx
  • web/src/__tests__/pages/org-edit/DepartmentsTab.test.tsx
  • web/src/__tests__/pages/org-edit/AgentCreateDialog.test.tsx
  • web/src/pages/LoginPage.stories.tsx
  • web/src/__tests__/pages/LoginPage.test.tsx
📚 Learning: 2026-03-28T11:47:10.822Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T11:47:10.822Z
Learning: Applies to web/src/**/__tests__/**/*.{ts,tsx} : Use property-based testing with fast-check in React: `fc.assert` + `fc.property` for Vitest unit tests

Applied to files:

  • web/src/__tests__/pages/org-edit/DepartmentCreateDialog.test.tsx
  • web/src/__tests__/pages/org-edit/AgentsTab.test.tsx
  • web/src/__tests__/pages/org-edit/DepartmentsTab.test.tsx
  • web/src/__tests__/pages/org-edit/AgentCreateDialog.test.tsx
  • web/src/__tests__/pages/org-edit/DepartmentEditDrawer.test.tsx
  • web/src/__tests__/pages/org-edit/GeneralTab.test.tsx
  • web/src/__tests__/pages/LoginPage.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-edit/DepartmentCreateDialog.test.tsx
  • web/src/__tests__/pages/org-edit/AgentsTab.test.tsx
  • web/src/__tests__/pages/org-edit/DepartmentsTab.test.tsx
  • web/src/__tests__/pages/org-edit/AgentCreateDialog.test.tsx
  • web/src/__tests__/pages/org-edit/DepartmentEditDrawer.test.tsx
  • web/src/__tests__/pages/org-edit/GeneralTab.test.tsx
  • web/src/__tests__/pages/LoginPage.test.tsx
📚 Learning: 2026-03-28T11:47:10.822Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T11:47:10.822Z
Learning: Applies to web/src/**/*.{ts,tsx} : Do NOT recreate status dots inline -- use `<StatusBadge>`

Applied to files:

  • web/src/pages/OrgEditPage.tsx
  • docs/design/brand-and-ux.md
📚 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 src/synthorg/templates/**/*.py : Templates: pre-built company templates, personality presets, and builder.

Applied to files:

  • src/synthorg/templates/loader.py
  • src/synthorg/api/controllers/setup.py
  • src/synthorg/api/controllers/setup_models.py
📚 Learning: 2026-03-28T11:47:10.822Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T11:47:10.822Z
Learning: Applies to web/src/**/*.stories.tsx : Use `parameters.a11y.test: 'error' | 'todo' | 'off'` for a11y testing in Storybook 10+ (replaces old `.element` and `.manual`); set globally in `preview.tsx` to enforce WCAG compliance on all stories

Applied to files:

  • web/src/__tests__/pages/org-edit/GeneralTab.test.tsx
  • web/src/pages/LoginPage.stories.tsx
📚 Learning: 2026-03-20T21:44:04.528Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-20T21:44:04.528Z
Learning: Applies to tests/**/*.py : Fix flaky tests completely and fundamentally; for timing-sensitive tests, mock `time.monotonic()` and `asyncio.sleep()` to make them deterministic instead of widening timing margins

Applied to files:

  • tests/unit/api/controllers/test_setup.py
📚 Learning: 2026-03-17T22:08:13.456Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T22:08:13.456Z
Learning: Applies to tests/**/*.py : Test markers: `pytest.mark.unit`, `pytest.mark.integration`, `pytest.mark.e2e`, `pytest.mark.slow`. Coverage: 80% minimum. Async: `asyncio_mode = 'auto'` — no manual `pytest.mark.asyncio` needed. Timeout: 30 seconds per test. Parallelism: `pytest-xdist` via `-n auto` — ALWAYS include `-n auto` when running pytest, never run tests sequentially.

Applied to files:

  • tests/unit/api/controllers/test_setup.py
📚 Learning: 2026-03-28T11:47:10.822Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T11:47:10.822Z
Learning: Applies to tests/**/*.py : For timing-sensitive Python tests, mock `time.monotonic()` and `asyncio.sleep()` to make them deterministic; use `asyncio.Event().wait()` for indefinite blocking instead of `asyncio.sleep(large_number)`

Applied to files:

  • tests/unit/api/controllers/test_setup.py
  • tests/integration/api/test_first_run_flow.py
📚 Learning: 2026-03-17T22:08:13.456Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T22:08:13.456Z
Learning: Applies to src/synthorg/**/*.py : Prefer `asyncio.TaskGroup` for fan-out/fan-in parallel operations in new code (e.g. multiple tool invocations, parallel agent calls). Prefer structured concurrency over bare `create_task`. Existing code is being migrated incrementally.

Applied to files:

  • tests/unit/api/controllers/test_setup.py
  • tests/integration/api/test_first_run_flow.py
📚 Learning: 2026-03-28T11:47:10.822Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T11:47:10.822Z
Learning: Applies to **/*.py : Prefer `asyncio.TaskGroup` for fan-out/fan-in parallel operations in new code (e.g. multiple tool invocations, parallel agent calls)

Applied to files:

  • tests/unit/api/controllers/test_setup.py
  • tests/integration/api/test_first_run_flow.py
📚 Learning: 2026-03-28T11:47:10.822Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T11:47:10.822Z
Learning: Applies to web/src/**/*.stories.tsx : Storybook 10+ essential addons (backgrounds, controls, viewport, actions, toolbars, measure, outline) and interactions are built into core `storybook`; do NOT import from removed packages

Applied to files:

  • web/src/pages/LoginPage.stories.tsx
📚 Learning: 2026-03-28T11:47:10.822Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T11:47:10.822Z
Learning: Applies to web/src/**/*.stories.tsx : Storybook 10+ is ESM-only; remove all CJS support from stories

Applied to files:

  • web/src/pages/LoginPage.stories.tsx
📚 Learning: 2026-03-28T11:47:10.822Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T11:47:10.822Z
Learning: Applies to web/src/components/ui/**/*.{ts,tsx} : When creating new shared components: place in `web/src/components/ui/`, create `.stories.tsx` file with all states, export props as TypeScript interface, use design tokens exclusively, import `cn` from `@/lib/utils` for class merging

Applied to files:

  • web/src/pages/LoginPage.stories.tsx
  • web/src/__tests__/pages/LoginPage.test.tsx
📚 Learning: 2026-03-28T11:47:10.822Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T11:47:10.822Z
Learning: Applies to web/src/**/*.stories.tsx : Use `parameters.backgrounds.options` (object keyed by name) + `initialGlobals.backgrounds.value` in Storybook 10+ (replaces old `default` + `values` array)

Applied to files:

  • web/src/pages/LoginPage.stories.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/observability/**/*.py : Observability package (observability/): structured logging, correlation tracking, log sinks; event constants organized by domain under observability/events/ (e.g., events.api, events.tool, events.git, events.context_budget, events.backup)

Applied to files:

  • src/synthorg/observability/events/setup.py
  • src/synthorg/api/app.py
  • src/synthorg/api/controllers/setup.py
📚 Learning: 2026-03-15T19:14:27.144Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T19:14:27.144Z
Learning: Applies to src/synthorg/**/*.py : Use event name constants from synthorg.observability.events domain-specific modules (e.g., PROVIDER_CALL_START from events.provider). Import directly: from synthorg.observability.events.<domain> import EVENT_CONSTANT.

Applied to files:

  • src/synthorg/observability/events/setup.py
  • src/synthorg/api/app.py
📚 Learning: 2026-03-20T11:18:48.128Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-20T11:18:48.128Z
Learning: Applies to src/synthorg/**/*.py : Use event name constants from domain-specific modules under `synthorg.observability.events` (e.g., `API_REQUEST_STARTED` from `events.api`, `TOOL_INVOKE_START` from `events.tool`). Import directly: `from synthorg.observability.events.<domain> import EVENT_CONSTANT`.

Applied to files:

  • src/synthorg/observability/events/setup.py
  • src/synthorg/api/app.py
📚 Learning: 2026-03-15T18:38:44.202Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:38:44.202Z
Learning: Applies to src/synthorg/**/*.py : Always use event name constants from domain-specific modules under `synthorg.observability.events` (e.g., `PROVIDER_CALL_START` from `events.provider`); import directly: `from synthorg.observability.events.<domain> import EVENT_CONSTANT`

Applied to files:

  • src/synthorg/observability/events/setup.py
📚 Learning: 2026-03-15T18:28:13.207Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:28:13.207Z
Learning: Applies to src/synthorg/**/*.py : Event names: always use constants from domain-specific modules under synthorg.observability.events (e.g., PROVIDER_CALL_START from events.provider, BUDGET_RECORD_ADDED from events.budget, etc.). Import directly: `from synthorg.observability.events.<domain> import EVENT_CONSTANT`.

Applied to files:

  • src/synthorg/observability/events/setup.py
📚 Learning: 2026-03-18T21:23:23.586Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-18T21:23:23.586Z
Learning: Applies to src/synthorg/**/*.py : Event names: always use constants from the domain-specific module under synthorg.observability.events (e.g., API_REQUEST_STARTED from events.api, TOOL_INVOKE_START from events.tool). Import directly from synthorg.observability.events.<domain>.

Applied to files:

  • src/synthorg/observability/events/setup.py
  • src/synthorg/api/app.py
📚 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/**/*.py : Always use event name constants from the domain-specific module under `synthorg.observability.events` in logging calls

Applied to files:

  • src/synthorg/observability/events/setup.py
📚 Learning: 2026-03-14T16:18:57.267Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T16:18:57.267Z
Learning: Applies to src/ai_company/!(observability)/**/*.py : Use event name constants from domain-specific modules under `ai_company.observability.events` (e.g., `PROVIDER_CALL_START` from `events.provider`). Import directly: `from ai_company.observability.events.<domain> import EVENT_CONSTANT`.

Applied to files:

  • src/synthorg/observability/events/setup.py
📚 Learning: 2026-03-20T21:44:04.528Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-20T21:44:04.528Z
Learning: Applies to src/synthorg/**/*.py : Always use event name constants from domain-specific modules under `synthorg.observability.events` (e.g., `API_REQUEST_STARTED` from `events.api`, `TOOL_INVOKE_START` from `events.tool`); import directly rather than using string literals

Applied to files:

  • src/synthorg/observability/events/setup.py
  • src/synthorg/api/app.py
📚 Learning: 2026-03-28T11:47:10.822Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T11:47:10.822Z
Learning: Applies to src/synthorg/**/*.py : Use event name constants from `synthorg.observability.events` (e.g., `API_REQUEST_STARTED` from `events.api`). Import directly and use as `logger.info(EVENT_CONSTANT, key=value)`

Applied to files:

  • src/synthorg/observability/events/setup.py
  • src/synthorg/api/app.py
📚 Learning: 2026-03-26T15:18:16.848Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-26T15:18:16.848Z
Learning: Applies to src/synthorg/api/**/*.py : Litestar API must include setup wizard, auth/, auto-wiring, and lifecycle management

Applied to files:

  • src/synthorg/api/app.py
  • CLAUDE.md
  • src/synthorg/api/controllers/setup.py
  • tests/integration/api/test_first_run_flow.py
  • src/synthorg/api/bootstrap.py
📚 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/api/**/*.py : API package (api/): Litestar REST + WebSocket with controllers, guards, channels, JWT + API key + WS ticket auth, approval gate integration, coordination endpoint, collaboration endpoint, settings endpoint, provider management endpoint (CRUD + test + presets), backup endpoint, RFC 9457 structured errors, AppState hot-reload slots, service auto-wiring (Phase 1 at construction, Phase 2 on startup), lifecycle helpers

Applied to files:

  • src/synthorg/api/app.py
  • CLAUDE.md
  • src/synthorg/api/controllers/setup.py
📚 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:

  • src/synthorg/api/app.py
  • CLAUDE.md
  • src/synthorg/api/bootstrap.py
📚 Learning: 2026-03-19T11:33:01.580Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T11:33:01.580Z
Learning: Applies to src/synthorg/**/*.py : Use event constants from `synthorg.observability.events.<domain>` (e.g., `API_REQUEST_STARTED` from `events.api`); import directly and log with structured kwargs: `logger.info(EVENT, key=value)`, never interpolated strings

Applied to files:

  • src/synthorg/api/app.py
  • src/synthorg/api/controllers/setup.py
📚 Learning: 2026-03-20T21:44:04.528Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-20T21:44:04.528Z
Learning: Applies to **/*.py : Use `except A, B:` syntax (without parentheses) per PEP 758 for exception handling in Python 3.14

Applied to files:

  • src/synthorg/api/app.py
  • src/synthorg/api/controllers/setup.py
  • src/synthorg/api/bootstrap.py
📚 Learning: 2026-03-28T11:47:10.822Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T11:47:10.822Z
Learning: Applies to **/*.py : Use `except A, B:` syntax (no parentheses) for multiple exception handling -- PEP 758 except syntax for Python 3.14

Applied to files:

  • src/synthorg/api/app.py
  • src/synthorg/api/controllers/setup.py
  • src/synthorg/api/bootstrap.py
📚 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 **/*.py : Handle errors explicitly, never silently swallow exceptions

Applied to files:

  • src/synthorg/api/app.py
  • src/synthorg/api/controllers/setup.py
  • src/synthorg/api/bootstrap.py
📚 Learning: 2026-03-16T07:22:28.134Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-16T07:22:28.134Z
Learning: Applies to **/*.py : Handle errors explicitly; never silently swallow exceptions

Applied to files:

  • src/synthorg/api/app.py
  • src/synthorg/api/controllers/setup.py
  • src/synthorg/api/bootstrap.py
📚 Learning: 2026-03-16T07:22:28.134Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-16T07:22:28.134Z
Learning: Applies to **/*.py : Use `except A, B:` syntax (no parentheses) for exception handling — PEP 758 exception syntax enforced by ruff on Python 3.14

Applied to files:

  • src/synthorg/api/app.py
  • src/synthorg/api/controllers/setup.py
  • src/synthorg/api/bootstrap.py
📚 Learning: 2026-03-14T16:18:57.267Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T16:18:57.267Z
Learning: Applies to **/*.py : Use PEP 758 except syntax with `except A, B:` (no parentheses) for multiple exceptions—ruff enforces this on Python 3.14.

Applied to files:

  • src/synthorg/api/app.py
  • src/synthorg/api/controllers/setup.py
  • src/synthorg/api/bootstrap.py
📚 Learning: 2026-03-14T16:18:57.267Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T16:18:57.267Z
Learning: Applies to **/*.py : Handle errors explicitly—never silently swallow exceptions.

Applied to files:

  • src/synthorg/api/app.py
  • src/synthorg/api/controllers/setup.py
  • src/synthorg/api/bootstrap.py
📚 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 **/*.py : Use PEP 758 except syntax: `except A, B:` (no parentheses) — enforced by ruff on Python 3.14

Applied to files:

  • src/synthorg/api/app.py
  • src/synthorg/api/controllers/setup.py
  • src/synthorg/api/bootstrap.py
📚 Learning: 2026-03-17T22:08:13.456Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T22:08:13.456Z
Learning: Applies to src/synthorg/api/**/*.py : REST API: Litestar framework, controllers with guards, channels for WebSocket, JWT + API key + WS ticket auth, approval gate integration, coordination endpoint, collaboration endpoint, settings endpoint. RFC 9457 structured errors (ErrorCategory, ErrorCode, ErrorDetail, ProblemDetail, CATEGORY_TITLES, category_title, category_type_uri, content negotiation).

Applied to files:

  • src/synthorg/api/app.py
  • CLAUDE.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 docs/design/*.md : Design spec pages: 7 pages in `docs/design/` — index, agents, organization, communication, engine, memory, operations

Applied to files:

  • CLAUDE.md
📚 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-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 docs/design/**/*.md : Design specification pages in `docs/design/` must be consulted before implementing features (7 pages: index, agents, organization, communication, engine, memory, operations)

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-03-17T06:30:14.180Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T06:30:14.180Z
Learning: Applies to src/synthorg/api/**/*.py : Use Litestar for REST + WebSocket API. Controllers, guards, channels, JWT + API key + WS ticket auth, RFC 9457 structured errors.

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-03-20T11:18:48.128Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-20T11:18:48.128Z
Learning: Applies to src/synthorg/api/**/*.py : Use Litestar for REST API and WebSocket API with JWT + API key + WS ticket authentication, RFC 9457 structured errors, and content negotiation.

Applied to files:

  • CLAUDE.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/engine/**/*.py : Engine package (engine/): agent orchestration, parallel execution, task decomposition, routing, TaskEngine (centralized single-writer), task lifecycle/recovery/shutdown, workspace isolation, coordination (4 dispatchers: SAS/centralized/decentralized/context-dependent, wave execution), approval gates (escalation detection, context parking/resume), stagnation detection (ToolRepetitionDetector, corrective prompt injection), AgentRuntimeState (execution status), context budget management, conversation compaction (oldest-turns summarizer)

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-03-17T06:30:14.180Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T06:30:14.180Z
Learning: Applies to src/synthorg/security/**/*.py : Security module includes SecOps agent, rule engine (soft-allow/hard-deny), audit log, output scanner, risk classifier, autonomy levels (4 strategies), timeout policies.

Applied to files:

  • CLAUDE.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/security/**/*.py : Security package (security/): SecOps agent, rule engine (soft-allow/hard-deny, fail-closed), audit log, output scanner, output scan response policies (redact/withhold/log-only/autonomy-tiered), risk classifier, risk tier classifier, action type registry, ToolInvoker security integration, progressive trust (4 strategies), autonomy levels (presets, resolver, change strategy), timeout policies (park/resume)

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-03-17T22:08:13.456Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T22:08:13.456Z
Learning: Documentation source in `docs/` (Markdown, built with Zensical). Design spec in `docs/design/` (7 pages: index, agents, organization, communication, engine, memory, operations). Architecture in `docs/architecture/` (overview, tech-stack, decision log). Roadmap in `docs/roadmap/`. Security in `docs/security.md`. Licensing in `docs/licensing.md`. Reference in `docs/reference/`. REST API reference in `docs/rest-api.md`. Library reference in `docs/api/` (auto-generated from docstrings). Custom templates in `docs/overrides/`. Config in `mkdocs.yml`.

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-03-28T11:47:10.822Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T11:47:10.822Z
Learning: Applies to web/src/**/*.{ts,tsx} : ALWAYS reuse existing components from `web/src/components/ui/` before creating new ones (StatusBadge, MetricCard, Sparkline, SectionCard, AgentCard, DeptHealthBar, ProgressGauge, StatPill, Avatar, Button, Toast, Skeleton variants, EmptyState, ErrorBoundary, ConfirmDialog, CommandPalette, InlineEdit, AnimatedPresence, StaggerGroup, Drawer, InputField, SelectField, SliderField, ToggleField, TaskStatusIndicator, PriorityBadge, ProviderHealthBadge)

Applied to files:

  • CLAUDE.md
  • docs/design/brand-and-ux.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.md
  • docs/design/brand-and-ux.md
📚 Learning: 2026-03-28T11:47:10.822Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T11:47:10.822Z
Learning: Applies to web/src/**/*.{ts,tsx} : Do NOT create metric displays with `text-metric font-bold` -- use `<MetricCard>`

Applied to files:

  • CLAUDE.md
  • docs/design/brand-and-ux.md
📚 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 src/synthorg/providers/**/*.py : Providers: LLM provider abstraction (LiteLLM adapter), auth types (api_key/oauth/custom_header/none), presets (PROVIDER_PRESETS), runtime CRUD (ProviderManagementService with asyncio.Lock serialization), hot-reload via AppState swap.

Applied to files:

  • src/synthorg/api/controllers/setup.py
📚 Learning: 2026-03-17T06:30:14.180Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T06:30:14.180Z
Learning: Applies to src/synthorg/persistence/**/*.py : Persistence uses pluggable PersistenceBackend protocol. SQLite is the initial backend. Settings use SettingsRepository (namespaced settings CRUD).

Applied to files:

  • src/synthorg/api/controllers/setup.py
📚 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/settings/**/*.py : Settings package (settings/): runtime-editable settings persistence (DB > env > YAML > code defaults), typed definitions (9 namespaces), Fernet encryption for sensitive values, config bridge (JSON serialization for Pydantic/collections), ConfigResolver (typed accessors), validation, registry, change notifications via message bus, SettingsSubscriber protocol, SettingsChangeDispatcher (polls `#settings` channel, routes to subscribers, restart_required filtering)

Applied to files:

  • src/synthorg/api/controllers/setup.py
📚 Learning: 2026-03-17T22:08:13.456Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T22:08:13.456Z
Learning: Persistence backend: pluggable PersistenceBackend protocol in `src/synthorg/persistence/`, SQLite initial, SettingsRepository (namespaced settings CRUD).

Applied to files:

  • src/synthorg/api/controllers/setup.py
📚 Learning: 2026-03-28T11:47:10.822Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T11:47:10.822Z
Learning: Applies to web/src/**/*.{ts,tsx} : Do NOT build card-with-header layouts from scratch -- use `<SectionCard>`

Applied to files:

  • docs/design/brand-and-ux.md
📚 Learning: 2026-03-28T11:47:10.822Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T11:47:10.822Z
Learning: Applies to web/src/**/*.{ts,tsx} : Use Tailwind semantic classes (`text-foreground`, `bg-card`, `text-accent`, `text-success`, `bg-danger`, etc.) or CSS variables (`var(--so-accent)`); NEVER hardcode hex values in `.tsx`/`.ts` files

Applied to files:

  • docs/design/brand-and-ux.md
📚 Learning: 2026-03-20T21:44:04.528Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-20T21:44:04.528Z
Learning: Applies to src/synthorg/**/*.py : Use frozen Pydantic models for config/identity; use separate mutable-via-copy models (via `model_copy(update=...)`) for runtime state that evolves

Applied to files:

  • src/synthorg/api/bootstrap.py
  • src/synthorg/api/controllers/setup_models.py
📚 Learning: 2026-03-15T18:38:44.202Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:38:44.202Z
Learning: Applies to src/synthorg/**/*.py : Use frozen Pydantic models for config/identity; separate mutable-via-copy models (using `model_copy(update=...)`) for runtime state

Applied to files:

  • src/synthorg/api/bootstrap.py
  • src/synthorg/api/controllers/setup_models.py
📚 Learning: 2026-03-15T16:55:07.730Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T16:55:07.730Z
Learning: Applies to **/*.py : Use PEP 758 except syntax: use `except A, B:` (no parentheses) — ruff enforces this on Python 3.14.

Applied to files:

  • src/synthorg/api/bootstrap.py
📚 Learning: 2026-03-19T21:11:37.538Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T21:11:37.538Z
Learning: Applies to **/*.py : Errors: handle explicitly, never silently swallow.

Applied to files:

  • src/synthorg/api/bootstrap.py
📚 Learning: 2026-03-15T19:14:27.144Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T19:14:27.144Z
Learning: Applies to src/synthorg/**/*.py : Use frozen Pydantic models for config/identity; use separate mutable-via-copy models (using model_copy(update=...)) for runtime state that evolves. Never mix static config fields with mutable runtime fields in one model.

Applied to files:

  • src/synthorg/api/controllers/setup_models.py
🪛 GitHub Check: Dashboard Lint
web/src/pages/LoginPage.tsx

[warning] 78-78:
Potential timing attack, left side: true

Comment on lines +563 to +597
def test_complete_succeeds_even_if_bootstrap_fails(
self,
test_client: TestClient[Any],
monkeypatch: pytest.MonkeyPatch,
) -> None:
"""Setup completion returns 201 even if agent bootstrap raises."""
app_state = test_client.app.state.app_state
repo = app_state.persistence._settings_repo
now = datetime.now(UTC).isoformat()
repo._store[("company", "company_name")] = ("Test Corp", now)
agents = json.dumps([{"name": "agent-001", "role": "CEO"}])
repo._store[("company", "agents")] = (agents, now)
stub = MagicMock(spec=BaseCompletionProvider)
original_registry = app_state._provider_registry
app_state._provider_registry = ProviderRegistry(
{"test-provider": stub},
)

# Make bootstrap_agents raise to simulate failure.
failing_bootstrap = AsyncMock(side_effect=RuntimeError("boom"))
monkeypatch.setattr(
"synthorg.api.bootstrap.bootstrap_agents",
failing_bootstrap,
)

try:
resp = test_client.post("/api/v1/setup/complete")
# Must succeed despite bootstrap failure (non-fatal).
assert resp.status_code == 201
assert resp.json()["data"]["setup_complete"] is True
finally:
app_state._provider_registry = original_registry
repo._store.pop(("company", "company_name"), None)
repo._store.pop(("company", "agents"), None)
repo._store.pop(("api", "setup_complete"), None)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Assert patched failure hooks were actually invoked.

Both failure-mode tests validate response status but don’t verify that the injected failing path was exercised. Add explicit call assertions so these tests fail if the code path regresses.

✅ Suggested assertion additions
@@
-        failing_bootstrap = AsyncMock(side_effect=RuntimeError("boom"))
+        failing_bootstrap = AsyncMock(side_effect=RuntimeError("boom"))
@@
             resp = test_client.post("/api/v1/setup/complete")
             # Must succeed despite bootstrap failure (non-fatal).
             assert resp.status_code == 201
             assert resp.json()["data"]["setup_complete"] is True
+            assert failing_bootstrap.await_count >= 1
@@
-        monkeypatch.setattr(
+        from_config_mock = MagicMock(
+            side_effect=RuntimeError("provider config broken"),
+        )
+        monkeypatch.setattr(
             "synthorg.providers.registry.ProviderRegistry.from_config",
-            MagicMock(side_effect=RuntimeError("provider config broken")),
+            from_config_mock,
         )
@@
             resp = test_client.post("/api/v1/setup/complete")
             assert resp.status_code == 201
             assert resp.json()["data"]["setup_complete"] is True
+            assert from_config_mock.call_count >= 1

Also applies to: 690-714

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/unit/api/controllers/test_setup.py` around lines 563 - 597, The test
test_complete_succeeds_even_if_bootstrap_fails injects failing_bootstrap via
monkeypatch for synthorg.api.bootstrap.bootstrap_agents but never asserts it was
invoked; update the test to assert the AsyncMock was awaited (e.g.,
failing_bootstrap.assert_awaited_once() or failing_bootstrap.assert_awaited())
after the POST so the failing path is actually verified, and make the analogous
change in the other failure-mode test around lines 690-714 to assert its
injected AsyncMock was awaited as well.

- Assert failing_bootstrap was awaited in bootstrap failure test
- Add negative type-array assertion in mixed union test
- Rewrite LoginPage stories: gate component instead of ESM patching,
  remove duplicate MemoryRouter in AdminCreation decorator
- Scope lockout to login mode only (setup mode stays interactive)
- Document variables field in TemplateInfo docstring
- Revert DepartmentEditDrawer resetAllMocks -> clearAllMocks

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

♻️ Duplicate comments (1)
web/src/pages/LoginPage.stories.tsx (1)

33-34: ⚠️ Potential issue | 🟠 Major

Replace the runtime export patch with a deterministic setup-status mock.

This story still tries to overwrite mod.getSetupStatus, but ESM namespace exports are not a reliable mutation point. LoginPage is already imported at Line 4 here and statically imports getSetupStatus at Line 6 of web/src/pages/LoginPage.tsx, so the component can still call the real endpoint. That leaves AdminCreation fragile and DefaultLogin dependent on a network failure to reach its intended state. Please switch both stories to an explicit request mock or injection seam instead of mutating the imported module at runtime.

Also applies to: 44-63

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@web/src/pages/LoginPage.stories.tsx` around lines 33 - 34, The story
currently mutates the ESM export at runtime (mod.getSetupStatus) which is
unreliable; instead update DefaultLogin and the AdminCreation story to use a
deterministic request mock or injection seam so LoginPage receives the mocked
setup state. Concretely: stop patching the imported getSetupStatus; instead
intercept the network call (e.g., Storybook's msw or your app's request-mocking
utility) to return the desired setup-state payload for LoginPage, or refactor
LoginPage to accept a prop/injection for getSetupStatus and pass a mocked
implementation from the stories; ensure references to LoginPage, getSetupStatus,
DefaultLogin and AdminCreation are updated accordingly so the component uses the
mock rather than attempting to mutate the module export at runtime.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@tests/unit/api/controllers/test_setup.py`:
- Around line 691-695: The test is patching ProviderRegistry.from_config but
_post_setup_reinit calls app_state.provider_registry.reload, so the failure
branch isn't exercised; update the monkeypatch to target the actual reload path
(either
monkeypatch.setattr("synthorg.providers.registry.ProviderRegistry.reload",
MagicMock(side_effect=RuntimeError("provider config broken"))) or patch the
instance method app_state.provider_registry.reload inside the test) and apply
the same change for the other occurrence around lines 698-710 so the
RuntimeError is raised when _post_setup_reinit invokes
app_state.provider_registry.reload.

In `@web/src/pages/LoginPage.tsx`:
- Around line 44-58: The login flow validates username with username.trim() but
still passes the raw username to the auth calls; update the handlers
(handleLogin and the analogous setup handler used at lines ~68-85) to normalize
the username by trimming before submission—e.g., compute a const
normalizedUsername = username.trim() after validation and call
login(normalizedUsername, password) / setup(normalizedUsername, ...) instead of
the raw username; optionally write the trimmed value back into state via
setUsername(normalizedUsername) if you want the UI to reflect the normalized
input.

---

Duplicate comments:
In `@web/src/pages/LoginPage.stories.tsx`:
- Around line 33-34: The story currently mutates the ESM export at runtime
(mod.getSetupStatus) which is unreliable; instead update DefaultLogin and the
AdminCreation story to use a deterministic request mock or injection seam so
LoginPage receives the mocked setup state. Concretely: stop patching the
imported getSetupStatus; instead intercept the network call (e.g., Storybook's
msw or your app's request-mocking utility) to return the desired setup-state
payload for LoginPage, or refactor LoginPage to accept a prop/injection for
getSetupStatus and pass a mocked implementation from the stories; ensure
references to LoginPage, getSetupStatus, DefaultLogin and AdminCreation are
updated accordingly so the component uses the mock rather than attempting to
mutate the module export at runtime.
🪄 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: 08786edc-fe14-41b2-bc04-f9ee946cec61

📥 Commits

Reviewing files that changed from the base of the PR and between c678769 and dad9ef7.

📒 Files selected for processing (5)
  • src/synthorg/templates/loader.py
  • tests/unit/api/controllers/test_setup.py
  • tests/unit/api/test_openapi_nullable.py
  • web/src/pages/LoginPage.stories.tsx
  • web/src/pages/LoginPage.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). (4)
  • GitHub Check: Build Backend
  • GitHub Check: Build Web
  • GitHub Check: Dashboard Test
  • GitHub Check: Test (Python 3.14)
🧰 Additional context used
📓 Path-based instructions (8)
**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.py: Do NOT use from __future__ import annotations -- Python 3.14 has PEP 649 native lazy annotations
Use except A, B: syntax (no parentheses) for multiple exception handling -- PEP 758 except syntax for Python 3.14
All public functions must have type hints; enforce with mypy strict mode
Docstrings must use Google style and are required on all public classes and functions; enforced by ruff D rules
Create new objects instead of mutating existing ones; use copy.deepcopy() for non-Pydantic internal collections and wrap with MappingProxyType for read-only enforcement
Use frozen Pydantic models for config/identity; use separate mutable-via-copy models for runtime state that evolves
Use Pydantic v2 conventions: @computed_field for derived values, NotBlankStr for identifier/name fields (including optional and tuple variants) instead of manual whitespace validators
Prefer asyncio.TaskGroup for fan-out/fan-in parallel operations in new code (e.g. multiple tool invocations, parallel agent calls)
Line length must not exceed 88 characters; enforced by ruff
Functions must be shorter than 50 lines; files must be shorter than 800 lines

Files:

  • src/synthorg/templates/loader.py
  • tests/unit/api/test_openapi_nullable.py
  • tests/unit/api/controllers/test_setup.py
src/synthorg/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

src/synthorg/**/*.py: Every module with business logic MUST import from synthorg.observability import get_logger and assign logger = get_logger(__name__)
Never use import logging / logging.getLogger() / print() in application code; only observability/setup.py and observability/sinks.py may use stdlib logging for bootstrap
Variable name must always be logger (not _logger, not log)
Use event name constants from synthorg.observability.events (e.g., API_REQUEST_STARTED from events.api). Import directly and use as logger.info(EVENT_CONSTANT, key=value)
Use structured kwargs in logging: logger.info(EVENT, key=value) -- never logger.info('msg %s', val)
All error paths must log at WARNING or ERROR with context before raising
All state transitions must log at INFO level
DEBUG logging should be used for object creation, internal flow, and entry/exit of key functions

Files:

  • src/synthorg/templates/loader.py
{src,tests,web/src,cli}/**/*.{py,ts,tsx,go}

📄 CodeRabbit inference engine (CLAUDE.md)

Never use real vendor names (Anthropic, OpenAI, Claude, GPT, etc.) in project-owned code, docstrings, comments, tests, or config examples; use generic names (example-provider, example-large-001, large/medium/small)

Files:

  • src/synthorg/templates/loader.py
  • tests/unit/api/test_openapi_nullable.py
  • web/src/pages/LoginPage.stories.tsx
  • web/src/pages/LoginPage.tsx
  • tests/unit/api/controllers/test_setup.py
{docs/design/operations.md,web/src/**,src/synthorg/providers/presets.py,src/synthorg/**/*.{py,ts,tsx},cli/**}

📄 CodeRabbit inference engine (CLAUDE.md)

Vendor names (Anthropic, OpenAI, Claude, GPT) may only appear in: (1) docs/design/operations.md, (2) .claude/ skill/agent files, (3) third-party import paths/module names, (4) provider presets (src/synthorg/providers/presets.py)

Files:

  • src/synthorg/templates/loader.py
  • web/src/pages/LoginPage.stories.tsx
  • web/src/pages/LoginPage.tsx
tests/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

tests/**/*.py: Use @pytest.mark.unit, @pytest.mark.integration, @pytest.mark.e2e, @pytest.mark.slow for test markers
Maintain 80% minimum test coverage; enforced in CI
Use asyncio_mode = 'auto' for async tests -- no manual @pytest.mark.asyncio needed
Global test timeout is 30 seconds per test; non-default overrides are allowed but should be minimal
Prefer @pytest.mark.parametrize for testing similar cases in Python tests
Use test-provider and test-small-001 in tests instead of vendor names
Use Hypothesis for Python property-based testing with @given and @settings decorators; use HYPOTHESIS_PROFILE env var to control example counts (ci=50, dev=1000)
For timing-sensitive Python tests, mock time.monotonic() and asyncio.sleep() to make them deterministic; use asyncio.Event().wait() for indefinite blocking instead of asyncio.sleep(large_number)
Use @given and @settings for Hypothesis property-based testing in Python

Files:

  • tests/unit/api/test_openapi_nullable.py
  • tests/unit/api/controllers/test_setup.py
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

TypeScript files must use baseUrl in tsconfig relative to tsconfig directory (deprecated in TS 6, removed in TS 7); prefer paths entries

Files:

  • web/src/pages/LoginPage.stories.tsx
  • web/src/pages/LoginPage.tsx
web/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

web/src/**/*.{ts,tsx}: ALWAYS reuse existing components from web/src/components/ui/ before creating new ones (StatusBadge, MetricCard, Sparkline, SectionCard, AgentCard, DeptHealthBar, ProgressGauge, StatPill, Avatar, Button, Toast, Skeleton variants, EmptyState, ErrorBoundary, ConfirmDialog, CommandPalette, InlineEdit, AnimatedPresence, StaggerGroup, Drawer, InputField, SelectField, SliderField, ToggleField, TaskStatusIndicator, PriorityBadge, ProviderHealthBadge)
Use Tailwind semantic classes (text-foreground, bg-card, text-accent, text-success, bg-danger, etc.) or CSS variables (var(--so-accent)); NEVER hardcode hex values in .tsx/.ts files
Use font-sans or font-mono for typography (maps to Geist tokens); NEVER set fontFamily directly
Use density-aware design tokens for spacing (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 shadow or border 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 text-metric font-bold -- use <MetricCard>
Do NOT render initials circles manually -- use <Avatar>
Do NOT create complex (>8 line) JSX inside .map() -- extract to a shared component
Do NOT use rgba() with hardcoded values -- use design token variables

Files:

  • web/src/pages/LoginPage.stories.tsx
  • web/src/pages/LoginPage.tsx
web/src/**/*.stories.tsx

📄 CodeRabbit inference engine (CLAUDE.md)

web/src/**/*.stories.tsx: Storybook 10+ is ESM-only; remove all CJS support from stories
Storybook 10+ essential addons (backgrounds, controls, viewport, actions, toolbars, measure, outline) and interactions are built into core storybook; do NOT import from removed packages
Use storybook/test imports (not @storybook/test), storybook/actions (not @storybook/addon-actions) in Storybook 10+ stories
Use parameters.backgrounds.options (object keyed by name) + initialGlobals.backgrounds.value in Storybook 10+ (replaces old default + values array)
Use parameters.a11y.test: 'error' | 'todo' | 'off' for a11y testing in Storybook 10+ (replaces old .element and .manual); set globally in preview.tsx to enforce WCAG compliance on all stories

Files:

  • web/src/pages/LoginPage.stories.tsx
🧠 Learnings (13)
📚 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 src/synthorg/templates/**/*.py : Templates: pre-built company templates, personality presets, and builder.

Applied to files:

  • src/synthorg/templates/loader.py
📚 Learning: 2026-03-28T11:47:10.822Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T11:47:10.822Z
Learning: Applies to web/src/**/*.stories.tsx : Storybook 10+ essential addons (backgrounds, controls, viewport, actions, toolbars, measure, outline) and interactions are built into core `storybook`; do NOT import from removed packages

Applied to files:

  • web/src/pages/LoginPage.stories.tsx
📚 Learning: 2026-03-28T11:47:10.822Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T11:47:10.822Z
Learning: Applies to web/src/**/*.stories.tsx : Use `storybook/test` imports (not `storybook/test`), `storybook/actions` (not `storybook/addon-actions`) in Storybook 10+ stories

Applied to files:

  • web/src/pages/LoginPage.stories.tsx
📚 Learning: 2026-03-28T11:47:10.822Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T11:47:10.822Z
Learning: Applies to web/src/**/*.stories.tsx : Storybook 10+ is ESM-only; remove all CJS support from stories

Applied to files:

  • web/src/pages/LoginPage.stories.tsx
📚 Learning: 2026-03-28T11:47:10.822Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T11:47:10.822Z
Learning: Applies to web/src/**/*.stories.tsx : Use `parameters.backgrounds.options` (object keyed by name) + `initialGlobals.backgrounds.value` in Storybook 10+ (replaces old `default` + `values` array)

Applied to files:

  • web/src/pages/LoginPage.stories.tsx
📚 Learning: 2026-03-28T11:47:10.822Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T11:47:10.822Z
Learning: Applies to web/src/components/ui/**/*.{ts,tsx} : When creating new shared components: place in `web/src/components/ui/`, create `.stories.tsx` file with all states, export props as TypeScript interface, use design tokens exclusively, import `cn` from `@/lib/utils` for class merging

Applied to files:

  • web/src/pages/LoginPage.stories.tsx
📚 Learning: 2026-03-28T11:47:10.822Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T11:47:10.822Z
Learning: Applies to web/src/**/*.stories.tsx : Use `parameters.a11y.test: 'error' | 'todo' | 'off'` for a11y testing in Storybook 10+ (replaces old `.element` and `.manual`); set globally in `preview.tsx` to enforce WCAG compliance on all stories

Applied to files:

  • web/src/pages/LoginPage.stories.tsx
📚 Learning: 2026-03-17T22:08:13.456Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T22:08:13.456Z
Learning: Applies to tests/**/*.py : Test markers: `pytest.mark.unit`, `pytest.mark.integration`, `pytest.mark.e2e`, `pytest.mark.slow`. Coverage: 80% minimum. Async: `asyncio_mode = 'auto'` — no manual `pytest.mark.asyncio` needed. Timeout: 30 seconds per test. Parallelism: `pytest-xdist` via `-n auto` — ALWAYS include `-n auto` when running pytest, never run tests sequentially.

Applied to files:

  • tests/unit/api/controllers/test_setup.py
📚 Learning: 2026-03-20T21:44:04.528Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-20T21:44:04.528Z
Learning: Applies to tests/**/*.py : Fix flaky tests completely and fundamentally; for timing-sensitive tests, mock `time.monotonic()` and `asyncio.sleep()` to make them deterministic instead of widening timing margins

Applied to files:

  • tests/unit/api/controllers/test_setup.py
📚 Learning: 2026-03-28T11:47:10.822Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T11:47:10.822Z
Learning: Applies to tests/**/*.py : For timing-sensitive Python tests, mock `time.monotonic()` and `asyncio.sleep()` to make them deterministic; use `asyncio.Event().wait()` for indefinite blocking instead of `asyncio.sleep(large_number)`

Applied to files:

  • tests/unit/api/controllers/test_setup.py
📚 Learning: 2026-03-17T22:08:13.456Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T22:08:13.456Z
Learning: Applies to src/synthorg/**/*.py : Prefer `asyncio.TaskGroup` for fan-out/fan-in parallel operations in new code (e.g. multiple tool invocations, parallel agent calls). Prefer structured concurrency over bare `create_task`. Existing code is being migrated incrementally.

Applied to files:

  • tests/unit/api/controllers/test_setup.py
📚 Learning: 2026-03-28T11:47:10.822Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-28T11:47:10.822Z
Learning: Applies to **/*.py : Prefer `asyncio.TaskGroup` for fan-out/fan-in parallel operations in new code (e.g. multiple tool invocations, parallel agent calls)

Applied to files:

  • tests/unit/api/controllers/test_setup.py
📚 Learning: 2026-03-16T07:22:28.134Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-16T07:22:28.134Z
Learning: Applies to tests/**/*.py : NEVER skip, dismiss, or ignore flaky tests — always fix them fully and fundamentally. For timing-sensitive tests, mock `time.monotonic()` and `asyncio.sleep()` to make them deterministic instead of widening timing margins

Applied to files:

  • tests/unit/api/controllers/test_setup.py
🪛 GitHub Check: Dashboard Lint
web/src/pages/LoginPage.tsx

[warning] 78-78:
Potential timing attack, left side: true

🔇 Additional comments (5)
src/synthorg/templates/loader.py (1)

44-45: Good propagation of template variables through loader metadata.

TemplateInfo.variables is wired end-to-end for both built-in and user templates, which keeps loader output aligned with the setup API contract.

Also applies to: 77-78, 87-87, 131-131, 159-159

tests/unit/api/test_openapi_nullable.py (2)

156-168: Flattening expectation for multi-primitive nullable unions is correctly asserted.

This test now matches the current _flatten_nullable behavior and protects the intended type-array collapse.


170-182: Mixed-union regression guard is in place.

Keeping the union representation (anyOf/oneOf) plus the negative type-array check improves coverage for the non-flattening branch.

tests/unit/api/controllers/test_setup.py (1)

54-55: Template contract check for variables is a solid addition.

This closes the backend/frontend schema expectation gap in setup templates responses.

web/src/pages/LoginPage.tsx (1)

106-107: Good login-only lockout gating.

Scoping both the disabled state and the warning banner to login mode keeps the first-run admin setup flow interactive.

Also applies to: 183-190

Comment on lines +691 to +695
# Make provider config loading raise to simulate reload failure.
monkeypatch.setattr(
"synthorg.providers.registry.ProviderRegistry.from_config",
MagicMock(side_effect=RuntimeError("provider config broken")),
)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Provider-reload failure is not actually being simulated in this test.

Line 693 patches ProviderRegistry.from_config, but _post_setup_reinit reloads through app_state.provider_registry.reload(...) (in src/synthorg/api/controllers/setup.py). So this test can pass without covering the intended failure branch.

🔧 Proposed fix
-        monkeypatch.setattr(
-            "synthorg.providers.registry.ProviderRegistry.from_config",
-            MagicMock(side_effect=RuntimeError("provider config broken")),
-        )
+        failing_reload = AsyncMock(side_effect=RuntimeError("provider config broken"))
+        monkeypatch.setattr(
+            app_state.provider_registry,
+            "reload",
+            failing_reload,
+        )

         try:
             resp = test_client.post("/api/v1/setup/complete")
             assert resp.status_code == 201
             assert resp.json()["data"]["setup_complete"] is True
+            failing_reload.assert_awaited_once()
             # Agent bootstrap should still have run despite provider
             # reload failure -- the two operations are independent.
             loop = asyncio.new_event_loop()

Also applies to: 698-710

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/unit/api/controllers/test_setup.py` around lines 691 - 695, The test is
patching ProviderRegistry.from_config but _post_setup_reinit calls
app_state.provider_registry.reload, so the failure branch isn't exercised;
update the monkeypatch to target the actual reload path (either
monkeypatch.setattr("synthorg.providers.registry.ProviderRegistry.reload",
MagicMock(side_effect=RuntimeError("provider config broken"))) or patch the
instance method app_state.provider_registry.reload inside the test) and apply
the same change for the other occurrence around lines 698-710 so the
RuntimeError is raised when _post_setup_reinit invokes
app_state.provider_registry.reload.

- Trim username in both handleLogin and handleSetup before passing
  to auth store (prevents " admin " from reaching the backend)
- Document ESM mutation trade-off in AdminCreationGate docstring

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@Aureliolo Aureliolo temporarily deployed to cloudflare-preview March 28, 2026 12:33 — with GitHub Actions Inactive
@Aureliolo Aureliolo merged commit 8758e8d into main Mar 28, 2026
32 of 34 checks passed
@Aureliolo Aureliolo deleted the feat/first-run-flow branch March 28, 2026 12:41
@Aureliolo Aureliolo temporarily deployed to cloudflare-preview March 28, 2026 12:41 — with GitHub Actions Inactive
Aureliolo added a commit that referenced this pull request Mar 30, 2026
🤖 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-&gt;3 and @types/node 22-&gt;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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: Login page + first-run bootstrap (login, setup, agent activation)

1 participant