Files
agent-radar 2ed3415fb7
Publish Claude Code Binaries / Stage and publish binaries (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-arm64 (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build linux-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build windows-amd64 (push) Canceled after 0s
Sync Tutti Agent Skills / sync (push) Canceled after 0s
Windows Agent Adapters / Test Windows agent adapters (push) Canceled after 0s
Windows Daemon Adapters / Test Windows daemon adapters (push) Canceled after 0s
Publish Tutti App Runtime / Publish runtime catalog (push) Canceled after 0s
源码快照 @ 2026-09-01 (source-only, 剔除非源码素材)
2026-09-01 20:17:27 +08:00

147 lines
7.2 KiB
Markdown

# AGENTS.md
## Scope
This file applies to `packages/ui/system/*`.
`packages/ui/system` is the source package for `@tutti-os/ui-system`, the
shared Tutti UI component library. It owns shared CSS tokens, theme styles,
icon exports, presentation primitives, reusable host-agnostic business display
components, component metadata, storyboard inventory, and the bundled
`tutti-ui-system` agent skill.
Before changing components, icons, metadata, styles, storyboard examples, or
the bundled skill, read `ui-system.md`.
UI-system design compliance is a release gate for this package, not a follow-up
task. If a promoted component does not yet follow the shared token model,
surface language, primitive vocabulary, and storyboard evidence standard, do
not report it as complete.
## Public API
Stable public imports are:
- `@tutti-os/ui-system`
- `@tutti-os/ui-system/components`
- `@tutti-os/ui-system/metadata`
- `@tutti-os/ui-system/icons`
- `@tutti-os/ui-system/styles.css`
- `@tutti-os/ui-system/utils`
Rules:
- prefer adding exports to an existing public barrel before introducing a new
public subpath
- do not expose `src/*` layout as public API
- do not encourage per-file deep imports such as
`@tutti-os/ui-system/components/button`
- if package exports change intentionally, update both the package exports and
the UI-boundary check script
## Component Library Rules
- keep `base` components low-level, generic, and
frontend-foundation-focused
- allow `business` components only when they are reusable business display
components that remain host-agnostic and side-effect-free
- business components may expose domain display props such as workspace, file,
task, agent, status, permission, and callbacks, but must not own daemon,
Electron, router, store, query, filesystem, persistence, or workflow calls
- before promoting a business component, scan source usage, build a
code-evidence state matrix, and define the public props boundary from that
evidence; after that, promote it directly into `packages/ui/system` and add
storyboard coverage for the accepted states
- business components should compose `base` primitives instead of recreating
buttons, fields, dialogs, cards, icons, or overlays
- promoted components and their storyboard examples must use UI-system semantic
tokens and approved shared CSS variables; do not leave raw `hex`,
`rgb(...)`, `rgba(...)`, ad hoc gradients, or app-local palette values in the
final UI-system implementation unless they already come from approved shared
tokens
- storyboard coverage must show the component's real promoted surface and
states; do not rely on surrounding docs chrome or wrapper panels to mask
component-level visual drift
- UI storyboard foundation content is JSON-driven. When changing documented
token, color, typography, spacing, radius, motion, or overview display data,
edit `apps/ui-storyboard/src/foundation/*.json` directly instead of
hardcoding those values in `apps/ui-storyboard/src/App.tsx`
- migrated consumers must end on the same UI-system visual implementation for
the promoted surface; temporary bridges are allowed only for wiring, not as a
separate long-lived token or styling system
- treat this package as the shared shadcn and Radix host package
- when a primitive exists in the shadcn registry, acquire it through shadcn CLI
targeted at this package instead of handwriting the component body
- keep `components.json` and package aliases usable enough that CLI download
remains the default path for shared primitives
- after CLI acquisition, limit edits to narrow package-specific adaptation such
as icon routing, import aliases, stable exports, and boundary-check fixes
- keep CSS variables as the source of truth for token values
- prefer semantic token naming over raw palette leakage in public APIs
- keep helper exports minimal and tied to primitive support, not general
convenience reuse
- build primitives for a calm workbench shell, not for marketing-card theatrics
- every public component, icon, utility, or style entry must have metadata with
a stable readable `id` and `layer`
- use the single `tutti-ui-system` skill for component reuse, extraction,
base/business classification, metadata, and storyboard work
## React Component Splitting Rules
- default to one component per directory; keep the component file, tests,
stories, local styles, and tightly coupled implementation-detail helpers
colocated inside that directory
- default to one React component per file; allow multiple small stateless
helpers in one file only when they are tightly coupled implementation detail
of the exported component
- split presentational components away from host wiring; components promoted
into ui-system must receive data, labels, status, and callbacks through props
rather than owning side effects or app workflow
- if a component does not need internal state or refs, prefer a plain function
component; introduce heavier component structure only when state, refs, or
lifecycle-like coordination is actually required
- when behavior is reusable but host-owned, extract it into caller-owned hooks,
adapters, or controller code instead of embedding that logic in the ui-system
component body
- do not use mixin-style reuse or implicit component coupling; prefer explicit
composition through child components, slots, helper modules, or narrow
wrappers
- keep component APIs semantic and stable; do not repurpose DOM prop names such
as `style` or `className` to carry business meaning when a clearer prop like
`variant`, `tone`, `status`, or `layout` is intended
- use spread props sparingly on public components; pass explicit props whenever
possible so the boundary stays readable and host-agnostic
- list and collection components must render with stable identity from caller
data; do not rely on array index keys in promoted UI-system surfaces
- when a component grows multiple visual regions or branches, first try to
split subparts into local render helpers or child components before adding
more mode booleans to one large component
- avoid boolean-prop sprawl for mutually exclusive modes; prefer a finite
variant, discriminated union, explicit slot, or separate subcomponent when
states represent distinct rendering modes
- keep user-visible copy caller-owned by default; if text changes by host,
locale, or workflow, expose it through props, labels, or children instead of
hardcoding it inside the shared component
- use the filename as the component name and keep exported component names in
PascalCase so file boundaries stay obvious during promotion, review, and
migration
## Validation
- Run `pnpm typecheck`
- Run `pnpm check:ui-boundaries`
- If component metadata changed, run `node tools/scripts/check-ui-metadata.mjs`
- If storyboard inventory changed, run
`pnpm --filter @tutti-os/ui-storyboard typecheck`
- If a change affects desktop integration, also run
`pnpm --filter @tutti-os/desktop build`
- In the handoff, explicitly state whether tokens, primitives, storyboard
surface, and migrated consumer all comply with the UI-system standard; if any
of those are still divergent, the work is not complete
## Related Docs
- `ui-system.md`
- `docs/conventions/desktop-visual-language.md`
- `docs/conventions/local-git-hooks.md`