A customer on 信保安全浏览器 (Chromium 108, no GPU acceleration) had daily chat stall on scroll and even on mouse movement. Forcing `backdrop-filter: none` from the console fixed it outright, which pinned the cause: every such element gets its own compositing layer and re-snapshots + re-blurs its backdrop each frame, and that machine rasterizes it on the CPU. The cost is per element, not per radius — a 4px blur on a 24px button costs the same order as a full-screen one. What made it fatal was multiplication: the per-message action buttons carry one each, so a long conversation ran dozens of blur layers, each with a `hover:` transition that repaints them on mouse-over. Removes all 40 occurrences (client 33, platform 7). Most were invisible anyway — their backgrounds sit at 70-100% opacity, where the blur contributes nothing. Two spellings were missed by a first pass that grepped only `backdrop-blur`: the arbitrary-property form `[backdrop-filter:blur(8px)]` in the notification dialog, and one inside an `@apply` in platform's applies.css. The rule is recorded where each audience will meet it: the design spec gets the reasoning plus the alternatives to reach for (translucent fill, noise texture, pre-blurred asset for static backdrops), root AGENTS.md gets the hard constraint, and the 总纲 hard-rules list gets a one-line pointer. Not duplicated into packages/ui/AGENTS.md — the rule spans both apps and the library, so it belongs at the root, and the library had no occurrences to begin with. Both apps typecheck clean.
9.1 KiB
AGENTS.md
1. Project Identity
BiSheng (毕昇) — Enterprise LLM application DevOps platform. Monorepo, three sub-projects:
| Path | Project | Stack |
|---|---|---|
src/backend/ |
FastAPI + Celery Workers + Linsight Worker | Python 3.11+, uv, SQLModel, LangGraph |
src/frontend/platform/ |
Admin / builder UI | Vite 5 + Zustand + react-query v3 + bs-ui |
src/frontend/client/ |
End-user chat UI (/workspace base path) |
Vite 6 + Recoil + react-query v4 (@tanstack) + shadcn/ui |
Runtime topology (full picture → docs/architecture/01-architecture-overview.md):
- Two SPAs — platform (:3001) and client (:4001, base
/workspace) — call FastAPI (:7860):/api/v1frontend-facing,/api/v2open RPC. Commercial edition inserts a Java gateway in front (→architecture/11-gateway.md). - Async work: Celery workers (knowledge / workflow / default queues) + Beat; the Linsight agent runs as an independent worker process fed by a Redis queue.
- Storage ×6: MySQL|DM8 (dual-DB law C2), Redis, Milvus + ES (RAG dual recall), MinIO, OpenFGA (ReBAC).
- Cross-cutting: tenant isolation auto-injected via ContextVar (C3); every permission check goes through PermissionService → OpenFGA (C4).
2. Commands
Dev / test / build commands live in each sub-project's AGENTS.md: src/backend/AGENTS.md · src/frontend/platform/AGENTS.md · src/frontend/client/AGENTS.md.
Middleware (MySQL / Redis / Milvus / ES / MinIO / OpenFGA): integration tests run in CI; per-developer middleware machines are pending.
3. Backend Rules (P0)
- Architectural laws (DDD layering / dual-DB / multi-tenancy / permissions / error codes / security) →
docs/constitution.md(C1–C7); enforced byscripts/arch-guard.sh+ Constitution Check in/sdd-review design. - Backend coding conventions (module layout, API/response helpers, pagination, error handling) + subsystem quick map →
src/backend/AGENTS.md(auto-loads when editing backend files).
4. Frontend Rules (P0)
Two React apps that must not be mixed. Per-app rules auto-load from each sub-project's AGENTS.md:
src/frontend/platform/AGENTS.md— Admin/builder UI (Zustand, react-query v3, bs-ui,@/)src/frontend/client/AGENTS.md— End-user chat UI (Recoil, react-query v4, shadcn,~/)
Hard rules (both apps — single source of truth here; per-app files add only app-specific detail):
- TypeScript only (
.ts/.tsx); functional components only; no class components. - Single file ≤ 600 lines. Extract sub-components or hooks when exceeded.
interfacefor Props;typefor internal types.handleXxxinternal handlers /onXxxprops. PascalCase components, camelCase utilities/hooks.- Named exports for components (
export function); no default exports. Minimizeany— if unavoidable,// eslint-disable-next-line+ a one-line reason. - Never
import axiosdirectly — use the wrapped request module. (store must not call HTTP = constitution C7) - Never introduce new UI or state-management libraries.
- All code comments in English.
- 403 handled automatically by response interceptors — never add 403 branches in business code.
- No frosted glass by default — no
backdrop-filter/backdrop-blur-*, including arbitrary values (backdrop-blur-[4px]), variant prefixes (hover:backdrop-blur-sm) and the arbitrary-property form[backdrop-filter:blur(…)]. Every such element gets its own compositing layer and re-snapshots + re-blurs its backdrop each frame; without GPU acceleration — the norm on 信创 machines — that runs on the CPU. A customer on 信保安全浏览器 (Chromium 108) had scrolling and mouse movement stall in daily chat; forcingbackdrop-filter: nonefixed it outright. Cost is per element, not per radius: a 4px blur on a 24px button costs the same order as a full-screen one, and the per-message action buttons multiplied it by conversation length. Use a translucent background instead (bg-white/80,bg-black/40) — past ~70% opacity the blur was invisible anyway. Only exception, and it must be justified: a full-screen overlay of which at most one exists at a time, verified on a 信创 browser. Never on anything that scales with content (list rows, message bubbles, cards, notification items). Rationale + alternatives:packages/ui/docs/基础-阴影与圆角规范.mdx§3. - i18n: no hardcoded Chinese in source (lint-enforced; legacy frozen). New keys ship all three languages (zh-Hans/en/ja) in the same PR. Error-code copy lives ONLY in
src/frontend/packages/locales(api_errorsdomain — platform addressesapi_errors:<code>, clientapi_errors.<code>); its generated artifacts (platform/public/locales/*/api_errors.json,client/src/locales/*/api_errors.gen.json) are never edited by hand (CI-checked). CI also runspnpm check-i18n— key parity across languages + backend error-code coverage; legacy drift is frozen inscripts/i18n-baseline.json(shrink-only,--update-baselineafter healing). Legacy hardcoded Chinese is paid down by whoever touches the file: when editing a file with frozen violations, extract its Chinese strings to i18n (/i18n-localizer) in the same change. Seepackages/locales/README.md. - Quality gate (CI-enforced,
frontend-quality.yml):pnpm lint+pnpm typecheck(run fromsrc/frontend/) must pass. Legacy violations are frozen — ESLint in each app'seslint-suppressions.json, TS strict via// @ts-strict-ignorefile headers — and may only shrink: never hand-edit the suppressions file, never add@ts-strict-ignoreto a new file. After fixing violations in a file, runpnpm lint:prune(per app) and delete its@ts-strict-ignoreheader if it now passes strict.
5. Architecture Guard (Auto-enforced)
scripts/arch-guard.sh runs after every Write/Edit via a PostToolUse hook (through .claude/hooks/arch-guard-hook.sh, which feeds violations back to the agent as additionalContext for self-correction).
The 8 RULEs are the machine-enforcement arm of constitution C1 / C4 / C6 / C7 — the clause↔RULE anchor table lives in docs/constitution.md. VIOLATION must be fixed immediately.
6. SDD Workflow (non-trivial features)
Full guide — track selection, ★ pause points, deviation re-confirm rule, document roles, constitution gate, harness → docs/SDD-Guide.md.
0. release-contract.md (features/v{X.Y.Z}/release-contract.md;
version's first feature creates it) + read constitution.md
1. Spec Discovery → ★ user confirms
2. spec.md → /sdd-review <dir> spec → ★ user confirms
3. design.md → /sdd-review <dir> design → ★ user confirms (Constitution Check)
4. tasks.md → /sdd-review <dir> tasks
5. branch feat/<version>/{NNN}-{name} (create early; docs + code on the branch)
6. implement wave-by-wave → /task-review <dir> <id> → check off
7. /e2e-test <dir> (mandatory)
8. /code-review --base <main> (+ CI auto-review)
9. merge
Artifacts: features/v{X.Y.Z}/{NNN}-{name}/{spec,design,tasks}.md. Templates: features/_templates/ (incl. release-contract.md).
★ cannot be skipped. Trivial/hotfix changes use a lighter track — see SDD-Guide §1.
Tests: new backend tests under test/<module>/ (e.g., test/approval/), not test/ root. asyncio_mode=auto.
7. Common Pitfalls
Backend runtime pitfalls (tenant-filter SELECT-only gap, ruff hook import trap, Celery Beat × multi-tenant, DB config Redis TTL) → src/backend/AGENTS.md §Known Pitfalls. MinIO sharepoint image-proxy pitfall → src/frontend/platform/AGENTS.md §Known Pitfalls. Commercial edition (BISHENG_PRO env, gateway proxy, SSO) → docs/architecture/11-gateway.md.
| Pitfall | Reality |
|---|---|
/api/v1/env version field |
Hardcoded 2.4.0 in source — unreliable. Use route probing instead. |
| Passwords in config.yaml | Fernet-encrypted. Never write plaintext passwords into the YAML. |
| First registered user | Becomes super_admin automatically. In multi-tenant mode, create the tenant first. |
8. Reference
- Docs index →
docs/README.md(navigation hub); onboarding & testing →docs/architecture/09-development-guide.md - Architecture docs →
docs/architecture/(overview, permission, gateway, multi-tenant, data-models, …) - Skills:
/sdd-review,/task-review,/code-review,/e2e-test,/i18n-localizer,/react-component-refactor
Instruction files (AGENTS.md map). Root = this file, loaded every session. Auto-loaded on top when editing the matching directory: src/backend/, src/frontend/platform/, src/frontend/client/, src/frontend/packages/ui/ (shared component library + design-token SSOT), plus deep-dir specials src/backend/bisheng/core/database/alembic/ (migrations) and src/backend/scripts/ (one-off scripts). Every CLAUDE.md is a symlink to its sibling AGENTS.md — edit AGENTS.md only. Put a new rule in the deepest file covering its scope (cross-app / cross-module → this file; app- or dir-specific → the nearest file); never duplicate a rule across levels — it will drift.