Skip to content

feat: embed MkDocs build output in React web dashboard at /docs#948

Merged
Aureliolo merged 5 commits intomainfrom
feat/embed-docs-dashboard
Mar 31, 2026
Merged

feat: embed MkDocs build output in React web dashboard at /docs#948
Aureliolo merged 5 commits intomainfrom
feat/embed-docs-dashboard

Conversation

@Aureliolo
Copy link
Copy Markdown
Owner

Summary

  • Add nginx location block to serve MkDocs static HTML at /docs/ with docs-scoped CSP (permits blob: for Material search workers)
  • Add docs-builder stage to web Dockerfile (Python 3.14.3-slim + uv 0.10.9 + Zensical), with pre-compression matching the React builder pattern
  • Customize MkDocs Material theme to match dashboard dark design system via docs/overrides/extra.css
  • Add "Docs" nav item in sidebar (BookOpen icon, between Providers and Settings) and command palette entry
  • Add external prop to SidebarNavItem for plain <a href> rendering (bypasses React Router)
  • Update design spec, CLAUDE.md, and web/CLAUDE.md to reflect the new docs embedding architecture

Test plan

  • npm --prefix web run lint -- zero warnings
  • npm --prefix web run type-check -- zero errors
  • npm --prefix web run test -- 2282 tests pass (4 new for external prop)
  • docker compose -f docker/compose.yml build web -- docs-builder stage completes
  • curl http://localhost:3000/docs/ -- returns MkDocs HTML with dark theme
  • curl http://localhost:3000/docs/nonexistent -- returns 404 (not React SPA)
  • Sidebar shows "Docs" item; clicking performs full page navigation to /docs/
  • Cmd+K palette shows "Documentation" command

Review coverage

Pre-reviewed by 6 agents (docs-consistency, frontend-reviewer, design-token-audit, infra-reviewer, security-reviewer, issue-resolution-verifier). 11 findings addressed, 0 skipped.

Closes #295

🤖 Generated with Claude Code

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 31, 2026

Walkthrough

Embed MkDocs-built static documentation into the web dashboard at /docs/: add a Docker docs-builder stage and update .dockerignore to include docs/ and scripts/export_openapi.py; copy built docs into the nginx image and add an nginx location /docs/ to serve them with security/cache headers; customize MkDocs theme via mkdocs.yml and overrides/extra.css; add ROUTES.DOCUMENTATION, a sidebar item and command-palette entry that link to /docs/; introduce external support for sidebar links; update tests and documentation.

Suggested labels

autorelease: tagged

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: embedding MkDocs documentation into the React dashboard at /docs, which aligns with all the significant code modifications across Docker, nginx, frontend components, and documentation.
Description check ✅ Passed The description clearly explains the major changes including nginx configuration, docs-builder stage, Material theme customization, sidebar navigation, and external link handling, all directly related to the changeset.
Linked Issues check ✅ Passed All primary objectives from #295 are met: nginx location block with static serving [#295], Docker docs-builder stage with pre-compression [#295], MkDocs Material theme customization via extra.css [#295], sidebar and command-palette navigation entries [#295], and external prop preventing SPA routing [#295].
Out of Scope Changes check ✅ Passed All changes are directly scoped to the objective of embedding MkDocs at /docs: Docker build, nginx routing, Material theme styling, React navigation, and design documentation are all necessary and on-topic.
Docstring Coverage ✅ Passed Docstring coverage is 40.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 31, 2026 13:21 — with GitHub Actions Inactive
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 31, 2026

Dependency Review

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

Snapshot Warnings

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

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

Inline comments:
In `@docs/design/page-structure.md`:
- Around line 143-146: Update the wording in docs/design/page-structure.md:
change the phrase "full page navigation" to the hyphenated compound adjective
"full-page navigation" in the sentence describing the sidebar "Docs" link
rendering a plain <a href> instead of a React Router <NavLink>; no code changes
required, just edit the Markdown text near the Documentation (`/docs/`) section
that also references docs/overrides/extra.css.

In `@web/nginx.conf`:
- Around line 54-59: Extract the shared security headers into a new file (e.g.,
security-headers-base.conf) containing the common add_header directives except
Content-Security-Policy, then update the nginx docs location (the location
/docs/ block in web/nginx.conf) to include that base file via include and keep
only the docs-specific add_header Content-Security-Policy and Cache-Control
lines there; this removes duplication of X-Content-Type-Options,
X-Frame-Options, Referrer-Policy, Permissions-Policy and
Strict-Transport-Security while leaving the CSP unique to the docs block.
🪄 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: ea90275e-6271-4dfa-8944-498631e920a5

📥 Commits

Reviewing files that changed from the base of the PR and between a1322cd and 5d59d91.

📒 Files selected for processing (13)
  • .dockerignore
  • CLAUDE.md
  • docker/web/Dockerfile
  • docs/design/page-structure.md
  • docs/overrides/extra.css
  • mkdocs.yml
  • web/CLAUDE.md
  • web/nginx.conf
  • web/src/__tests__/components/layout/SidebarNavItem.test.tsx
  • web/src/components/layout/AppLayout.tsx
  • web/src/components/layout/Sidebar.tsx
  • web/src/components/layout/SidebarNavItem.tsx
  • web/src/router/routes.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: Dashboard Test
  • GitHub Check: Build Web
  • GitHub Check: Build Backend
  • GitHub Check: Build Sandbox
  • GitHub Check: Dependency Review
  • GitHub Check: Analyze (python)
🧰 Additional context used
📓 Path-based instructions (6)
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
Never hardcode hex colors, font-family, pixel spacing, or Framer Motion transitions—use design tokens and @/lib/motion presets

Files:

  • web/src/router/routes.ts
  • web/src/components/layout/Sidebar.tsx
  • web/src/components/layout/AppLayout.tsx
  • web/src/__tests__/components/layout/SidebarNavItem.test.tsx
  • web/src/components/layout/SidebarNavItem.tsx
web/src/**/*.{tsx,ts}

📄 CodeRabbit inference engine (web/CLAUDE.md)

web/src/**/*.{tsx,ts}: Do NOT use rgba() with hardcoded values -- use design token variables instead
Use Tailwind semantic classes (text-foreground, bg-card, text-accent, text-success, bg-danger, etc.) or CSS variables (var(--so-*)) for colors. NEVER hardcode hex values in .tsx/.ts files.
Use font-sans or font-mono (maps to Geist tokens) for typography. NEVER set fontFamily directly.
Use density-aware tokens (p-card, gap-section-gap, gap-grid-gap) or standard Tailwind spacing. NEVER hardcode pixel values for layout spacing.
Use token variables (var(--so-shadow-card-hover), border-border, border-bright) for shadows and borders.
Ensure CSS side-effect imports have type declarations in TypeScript 6 where noUncheckedSideEffectImports defaults to true. Use /// <reference types="vite/client" /> for Vite projects.
ESLint must enforce zero warnings on the web package. Run npm --prefix web run lint and fix all warnings.
TypeScript type checking must pass. Run npm --prefix web run type-check and resolve all type errors.

Files:

  • web/src/router/routes.ts
  • web/src/components/layout/Sidebar.tsx
  • web/src/components/layout/AppLayout.tsx
  • web/src/__tests__/components/layout/SidebarNavItem.test.tsx
  • web/src/components/layout/SidebarNavItem.tsx
web/src/**/*

📄 CodeRabbit inference engine (web/CLAUDE.md)

A PostToolUse hook (scripts/check_web_design_system.py) runs automatically on every Edit/Write to web/src/ files and catches hardcoded hex colors, rgba values, font-family declarations, hardcoded Framer Motion transition durations, missing Storybook stories, duplicate patterns, and complex .map() blocks. Fix all violations before proceeding.

Files:

  • web/src/router/routes.ts
  • web/src/components/layout/Sidebar.tsx
  • web/src/components/layout/AppLayout.tsx
  • web/src/__tests__/components/layout/SidebarNavItem.test.tsx
  • web/src/components/layout/SidebarNavItem.tsx
web/src/{components,pages}/**/*.{tsx,ts}

📄 CodeRabbit inference engine (web/CLAUDE.md)

ALWAYS reuse existing components from web/src/components/ui/ before creating new ones (StatusBadge, MetricCard, Sparkline, SectionCard, AgentCard, DeptHealthBar, ProgressGauge, StatPill, Avatar, Button, Toast, ToastContainer, Skeleton variants, EmptyState, ErrorBoundary, ConfirmDialog, CommandPalette, InlineEdit, AnimatedPresence, StaggerGroup, StaggerItem, Drawer, InputField, SelectField, SliderField, ToggleField, TaskStatusIndicator, PriorityBadge, ProviderHealthBadge, TokenUsageBar, CodeMirrorEditor, SegmentedControl, ThemeToggle, LiveRegion, MobileUnsupportedOverlay, LazyCodeMirrorEditor, TagInput)

Files:

  • web/src/components/layout/Sidebar.tsx
  • web/src/components/layout/AppLayout.tsx
  • web/src/components/layout/SidebarNavItem.tsx
web/src/{components,pages}/**/*.tsx

📄 CodeRabbit inference engine (web/CLAUDE.md)

web/src/{components,pages}/**/*.tsx: Do NOT recreate status dots inline -- use <StatusBadge> from @/components/ui/status-badge
Do NOT build card-with-header layouts from scratch -- use <SectionCard> from @/components/ui/section-card
Do NOT create metric displays with text-metric font-bold -- use <MetricCard> from @/components/ui/metric-card
Do NOT render initials circles manually -- use <Avatar> from @/components/ui/avatar
Do NOT create complex (>8 line) JSX inside .map() -- extract to a shared component

Files:

  • web/src/components/layout/Sidebar.tsx
  • web/src/components/layout/AppLayout.tsx
  • web/src/components/layout/SidebarNavItem.tsx
docker/**/*

📄 CodeRabbit inference engine (CLAUDE.md)

CLI verifies cosign signatures and SLSA provenance at pull time; bypass with --skip-verify

Files:

  • docker/web/Dockerfile
🧠 Learnings (49)
📓 Common learnings
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`.
📚 Learning: 2026-03-15T18:17:43.675Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:17:43.675Z
Learning: Applies to docker/{Dockerfile*,compose.yml} : Docker: Backend uses 3-stage build (builder → setup → distroless runtime), Chainguard Python, non-root (UID 65532), CIS-hardened. Web uses nginxinc/nginx-unprivileged, Vue 3 SPA with PrimeVue + Tailwind CSS, SPA routing, API/WebSocket proxy to backend.

Applied to files:

  • CLAUDE.md
  • docker/web/Dockerfile
📚 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
  • web/CLAUDE.md
  • .dockerignore
  • docs/overrides/extra.css
  • mkdocs.yml
  • web/nginx.conf
  • docs/design/page-structure.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
  • .dockerignore
  • docs/overrides/extra.css
  • mkdocs.yml
  • web/nginx.conf
  • docs/design/page-structure.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
  • mkdocs.yml
  • docs/design/page-structure.md
📚 Learning: 2026-03-19T07:13:44.964Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T07:13:44.964Z
Learning: Always read the relevant `docs/design/` page before implementing any feature or planning any issue — DESIGN_SPEC.md is a pointer file linking to 7 design pages (Agents, Organization, Communication, Engine, Memory, Operations)

Applied to files:

  • CLAUDE.md
  • docs/design/page-structure.md
📚 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: Always read the relevant `docs/design/` page before implementing any feature or planning any issue. DESIGN_SPEC.md is a pointer file linking to the 7 design pages (index, agents, organization, communication, engine, memory, operations).

Applied to files:

  • CLAUDE.md
  • docs/design/page-structure.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
  • docs/design/page-structure.md
📚 Learning: 2026-03-31T12:07:37.364Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T12:07:37.364Z
Learning: Applies to **/*.py : Always read the relevant `docs/design/` page before implementing any feature or planning any issue

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 docs/**/*.md : Markdown documentation must use valid Markdown syntax parseable by Zensical.

Applied to files:

  • CLAUDE.md
  • .dockerignore
📚 Learning: 2026-03-21T14:12:17.848Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-21T14:12:17.848Z
Learning: Applies to Dockerfile* : Backend images must use Chainguard distroless with non-root user; web image must use nginx-unprivileged with non-root user; sandbox image must use Python + Node.js with non-root user. All Docker files in `docker/` -- Dockerfiles, compose, `.env.example`. Single root `.dockerignore`. All images build with `context: .`

Applied to files:

  • CLAUDE.md
  • docker/web/Dockerfile
📚 Learning: 2026-03-15T21:32:02.880Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T21:32:02.880Z
Learning: Applies to .github/workflows/docker.yml : Docker workflow: builds backend + web + sandbox images, pushes to GHCR, signs with cosign. SLSA L3 provenance attestations via actions/attest-build-provenance. Scans: Trivy (CRITICAL = hard fail, HIGH = warn) + Grype (critical cutoff) + CIS Docker Benchmark v1.6.0 compliance (informational). CVE triage via .github/.trivyignore.yaml and .github/.grype.yaml. Images only pushed after scans pass. Triggers on push to main and version tags (v*).

Applied to files:

  • CLAUDE.md
  • docker/web/Dockerfile
📚 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 docker/Dockerfile : Docker: 3-stage build (builder → setup → distroless runtime) for backend, Chainguard Python, non-root (UID 65532), CIS-hardened

Applied to files:

  • CLAUDE.md
  • docker/web/Dockerfile
📚 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 docker/Dockerfile.web : `nginxinc/nginx-unprivileged` base with non-root user (UID 101), Vue 3 SPA (PrimeVue + Tailwind CSS), SPA routing, API/WebSocket proxy to backend

Applied to files:

  • CLAUDE.md
  • docker/web/Dockerfile
📚 Learning: 2026-03-31T12:07:37.367Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T12:07:37.367Z
Learning: Applies to Dockerfile : All Docker images must be non-root and use distroless/unprivileged base images (backend: Chainguard distroless, web: nginx-unprivileged, sandbox: Python + Node.js non-root)

Applied to files:

  • CLAUDE.md
  • docker/web/Dockerfile
📚 Learning: 2026-03-21T14:12:17.848Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-21T14:12:17.848Z
Learning: Docker workflow (`docker.yml`): build + Trivy/Grype scan + push to GHCR + cosign sign + SLSA L3 provenance. CVE triage: `.github/.trivyignore.yaml`, `.github/.grype.yaml`

Applied to files:

  • CLAUDE.md
  • docker/web/Dockerfile
📚 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 docker/Dockerfile.sandbox : Docker sandbox: `synthorg-sandbox` — Python 3.14 + Node.js + git, non-root (UID 10001), agent code execution sandbox

Applied to files:

  • CLAUDE.md
  • docker/web/Dockerfile
📚 Learning: 2026-03-21T14:12:17.848Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-21T14:12:17.848Z
Learning: CLI workflow (`cli.yml`): Go lint/test/build (cross-compile) + govulncheck + fuzz. GoReleaser release on `v*` tags with cosign signing + SLSA provenance

Applied to files:

  • CLAUDE.md
  • .dockerignore
📚 Learning: 2026-03-15T12:00:18.113Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T12:00:18.113Z
Learning: Applies to .github/workflows/docker.yml : CI Docker: build → scan → push to GHCR + cosign sign + SLSA L3 provenance via attest-build-provenance (images only pushed after Trivy/Grype scans pass).

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-03-15T21:20:09.993Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T21:20:09.993Z
Learning: Applies to web/src/components/** : Vue components organized by feature (agents/, approvals/, budget/, common/, dashboard/, layout/, messages/, org-chart/, tasks/).

Applied to files:

  • web/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:

  • web/CLAUDE.md
  • mkdocs.yml
📚 Learning: 2026-03-31T12:08:03.565Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-03-31T12:08:03.565Z
Learning: Applies to web/src/components/ui/**/*.{tsx,ts} : When creating new shared components in `web/src/components/ui/`, place it with a descriptive kebab-case filename, create a `.stories.tsx` file with all states (default, hover, loading, error, empty), export props as a TypeScript interface, use design tokens exclusively, and import `cn` from `@/lib/utils` for conditional class merging

Applied to files:

  • web/CLAUDE.md
  • web/src/components/layout/AppLayout.tsx
  • web/src/__tests__/components/layout/SidebarNavItem.test.tsx
  • web/src/components/layout/SidebarNavItem.tsx
📚 Learning: 2026-03-31T12:08:03.565Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-03-31T12:08:03.565Z
Learning: Applies to web/src/{components,pages}/**/*.{tsx,ts} : ALWAYS reuse existing components from `web/src/components/ui/` before creating new ones (StatusBadge, MetricCard, Sparkline, SectionCard, AgentCard, DeptHealthBar, ProgressGauge, StatPill, Avatar, Button, Toast, ToastContainer, Skeleton variants, EmptyState, ErrorBoundary, ConfirmDialog, CommandPalette, InlineEdit, AnimatedPresence, StaggerGroup, StaggerItem, Drawer, InputField, SelectField, SliderField, ToggleField, TaskStatusIndicator, PriorityBadge, ProviderHealthBadge, TokenUsageBar, CodeMirrorEditor, SegmentedControl, ThemeToggle, LiveRegion, MobileUnsupportedOverlay, LazyCodeMirrorEditor, TagInput)

Applied to files:

  • web/CLAUDE.md
  • web/src/components/layout/AppLayout.tsx
📚 Learning: 2026-03-31T12:08:03.565Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-03-31T12:08:03.565Z
Learning: Applies to web/src/{components,pages}/**/*.tsx : Do NOT build card-with-header layouts from scratch -- use `<SectionCard>` from `@/components/ui/section-card`

Applied to files:

  • web/CLAUDE.md
  • web/src/components/layout/AppLayout.tsx
📚 Learning: 2026-03-15T18:17:43.675Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:17:43.675Z
Learning: Applies to web/** : Web dashboard: Node.js 20+, dependencies in web/package.json (Vue 3, PrimeVue, Tailwind CSS, Pinia, VueFlow, ECharts, Axios, vue-draggable-plus, Vitest, fast-check, ESLint, vue-tsc).

Applied to files:

  • web/CLAUDE.md
📚 Learning: 2026-03-31T12:08:03.565Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-03-31T12:08:03.565Z
Learning: Applies to web/src/{components,pages}/**/*.tsx : Do NOT create complex (>8 line) JSX inside `.map()` -- extract to a shared component

Applied to files:

  • web/CLAUDE.md
📚 Learning: 2026-03-31T12:07:37.367Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T12:07:37.367Z
Learning: Applies to web/src/**/*.{ts,tsx} : Always reuse existing components from `web/src/components/ui/` before creating new ones

Applied to files:

  • web/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 web/package.json : Web dashboard Node.js 20+; dependencies in web/package.json (Vue 3, PrimeVue, Tailwind CSS, Pinia, VueFlow, ECharts, Axios, vue-draggable-plus, Vitest, ESLint, vue-tsc)

Applied to files:

  • web/CLAUDE.md
📚 Learning: 2026-03-15T16:38:08.735Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T16:38:08.735Z
Learning: Applies to docker/** : Docker build context: single root .dockerignore (both images build with context: .). Tags: CI tags images with version from pyproject.toml ([tool.commitizen].version), semver, and SHA.

Applied to files:

  • .dockerignore
  • docker/web/Dockerfile
📚 Learning: 2026-03-31T12:07:37.367Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T12:07:37.367Z
Learning: Applies to docker/**/*.yml : All images build with `context: .` from the repo root; use a single root `.dockerignore` for all images

Applied to files:

  • .dockerignore
📚 Learning: 2026-03-15T21:32:02.880Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T21:32:02.880Z
Learning: Applies to cli/**/*.go : Go CLI (Go 1.26+) uses Cobra for commands, charmbracelet/huh for interactive CLI, charmbracelet/lipgloss for styled output. Cross-platform builds (linux/darwin/windows × amd64/arm64). GoReleaser for releases with cosign keyless signing of checksums.txt. SLSA L3 provenance attestations via actions/attest-build-provenance.

Applied to files:

  • .dockerignore
📚 Learning: 2026-03-16T19:52:03.656Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-16T19:52:03.656Z
Learning: Applies to cli/**/*.go : Lint CLI Go code with golangci-lint and go vet; test with go test -race; check vulnerabilities with govulncheck

Applied to files:

  • .dockerignore
📚 Learning: 2026-03-21T12:54:22.557Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-21T12:54:22.557Z
Learning: Go 1.26+ required; CLI dependencies in `cli/go.mod` (Cobra, charmbracelet/huh, charmbracelet/lipgloss, sigstore-go, go-containerregistry, go-tuf)

Applied to files:

  • .dockerignore
📚 Learning: 2026-03-19T11:19:40.044Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T11:19:40.044Z
Learning: CLI workflow (`.github/workflows/cli.yml`) runs Go lint (golangci-lint + go vet) + test (race, coverage) + build (cross-compile matrix) + vulnerability check (govulncheck) + fuzz testing. Cross-compiles for linux/darwin/windows × amd64/arm64. GoReleaser release on v* tags with cosign keyless signing and SLSA L3 attestations.

Applied to files:

  • .dockerignore
📚 Learning: 2026-03-15T18:17:43.675Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:17:43.675Z
Learning: Applies to cli/** : CLI: Go 1.26+, dependencies in cli/go.mod (Cobra, charmbracelet/huh).

Applied to files:

  • .dockerignore
📚 Learning: 2026-03-15T21:32:02.880Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T21:32:02.880Z
Learning: Applies to .github/workflows/cli.yml : CLI workflow: Go lint (golangci-lint + go vet) + test (-race -coverprofile) + build (cross-compile: linux/darwin/windows × amd64/arm64) + govulncheck + fuzz testing (main-only, 30s/target, continue-on-error, matrix over 4 packages). cli-pass gate includes fuzz as informational. GoReleaser release on v* tags. Cosign keyless signing of checksums.txt. SLSA L3 provenance attestations. Sigstore bundle (.sigstore.json) attached. Post-release appends checksums/verification/provenance to draft release notes.

Applied to files:

  • .dockerignore
📚 Learning: 2026-03-15T20:45:14.430Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T20:45:14.430Z
Learning: Shell commands: for Go CLI work, cd cli is an exception because Go tooling requires working directory to be the module root. Go commands require `cd cli` for other work, never use `cd`.

Applied to files:

  • .dockerignore
📚 Learning: 2026-03-30T16:36:33.495Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: cli/CLAUDE.md:0-0
Timestamp: 2026-03-30T16:36:33.495Z
Learning: Applies to cli/internal/**/*.go : Place internal packages in `internal/` directory, including version, config, docker, compose, health, diagnostics, images, selfupdate, completion, ui, and verify functionality

Applied to files:

  • .dockerignore
📚 Learning: 2026-03-15T18:17:43.675Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:17:43.675Z
Learning: Pre-push hooks: mypy type-check + pytest unit tests + golangci-lint + go vet + go test (CLI, conditional on cli/**/*.go) (fast gate before push, skipped in pre-commit.ci — dedicated CI jobs already run these).

Applied to files:

  • .dockerignore
📚 Learning: 2026-03-31T12:07:37.367Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T12:07:37.367Z
Learning: Applies to web/src/**/*.{ts,tsx} : Never hardcode hex colors, font-family, pixel spacing, or Framer Motion transitions—use design tokens and `@/lib/motion` presets

Applied to files:

  • docs/overrides/extra.css
📚 Learning: 2026-03-31T12:08:03.565Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-03-31T12:08:03.565Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use token variables (`var(--so-shadow-card-hover)`, `border-border`, `border-bright`) for shadows and borders.

Applied to files:

  • docs/overrides/extra.css
📚 Learning: 2026-03-31T12:08:03.565Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-03-31T12:08:03.565Z
Learning: Applies to web/src/**/*.{tsx,ts} : Do NOT use `rgba()` with hardcoded values -- use design token variables instead

Applied to files:

  • docs/overrides/extra.css
📚 Learning: 2026-03-31T12:08:03.565Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-03-31T12:08:03.565Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use Tailwind semantic classes (`text-foreground`, `bg-card`, `text-accent`, `text-success`, `bg-danger`, etc.) or CSS variables (`var(--so-*)`) for colors. NEVER hardcode hex values in `.tsx`/`.ts` files.

Applied to files:

  • docs/overrides/extra.css
📚 Learning: 2026-03-31T12:08:03.565Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-03-31T12:08:03.565Z
Learning: Applies to web/src/{components,pages}/**/*.tsx : Do NOT recreate status dots inline -- use `<StatusBadge>` from `@/components/ui/status-badge`

Applied to files:

  • web/src/components/layout/AppLayout.tsx
  • web/src/components/layout/SidebarNavItem.tsx
📚 Learning: 2026-03-15T18:17:43.675Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:17:43.675Z
Learning: Dependabot: auto-updates Docker image digests and versions daily.

Applied to files:

  • docker/web/Dockerfile
📚 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__/components/layout/SidebarNavItem.test.tsx
📚 Learning: 2026-03-31T12:08:03.565Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-03-31T12:08:03.565Z
Learning: Applies to web/**/*.stories.{tsx,ts} : In Storybook 10, use `parameters.a11y.test: 'error' | 'todo' | 'off'` for accessibility testing configuration instead of old `.element` and `.manual` properties

Applied to files:

  • web/src/__tests__/components/layout/SidebarNavItem.test.tsx
📚 Learning: 2026-03-31T12:07:37.367Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T12:07:37.367Z
Learning: Update the relevant `docs/design/` page to reflect new reality when approved deviations occur

Applied to files:

  • docs/design/page-structure.md
📚 Learning: 2026-03-18T08:23:08.912Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-18T08:23:08.912Z
Learning: When approved deviations occur, update the relevant `docs/design/` page to reflect the new reality.

Applied to files:

  • docs/design/page-structure.md
🪛 LanguageTool
docs/design/page-structure.md

[uncategorized] ~145-~145: If this is a compound adjective that modifies the following noun, use a hyphen.
Context: ..."Docs" link renders a plain <a href> (full page navigation) instead of a React Router `...

(EN_COMPOUND_ADJECTIVE_INTERNAL)

🔇 Additional comments (24)
web/src/components/layout/Sidebar.tsx (1)

225-225: LGTM!

The "Docs" navigation item is correctly placed between Providers and Settings, uses the external prop to trigger anchor-based navigation (bypassing React Router), and reuses the existing SidebarNavItem component with the BookOpen icon.

web/src/router/routes.ts (1)

29-29: LGTM!

The DOCUMENTATION route constant correctly uses a trailing slash to match the nginx location /docs/ block. This route is intentionally not in PUBLIC_ROUTES since /docs/ is served directly by nginx as static HTML, bypassing React Router entirely.

web/src/components/layout/AppLayout.tsx (1)

75-75: LGTM!

The "Documentation" command correctly uses window.location.href for full-page navigation to /docs/, bypassing React Router. The keywords array enhances discoverability in the command palette.

CLAUDE.md (1)

57-57: LGTM!

Documentation accurately reflects the new architecture: docs are built with Zensical and embedded in the web Docker image at /docs/ via a docs-builder stage.

Also applies to: 80-80

web/CLAUDE.md (1)

27-27: LGTM!

The documentation correctly describes the new external link support in the sidebar layout and clarifies that DOCUMENTATION is an external, non-SPA-routed destination.

Also applies to: 32-32

.dockerignore (2)

20-23: LGTM!

The negation pattern correctly re-includes docs/ for the docs-builder stage. The order (exclude *.md, then un-ignore !docs/) ensures the docs/ directory and its contents are available during the Docker build.


64-65: LGTM!

Correctly un-ignores scripts/export_openapi.py needed by the docs-builder stage to generate the OpenAPI schema before building documentation.

docker/web/Dockerfile (3)

23-56: Well-structured docs-builder stage.

The multi-stage build follows best practices:

  • SHA-pinned base images for reproducibility
  • Layer caching with deps-first strategy (--no-install-project then project install)
  • Pre-compression matching the React builder pattern

69-70: LGTM!

Both the React SPA and docs are correctly copied into the nginx HTML root. The docs path /usr/share/nginx/html/docs/ aligns with the nginx location /docs/ block and the ROUTES.DOCUMENTATION constant.


48-49: zensical build output path is correctly configured.

Verification confirms that mkdocs.yml specifies site_dir: _site/docs, which matches the build source path in the Dockerfile.

web/nginx.conf (1)

51-62: Well-documented CSP override for docs.

The /docs/ location block correctly:

  • Adds blob: to script-src for MkDocs Material search Web Workers
  • Uses try_files $uri $uri/ =404 to serve static files without SPA fallback
  • Includes all security headers inline (necessary since add_header doesn't inherit when the block defines its own)
  • Sets a reasonable 1-hour cache for documentation that may change
web/src/__tests__/components/layout/SidebarNavItem.test.tsx (1)

99-136: Well-structured test coverage for the external prop.

The test suite covers the critical behaviors: anchor element rendering with correct attributes (href, rel), tooltip behavior when collapsed, label visibility when expanded, and badge rendering. The tests align with the implementation in SidebarNavItem.tsx and follow existing test patterns in this file.

docs/design/page-structure.md (2)

203-204: Documentation accurately reflects the implementation.

The navigation hierarchy entry correctly documents /docs/ as an external static HTML destination, matching the implementation in Sidebar.tsx (using external prop) and the nginx configuration.


267-268: Routing map entry is correct.

The URL routing map accurately describes /docs/ as static MkDocs HTML served by nginx, bypassing React Router. This aligns with the nginx location /docs/ block that uses try_files $uri $uri/ =404 instead of the SPA fallback.

docs/overrides/extra.css (3)

1-9: Well-documented rationale for hardcoded values.

The comment clearly explains why hex values are necessary here (MkDocs Material's --md-* variables live outside the React app's DOM tree). Documenting the single source of truth (web/src/styles/design-tokens.css) and the update requirement is good practice for maintainability.


11-54: CSS variables properly map to dashboard design system.

The variable definitions create a cohesive dark theme with appropriate hierarchy for backgrounds, text contrast levels, and accent colors. The typography fallback chain ("Geist Variable" → system fonts) handles cases where Geist fonts aren't loaded on docs pages.


56-85: Element overrides correctly target MkDocs Material components.

The selectors target MkDocs Material's specific class names (.md-header, .md-sidebar, .md-search__overlay, .md-tabs) with consistent border and background colors that match the defined CSS variables.

mkdocs.yml (2)

24-28: Palette configuration aligns with dashboard dark-only design.

Setting scheme: slate with primary: custom and accent: custom correctly delegates color definitions to extra.css. Disabling fonts (font: false) prevents MkDocs from loading Google Fonts, allowing the CSS to specify Geist with system fallbacks.


139-141: Extra CSS correctly wired.

The extra_css entry properly loads the dashboard theme overrides from docs/overrides/extra.css.

web/src/components/layout/SidebarNavItem.tsx (5)

13-14: Clear prop documentation.

The JSDoc comment succinctly explains the purpose of the external prop.


27-31: Good refactor: extracted shared base class.

Extracting baseClass avoids duplication between the anchor and NavLink branches while maintaining identical styling for both.


33-62: Content fragment enables clean code reuse.

Extracting the shared content (icon, label, badge, dot) into a fragment keeps the conditional rendering branches focused on the element type difference only.


64-70: External link implementation is correct.

The anchor element properly includes rel="noopener noreferrer" for security. Not using target="_blank" is intentional here since /docs/ is same-origin and should perform a full-page navigation rather than opening a new tab.


72-83: NavLink branch maintains active state styling.

The isActive callback correctly applies active styling only to internal router links. External links appropriately don't receive active state since React Router can't track navigation outside its control.

Comment on lines +54 to +59
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "DENY" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "geolocation=(), camera=(), microphone=()" always;
add_header Content-Security-Policy "default-src 'self'; script-src 'self' blob:; style-src 'self' 'unsafe-inline'; connect-src 'self'; img-src 'self' data:; font-src 'self'; object-src 'none'; base-uri 'self'; form-action 'self'" always;
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains" always;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Consider extracting shared headers to reduce duplication.

The security headers (lines 54-59) duplicate most of security-headers.conf except for the Content-Security-Policy. While the current approach works and is well-documented, you could reduce duplication by creating a security-headers-base.conf (without CSP) and including it here, then adding only the docs-specific CSP.

This is a minor maintainability suggestion — the current implementation is correct.

♻️ Optional: Extract base headers to reduce duplication

Create web/security-headers-base.conf:

add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "DENY" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "geolocation=(), camera=(), microphone=()" always;
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains" always;

Then in the /docs/ block:

location /docs/ {
    include /etc/nginx/security-headers-base.conf;
    add_header Content-Security-Policy "default-src 'self'; script-src 'self' blob:; ..." always;
    add_header Cache-Control "public, max-age=3600" always;
    try_files $uri $uri/ =404;
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@web/nginx.conf` around lines 54 - 59, Extract the shared security headers
into a new file (e.g., security-headers-base.conf) containing the common
add_header directives except Content-Security-Policy, then update the nginx docs
location (the location /docs/ block in web/nginx.conf) to include that base file
via include and keep only the docs-specific add_header Content-Security-Policy
and Cache-Control lines there; this removes duplication of
X-Content-Type-Options, X-Frame-Options, Referrer-Policy, Permissions-Policy and
Strict-Transport-Security while leaving the CSP unique to the docs block.

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 integrates static MkDocs documentation into the web Docker image, serving it via a dedicated nginx location block at /docs/ to bypass the React SPA. Key changes include a new docs-builder multi-stage Docker build, custom CSS for documentation theming, and updates to the sidebar component to support external links. Review feedback highlights a non-existent Python version tag in the Dockerfile that would cause build failures and suggests removing unnecessary rel attributes from the new anchor tags in the sidebar navigation.


# Stage 2: Serve with nginx
# Stage 2: Build MkDocs documentation
FROM python:3.14.3-slim@sha256:fb83750094b46fd6b8adaa80f66e2302ecbe45d513f6cece637a841e1025b4ca AS docs-builder
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.

high

Python 3.14 is currently in development and has not reached version 3.14.3. Using a non-existent version tag will cause the Docker build to fail. Consider using a valid tag like 3.14-slim (if available) or 3.13-slim if the 3.14 features are not strictly required for the build stage.

FROM python:3.14-slim@sha256:fb83750094b46fd6b8adaa80f66e2302ecbe45d513f6cece637a841e1025b4ca AS docs-builder


if (external) {
return (
<a href={to} rel="noopener noreferrer" title={collapsed ? label : undefined} className={baseClass}>
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.

medium

The rel="noopener noreferrer" attribute is unnecessary for internal links navigating in the same tab. Furthermore, noreferrer prevents the browser from sending the Referer header, which can be useful for internal analytics or security checks. Since target="_blank" is not used here, these attributes should be removed.

Suggested change
<a href={to} rel="noopener noreferrer" title={collapsed ? label : undefined} className={baseClass}>
<a href={to} title={collapsed ? label : undefined} className={baseClass}>

const link = screen.getByRole('link', { name: /docs/i })
expect(link.tagName).toBe('A')
expect(link).toHaveAttribute('href', '/docs/')
expect(link).toHaveAttribute('rel', 'noopener noreferrer')
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.

medium

Update the test expectation to match the removal of the rel attribute from the SidebarNavItem component.

Suggested change
expect(link).toHaveAttribute('rel', 'noopener noreferrer')
expect(link).not.toHaveAttribute('rel')

@Aureliolo Aureliolo temporarily deployed to cloudflare-preview March 31, 2026 14:00 — with GitHub Actions Inactive
@Aureliolo Aureliolo temporarily deployed to cloudflare-preview March 31, 2026 14:03 — with GitHub Actions Inactive
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

Caution

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

⚠️ Outside diff range comments (1)
web/src/components/layout/SidebarNavItem.tsx (1)

53-57: 🛠️ Refactor suggestion | 🟠 Major

Use <StatusBadge> instead of an inline dot.

This branch still hand-renders the status indicator and keeps dotColor as an arbitrary class string, so the component is still bypassing the shared status primitive.

As per coding guidelines "Do NOT recreate status dots inline -- use <StatusBadge> from @/components/ui/status-badge".

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

In `@web/src/components/layout/SidebarNavItem.tsx` around lines 53 - 57, Replace
the inline dot span in SidebarNavItem with the shared StatusBadge component:
import StatusBadge from '@/components/ui/status-badge', remove the ad-hoc
dotColor class string usage, and render <StatusBadge .../> instead of the span
(map the existing dotColor value to the appropriate StatusBadge prop such as
color/variant or className so the shared primitive controls styling/ARIA).
Update references to dotColor inside SidebarNavItem to use the StatusBadge API
and delete the inline span markup.
🤖 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/nginx.conf`:
- Around line 60-64: Update the Content-Security-Policy header in the add_header
line that sets Content-Security-Policy so the worker-src directive includes
'self' in addition to blob: (i.e., change worker-src blob:; to worker-src 'self'
blob:;), ensuring the CSP string built in the add_header
"Content-Security-Policy" directive will allow file-based workers served from
the same origin (restoring MkDocs Material search). Target the add_header
Content-Security-Policy statement in the nginx config where worker-src is
currently set.

In `@web/src/__tests__/components/layout/SidebarNavItem.test.tsx`:
- Around line 174-192: Replace the hard-coded routerPaths array in
SidebarNavItem.test.tsx with an assertion against the actual router route
definitions: import the route table exported from your router (e.g., the routes
or ROUTES export from router/index.tsx) and iterate its path entries to assert
none equal or startWith '/docs' or 'docs' (and none contain a docs wildcard like
'docs/*'); update the test (still referencing ROUTES.DOCUMENTATION) to read the
real route config rather than a copied array so adding a docs route in
router/index.tsx will fail this test.

---

Outside diff comments:
In `@web/src/components/layout/SidebarNavItem.tsx`:
- Around line 53-57: Replace the inline dot span in SidebarNavItem with the
shared StatusBadge component: import StatusBadge from
'@/components/ui/status-badge', remove the ad-hoc dotColor class string usage,
and render <StatusBadge .../> instead of the span (map the existing dotColor
value to the appropriate StatusBadge prop such as color/variant or className so
the shared primitive controls styling/ARIA). Update references to dotColor
inside SidebarNavItem to use the StatusBadge API and delete the inline span
markup.
🪄 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: 9d123472-3262-4dd6-94f5-0ee0e711d93a

📥 Commits

Reviewing files that changed from the base of the PR and between 5d59d91 and 3865d98.

📒 Files selected for processing (8)
  • docker/web/Dockerfile
  • docs/design/page-structure.md
  • docs/user_guide.md
  • web/nginx.conf
  • web/src/__tests__/components/layout/Sidebar.test.tsx
  • web/src/__tests__/components/layout/SidebarNavItem.test.tsx
  • web/src/components/layout/AppLayout.tsx
  • web/src/components/layout/SidebarNavItem.tsx
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: Build Backend
  • GitHub Check: Build Sandbox
  • GitHub Check: Dashboard Test
  • GitHub Check: Dependency Review
  • GitHub Check: Analyze (go)
  • GitHub Check: Analyze (python)
🧰 Additional context used
📓 Path-based instructions (6)
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
Never hardcode hex colors, font-family, pixel spacing, or Framer Motion transitions—use design tokens and @/lib/motion presets

Files:

  • web/src/__tests__/components/layout/Sidebar.test.tsx
  • web/src/components/layout/AppLayout.tsx
  • web/src/components/layout/SidebarNavItem.tsx
  • web/src/__tests__/components/layout/SidebarNavItem.test.tsx
web/src/**/*.{tsx,ts}

📄 CodeRabbit inference engine (web/CLAUDE.md)

web/src/**/*.{tsx,ts}: Do NOT use rgba() with hardcoded values -- use design token variables instead
Use Tailwind semantic classes (text-foreground, bg-card, text-accent, text-success, bg-danger, etc.) or CSS variables (var(--so-*)) for colors. NEVER hardcode hex values in .tsx/.ts files.
Use font-sans or font-mono (maps to Geist tokens) for typography. NEVER set fontFamily directly.
Use density-aware tokens (p-card, gap-section-gap, gap-grid-gap) or standard Tailwind spacing. NEVER hardcode pixel values for layout spacing.
Use token variables (var(--so-shadow-card-hover), border-border, border-bright) for shadows and borders.
Ensure CSS side-effect imports have type declarations in TypeScript 6 where noUncheckedSideEffectImports defaults to true. Use /// <reference types="vite/client" /> for Vite projects.
ESLint must enforce zero warnings on the web package. Run npm --prefix web run lint and fix all warnings.
TypeScript type checking must pass. Run npm --prefix web run type-check and resolve all type errors.

Files:

  • web/src/__tests__/components/layout/Sidebar.test.tsx
  • web/src/components/layout/AppLayout.tsx
  • web/src/components/layout/SidebarNavItem.tsx
  • web/src/__tests__/components/layout/SidebarNavItem.test.tsx
web/src/**/*

📄 CodeRabbit inference engine (web/CLAUDE.md)

A PostToolUse hook (scripts/check_web_design_system.py) runs automatically on every Edit/Write to web/src/ files and catches hardcoded hex colors, rgba values, font-family declarations, hardcoded Framer Motion transition durations, missing Storybook stories, duplicate patterns, and complex .map() blocks. Fix all violations before proceeding.

Files:

  • web/src/__tests__/components/layout/Sidebar.test.tsx
  • web/src/components/layout/AppLayout.tsx
  • web/src/components/layout/SidebarNavItem.tsx
  • web/src/__tests__/components/layout/SidebarNavItem.test.tsx
web/src/{components,pages}/**/*.{tsx,ts}

📄 CodeRabbit inference engine (web/CLAUDE.md)

ALWAYS reuse existing components from web/src/components/ui/ before creating new ones (StatusBadge, MetricCard, Sparkline, SectionCard, AgentCard, DeptHealthBar, ProgressGauge, StatPill, Avatar, Button, Toast, ToastContainer, Skeleton variants, EmptyState, ErrorBoundary, ConfirmDialog, CommandPalette, InlineEdit, AnimatedPresence, StaggerGroup, StaggerItem, Drawer, InputField, SelectField, SliderField, ToggleField, TaskStatusIndicator, PriorityBadge, ProviderHealthBadge, TokenUsageBar, CodeMirrorEditor, SegmentedControl, ThemeToggle, LiveRegion, MobileUnsupportedOverlay, LazyCodeMirrorEditor, TagInput)

Files:

  • web/src/components/layout/AppLayout.tsx
  • web/src/components/layout/SidebarNavItem.tsx
web/src/{components,pages}/**/*.tsx

📄 CodeRabbit inference engine (web/CLAUDE.md)

web/src/{components,pages}/**/*.tsx: Do NOT recreate status dots inline -- use <StatusBadge> from @/components/ui/status-badge
Do NOT build card-with-header layouts from scratch -- use <SectionCard> from @/components/ui/section-card
Do NOT create metric displays with text-metric font-bold -- use <MetricCard> from @/components/ui/metric-card
Do NOT render initials circles manually -- use <Avatar> from @/components/ui/avatar
Do NOT create complex (>8 line) JSX inside .map() -- extract to a shared component

Files:

  • web/src/components/layout/AppLayout.tsx
  • web/src/components/layout/SidebarNavItem.tsx
docker/**/*

📄 CodeRabbit inference engine (CLAUDE.md)

CLI verifies cosign signatures and SLSA provenance at pull time; bypass with --skip-verify

Files:

  • docker/web/Dockerfile
🧠 Learnings (33)
📓 Common learnings
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:17:43.675Z
Learning: Applies to docker/{Dockerfile*,compose.yml} : Docker: Backend uses 3-stage build (builder → setup → distroless runtime), Chainguard Python, non-root (UID 65532), CIS-hardened. Web uses nginxinc/nginx-unprivileged, Vue 3 SPA with PrimeVue + Tailwind CSS, SPA routing, API/WebSocket proxy to backend.
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`.
📚 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__/components/layout/Sidebar.test.tsx
  • web/src/__tests__/components/layout/SidebarNavItem.test.tsx
📚 Learning: 2026-03-31T12:08:03.565Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-03-31T12:08:03.565Z
Learning: Applies to web/src/**/*.{tsx,ts} : Ensure CSS side-effect imports have type declarations in TypeScript 6 where `noUncheckedSideEffectImports` defaults to `true`. Use `/// <reference types="vite/client" />` for Vite projects.

Applied to files:

  • web/src/__tests__/components/layout/Sidebar.test.tsx
📚 Learning: 2026-03-15T18:17:43.675Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:17:43.675Z
Learning: Applies to docker/{Dockerfile*,compose.yml} : Docker: Backend uses 3-stage build (builder → setup → distroless runtime), Chainguard Python, non-root (UID 65532), CIS-hardened. Web uses nginxinc/nginx-unprivileged, Vue 3 SPA with PrimeVue + Tailwind CSS, SPA routing, API/WebSocket proxy to backend.

Applied to files:

  • docs/user_guide.md
  • docker/web/Dockerfile
📚 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:

  • docs/user_guide.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 docker/Dockerfile.sandbox : Docker sandbox: `synthorg-sandbox` — Python 3.14 + Node.js + git, non-root (UID 10001), agent code execution sandbox

Applied to files:

  • docs/user_guide.md
  • docker/web/Dockerfile
📚 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:

  • docs/user_guide.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 docker/Dockerfile : Docker: 3-stage build (builder → setup → distroless runtime) for backend, Chainguard Python, non-root (UID 65532), CIS-hardened

Applied to files:

  • docs/user_guide.md
  • docker/web/Dockerfile
📚 Learning: 2026-03-21T14:12:17.848Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-21T14:12:17.848Z
Learning: Applies to Dockerfile* : Backend images must use Chainguard distroless with non-root user; web image must use nginx-unprivileged with non-root user; sandbox image must use Python + Node.js with non-root user. All Docker files in `docker/` -- Dockerfiles, compose, `.env.example`. Single root `.dockerignore`. All images build with `context: .`

Applied to files:

  • docs/user_guide.md
  • docker/web/Dockerfile
📚 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 docker/Dockerfile.web : `nginxinc/nginx-unprivileged` base with non-root user (UID 101), Vue 3 SPA (PrimeVue + Tailwind CSS), SPA routing, API/WebSocket proxy to backend

Applied to files:

  • docs/user_guide.md
  • docker/web/Dockerfile
📚 Learning: 2026-03-15T21:32:02.880Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T21:32:02.880Z
Learning: Applies to .github/workflows/docker.yml : Docker workflow: builds backend + web + sandbox images, pushes to GHCR, signs with cosign. SLSA L3 provenance attestations via actions/attest-build-provenance. Scans: Trivy (CRITICAL = hard fail, HIGH = warn) + Grype (critical cutoff) + CIS Docker Benchmark v1.6.0 compliance (informational). CVE triage via .github/.trivyignore.yaml and .github/.grype.yaml. Images only pushed after scans pass. Triggers on push to main and version tags (v*).

Applied to files:

  • docs/user_guide.md
  • docker/web/Dockerfile
📚 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:

  • docs/user_guide.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:

  • docs/user_guide.md
📚 Learning: 2026-03-31T12:08:03.565Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-03-31T12:08:03.565Z
Learning: Applies to web/src/{components,pages}/**/*.tsx : Do NOT build card-with-header layouts from scratch -- use `<SectionCard>` from `@/components/ui/section-card`

Applied to files:

  • web/src/components/layout/AppLayout.tsx
📚 Learning: 2026-03-31T12:08:03.565Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-03-31T12:08:03.565Z
Learning: Applies to web/src/components/ui/**/*.{tsx,ts} : When creating new shared components in `web/src/components/ui/`, place it with a descriptive kebab-case filename, create a `.stories.tsx` file with all states (default, hover, loading, error, empty), export props as a TypeScript interface, use design tokens exclusively, and import `cn` from `@/lib/utils` for conditional class merging

Applied to files:

  • web/src/components/layout/AppLayout.tsx
  • web/src/components/layout/SidebarNavItem.tsx
  • web/src/__tests__/components/layout/SidebarNavItem.test.tsx
📚 Learning: 2026-03-31T12:08:03.565Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-03-31T12:08:03.565Z
Learning: Applies to web/src/{components,pages}/**/*.{tsx,ts} : ALWAYS reuse existing components from `web/src/components/ui/` before creating new ones (StatusBadge, MetricCard, Sparkline, SectionCard, AgentCard, DeptHealthBar, ProgressGauge, StatPill, Avatar, Button, Toast, ToastContainer, Skeleton variants, EmptyState, ErrorBoundary, ConfirmDialog, CommandPalette, InlineEdit, AnimatedPresence, StaggerGroup, StaggerItem, Drawer, InputField, SelectField, SliderField, ToggleField, TaskStatusIndicator, PriorityBadge, ProviderHealthBadge, TokenUsageBar, CodeMirrorEditor, SegmentedControl, ThemeToggle, LiveRegion, MobileUnsupportedOverlay, LazyCodeMirrorEditor, TagInput)

Applied to files:

  • web/src/components/layout/AppLayout.tsx
📚 Learning: 2026-03-31T12:08:03.565Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-03-31T12:08:03.565Z
Learning: Applies to web/src/{components,pages}/**/*.tsx : Do NOT recreate status dots inline -- use `<StatusBadge>` from `@/components/ui/status-badge`

Applied to files:

  • web/src/components/layout/AppLayout.tsx
📚 Learning: 2026-03-31T12:07:37.367Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T12:07:37.367Z
Learning: Update the relevant `docs/design/` page to reflect new reality when approved deviations occur

Applied to files:

  • docs/design/page-structure.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:

  • docs/design/page-structure.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:

  • docs/design/page-structure.md
📚 Learning: 2026-03-18T08:23:08.912Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-18T08:23:08.912Z
Learning: When approved deviations occur, update the relevant `docs/design/` page to reflect the new reality.

Applied to files:

  • docs/design/page-structure.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:

  • docs/design/page-structure.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:

  • docs/design/page-structure.md
📚 Learning: 2026-03-15T18:17:43.675Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:17:43.675Z
Learning: Dependabot: auto-updates Docker image digests and versions daily.

Applied to files:

  • docker/web/Dockerfile
📚 Learning: 2026-03-21T14:12:17.848Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-21T14:12:17.848Z
Learning: Docker workflow (`docker.yml`): build + Trivy/Grype scan + push to GHCR + cosign sign + SLSA L3 provenance. CVE triage: `.github/.trivyignore.yaml`, `.github/.grype.yaml`

Applied to files:

  • docker/web/Dockerfile
📚 Learning: 2026-03-31T12:07:37.367Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T12:07:37.367Z
Learning: Applies to Dockerfile : All Docker images must be non-root and use distroless/unprivileged base images (backend: Chainguard distroless, web: nginx-unprivileged, sandbox: Python + Node.js non-root)

Applied to files:

  • docker/web/Dockerfile
📚 Learning: 2026-03-15T16:38:08.735Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T16:38:08.735Z
Learning: Applies to docker/** : Docker build context: single root .dockerignore (both images build with context: .). Tags: CI tags images with version from pyproject.toml ([tool.commitizen].version), semver, and SHA.

Applied to files:

  • docker/web/Dockerfile
📚 Learning: 2026-03-21T11:08:01.542Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-21T11:08:01.542Z
Learning: Applies to **/*.py : No `from __future__ import annotations` — Python 3.14 has PEP 649 native lazy annotations.

Applied to files:

  • docker/web/Dockerfile
📚 Learning: 2026-03-31T12:07:37.364Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T12:07:37.364Z
Learning: Applies to src/**/*.py : No `from __future__ import annotations` — Python 3.14 has PEP 649 native lazy annotations

Applied to files:

  • docker/web/Dockerfile
📚 Learning: 2026-03-15T12:00:18.113Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T12:00:18.113Z
Learning: Applies to .github/workflows/docker.yml : CI Docker: build → scan → push to GHCR + cosign sign + SLSA L3 provenance via attest-build-provenance (images only pushed after Trivy/Grype scans pass).

Applied to files:

  • docker/web/Dockerfile
📚 Learning: 2026-03-31T12:08:03.565Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-03-31T12:08:03.565Z
Learning: Applies to web/**/*.stories.{tsx,ts} : In Storybook 10, use `storybook/test` (not `storybook/test`) and `storybook/actions` (not `storybook/addon-actions`) for imports

Applied to files:

  • web/src/__tests__/components/layout/SidebarNavItem.test.tsx
📚 Learning: 2026-03-31T12:08:03.565Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-03-31T12:08:03.565Z
Learning: Applies to web/**/*.stories.{tsx,ts} : In Storybook 10, use `parameters.a11y.test: 'error' | 'todo' | 'off'` for accessibility testing configuration instead of old `.element` and `.manual` properties

Applied to files:

  • web/src/__tests__/components/layout/SidebarNavItem.test.tsx
📚 Learning: 2026-03-31T12:07:37.367Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T12:07:37.367Z
Learning: Applies to src/**/*.{js,ts,tsx} : Use property-based testing with fast-check (`fc.assert` + `fc.property`)

Applied to files:

  • web/src/__tests__/components/layout/SidebarNavItem.test.tsx

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: 1

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

Inline comments:
In `@docker/web/Dockerfile`:
- Around line 43-47: Add a brief inline comment above the RUN touch README.md
line in the Dockerfile explaining that README.md is intentionally created as a
placeholder because .dockerignore excludes *.md while pyproject.toml references
README.md for package metadata, and that this ensures synthorg.api.app (and the
docs build via the uv sync step) can import/read the file; optionally note that
the alternative is to copy README.md explicitly or adjust .dockerignore if
maintainers prefer.
🪄 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: a9090372-8018-4b0a-813a-ea669db0207a

📥 Commits

Reviewing files that changed from the base of the PR and between 3865d98 and 0ae89e6.

📒 Files selected for processing (1)
  • docker/web/Dockerfile
📜 Review details
🧰 Additional context used
📓 Path-based instructions (1)
docker/**/*

📄 CodeRabbit inference engine (CLAUDE.md)

CLI verifies cosign signatures and SLSA provenance at pull time; bypass with --skip-verify

Files:

  • docker/web/Dockerfile
🧠 Learnings (14)
📓 Common learnings
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:17:43.675Z
Learning: Applies to docker/{Dockerfile*,compose.yml} : Docker: Backend uses 3-stage build (builder → setup → distroless runtime), Chainguard Python, non-root (UID 65532), CIS-hardened. Web uses nginxinc/nginx-unprivileged, Vue 3 SPA with PrimeVue + Tailwind CSS, SPA routing, API/WebSocket proxy to backend.
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T11:33:01.580Z
Learning: Applies to docker/Dockerfile.web : `nginxinc/nginx-unprivileged` base with non-root user (UID 101), Vue 3 SPA (PrimeVue + Tailwind CSS), SPA routing, API/WebSocket proxy to backend
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`.
📚 Learning: 2026-03-15T18:17:43.675Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:17:43.675Z
Learning: Applies to docker/{Dockerfile*,compose.yml} : Docker: Backend uses 3-stage build (builder → setup → distroless runtime), Chainguard Python, non-root (UID 65532), CIS-hardened. Web uses nginxinc/nginx-unprivileged, Vue 3 SPA with PrimeVue + Tailwind CSS, SPA routing, API/WebSocket proxy to backend.

Applied to files:

  • docker/web/Dockerfile
📚 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 docker/Dockerfile : Docker: 3-stage build (builder → setup → distroless runtime) for backend, Chainguard Python, non-root (UID 65532), CIS-hardened

Applied to files:

  • docker/web/Dockerfile
📚 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 docker/Dockerfile.web : `nginxinc/nginx-unprivileged` base with non-root user (UID 101), Vue 3 SPA (PrimeVue + Tailwind CSS), SPA routing, API/WebSocket proxy to backend

Applied to files:

  • docker/web/Dockerfile
📚 Learning: 2026-03-21T14:12:17.848Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-21T14:12:17.848Z
Learning: Applies to Dockerfile* : Backend images must use Chainguard distroless with non-root user; web image must use nginx-unprivileged with non-root user; sandbox image must use Python + Node.js with non-root user. All Docker files in `docker/` -- Dockerfiles, compose, `.env.example`. Single root `.dockerignore`. All images build with `context: .`

Applied to files:

  • docker/web/Dockerfile
📚 Learning: 2026-03-21T14:12:17.848Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-21T14:12:17.848Z
Learning: Docker workflow (`docker.yml`): build + Trivy/Grype scan + push to GHCR + cosign sign + SLSA L3 provenance. CVE triage: `.github/.trivyignore.yaml`, `.github/.grype.yaml`

Applied to files:

  • docker/web/Dockerfile
📚 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 docker/Dockerfile.sandbox : Docker sandbox: `synthorg-sandbox` — Python 3.14 + Node.js + git, non-root (UID 10001), agent code execution sandbox

Applied to files:

  • docker/web/Dockerfile
📚 Learning: 2026-03-15T18:17:43.675Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:17:43.675Z
Learning: Dependabot: auto-updates Docker image digests and versions daily.

Applied to files:

  • docker/web/Dockerfile
📚 Learning: 2026-03-15T21:32:02.880Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T21:32:02.880Z
Learning: Applies to .github/workflows/docker.yml : Docker workflow: builds backend + web + sandbox images, pushes to GHCR, signs with cosign. SLSA L3 provenance attestations via actions/attest-build-provenance. Scans: Trivy (CRITICAL = hard fail, HIGH = warn) + Grype (critical cutoff) + CIS Docker Benchmark v1.6.0 compliance (informational). CVE triage via .github/.trivyignore.yaml and .github/.grype.yaml. Images only pushed after scans pass. Triggers on push to main and version tags (v*).

Applied to files:

  • docker/web/Dockerfile
📚 Learning: 2026-03-31T12:07:37.367Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T12:07:37.367Z
Learning: Applies to Dockerfile : All Docker images must be non-root and use distroless/unprivileged base images (backend: Chainguard distroless, web: nginx-unprivileged, sandbox: Python + Node.js non-root)

Applied to files:

  • docker/web/Dockerfile
📚 Learning: 2026-03-15T16:38:08.735Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T16:38:08.735Z
Learning: Applies to docker/** : Docker build context: single root .dockerignore (both images build with context: .). Tags: CI tags images with version from pyproject.toml ([tool.commitizen].version), semver, and SHA.

Applied to files:

  • docker/web/Dockerfile
📚 Learning: 2026-03-21T11:08:01.542Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-21T11:08:01.542Z
Learning: Applies to **/*.py : No `from __future__ import annotations` — Python 3.14 has PEP 649 native lazy annotations.

Applied to files:

  • docker/web/Dockerfile
📚 Learning: 2026-03-31T12:07:37.364Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T12:07:37.364Z
Learning: Applies to src/**/*.py : No `from __future__ import annotations` — Python 3.14 has PEP 649 native lazy annotations

Applied to files:

  • docker/web/Dockerfile
📚 Learning: 2026-03-15T12:00:18.113Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T12:00:18.113Z
Learning: Applies to .github/workflows/docker.yml : CI Docker: build → scan → push to GHCR + cosign sign + SLSA L3 provenance via attest-build-provenance (images only pushed after Trivy/Grype scans pass).

Applied to files:

  • docker/web/Dockerfile
🔇 Additional comments (3)
docker/web/Dockerfile (3)

49-60: LGTM!

The docs build stage follows good practices:

  • COPY commands align with .dockerignore re-inclusion patterns
  • Pre-compression pattern matches the React builder (line 21) with appropriate additions (.xml for sitemaps)
  • Works correctly with nginx's gzip_static on directive

74-75: LGTM!

The COPY destination /usr/share/nginx/html/docs/ correctly aligns with the nginx.conf /docs/ location block which inherits the global root /usr/share/nginx/html; directive. The trailing slashes ensure directory contents are properly copied.


24-26: Confirm uv 0.10.9 is available and stable.

Python 3.14.3-slim is confirmed on Docker Hub. However, the uv 0.10.9 tag cannot be verified through public GHCR APIs (authentication required). While the SHA256 digest provides reproducibility guarantees, please confirm this version exists on GHCR and is actively maintained before merging.

Comment on lines +43 to +47
# Install project (export_openapi.py imports synthorg.api.app)
RUN touch README.md
COPY --chown=docsbuild:docsbuild src/ src/
RUN --mount=type=cache,target=/tmp/uv-cache,uid=1001,gid=1001 \
uv sync --frozen --group docs --no-dev
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Document the README.md placeholder workaround.

The empty README.md is created because .dockerignore excludes *.md files, but pyproject.toml likely references README.md for package metadata. While this works for the docs build, consider adding a brief comment explaining the workaround for maintainability.

📝 Suggested documentation
-# Install project (export_openapi.py imports synthorg.api.app)
-RUN touch README.md
+# Install project (export_openapi.py imports synthorg.api.app).
+# Create empty README.md: .dockerignore excludes *.md but pyproject.toml
+# references it for metadata; uv sync tolerates an empty placeholder.
+RUN touch README.md
📝 Committable suggestion

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

Suggested change
# Install project (export_openapi.py imports synthorg.api.app)
RUN touch README.md
COPY --chown=docsbuild:docsbuild src/ src/
RUN --mount=type=cache,target=/tmp/uv-cache,uid=1001,gid=1001 \
uv sync --frozen --group docs --no-dev
# Install project (export_openapi.py imports synthorg.api.app).
# Create empty README.md: .dockerignore excludes *.md but pyproject.toml
# references it for metadata; uv sync tolerates an empty placeholder.
RUN touch README.md
COPY --chown=docsbuild:docsbuild src/ src/
RUN --mount=type=cache,target=/tmp/uv-cache,uid=1001,gid=1001 \
uv sync --frozen --group docs --no-dev
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docker/web/Dockerfile` around lines 43 - 47, Add a brief inline comment above
the RUN touch README.md line in the Dockerfile explaining that README.md is
intentionally created as a placeholder because .dockerignore excludes *.md while
pyproject.toml references README.md for package metadata, and that this ensures
synthorg.api.app (and the docs build via the uv sync step) can import/read the
file; optionally note that the alternative is to copy README.md explicitly or
adjust .dockerignore if maintainers prefer.

Aureliolo and others added 5 commits March 31, 2026 16:20
Add nginx location block to serve MkDocs static HTML at /docs/,
a docs builder stage in the web Dockerfile (Python + uv + Zensical),
and MkDocs Material theme overrides matching the dashboard dark design
system. The React sidebar gets a "Docs" nav item and command palette
entry that perform full-page navigation to the static docs.

Closes #295

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add docs-scoped CSP override with blob: for Material search workers
- Add rel="noopener noreferrer" to external SidebarNavItem links
- Add tests for SidebarNavItem external prop (4 new tests)
- Document hex values in extra.css as intentional (MkDocs override)
- Update CLAUDE.md Docker/docs sections for embedded docs
- Update page-structure.md sidebar hierarchy, routing table, and
  architecture note for /docs/ static serving
- Update web/CLAUDE.md router and component descriptions

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

- Fix CSP: move blob: from script-src to worker-src for MkDocs Material search
- Add maintenance comment for /docs/ inline security headers
- Remove unnecessary rel="noopener noreferrer" on same-origin anchor
- Add non-root user to docs-builder Docker stage (defense-in-depth)
- Update Dockerfile header comment to reflect 3-stage build
- Update docs/user_guide.md web container description with embedded docs
- Add API/WS annotations to Documentation section in page-structure.md
- Hyphenate "full-page navigation" compound adjective
- Add inline comment explaining window.location.href in command palette
- Add 7 new tests: isActive styling, dotColor, end prop, trailing slash,
  route invariant, Docs sidebar item, rel attribute removal
- Add Docs item assertion to Sidebar workspace nav test

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
BuildKit cache mounts default to root ownership. The docsbuild user
(uid=1001) needs write access, so pin uid/gid on the mount directive.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add 'self' to worker-src CSP for file-based workers alongside blob:
- Replace hardcoded routerPaths array in test with actual router.routes
  introspection (export router from index.tsx for test access)
- Skip StatusBadge replacement for dotColor (different API contract:
  StatusBadge takes typed AgentRuntimeStatus enum, dotColor accepts
  arbitrary CSS classes -- incompatible without breaking changes)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@Aureliolo Aureliolo force-pushed the feat/embed-docs-dashboard branch from 0ae89e6 to dadf69a Compare March 31, 2026 14:26
@Aureliolo Aureliolo temporarily deployed to cloudflare-preview March 31, 2026 14:27 — with GitHub Actions Inactive
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: 1

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

Inline comments:
In @.dockerignore:
- Around line 20-24: The .dockerignore currently ignores docs/ and *.md then
attempts to re-include the docs folder with !docs/, but that does not un-ignore
nested files; update the negation to be recursive (e.g., add or replace with
!docs/**) so all files and subdirectories under docs are included in the build
context; ensure the recursive negation line (e.g., "!docs/**") appears after the
docs/ and *.md ignore entries in the .dockerignore.
🪄 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: 8eb088fd-d003-4cd4-a500-a9c322d1c2e3

📥 Commits

Reviewing files that changed from the base of the PR and between 0ae89e6 and dadf69a.

📒 Files selected for processing (16)
  • .dockerignore
  • CLAUDE.md
  • docker/web/Dockerfile
  • docs/design/page-structure.md
  • docs/overrides/extra.css
  • docs/user_guide.md
  • mkdocs.yml
  • web/CLAUDE.md
  • web/nginx.conf
  • web/src/__tests__/components/layout/Sidebar.test.tsx
  • web/src/__tests__/components/layout/SidebarNavItem.test.tsx
  • web/src/components/layout/AppLayout.tsx
  • web/src/components/layout/Sidebar.tsx
  • web/src/components/layout/SidebarNavItem.tsx
  • web/src/router/index.tsx
  • web/src/router/routes.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: Dashboard Test
  • GitHub Check: Build Backend
  • GitHub Check: Build Sandbox
  • GitHub Check: Build Web
  • GitHub Check: Analyze (python)
  • GitHub Check: Dependency Review
🧰 Additional context used
📓 Path-based instructions (9)
docs/**/*.md

📄 CodeRabbit inference engine (CLAUDE.md)

docs/**/*.md: Pages CI job: version extraction from pyproject.toml, OpenAPI export, Astro + Zensical docs build with version banner, GitHub Pages deploy on push to main.
Docs: Markdown in docs/, built with Zensical. Design spec: docs/design/ (11 pages), Architecture: docs/architecture/, Roadmap: docs/roadmap/. Security: docs/security.md, Licensing: docs/licensing.md, Reference: docs/reference/.

Files:

  • docs/user_guide.md
  • docs/design/page-structure.md
web/src/{components,pages}/**/*.{tsx,ts}

📄 CodeRabbit inference engine (web/CLAUDE.md)

ALWAYS reuse existing components from web/src/components/ui/ before creating new ones (StatusBadge, MetricCard, Sparkline, SectionCard, AgentCard, DeptHealthBar, ProgressGauge, StatPill, Avatar, Button, Toast, ToastContainer, Skeleton variants, EmptyState, ErrorBoundary, ConfirmDialog, CommandPalette, InlineEdit, AnimatedPresence, StaggerGroup, StaggerItem, Drawer, InputField, SelectField, SliderField, ToggleField, TaskStatusIndicator, PriorityBadge, ProviderHealthBadge, TokenUsageBar, CodeMirrorEditor, SegmentedControl, ThemeToggle, LiveRegion, MobileUnsupportedOverlay, LazyCodeMirrorEditor, TagInput)

Files:

  • web/src/components/layout/Sidebar.tsx
  • web/src/components/layout/AppLayout.tsx
  • web/src/components/layout/SidebarNavItem.tsx
web/src/{components,pages}/**/*.tsx

📄 CodeRabbit inference engine (web/CLAUDE.md)

web/src/{components,pages}/**/*.tsx: Do NOT recreate status dots inline -- use <StatusBadge> from @/components/ui/status-badge
Do NOT build card-with-header layouts from scratch -- use <SectionCard> from @/components/ui/section-card
Do NOT create metric displays with text-metric font-bold -- use <MetricCard> from @/components/ui/metric-card
Do NOT render initials circles manually -- use <Avatar> from @/components/ui/avatar
Do NOT create complex (>8 line) JSX inside .map() -- extract to a shared component

Files:

  • web/src/components/layout/Sidebar.tsx
  • web/src/components/layout/AppLayout.tsx
  • web/src/components/layout/SidebarNavItem.tsx
web/src/**/*.{tsx,ts}

📄 CodeRabbit inference engine (web/CLAUDE.md)

web/src/**/*.{tsx,ts}: Do NOT use rgba() with hardcoded values -- use design token variables instead
Use Tailwind semantic classes (text-foreground, bg-card, text-accent, text-success, bg-danger, etc.) or CSS variables (var(--so-*)) for colors. NEVER hardcode hex values in .tsx/.ts files.
Use font-sans or font-mono (maps to Geist tokens) for typography. NEVER set fontFamily directly.
Use density-aware tokens (p-card, gap-section-gap, gap-grid-gap) or standard Tailwind spacing. NEVER hardcode pixel values for layout spacing.
Use token variables (var(--so-shadow-card-hover), border-border, border-bright) for shadows and borders.
Ensure CSS side-effect imports have type declarations in TypeScript 6 where noUncheckedSideEffectImports defaults to true. Use /// <reference types="vite/client" /> for Vite projects.
ESLint must enforce zero warnings on the web package. Run npm --prefix web run lint and fix all warnings.
TypeScript type checking must pass. Run npm --prefix web run type-check and resolve all type errors.

Files:

  • web/src/components/layout/Sidebar.tsx
  • web/src/components/layout/AppLayout.tsx
  • web/src/__tests__/components/layout/Sidebar.test.tsx
  • web/src/router/index.tsx
  • web/src/components/layout/SidebarNavItem.tsx
  • web/src/router/routes.ts
  • web/src/__tests__/components/layout/SidebarNavItem.test.tsx
web/src/**/*

📄 CodeRabbit inference engine (web/CLAUDE.md)

A PostToolUse hook (scripts/check_web_design_system.py) runs automatically on every Edit/Write to web/src/ files and catches hardcoded hex colors, rgba values, font-family declarations, hardcoded Framer Motion transition durations, missing Storybook stories, duplicate patterns, and complex .map() blocks. Fix all violations before proceeding.

Files:

  • web/src/components/layout/Sidebar.tsx
  • web/src/components/layout/AppLayout.tsx
  • web/src/__tests__/components/layout/Sidebar.test.tsx
  • web/src/router/index.tsx
  • web/src/components/layout/SidebarNavItem.tsx
  • web/src/router/routes.ts
  • web/src/__tests__/components/layout/SidebarNavItem.test.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. NEVER hardcode hex colors, font-family, pixel spacing, or Framer Motion transitions -- use design tokens and @/lib/motion presets.
A PostToolUse hook (scripts/check_web_design_system.py) enforces web design system rules on every Edit/Write to web/src/.

Files:

  • web/src/components/layout/Sidebar.tsx
  • web/src/components/layout/AppLayout.tsx
  • web/src/__tests__/components/layout/Sidebar.test.tsx
  • web/src/router/index.tsx
  • web/src/components/layout/SidebarNavItem.tsx
  • web/src/router/routes.ts
  • web/src/__tests__/components/layout/SidebarNavItem.test.tsx
docker/**/*

📄 CodeRabbit inference engine (CLAUDE.md)

docker/**/*: Docker CI (docker.yml): build + Trivy/Grype scan + push to GHCR + cosign sign + SLSA L3 provenance. CVE triage in .github/.trivyignore.yaml and .github/.grype.yaml.
Docker: build from root with docker-compose -f docker/compose.yml. Config: all Docker files in docker/ -- Dockerfiles, compose, .env.example. Single root .dockerignore.

Files:

  • docker/web/Dockerfile
mkdocs.yml

📄 CodeRabbit inference engine (CLAUDE.md)

Docs config: mkdocs.yml with Zensical, mkdocstrings[python], griffe-pydantic. Docs group in pyproject.toml.

Files:

  • mkdocs.yml
docs/design/**/*.md

📄 CodeRabbit inference engine (CLAUDE.md)

When approved deviations occur, update the relevant docs/design/ page to reflect the new reality.

Files:

  • docs/design/page-structure.md
🧠 Learnings (69)
📓 Common learnings
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:18:06.442Z
Learning: Applies to docs/**/*.md : Docs: Markdown in docs/, built with Zensical. Design spec: docs/design/ (11 pages), Architecture: docs/architecture/, Roadmap: docs/roadmap/. Security: docs/security.md, Licensing: docs/licensing.md, Reference: docs/reference/.
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:17:24.182Z
Learning: Web dashboard: see `web/CLAUDE.md` for commands, design system, and component inventory
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:17:24.182Z
Learning: Applies to docs/**/*.md : Documentation files in `docs/` (Markdown, built with Zensical, config: `mkdocs.yml`); design spec in `docs/design/` (11 pages)
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:17:43.675Z
Learning: Applies to docker/{Dockerfile*,compose.yml} : Docker: Backend uses 3-stage build (builder → setup → distroless runtime), Chainguard Python, non-root (UID 65532), CIS-hardened. Web uses nginxinc/nginx-unprivileged, Vue 3 SPA with PrimeVue + Tailwind CSS, SPA routing, API/WebSocket proxy to backend.
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:18:06.443Z
Learning: Web dashboard structure: React 19, TypeScript 6, see web/CLAUDE.md for full component inventory, design token rules, post-training references (TS6, Storybook 10).
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:18:06.442Z
Learning: Applies to docs/**/*.md : Pages CI job: version extraction from pyproject.toml, OpenAPI export, Astro + Zensical docs build with version banner, GitHub Pages deploy on push to main.
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)
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`.
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:17:24.182Z
Learning: Build docs with `uv run zensical build` (output: `_site/docs/`); preview locally with `uv run zensical serve`
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:18:06.442Z
Learning: Applies to mkdocs.yml : Docs config: mkdocs.yml with Zensical, mkdocstrings[python], griffe-pydantic. Docs group in pyproject.toml.
📚 Learning: 2026-03-15T18:17:43.675Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:17:43.675Z
Learning: Applies to docker/{Dockerfile*,compose.yml} : Docker: Backend uses 3-stage build (builder → setup → distroless runtime), Chainguard Python, non-root (UID 65532), CIS-hardened. Web uses nginxinc/nginx-unprivileged, Vue 3 SPA with PrimeVue + Tailwind CSS, SPA routing, API/WebSocket proxy to backend.

Applied to files:

  • docs/user_guide.md
  • CLAUDE.md
  • docker/web/Dockerfile
📚 Learning: 2026-03-31T14:17:24.182Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:17:24.182Z
Learning: Applies to docker/**/Dockerfile* : Docker images: backend (Chainguard distroless, non-root), web (nginx-unprivileged, SPA + API proxy), sandbox (Python + Node.js, non-root)

Applied to files:

  • docs/user_guide.md
  • CLAUDE.md
  • .dockerignore
  • docker/web/Dockerfile
📚 Learning: 2026-03-31T14:18:06.442Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:18:06.442Z
Learning: Applies to docker/Dockerfile* : Docker images: backend (Chainguard distroless, non-root), web (nginx-unprivileged, SPA + API proxy), sandbox (Python + Node.js, non-root).

Applied to files:

  • docs/user_guide.md
  • CLAUDE.md
  • docker/web/Dockerfile
📚 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:

  • docs/user_guide.md
  • mkdocs.yml
  • web/CLAUDE.md
📚 Learning: 2026-03-31T14:18:06.443Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:18:06.443Z
Learning: Python package structure: src/synthorg/ (src layout with 11 subpackages), tests/, web/ (React 19 dashboard), cli/ (Go CLI binary). Design spec: docs/DESIGN_SPEC.md (pointer to docs/design/ pages).

Applied to files:

  • docs/user_guide.md
  • CLAUDE.md
  • .dockerignore
  • mkdocs.yml
  • web/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 docker/Dockerfile.sandbox : Docker sandbox: `synthorg-sandbox` — Python 3.14 + Node.js + git, non-root (UID 10001), agent code execution sandbox

Applied to files:

  • docs/user_guide.md
  • docker/web/Dockerfile
📚 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:

  • docs/user_guide.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 docker/Dockerfile : Docker: 3-stage build (builder → setup → distroless runtime) for backend, Chainguard Python, non-root (UID 65532), CIS-hardened

Applied to files:

  • docs/user_guide.md
  • CLAUDE.md
  • docker/web/Dockerfile
📚 Learning: 2026-03-21T14:12:17.848Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-21T14:12:17.848Z
Learning: Applies to Dockerfile* : Backend images must use Chainguard distroless with non-root user; web image must use nginx-unprivileged with non-root user; sandbox image must use Python + Node.js with non-root user. All Docker files in `docker/` -- Dockerfiles, compose, `.env.example`. Single root `.dockerignore`. All images build with `context: .`

Applied to files:

  • docs/user_guide.md
  • CLAUDE.md
  • .dockerignore
  • docker/web/Dockerfile
📚 Learning: 2026-03-31T14:17:24.182Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:17:24.182Z
Learning: Web dashboard: see `web/CLAUDE.md` for commands, design system, and component inventory

Applied to files:

  • docs/user_guide.md
  • CLAUDE.md
  • docs/overrides/extra.css
  • web/CLAUDE.md
  • docs/design/page-structure.md
📚 Learning: 2026-03-31T14:18:06.442Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:18:06.442Z
Learning: Applies to docs/**/*.md : Docs: Markdown in docs/, built with Zensical. Design spec: docs/design/ (11 pages), Architecture: docs/architecture/, Roadmap: docs/roadmap/. Security: docs/security.md, Licensing: docs/licensing.md, Reference: docs/reference/.

Applied to files:

  • CLAUDE.md
  • docs/overrides/extra.css
  • .dockerignore
  • mkdocs.yml
  • docs/design/page-structure.md
  • web/nginx.conf
📚 Learning: 2026-03-31T14:18:06.442Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:18:06.442Z
Learning: Applies to docs/**/*.md : Pages CI job: version extraction from pyproject.toml, OpenAPI export, Astro + Zensical docs build with version banner, GitHub Pages deploy on push to main.

Applied to files:

  • CLAUDE.md
  • .dockerignore
  • docker/web/Dockerfile
  • mkdocs.yml
📚 Learning: 2026-03-31T14:17:24.182Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:17:24.182Z
Learning: Applies to docs/**/*.md : Documentation files in `docs/` (Markdown, built with Zensical, config: `mkdocs.yml`); design spec in `docs/design/` (11 pages)

Applied to files:

  • CLAUDE.md
  • docs/overrides/extra.css
  • .dockerignore
  • mkdocs.yml
  • docs/design/page-structure.md
  • web/nginx.conf
📚 Learning: 2026-03-31T14:17:24.182Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:17:24.182Z
Learning: CLI (Go binary): see `cli/CLAUDE.md` for commands, flags, and reference; use `go -C cli` (never `cd cli`)

Applied to files:

  • CLAUDE.md
  • .dockerignore
📚 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
  • .dockerignore
  • mkdocs.yml
  • docs/design/page-structure.md
  • web/nginx.conf
📚 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
  • docs/overrides/extra.css
  • .dockerignore
  • mkdocs.yml
  • docs/design/page-structure.md
  • web/nginx.conf
📚 Learning: 2026-03-31T14:17:24.182Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:17:24.182Z
Learning: Applies to {docs/rest-api.md,docs/_generated/api-reference.html} : REST API reference in `docs/rest-api.md` + `docs/_generated/api-reference.html` (generated by `scripts/export_openapi.py`)

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-03-31T14:18:06.442Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:18:06.442Z
Learning: Applies to docs/rest-api.md : REST API reference: docs/rest-api.md + docs/_generated/api-reference.html (generated by scripts/export_openapi.py).

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

Applied to files:

  • CLAUDE.md
  • mkdocs.yml
  • docs/design/page-structure.md
📚 Learning: 2026-03-19T07:13:44.964Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T07:13:44.964Z
Learning: Always read the relevant `docs/design/` page before implementing any feature or planning any issue — DESIGN_SPEC.md is a pointer file linking to 7 design pages (Agents, Organization, Communication, Engine, Memory, Operations)

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-03-31T14:17:24.182Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:17:24.182Z
Learning: Build docs with `uv run zensical build` (output: `_site/docs/`); preview locally with `uv run zensical serve`

Applied to files:

  • CLAUDE.md
  • .dockerignore
  • docker/web/Dockerfile
📚 Learning: 2026-03-15T21:32:02.880Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T21:32:02.880Z
Learning: Applies to .github/workflows/docker.yml : Docker workflow: builds backend + web + sandbox images, pushes to GHCR, signs with cosign. SLSA L3 provenance attestations via actions/attest-build-provenance. Scans: Trivy (CRITICAL = hard fail, HIGH = warn) + Grype (critical cutoff) + CIS Docker Benchmark v1.6.0 compliance (informational). CVE triage via .github/.trivyignore.yaml and .github/.grype.yaml. Images only pushed after scans pass. Triggers on push to main and version tags (v*).

Applied to files:

  • CLAUDE.md
  • docker/web/Dockerfile
📚 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 docker/Dockerfile.web : `nginxinc/nginx-unprivileged` base with non-root user (UID 101), Vue 3 SPA (PrimeVue + Tailwind CSS), SPA routing, API/WebSocket proxy to backend

Applied to files:

  • CLAUDE.md
  • docker/web/Dockerfile
📚 Learning: 2026-03-31T14:18:06.443Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:18:06.443Z
Learning: Docker verification: CLI verifies cosign signatures + SLSA provenance at pull time; bypass with --skip-verify. Tags: version from pyproject.toml, semver, SHA, plus dev tags (v0.4.7-dev.3, dev rolling).

Applied to files:

  • CLAUDE.md
  • docker/web/Dockerfile
📚 Learning: 2026-03-21T14:12:17.848Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-21T14:12:17.848Z
Learning: Docker workflow (`docker.yml`): build + Trivy/Grype scan + push to GHCR + cosign sign + SLSA L3 provenance. CVE triage: `.github/.trivyignore.yaml`, `.github/.grype.yaml`

Applied to files:

  • CLAUDE.md
  • docker/web/Dockerfile
📚 Learning: 2026-03-31T14:18:06.442Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:18:06.442Z
Learning: Applies to docker/**/* : Docker CI (docker.yml): build + Trivy/Grype scan + push to GHCR + cosign sign + SLSA L3 provenance. CVE triage in .github/.trivyignore.yaml and .github/.grype.yaml.

Applied to files:

  • CLAUDE.md
  • .dockerignore
  • docker/web/Dockerfile
📚 Learning: 2026-03-31T14:17:24.182Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:17:24.182Z
Learning: Applies to web/src/**/*.{ts,tsx} : Use React 19, TypeScript 6.0+, and design system tokens from shadcn/ui + Tailwind CSS 4 + Radix UI in web dashboard

Applied to files:

  • web/src/components/layout/AppLayout.tsx
  • docs/overrides/extra.css
  • web/CLAUDE.md
📚 Learning: 2026-03-31T12:08:03.565Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-03-31T12:08:03.565Z
Learning: Applies to web/src/{components,pages}/**/*.tsx : Do NOT build card-with-header layouts from scratch -- use `<SectionCard>` from `@/components/ui/section-card`

Applied to files:

  • web/src/components/layout/AppLayout.tsx
  • web/CLAUDE.md
📚 Learning: 2026-03-31T12:08:03.565Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-03-31T12:08:03.565Z
Learning: Applies to web/src/components/ui/**/*.{tsx,ts} : When creating new shared components in `web/src/components/ui/`, place it with a descriptive kebab-case filename, create a `.stories.tsx` file with all states (default, hover, loading, error, empty), export props as a TypeScript interface, use design tokens exclusively, and import `cn` from `@/lib/utils` for conditional class merging

Applied to files:

  • web/src/components/layout/AppLayout.tsx
  • web/CLAUDE.md
  • web/src/components/layout/SidebarNavItem.tsx
  • web/src/__tests__/components/layout/SidebarNavItem.test.tsx
📚 Learning: 2026-03-31T12:08:03.565Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-03-31T12:08:03.565Z
Learning: Applies to web/src/{components,pages}/**/*.{tsx,ts} : ALWAYS reuse existing components from `web/src/components/ui/` before creating new ones (StatusBadge, MetricCard, Sparkline, SectionCard, AgentCard, DeptHealthBar, ProgressGauge, StatPill, Avatar, Button, Toast, ToastContainer, Skeleton variants, EmptyState, ErrorBoundary, ConfirmDialog, CommandPalette, InlineEdit, AnimatedPresence, StaggerGroup, StaggerItem, Drawer, InputField, SelectField, SliderField, ToggleField, TaskStatusIndicator, PriorityBadge, ProviderHealthBadge, TokenUsageBar, CodeMirrorEditor, SegmentedControl, ThemeToggle, LiveRegion, MobileUnsupportedOverlay, LazyCodeMirrorEditor, TagInput)

Applied to files:

  • web/src/components/layout/AppLayout.tsx
  • web/CLAUDE.md
📚 Learning: 2026-03-31T14:18:06.442Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:18:06.442Z
Learning: Applies to web/src/**/*.{ts,tsx} : ALWAYS reuse existing components from web/src/components/ui/ before creating new ones. NEVER hardcode hex colors, font-family, pixel spacing, or Framer Motion transitions -- use design tokens and `@/lib/motion` presets.

Applied to files:

  • web/src/components/layout/AppLayout.tsx
  • docs/overrides/extra.css
  • web/CLAUDE.md
📚 Learning: 2026-03-31T14:18:06.443Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:18:06.443Z
Learning: Web dashboard structure: React 19, TypeScript 6, see web/CLAUDE.md for full component inventory, design token rules, post-training references (TS6, Storybook 10).

Applied to files:

  • web/src/components/layout/AppLayout.tsx
  • web/CLAUDE.md
  • docs/design/page-structure.md
📚 Learning: 2026-03-31T12:08:03.565Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-03-31T12:08:03.565Z
Learning: Applies to web/src/{components,pages}/**/*.tsx : Do NOT recreate status dots inline -- use `<StatusBadge>` from `@/components/ui/status-badge`

Applied to files:

  • web/src/components/layout/AppLayout.tsx
📚 Learning: 2026-03-31T14:18:06.443Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:18:06.443Z
Learning: Web dashboard: Node.js 22+, TypeScript 6.0+. Dependencies in web/package.json (React 19, react-router, shadcn/ui, Radix UI, Tailwind CSS 4, etc.).

Applied to files:

  • web/src/components/layout/AppLayout.tsx
  • web/CLAUDE.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__/components/layout/Sidebar.test.tsx
  • web/src/__tests__/components/layout/SidebarNavItem.test.tsx
📚 Learning: 2026-03-31T12:08:03.565Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-03-31T12:08:03.565Z
Learning: Applies to web/**/*.stories.{tsx,ts} : In Storybook 10, use `storybook/test` (not `storybook/test`) and `storybook/actions` (not `storybook/addon-actions`) for imports

Applied to files:

  • web/src/__tests__/components/layout/Sidebar.test.tsx
  • web/src/__tests__/components/layout/SidebarNavItem.test.tsx
📚 Learning: 2026-03-31T14:17:24.182Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:17:24.182Z
Learning: Applies to web/src/**/*.{ts,tsx} : NEVER hardcode hex colors, font-family, pixel spacing, or Framer Motion transitions — use design tokens and `@/lib/motion` presets

Applied to files:

  • docs/overrides/extra.css
📚 Learning: 2026-03-31T12:08:03.565Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-03-31T12:08:03.565Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use token variables (`var(--so-shadow-card-hover)`, `border-border`, `border-bright`) for shadows and borders.

Applied to files:

  • docs/overrides/extra.css
📚 Learning: 2026-03-31T12:08:03.565Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-03-31T12:08:03.565Z
Learning: Applies to web/src/**/*.{tsx,ts} : Do NOT use `rgba()` with hardcoded values -- use design token variables instead

Applied to files:

  • docs/overrides/extra.css
📚 Learning: 2026-03-31T12:08:03.565Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-03-31T12:08:03.565Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use Tailwind semantic classes (`text-foreground`, `bg-card`, `text-accent`, `text-success`, `bg-danger`, etc.) or CSS variables (`var(--so-*)`) for colors. NEVER hardcode hex values in `.tsx`/`.ts` files.

Applied to files:

  • docs/overrides/extra.css
📚 Learning: 2026-03-31T14:17:24.182Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:17:24.182Z
Learning: Applies to docker/** : All Docker files in `docker/` — Dockerfiles, compose, `.env.example`; single root `.dockerignore`; all images build with `context: .`

Applied to files:

  • .dockerignore
📚 Learning: 2026-03-15T16:38:08.735Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T16:38:08.735Z
Learning: Applies to docker/** : Docker build context: single root .dockerignore (both images build with context: .). Tags: CI tags images with version from pyproject.toml ([tool.commitizen].version), semver, and SHA.

Applied to files:

  • .dockerignore
📚 Learning: 2026-03-31T14:18:06.442Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:18:06.442Z
Learning: Applies to docker/**/* : Docker: build from root with docker-compose -f docker/compose.yml. Config: all Docker files in docker/ -- Dockerfiles, compose, .env.example. Single root .dockerignore.

Applied to files:

  • .dockerignore
📚 Learning: 2026-03-31T14:18:06.442Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:18:06.442Z
Learning: Applies to mkdocs.yml : Docs config: mkdocs.yml with Zensical, mkdocstrings[python], griffe-pydantic. Docs group in pyproject.toml.

Applied to files:

  • .dockerignore
  • mkdocs.yml
📚 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 docs/**/*.md : Markdown documentation must use valid Markdown syntax parseable by Zensical.

Applied to files:

  • .dockerignore
📚 Learning: 2026-03-31T14:17:24.182Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:17:24.182Z
Learning: Export OpenAPI schema with `uv run python scripts/export_openapi.py` (required before docs build)

Applied to files:

  • .dockerignore
  • docker/web/Dockerfile
📚 Learning: 2026-03-31T14:18:06.443Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:18:06.443Z
Learning: CLI structure: Go CLI binary, see cli/CLAUDE.md for commands, flags, reference. Key rule: use `go -C cli` (never `cd cli`).

Applied to files:

  • .dockerignore
📚 Learning: 2026-03-31T14:18:06.443Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:18:06.443Z
Learning: CLI: Go 1.26+, dependencies in cli/go.mod (Cobra, charmbracelet/huh, charmbracelet/lipgloss, sigstore-go, etc.).

Applied to files:

  • .dockerignore
📚 Learning: 2026-03-15T21:32:02.880Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T21:32:02.880Z
Learning: Applies to cli/**/*.go : Go CLI (Go 1.26+) uses Cobra for commands, charmbracelet/huh for interactive CLI, charmbracelet/lipgloss for styled output. Cross-platform builds (linux/darwin/windows × amd64/arm64). GoReleaser for releases with cosign keyless signing of checksums.txt. SLSA L3 provenance attestations via actions/attest-build-provenance.

Applied to files:

  • .dockerignore
📚 Learning: 2026-03-31T14:17:24.182Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:17:24.182Z
Learning: Applies to scripts/**/*.py : Scripts in `scripts/` (CI/build utilities and development-time validation hooks) — relaxed ruff rules: `print` and deferred imports allowed

Applied to files:

  • .dockerignore
📚 Learning: 2026-03-31T14:18:06.442Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:18:06.442Z
Learning: Applies to scripts/**/*.py : Scripts in scripts/ are CI/build utilities with relaxed ruff rules: print and deferred imports allowed.

Applied to files:

  • .dockerignore
📚 Learning: 2026-03-16T19:52:03.656Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-16T19:52:03.656Z
Learning: Applies to cli/**/*.go : Lint CLI Go code with golangci-lint and go vet; test with go test -race; check vulnerabilities with govulncheck

Applied to files:

  • .dockerignore
📚 Learning: 2026-03-21T14:12:17.848Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-21T14:12:17.848Z
Learning: CLI workflow (`cli.yml`): Go lint/test/build (cross-compile) + govulncheck + fuzz. GoReleaser release on `v*` tags with cosign signing + SLSA provenance

Applied to files:

  • .dockerignore
📚 Learning: 2026-03-21T12:54:22.557Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-21T12:54:22.557Z
Learning: Go 1.26+ required; CLI dependencies in `cli/go.mod` (Cobra, charmbracelet/huh, charmbracelet/lipgloss, sigstore-go, go-containerregistry, go-tuf)

Applied to files:

  • .dockerignore
📚 Learning: 2026-03-15T18:17:43.675Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:17:43.675Z
Learning: Dependabot: auto-updates Docker image digests and versions daily.

Applied to files:

  • docker/web/Dockerfile
📚 Learning: 2026-03-31T14:17:24.182Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:17:24.182Z
Learning: Docker tags: version from `pyproject.toml`, semver, SHA, plus dev tags (`v0.4.7-dev.3`, `dev` rolling) for dev channel builds

Applied to files:

  • docker/web/Dockerfile
📚 Learning: 2026-03-31T14:18:06.442Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:18:06.442Z
Learning: Applies to **/*.py : No `from __future__ import annotations` -- Python 3.14 has native PEP 649 lazy annotations.

Applied to files:

  • docker/web/Dockerfile
📚 Learning: 2026-03-21T11:08:01.542Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-21T11:08:01.542Z
Learning: Applies to **/*.py : No `from __future__ import annotations` — Python 3.14 has PEP 649 native lazy annotations.

Applied to files:

  • docker/web/Dockerfile
📚 Learning: 2026-03-31T14:17:24.182Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:17:24.182Z
Learning: Applies to **/*.py : No `from __future__ import annotations` — Python 3.14 has PEP 649 native lazy annotations

Applied to files:

  • docker/web/Dockerfile
📚 Learning: 2026-03-31T14:18:06.442Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:18:06.442Z
Learning: Applies to site/**/*.{astro,ts,tsx,css} : Landing page: site/ (Astro). Includes /get/ CLI install page, contact form, SEO.

Applied to files:

  • mkdocs.yml
  • docs/design/page-structure.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:

  • web/CLAUDE.md
📚 Learning: 2026-03-31T14:17:24.182Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:17:24.182Z
Learning: Applies to docs/design/*.md : Update the relevant `docs/design/` page when approved deviations occur to reflect the new reality

Applied to files:

  • docs/design/page-structure.md
📚 Learning: 2026-03-31T14:18:06.442Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:18:06.442Z
Learning: Applies to docs/design/**/*.md : When approved deviations occur, update the relevant `docs/design/` page to reflect the new reality.

Applied to files:

  • docs/design/page-structure.md
📚 Learning: 2026-03-18T08:23:08.912Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-18T08:23:08.912Z
Learning: When approved deviations occur, update the relevant `docs/design/` page to reflect the new reality.

Applied to files:

  • docs/design/page-structure.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:

  • docs/design/page-structure.md
📚 Learning: 2026-03-31T14:17:24.182Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:17:24.182Z
Learning: Always read the relevant `docs/design/` page before implementing any feature or planning any issue

Applied to files:

  • docs/design/page-structure.md
📚 Learning: 2026-03-31T12:08:03.565Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-03-31T12:08:03.565Z
Learning: Applies to web/**/*.stories.{tsx,ts} : In Storybook 10, use `parameters.a11y.test: 'error' | 'todo' | 'off'` for accessibility testing configuration instead of old `.element` and `.manual` properties

Applied to files:

  • web/src/__tests__/components/layout/SidebarNavItem.test.tsx
📚 Learning: 2026-03-31T12:08:03.565Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-03-31T12:08:03.565Z
Learning: Applies to web/src/**/*.{tsx,ts} : TypeScript type checking must pass. Run `npm --prefix web run type-check` and resolve all type errors.

Applied to files:

  • web/src/__tests__/components/layout/SidebarNavItem.test.tsx
🔇 Additional comments (25)
docs/overrides/extra.css (2)

11-54: Solid token mapping for MkDocs Material dark theme.

The variable coverage is comprehensive and consistent for embedded docs styling.


56-85: Targeted structural overrides look good.

Header/sidebar/search/tabs/border overrides are scoped and align with the intended /docs/ dark presentation.

mkdocs.yml (2)

25-28: Theme palette/font changes are coherent with the embedded dark-docs strategy.

This cleanly centralizes the docs scheme on slate with custom color hooks.


139-140: extra_css wiring is correct.

Loading overrides/extra.css here cleanly connects the MkDocs theme customization.

web/src/components/layout/Sidebar.tsx (1)

225-225: Good /docs/ navigation integration in Sidebar.

Using the existing SidebarNavItem with external keeps behavior explicit and consistent with static docs serving.

web/src/__tests__/components/layout/Sidebar.test.tsx (1)

104-104: Nice test coverage extension for the new nav item.

This assertion closes the gap for Workspace nav completeness after adding Documentation.

CLAUDE.md (1)

57-57: Docs are now aligned with the new embedded-docs architecture.

These updates accurately reflect the /docs/ embed strategy and current web image responsibilities.

Also applies to: 80-80

web/src/router/routes.ts (1)

29-29: Good addition to the route source of truth.

Defining ROUTES.DOCUMENTATION here keeps /docs/ references consistent across UI entry points.

docs/user_guide.md (1)

49-49: Accurate runtime description update in the user guide.

Calling out /docs/ here improves discoverability of the embedded documentation experience.

web/src/components/layout/AppLayout.tsx (1)

75-76: Command-palette docs action is implemented correctly for static /docs/.

Using full-page navigation here is the right behavior for nginx-served docs content outside React Router.

docker/web/Dockerfile (3)

43-47: Consider documenting the README.md placeholder workaround.

The empty README.md is created because .dockerignore excludes *.md files, but pyproject.toml likely references it for package metadata. While this works correctly, a brief inline comment would help future maintainers understand the workaround.


23-61: LGTM!

The docs-builder stage follows established patterns:

  • Non-root user (docsbuild, UID 1001) for defense-in-depth
  • Pinned image digests for reproducibility
  • Layer-optimized dependency installation with cache mounts
  • Pre-compression matching the React builder stage (gzip -9 -k)

The build output path (/app/_site/docs/) correctly aligns with mkdocs.yml's site_dir: _site/docs configuration.


75-75: LGTM!

The COPY path correctly matches the MkDocs build output directory and places docs at the expected nginx serving location.

web/nginx.conf (2)

52-54: Consider extracting shared headers to reduce duplication.

The security headers (lines 56-64) duplicate most of security-headers.conf except for the Content-Security-Policy. While the current approach works and is well-documented, you could reduce duplication by creating a security-headers-base.conf (without CSP) and including it here.

This is a minor maintainability suggestion — the current implementation is correct.


51-67: LGTM!

The /docs/ location block is correctly configured:

  • try_files $uri $uri/ =404 ensures static file serving without SPA fallback
  • CSP includes worker-src 'self' blob: for MkDocs Material's search workers (both file-based and inline)
  • Security headers are appropriately duplicated (nginx doesn't inherit add_header across blocks)
  • 1-hour cache is reasonable for documentation that updates periodically
web/src/router/index.tsx (1)

43-45: LGTM!

Clean approach to export the router for test introspection. The eslint-disable comment is appropriate since this export is specifically for testing purposes (verifying /docs/ is not registered), and the JSDoc comment clearly documents the intent.

web/CLAUDE.md (1)

27-32: LGTM!

Documentation updates accurately reflect the new external link support in the sidebar layout and the DOCUMENTATION route constant that bypasses React Router for static MkDocs serving.

web/src/components/layout/SidebarNavItem.tsx (2)

27-31: LGTM!

Clean extraction of baseClass using cn() for conditional class merging. All Tailwind classes are semantic tokens (text-text-secondary, bg-card-hover, text-foreground) as required by coding guidelines.


64-70: LGTM!

The external link branch correctly:

  • Renders a plain <a href> for full-page navigation (bypassing React Router)
  • Shows title tooltip only when collapsed (consistent with NavLink behavior)
  • Omits rel attribute (appropriate since this isn't opening a new tab)
  • Uses the shared baseClass without active-state styling

This properly supports the docs link that navigates to nginx-served static content.

docs/design/page-structure.md (3)

143-149: LGTM!

Comprehensive documentation of the /docs/ architecture:

  • Clearly explains nginx static serving vs SPA routing
  • Documents the <a href> vs <NavLink> distinction
  • Correctly notes MkDocs Material features operate independently
  • Properly indicates no API/WS dependencies

206-206: LGTM!

The navigation hierarchy correctly reflects the "Docs" entry with the (external -- static HTML, not SPA) annotation, aligning with the implementation in Sidebar.tsx.


270-270: LGTM!

URL routing map entry correctly documents that /docs/ bypasses React Router and is served as static HTML by nginx.

web/src/__tests__/components/layout/SidebarNavItem.test.tsx (2)

103-168: LGTM!

Comprehensive test coverage for the external prop:

  • Verifies anchor element rendering with correct href
  • Confirms no rel attribute (since not opening new tab)
  • Tests collapsed/expanded states
  • Verifies badge and dot indicator rendering
  • Confirms no router active-state styling is applied
  • Ensures end attribute isn't passed to HTML anchor

170-197: LGTM!

Excellent route invariant tests that address the earlier review feedback:

  • Uses actual router.routes instead of a hardcoded path array
  • Recursively extracts paths to catch nested route definitions
  • Verifies multiple path variants (/docs/, /docs, docs, docs/)
  • Additional startsWith('docs') check catches any docs-prefixed wildcard routes

This ensures the test will fail if someone accidentally adds a /docs/ route to React Router.

.dockerignore (1)

64-65: No changes needed—pattern is correct.

The .dockerignore pattern is already valid. Negating !scripts/export_openapi.py after scripts/ is sufficient to re-include the specific file without requiring an explicit !scripts/ first. Docker processes patterns sequentially and implicitly preserves parent directories for included files, so the COPY scripts/export_openapi.py scripts/ step in docs-builder will succeed.

Comment on lines +20 to 24
# Documentation -- re-included for docs builder stage in web Dockerfile
docs/
*.md
!docs/

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 | 🔴 Critical

🧩 Analysis chain

🌐 Web query:

In Docker .dockerignore, if I ignore docs/and*.md, is !docs/alone enough to include all files under docs, or do I need!docs/** (and/or more specific negations)?

💡 Result:

No, !docs/ alone is not enough to include all files under docs/ after ignoring docs/ and *.md. You need !docs/ to recursively include all contents of the docs/ directory. .dockerignore patterns are processed in order, with later rules overriding earlier ones for specific paths. Ignoring docs/ excludes the entire directory and its contents (like a recursive ignore). The negation !docs/ only un-ignores the docs/ directory entry itself, but since directories are traversed recursively and subpaths like docs/sub/file.md were excluded by the docs/ rule (and potentially *.md), they remain excluded unless explicitly un-ignored. To include everything under docs/, use !docs/. This matches all paths under docs/ (using the special wildcard for recursion) and overrides prior exclusions. Additionally, since .md ignores markdown files everywhere, you may need !docs//.md if you want to include .md files specifically under docs/. Example .dockerignore: docs/ .md !docs/ # Optionally: !docs//.md # if you want .md files under docs/ This works because: - docs/ excludes the directory and all contents. - *.md excludes any remaining .md files. - !docs/ includes all files recursively under docs/, overriding both prior rules for those paths. Note that order matters: negations must come after the ignores they override. Single-file negations like !docs/README.md would also be needed for specific files without . Sources confirm .dockerignore uses Go filepath.Match with extended support (matches any number of directories), and directory ignores exclude contents recursively. Recursive negation requires , as shown in examples for excluding/including subdir contents (e.g., /node_modules, !src/).

Citations:


Add recursive negation to include docs source in build context.

The pattern !docs/ alone does not un-ignore nested files under docs/ after the docs/ and *.md exclusion rules. Files like docs/index.md remain excluded from the Docker build context, preventing the docs-builder stage from accessing documentation source.

Proposed fix
 # Documentation -- re-included for docs builder stage in web Dockerfile
 docs/
 *.md
 !docs/
+!docs/**
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.dockerignore around lines 20 - 24, The .dockerignore currently ignores
docs/ and *.md then attempts to re-include the docs folder with !docs/, but that
does not un-ignore nested files; update the negation to be recursive (e.g., add
or replace with !docs/**) so all files and subdirectories under docs are
included in the build context; ensure the recursive negation line (e.g.,
"!docs/**") appears after the docs/ and *.md ignore entries in the
.dockerignore.

@Aureliolo Aureliolo merged commit f229fc2 into main Mar 31, 2026
32 checks passed
@Aureliolo Aureliolo deleted the feat/embed-docs-dashboard branch March 31, 2026 14:39
@Aureliolo Aureliolo temporarily deployed to cloudflare-preview March 31, 2026 14:39 — with GitHub Actions Inactive
Aureliolo added a commit that referenced this pull request Apr 1, 2026
🤖 I have created a release *beep* *boop*
---


##
[0.5.4](v0.5.3...v0.5.4)
(2026-04-01)


### Features

* artifact and project management UI in web dashboard
([#954](#954))
([00a0430](00a0430))
* embed MkDocs build output in React web dashboard at /docs
([#948](#948))
([f229fc2](f229fc2))
* personality preset discovery API and user-defined preset CRUD
([#952](#952))
([497848a](497848a))
* support multi-provider model resolution with budget-based selection
([#953](#953))
([146b782](146b782))
* support per-agent memory retention overrides
([#209](#209))
([#951](#951))
([020c610](020c610))


### Documentation

* write user guides and tutorials
([#949](#949))
([1367225](1367225))

---
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: embed MkDocs build output in React web dashboard at /docs

1 participant