---
id: glyco-ai-guidelines
title: AI Guidelines — Decision Rules for Agents Working on Glyco
chapter: 06
priority: read-first
applies-to: any AI agent generating code, UI, or copy in this repository
---

# 06 — AI Guidelines

Condensed, deterministic rules. When in doubt, follow these; for rationale and exact
values, follow the links into the other chapters.

## 0. Before writing any code

1. Read repo `AGENTS.md`: **Next.js 16** — check `node_modules/next/dist/docs/` for the
   API you're about to use; do not trust training-data Next.js conventions.
2. Identify the layer you're in (`app / features / design-system / lib`) and respect the
   import direction `app → features → design-system → lib`
   ([05 §2](05-architecture.md)). `npm run lint:arch` will fail otherwise.
3. Check for an existing component/pattern in
   [03-components.md](03-components.md) / [04-patterns.md](04-patterns.md) before
   creating anything new.

## 1. Styling decision rules

| If you need… | Then use… | Never… |
|--------------|-----------|--------|
| Any color | A token from `src/app/globals.css` (`--primary`, `--success-fg`, `--color-risk`…) | hardcode hex/oklch in components |
| A surface on the dashboard canvas | `<Card variant="glass-regular">` | re-implement glass with raw `backdrop-filter` |
| A media-rich / hero surface | `glass-clear` or `GlassSurface` | stacking glass on glass more than 2 deep |
| Surfaces inside drawers/modals | `solid` variant | glass inside glass |
| Semantic state on clinical data | `--color-ok / --color-attention / --color-risk` + text/glyph | color as the only signal |
| Shadows | `--elevation-1…4` | custom box-shadows |
| Layering | `--z-sidebar/header/dropdown/modal/toast/tooltip` | arbitrary z-index |
| Radius | the `--radius` scale; child = parent − 4px when nested | mixing radii arbitrarily |
| New accent for a feature | propose a token in `globals.css` first | extending `src/design-system/tokens/colors.css` (legacy) |

## 2. Component decision rules

- Buttons: `Button` with an existing variant; primary action = `variant="primary"` (one
  per view); destructive = `destructive`; on-glass = `glass`. Loading via the `loading`
  prop, not a custom spinner.
- Forms: always `Form` (Zod schema) + `Field` — never raw `<form>` + manual state.
- Async feedback: `useToast()`; severity decides polite vs assertive.
- Lists/data: provide skeleton + empty + error states (Card.Skeleton / EmptyState /
  Card.Error). A failed query degrades the card, never the page.
- New variant > new component. Extend the CVA of an existing primitive before forking.
- Interactive components: `'use client'`; pages stay server components.
- Icons: lucide (generic UI) or iconsax (clinical/dashboard) or `sf-icons` (timeline/
  medication) — one family per control group.

## 3. Copy decision rules (pt-BR)

- Language: Brazilian Portuguese; jargon whitelist: KPIs, TRT, GLP-1, CGM, CFM, SBEM,
  Glyco Brief, Clinical AI.
- Address the physician as `você/seu`; greetings use "Dr./Dra. {nome}".
- CTAs: imperative verbs ("Cadastre", "Gerar receita", "Pergunte").
- UI lines short (2–10 words); no exclamation inflation; no emoji (exception: 🧠
  reasoning pill).
- Errors: state what happened + what to do next; never blame; never expose internals to
  physicians (developer detail goes to logs/Sentry).
- Feature names: Title Case in nav/headings, lowercase in prose
  ([01 §5](01-brand.md) for the canonical glossary).

## 4. Motion decision rules

- Durations/easings from the tokens (instant/fast/base/slow; `EASE.*`,
  `--glyco-ease-*`). Entrances: `card-rise`/stagger. Press: scale 0.95 spring.
- Every JS animation gated by `useReducedMotion()` / `gsap.matchMedia()`.
- Ambient loops only on the composer orb, timeline pulse, CGM ping.

## 5. Accessibility gate (must pass before "done")

```
[ ] Focus visible on every interactive element (--focus-ring, 2px, offset per type)
[ ] Hit areas ≥ 44px (use ::after extender on compact controls)
[ ] aria-disabled (not disabled) for inert-but-focusable controls
[ ] Semantic state = color + text/glyph + aria-label
[ ] Async updates announced (aria-live polite/assertive)
[ ] Works with prefers-reduced-motion and prefers-reduced-transparency
[ ] Keyboard path complete (Tab, Esc, arrows where applicable)
[ ] axe e2e (npm run e2e) clean on touched pages
```

## 6. Data & security rules

- Client/server data access goes through the **RLS-scoped anon client**; never import the
  service-role key outside server scripts; never in copilot tools.
- Anything reaching an LLM boundary uses **anonymized** patient refs (initials + age +
  condition) — never name/CPF/phone/email.
- New copilot capabilities = a typed tool (`kind/risk/surface`, Zod input, preview for
  writes, undo when reversible, audit via ctx) — never a raw fetch from the client.
- User-controlled text inside prompts must stay inside the data sentinel tags.
- New routes under `/dashboard` are auth-gated by middleware automatically — don't add
  auth bypasses; public routes require explicit review.
- Schema changes = new file in `supabase/migrations/` (timestamp naming), applied and
  committed together.

## 7. Quality gates to run

`npm run typecheck && npm run lint && npm run lint:arch && npm test` — plus
`npm run e2e` when touching flows, and update the matching design-system chapter in the
same PR when you change tokens/components/patterns.

## 8. Canonical anti-patterns (reject in review)

1. Hardcoded hex colors (the existing ones in [02 §7](02-foundations.md) are debt).
2. `disabled` attribute on buttons; uppercase tracked labels; custom focus styles.
3. Glass surfaces without token-based reduced-transparency fallback.
4. `any`, `@ts-ignore`, `as any` (ESLint-blocked).
5. Cross-feature imports or `lib → app` imports.
6. English UI copy, or new English feature names.
7. Un-audited copilot writes; service-role in request paths.
8. Pages that blank out when one query fails.
