diff --git a/.agents/skills/kilo-design-cloud/SKILL.md b/.agents/skills/kilo-design-cloud/SKILL.md new file mode 100644 index 0000000000..c8da4e9296 --- /dev/null +++ b/.agents/skills/kilo-design-cloud/SKILL.md @@ -0,0 +1,82 @@ +--- +name: kilo-design-cloud +description: Kilo Cloud web UI overlay and pilot pattern recipes. Use when editing or reviewing Kilo Cloud UI paths such as apps/web/src/**, or when the Cloud repo path-scoped trigger requests Kilo design guidance. +--- + +# Kilo Design Cloud + +This is the first agent-facing adapter for the Kilo design system. It covers Kilo Cloud's web app and the first Cloud pattern recipes. + +## Run Order + +1. If the task has a target Cloud file, read it first. For components, also read the matching primitive in `apps/web/src/components/ui/`. +2. If the task asks for a standalone mockup, prototype, or self-contained HTML with no target Cloud file, use Standalone Generation Mode. +3. Load `overlay.md` for all Cloud UI work. +4. Load one internal reference only when the task needs it: product judgment, brand, token architecture, voice, or interaction quality. +5. Load at most one matching recipe unless the task clearly spans multiple patterns. +6. If no recipe exists, use the overlay plus current Cloud code and report a coverage gap. +7. Keep broad product cleanup out of focused tasks. +8. Do not use playground specimen UI as a Cloud Canonical Example. + +Completion criterion: the answer or change names the loaded overlay/recipe, follows real Cloud code, and does not normalize unrelated UI. + +## Token Contract + +- Cloud's generated token artifact is `src/tokens.cloud.ts`. +- Cloud UI code maps token values through `apps/web/src/app/globals.css` and semantic roles such as `--primary`, `--background`, and `--ring`. +- Do not use `src/tokens.landing.css` or `src/tokens.extension-host-map.md` as Cloud UI sources. + +## Recipe Router + +| Prompt or file signal | Load | +|---|---| +| primary action, CTA, button hierarchy, blue button drift | `patterns/cloud-web/primary-actions.md` | +| tabs, segmented navigation, Radix tabs, active tab state | `patterns/cloud-web/tabs.md` | +| tokens, globals.css, semantic mapping | `reference/token-architecture.md`; record that Cloud token adoption is `VVV-130` | +| copy, empty states, labels, errors, confirmations | `reference/voice.md` | +| forms, focus, keyboard, overlays, responsive layout, touch targets, loading, disabled, motion | `reference/interaction-quality.md` | +| badges, alerts, dialogs, sidebar, empty states | `overlay.md`; report coverage gap if a rule is missing | +| standalone mockup, prototype, generated HTML, arena pass, no target Cloud file | Standalone Generation Mode | +| login, auth, workspace slug, returning team, security status | `reference/brand.md`; `reference/voice.md`; `reference/token-architecture.md`; `reference/interaction-quality.md`; `patterns/cloud-web/primary-actions.md` | + +## Standalone Generation Mode + +Use this mode only when the task asks for generated UI without a real Cloud source file to read. The goal is a product-faithful Kilo Cloud surface, not a generic SaaS screen with Kilo labels. + +Load these before designing: + +1. `overlay.md` +2. `reference/brand.md` +3. `reference/voice.md` +4. `reference/token-architecture.md` +5. `reference/interaction-quality.md` when the surface includes forms, auth, overlays, responsive behavior, loading, disabled, error, or success states +6. One matching pattern recipe when available + +Allowed read-only product artifact: `src/tokens.cloud.ts` when exact token values are needed. + +Generated standalone HTML should: + +- Define semantic CSS roles such as `--background`, `--foreground`, `--card`, `--muted-foreground`, `--primary`, `--primary-foreground`, `--border`, `--input`, and `--ring`. +- Resolve `--primary` to Kilo brand primary and `--primary-foreground` to Kilo brand foreground when writing self-contained CSS. +- Use Kilo Cloud product nouns from the prompt: workspaces, teams, agent runs, tool calls, changed files, billing, subscriptions, KiloClaw, security, or operational status. +- Stay compact, dark-first, technical, and task-oriented. +- Keep generated product UI free of guidance notes, gap reports, arena labels, skill labels, or comparison text. + +## Non-Goals + +- Do not build Landing, Editor, Console, Mobile, JetBrains, or CLI guidance here. +- Do not recreate a Cloud `DESIGN.md`. +- Do not migrate every hardcoded blue button unless the task is `primary-actions` implementation. +- Do not invent recipes without a real Canonical Example in shipped Cloud code. +- Do not copy UI structures from `playground/`; it previews token behavior only. + +## Reference Map + +- `overlay.md`: Cloud product overlay and known drift. +- `reference/product-judgment.md`: modes, authority order, and coverage gaps. +- `reference/brand.md`: Cloud use of Kilo brand language. +- `reference/token-architecture.md`: how Cloud agents should read product-facing token artifacts. +- `reference/voice.md`: Kilo Cloud UI copy rules. +- `reference/interaction-quality.md`: interaction states, form behavior, overlays, responsive checks, touch, and motion. +- `patterns/cloud-web/primary-actions.md`: primary CTA and button hierarchy recipe. +- `patterns/cloud-web/tabs.md`: Cloud tab recipe. diff --git a/.agents/skills/kilo-design-cloud/overlay.md b/.agents/skills/kilo-design-cloud/overlay.md new file mode 100644 index 0000000000..2bb70ba83a --- /dev/null +++ b/.agents/skills/kilo-design-cloud/overlay.md @@ -0,0 +1,72 @@ +# Kilo Cloud Overlay + +Cloud is the pilot product for Kilo's agent-consumable design system. It is a dense, dark-first infrastructure console built with Next.js, React, Tailwind, shadcn/ui, Radix, and `lucide-react`. + +## Product Intent + +- Help teams understand workspaces, billing, subscriptions, KiloClaw, and operational status without marketing noise. +- Stay compact and task-oriented. Cloud can be visually polished, but it should not feel like a landing page. +- Make one action obvious per surface. Surrounding actions should be secondary, ghost, outline, or links. + +## Code Sources To Read First + +| Concern | Cloud path | +|---|---| +| Base theme and Tailwind tokens | `apps/web/src/app/globals.css` | +| Font variables | `apps/web/src/app/layout.tsx` | +| shadcn config | `apps/web/components.json` | +| UI primitives | `apps/web/src/components/ui/*.tsx` | +| Legacy button drift | `apps/web/src/components/Button.tsx` | + +## Token Mapping + +Use semantic roles, not raw values: + +| Role | Cloud token | +|---|---| +| Page background | `--background` / `bg-background` | +| Default text | `--foreground` / `text-foreground` | +| Raised surface | `--card`, `--popover` | +| Secondary surface | `--secondary`, `--muted`, `--accent` | +| Muted text | `--muted-foreground` | +| Primary action | `--primary` / `bg-primary` | +| Primary action text | `--primary-foreground` / `text-primary-foreground` | +| Border and focus | `--border`, `--input`, `--ring` | + +Known drift: Cloud token adoption is tracked by `VVV-130`. Until that lands, recipe guidance should still point agents at semantic roles, not hardcoded replacements. + +## Cloud Rhythm + +- Controls are compact: `h-8`, `h-9`, `h-10`; icons are usually `size-4`. +- Cards and dialogs use existing shadcn primitives before custom containers. +- Prefer `gap-*` and grouped spacing over dividers between every row. +- Keep status color as small signals: badges, inline text, rings, or charts. Do not let status hues become the UI palette. +- Use Inter for UI and Roboto Mono for code, identifiers, token names, and tabular data. +- Treat focus, disabled, loading, error, and responsive states as part of the surface, not follow-up polish. + +## Cloud Anti-Patterns + +- Blue button fills as primary actions. +- Yellow-green applied to multiple unrelated controls. +- Equal-card dashboard grids when the task has one focal action. +- New component libraries or new design primitives when shadcn/Radix already exists. +- Marketing copy, fake slogans, avatars, decorative AI stars, glass panels, or gradient text inside product UI. +- Hover-only required actions, missing focus-visible states, or custom overlay behavior that bypasses Radix. +- Large implementation sweeps before the matching recipe exists. + +## Current Coverage + +Covered now: + +- Primary actions. +- Tabs. + +Known gaps: + +- Status badges. +- Alerts and feedback banners. +- Dialogs and destructive confirmations. +- Sidebar/topbar chrome. +- Empty states. + +When a gap appears in real work, use the nearest shipped code and report the missing recipe instead of adding broad rules. diff --git a/.agents/skills/kilo-design-cloud/patterns/cloud-web/primary-actions.md b/.agents/skills/kilo-design-cloud/patterns/cloud-web/primary-actions.md new file mode 100644 index 0000000000..41446d7891 --- /dev/null +++ b/.agents/skills/kilo-design-cloud/patterns/cloud-web/primary-actions.md @@ -0,0 +1,44 @@ +# Cloud Web Pattern: Primary Actions + +Pattern ID: `cloud-web.primary-actions` + +## When To Use + +Use this recipe when a Cloud surface has a main CTA, button hierarchy, primary button drift, or hardcoded blue button background. + +## Rule + +Each surface gets one primary action. It uses the semantic primary action role, not a color name. Secondary choices use secondary, outline, ghost, destructive, or link variants. + +## Canonical Example + +Real code to copy: + +- `apps/web/src/components/ui/button.tsx` +- The current shared `Button` primitive and its current variant source in the Cloud repo. +- Primary action styling should resolve to semantic `primary` and `primary-foreground` tokens. + +Before adopting this recipe in Cloud, verify the exact current variant file and class string from the active Cloud branch. Do not copy legacy color variants when building new Cloud UI. + +## Implementation Rules + +- Use ` - -``` - -**In Kilo**, use `@/components/ui/popover`, `@/components/ui/dropdown-menu`, -or `@/components/ui/tooltip` — those already provide light-dismiss, -correct stacking, and accessibility. - -## Dropdown & Overlay Positioning - -Dropdowns rendered with `position: absolute` inside a container that has -`overflow: hidden` or `overflow: auto` will be clipped. The single most -common dropdown bug in generated code. - -### CSS Anchor Positioning - -Modern solution ties an overlay to its trigger without JavaScript: - -```css -.trigger { - anchor-name: --menu-trigger; -} - -.dropdown { - position: fixed; - position-anchor: --menu-trigger; - position-area: block-end span-inline-end; - margin-top: 4px; -} - -@position-try --flip-above { - position-area: block-start span-inline-end; - margin-bottom: 4px; -} -``` - -`position: fixed` escapes overflow clipping. `@position-try` handles -viewport edges. Browser support: Chrome 125+, Edge 125+ — use a fallback -for Firefox/Safari. - -### Portal / Teleport Pattern - -In component frameworks, render the dropdown at the document root and -position it from the trigger's `getBoundingClientRect()`. Radix and -shadcn already do this. Do not replace it with `position: absolute` -inside a scroll container. - -### Anti-Patterns - -- `position: absolute` inside `overflow: hidden` — the dropdown clips. - Use `position: fixed` or the top layer. -- Arbitrary z-index like `z-index: 9999` — use a semantic z-index scale - (dropdown 100 → sticky 200 → modal-backdrop 300 → modal 400 → toast - 500 → tooltip 600). In Kilo, Radix handles stacking; do not override - its layers. -- Rendering dropdown markup inline without an escape hatch from the - parent's stacking context. Use `popover`, a portal, or `position: fixed`. - -## Destructive Actions: Undo > Confirm - -Undo beats confirmation dialogs for reversible operations — users click -through confirmations mindlessly. Remove from UI immediately, show undo -toast, actually delete after the toast expires. - -Use confirmation for: - -- Truly irreversible actions (account deletion, workspace deletion). -- High-cost actions (paid plan downgrade). -- Bulk operations where the blast radius is unclear. - -Confirmation labels name the action. `Delete workspace` / `Keep editing`, -not `Yes` / `No`. - -## Keyboard Navigation Patterns - -### Roving Tabindex - -For component groups (tabs, menu items, radio groups), one item is -tabbable; arrow keys move within: - -```html -
- - - -
-``` - -Arrow keys move `tabindex="0"` between items. Tab moves to the next -component entirely. In Kilo, `@/components/ui/tabs` already does this. - -### Skip Links - -Provide `Skip to main content` for keyboard -users to jump past navigation. Hide off-screen, show on focus. - -## Gesture Discoverability - -Swipe-to-delete and similar gestures are invisible. Hint at their -existence: - -- **Partially reveal** — show the delete button peeking from the edge. -- **Onboarding** — coach marks on first use. -- **Alternative** — always provide a visible fallback (a menu with - "Delete"). - -Don't rely on gestures as the only way to perform actions. In React -Native (`apps/mobile/`), use accessible gesture patterns from the -existing component library. - ---- - -**Avoid**: Removing focus indicators without alternatives. Placeholder -text as labels. Touch targets <44×44px. Generic error messages. Custom -controls without ARIA / keyboard support. Reimplementing Radix primitives. diff --git a/.kilo/skills/kilo-design/reference/kilo-brand.md b/.kilo/skills/kilo-design/reference/kilo-brand.md deleted file mode 100644 index ccae4ecf23..0000000000 --- a/.kilo/skills/kilo-design/reference/kilo-brand.md +++ /dev/null @@ -1,238 +0,0 @@ -# Kilo Brand - -Canonical application overlay for every other reference in this skill. Root `DESIGN.md` wins for token contracts; this document wins when general references conflict on Kilo-specific application guidance. - -Root `DESIGN.md` owns exact token values and roles. This reference explains how to apply that contract in the Kilo Code codebase so changes stay coherent instead of drifting into generic AI-flavored "modern SaaS." If implementation differs from `DESIGN.md`, treat it as drift. - -## Sources of Truth - -Before changing tokens, colors, type, radius, or animation, consult these -files directly: - -| Concern | File | -|---|---| -| Canonical token contract | `DESIGN.md` | -| Web token implementation | `apps/web/src/app/globals.css` | -| Font loading & variables | `apps/web/src/app/layout.tsx` | -| shadcn config | `apps/web/components.json` | -| Core UI primitives | `apps/web/src/components/ui/*.tsx` | -| Brand lockup | `apps/web/src/components/HeaderLogo.tsx` | -| Storybook canvas | `apps/storybook/.storybook/preview.ts` and `storybook.css` | -| Mobile tokens | `apps/mobile/src/global.css` | - -If a compliant token or component already exists, **use it**. Do not reintroduce a parallel system. If existing code conflicts with `DESIGN.md`, report or fix the drift rather than copying it. - -## Register - -Kilo has two surfaces with slightly different design rules. Identify which -one you are designing for before picking colors, type scale, or motion. - -| Register | Scope | -|---|---| -| **Product UI** | Web app, dashboards, settings, billing, admin, Storybook components, mobile app screens | -| **Brand / Marketing** | Landing pages, docs, pricing, hero surfaces, on-brand campaign moments | - -Both use the same tokens and fonts. Brand permits more visual expression -(hero type, animation, committed color, imagery). Product UI stays calm, -compact, and task-oriented. - -## Theme - -Kilo's web app is **dark-first**. `:root` in `apps/web/src/app/globals.css` -forces `color-scheme: dark`. Mobile's `apps/mobile/src/global.css` defines -light tokens in `:root` and dark tokens under `prefers-color-scheme`. Design -web surfaces with dark as the default; check mobile surfaces in both system -themes. - -Do not "add a light mode" speculatively. If asked to work in light, check -that the surface actually participates in theme switching and that the -tokens you need are defined for both modes. - -## Color Primitives - -### Semantic (use these first) - -These are declared as CSS variables in `globals.css` and surfaced to -Tailwind via `@theme inline`. Prefer the Tailwind utility that maps to the -token (e.g. `bg-background`, `text-foreground`, `border-border`) over hex. - -| Token | Role | -|---|---| -| `background` | Alias of `surface.background` (`#151515`) for the page/body canvas. | -| `foreground` | Alias of `foreground.default` (`#FAFAFA`). | -| `card` | Alias of `surface.raised` (`#202020`). | -| `popover` | Alias of `surface.overlay` (`#333333`). | -| `card-foreground`, `popover-foreground` | Default foreground on those surfaces. | -| `primary` | Brand yellow-green primary CTA token (`#F7F586`). | -| `primary-foreground` | Near-black text on primary (`#1F1F1F`). | -| `secondary` | Alias of `surface.overlay`; neutral action surface. | -| `muted` | Alias of `surface.raised`; de-emphasized region. | -| `accent` | Alias of `surface.hover`; interaction hover state. | -| `muted-foreground` | Alias of `foreground.muted` (`#A3A3A3`). | -| `border`, `input`, `ring` | Default border, strong input border, and brand focus ring. | -| `destructive` | Red error/danger state. | -| `sidebar-*` | Sidebar app-shell tokens. | -| `chart-1`..`chart-5` | Data viz palette. | - -### Kilo-specific primitives - -| Token | Value | Use | -|---|---|---| -| `--brand-primary` / `brand-primary` | `#F7F586` | Alias of primary for brand roles | -| `--brand-primary-hover` | `#E6E475` | Primary hover | -| `--brand-primary-ring` | `#F7F58659` | Brand focus ring | -| `--color-kilo-gray` | `surface.raised` (`#202020`) | Compatibility alias | -| `--color-kilo-gray-lighter` | `surface.overlay` (`#333333`) | Compatibility alias | -| `--ease-out-strong` | `cubic-bezier(0.23, 1, 0.32, 1)` | Preferred easing for transitions | - -### Primary action color - -The product primary CTA is the Kilo brand yellow-green, exposed through the -semantic `primary` token and `--brand-primary` alias: - -| Role | Value | -|---|---| -| Background | `#F7F586` via `primary` / `brand-primary` | -| Hover | `#E6E475` via `primary-hover` / `brand-primary-hover` | -| Text | `#1F1F1F` via `primary-foreground` | -| Focus ring | `#F7F58659` via `ring` / `brand-primary-ring` | - -Use it for the main action on a surface, exactly once. Blue is no longer a -primary CTA color; treat hardcoded `#2B6AD2` buttons as legacy drift and -migrate them to semantic `primary` when the owning surface is updated. Blue -remains acceptable for inline links and historical references only. - -## Surface and Domain Tokens - -Use the six-role surface ladder exactly: `surface.inset` for terminal and recessed regions, `surface.background` for canvas, `surface.raised` for cards and persistent chrome, `surface.overlay` for floating UI, `surface.hover` for hover, and `surface.selected` for selected neutral states. - -Status domain assignments are fixed: Cloud blue, VS Code purple, CLI gray, Slack teal, Agent Manager orange, success green, warning yellow, destructive red. Do not rename teal to emerald or gray to zinc. Use syntax tokens only on code-oriented surfaces and dedicated diff text/surface pairs with non-color `+`/`-` cues. - -## Brand Accent Discipline - -The yellow-green primary is load-bearing precisely because it is rare. -Reserve it for: - -- The Kilo logo and wordmark. -- The primary CTA, once per surface. -- Focus rings on branded / hero controls. -- Confirmation glow on intentional brand moments (see - `animate-pulse-once` / `pulse-glow` in `globals.css`). -- Selected / "on" state for a small number of brand-critical toggles. - -Avoid: - -- Using it for every button. -- Using it as a default text color. -- Pairing it with long body copy (contrast and reading feel drop fast). -- Decorative use on dense product UI. - -## Typography - -Font loading is in `apps/web/src/app/layout.tsx`: - -| Family | CSS variable | Use | -|---|---|---| -| Inter | `--font-sans-loaded` / Tailwind `font-sans` | Default UI text | -| Roboto Mono | `--font-mono-loaded` / Tailwind `font-mono` | Code, identifiers, metadata | -| JetBrains Mono | `--font-jetbrains` | Terminal-like and code-editor surfaces (`.font-jetbrains`) | - -`globals.css` maps Tailwind font tokens to the variables loaded by `layout.tsx`. Do not add per-component font fallbacks. - -Type scale rules for product UI: - -- Prefer canonical utilities: `type-title`, `type-heading`, `type-body-lg`, `type-body`, `type-label`, `type-eyebrow`, and `type-code`. -- Do not stack near-duplicate sizes or replace exact typography roles with arbitrary Tailwind combinations. -- Use `type-label` for buttons and controls, `type-title` for top-level page titles, and existing lockup styling for logos. -- Use `tabular-nums` for billing, usage counters, metrics, and anything - that aligns in columns. - -## Shape and Radius - -Use the exact radius contract: - -| Token | Value | Typical use | -|---|---|---| -| `--radius-sm` | `4px` | Tight inline chips | -| `--radius-md` | `8px` | Buttons, inputs | -| `--radius-lg` | `10px` | Popovers, medium containers | -| `--radius-xl` | `14px` | Cards, dialogs | -| (pill) | `rounded-full` | Badges, avatars, status pills | - -Follow existing shadcn primitives. Buttons/inputs `rounded-md`, cards -`rounded-xl`, badges full-pill. Do not introduce new radius values. - -## Spacing Rhythm - -The app-shell rhythm in the current codebase: - -- Controls are compact: `h-8` (sm), `h-control-default` / 36px (default), `h-10` (lg). Touch surfaces use `h-control-touch` or `size-control-touch` for 44px targets. -- Icons in controls are usually `size-4`; compact/status icons use `size-icon-sm` (14px). -- Topbars are `h-14`. -- Cards use `p-6` for header/content/footer, `gap-1.5` between title and - description. -- Sidebars have their own token set (`sidebar-*`). -- Prefer Tailwind's 4pt-aligned scale (`gap-2`, `gap-3`, `gap-4`, `gap-6`, - `gap-8`). Avoid one-off spacing. - -## Components - -The design system is shadcn/ui in the **New York** style, neutral base -color, CSS variables enabled (`apps/web/components.json`). Icons come from -`lucide-react`. - -Work inside this system: - -- Before building a new control, check `apps/web/src/components/ui/` for a - primitive. Extend variants before creating new files. -- Radix primitives back most overlays (dialog, dropdown, popover, select, - tabs, tooltip, sheet). Use them — do not hand-roll positioning. -- Mobile uses a sibling shadcn setup in `apps/mobile/`. React Native does - not accept every Tailwind pattern; check `apps/mobile/AGENTS.md` (if - present) and the components there before styling across mobile surfaces. - -## Motion - -Current conventions: - -- `--ease-out-strong` is the preferred curve for most transitions. -- `motion/react` is already in use (see `HeaderLogo.tsx`) for brand - interactions. `tw-animate-css` is imported in `globals.css` for small - utility animations. -- Brand moments can use `animate-pulse-once` (see `globals.css`) or the - logo hover flourish. Treat these as branded punctuation, not defaults. -- Respect `prefers-reduced-motion`. Product motion should be short and - functional. - -## Iconography - -- `lucide-react` is the default set. -- `size-4` inside controls, inheriting `currentColor`. -- Icon-only buttons need an `aria-label`. -- Do not mix icon packs without a strong reason. - -## Anti-Patterns To Reject On Sight - -These hurt Kilo specifically, on top of general anti-slop rules: - -- **Yellow everywhere.** If the screen screams yellow, keep yellow to the - single primary action plus real brand moments. -- **Blue button backgrounds.** Blue is for inline links and legacy drift, - not primary action fills. -- **Inventing a new primary color** instead of using the `primary` token. -- **Purple gradient heroes, gradient text, glassmorphism defaults.** -- **Nested cards** (card inside card). Use hierarchy and spacing instead. -- **New font families** beyond Inter / Roboto Mono / JetBrains Mono. -- **New radius values** outside the token set above. -- **Ignoring the sidebar tokens** and hand-coloring sidebar surfaces. -- **Light-mode-only designs** that ignore Kilo's dark-first app. - -## How Agents Should Use This File - -- Load `kilo-brand.md` whenever a design change touches Kilo's UI. -- When producing code, prefer existing tokens, utilities, and components - before writing new ones. -- When producing review/critique output, cite specific tokens, files, and - components by path. -- When a user's request conflicts with these rules, surface the conflict - first. Do not quietly override the brand system. diff --git a/.kilo/skills/kilo-design/reference/motion-design.md b/.kilo/skills/kilo-design/reference/motion-design.md deleted file mode 100644 index 13718006a0..0000000000 --- a/.kilo/skills/kilo-design/reference/motion-design.md +++ /dev/null @@ -1,197 +0,0 @@ -# Motion Design - -> Adapted from Impeccable's `motion-design.md` (Apache 2.0). See -> `NOTICE.md` for attribution and upstream source. - -## Kilo application - -Kilo motion is **purposeful and subtle** in product UI, with occasional -**branded flourishes** at specific hero/logo moments. - -### Libraries and tokens - -- `motion/react` (formerly `framer-motion`) is already in use. - `HeaderLogo.tsx` is the canonical example of a branded interaction. -- `tw-animate-css` is imported in `apps/web/src/app/globals.css` for - small utility animations. -- Preferred easing: `--ease-out-strong` → `cubic-bezier(0.23, 1, 0.32, 1)`. - It is defined as a Tailwind token via `@theme inline`. -- Named brand keyframes already live in `globals.css`: - `pulse-glow` / `animate-pulse-once`, `pulse-opacity`, - `pulse-opacity-dim`. Reuse these instead of inventing new glow/pulse - effects. -- Brand glow uses `--brand-primary-ring` (`#F7F58659`) or alpha derived from `--brand-primary` (`#F7F586`). Never copy legacy `rgba(237, 255, 0, ...)` values. - -### Kilo-specific motion rules - -- **Product UI should feel calm.** Default to opacity/transform fades - (100–200ms) for hover, focus, and state changes. Resist adding motion - to every element. -- **Brand moments are opt-in.** The logo hover rotation, the pulse-glow - CTA, Lottie logo swap — these are branded punctuation, not templates - to copy elsewhere. -- **Never animate layout properties casually** (`width`, `height`, `top`, - `left`, `margin`). Use `transform`, `opacity`, `filter` or layout - libraries (Framer Motion's `layout` prop, FLIP, `grid-template-rows`). -- **Respect `prefers-reduced-motion`.** For anything more than a small - hover transform, provide a reduced fallback. Browsers with - reduced-motion preference get functional behavior only. -- **No bouncy/elastic curves** on product UI. Ease-out exponential - (`--ease-out-strong`) and short durations are the house style. -- **Do not animate modals/dropdowns by hand.** Radix + shadcn already - ship well-tuned enter/exit transitions; configure them with - Tailwind's `data-[state=open]` utilities. - -### Durations - -| Duration | Use | Examples | -|---|---|---| -| 100–150ms | Instant feedback | Button press, toggle, color shift | -| 200–300ms | State changes | Menu open, tooltip, hover, focus bloom | -| 300–500ms | Layout changes | Accordion, drawer open, sheet open | -| 500–800ms | Entrance animations (brand surfaces) | Hero reveal, first-paint choreography | - -Exit animations are faster than entrances (≈75% of enter duration). - -### Absolute rejects in Kilo UI - -- Animated gradients on product surfaces. -- Long (≥ 800ms) transitions in app UIs. -- `ease` (the CSS default) as the only easing on important motion. -- Bounce/elastic on buttons. -- Hover-only affordances on touch-capable surfaces (see - `responsive-design.md`). -- Animating `will-change` globally or preemptively. - ---- - -## Duration: The 100/300/500 Rule - -Timing matters more than easing. These durations feel right for most UI: - -| Duration | Use | Examples | -|---|---|---| -| 100–150ms | Instant feedback | Button press, toggle, color change | -| 200–300ms | State changes | Menu open, tooltip, hover states | -| 300–500ms | Layout changes | Accordion, modal, drawer | -| 500–800ms | Entrance animations | Page load, hero reveals | - -Exit animations are faster than entrances — use ~75% of enter duration. - -## Easing: Pick the Right Curve - -Don't use `ease` — it's a compromise that's rarely optimal. Instead: - -| Curve | Use for | CSS | -|---|---|---| -| **ease-out** | Elements entering | `cubic-bezier(0.16, 1, 0.3, 1)` | -| **ease-in** | Elements leaving | `cubic-bezier(0.7, 0, 0.84, 0)` | -| **ease-in-out** | State toggles (there → back) | `cubic-bezier(0.65, 0, 0.35, 1)` | - -For micro-interactions, exponential curves feel natural (friction, -deceleration): - -```css -/* Quart out — smooth, refined (Kilo's --ease-out-strong is close) */ ---ease-out-quart: cubic-bezier(0.25, 1, 0.5, 1); - -/* Quint out — slightly more dramatic */ ---ease-out-quint: cubic-bezier(0.22, 1, 0.36, 1); - -/* Expo out — snappy, confident */ ---ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1); -``` - -**Avoid bounce and elastic curves.** They feel tacky and amateurish. Real -objects don't bounce when they stop — they decelerate smoothly. - -## Premium Motion Materials - -Transform and opacity are reliable defaults, not the whole palette. -Premium interfaces often need atmospheric properties: blur reveals, -backdrop-filter panels, saturation or brightness shifts, shadow bloom, -SVG filters, masks, clip paths, gradient-position movement, and variable -font or shader-driven effects. - -Use the right material for the effect: - -- **Transform / opacity** — movement, press feedback, simple reveals, - list choreography. -- **Blur / filter / backdrop-filter** — focus pulls, depth, glass/lens - effects, softened entrances, atmospheric transitions. -- **Clip path / masks** — wipes, reveals, editorial cropping, product- - like transitions. -- **Shadow / glow / color filters** — energy, affordance, focus, warmth, - active state. -- **Grid-template rows or FLIP-style transforms** — expanding and - reflowing layout without animating `height` directly. - -Avoid animating layout-driving properties casually (`width`, `height`, -`top`, `left`, margins). Keep expensive effects bounded to small or -isolated areas, and verify in-browser that the result is smooth on -target viewports. - -## Staggered Animations - -Use CSS custom properties for cleaner stagger: -`animation-delay: calc(var(--i, 0) * 50ms)` with `style="--i: 0"` on each -item. **Cap total stagger time** — 10 items × 50ms = 500ms total. For -many items, reduce per-item delay or cap staggered count. - -## Reduced Motion - -Not optional. Vestibular disorders affect ~35% of adults over 40. - -```css -/* Define animations normally */ -.card { - animation: slide-up 500ms ease-out; -} - -/* Provide alternative for reduced motion */ -@media (prefers-reduced-motion: reduce) { - .card { - animation: fade-in 200ms ease-out; - } -} - -/* Or disable entirely */ -@media (prefers-reduced-motion: reduce) { - *, - *::before, - *::after { - animation-duration: 0.01ms !important; - transition-duration: 0.01ms !important; - } -} -``` - -Preserve functional animations: progress bars, loading spinners (slowed), -focus indicators. - -## Perceived Performance - -Nobody cares how fast your site is — only how fast it feels. - -- **80ms threshold.** Anything under ~80ms feels instant. Target this - for micro-interactions. -- **Active vs passive time.** Passive waiting (staring at a spinner) - feels longer than active engagement. Preemptive transitions, early - completion, and optimistic UI shift the balance. -- **Easing affects perceived duration.** Ease-in toward a task's end - compresses perceived time. -- **Caution.** Instantaneous responses can decrease perceived value - for complex operations — a brief delay can signal "real work." - -## Performance - -Don't use `will-change` preemptively — only when animation is imminent -(`:hover`, `.animating`). For scroll-triggered animations, use -Intersection Observer, and `unobserve()` after animating once. Create -motion tokens for consistency (Kilo already has `--ease-out-strong`). - ---- - -**Avoid**: Animating everything (animation fatigue is real). >500ms for -UI feedback. Ignoring `prefers-reduced-motion`. Using animation to hide -slow loading. Reinventing Radix primitives' transitions. diff --git a/.kilo/skills/kilo-design/reference/responsive-design.md b/.kilo/skills/kilo-design/reference/responsive-design.md deleted file mode 100644 index e5b59b28dc..0000000000 --- a/.kilo/skills/kilo-design/reference/responsive-design.md +++ /dev/null @@ -1,202 +0,0 @@ -# Responsive Design - -> Adapted from Impeccable's `responsive-design.md` (Apache 2.0). See -> `NOTICE.md` for attribution and upstream source. - -## Kilo application - -Kilo has two parallel responsive surfaces: - -1. **Web** (`apps/web/`) — Next.js + Tailwind v4. Responsive tooling is - Tailwind breakpoints + container queries + `env(safe-area-inset-*)`. -2. **Mobile** (`apps/mobile/`) — React Native + NativeWind. Tailwind - breakpoints do **not** map to RN components the same way; use the - device conventions already in that app. - -### Kilo-specific rules - -- **Design mobile-first** for web flows that appear on both marketing - and the app shell. Add complexity at `md:` / `lg:` / `xl:` breakpoints, - not the other way around. -- **Do not rely on hover for required functionality.** Hover is - supplementary. Touch users can't use it. -- **Cards and forms should reflow**, not clip. Long labels, long email - addresses, long plan names are the norm, not the edge case. -- **Sidebar rules.** The app shell sidebar has its own mobile behavior - via `@/components/ui/sidebar`. Don't reinvent mobile nav — wrap into - the existing sidebar state or use `Sheet` from shadcn. -- **Respect safe areas** on mobile web (iPhone notches, rounded corners). - Use `max(…, env(safe-area-inset-*))` on fixed bottom/top bars. -- **Test at least three widths** for any visual change: - - A narrow mobile viewport (~375px). - - A tablet or narrow laptop (~768–1024px). - - A wide desktop (~1440px+). -- **React Native + NativeWind caveat:** opacity modifiers (`bg-card/40`) - do not work on CSS-variable theme colors. Verify with the component in - `apps/mobile/` before assuming a utility composes the same way it does - on web. - -### Absolute rejects in Kilo UI - -- Hover-only required actions. -- Fixed-pixel widths that break at mobile widths without reflow. -- Device-user-agent sniffing instead of feature queries. -- Separate mobile/desktop component trees built from scratch when a - shared responsive component would work. -- Hiding content on mobile (`hidden md:block`) just because the layout - is inconvenient. If information matters at desktop, it matters on - mobile — reshape it. - ---- - -## Mobile-First: Write It Right - -Start with base styles for mobile, use `min-width` queries to layer -complexity. Desktop-first (`max-width`) means mobile loads unnecessary -styles first. In Tailwind this is the default behavior: unprefixed -utilities apply at the smallest viewport, and `md:`, `lg:`, `xl:` add -complexity upward. - -## Breakpoints: Content-Driven - -Don't chase device sizes — let content tell you where to break. Start -narrow, stretch until the design breaks, and add a breakpoint there. -Three breakpoints usually suffice (the Tailwind `md` 768, `lg` 1024, -`xl` 1280 defaults work). Use `clamp()` for fluid values without -breakpoints — but only on marketing/brand pages (see `typography.md`). - -## Detect Input Method, Not Just Screen Size - -Screen size doesn't tell you input method. A laptop with a touchscreen, -a tablet with a keyboard — use pointer and hover queries: - -```css -/* Fine pointer (mouse, trackpad) */ -@media (pointer: fine) { - .button { - padding: 8px 16px; - } -} - -/* Coarse pointer (touch, stylus) */ -@media (pointer: coarse) { - .button { - padding: 12px 20px; - } /* Larger touch target */ -} - -/* Device supports hover */ -@media (hover: hover) { - .card:hover { - transform: translateY(-2px); - } -} - -/* Device doesn't support hover (touch) */ -@media (hover: none) { - /* No hover state — use active instead */ -} -``` - -**Critical**: Don't rely on hover for functionality. Touch users can't -hover. In Tailwind, `hover:` + `@media (hover: hover)` wrapping via the -`hocus` pattern / `@custom-variant` is fine, but design the no-hover -path first. - -## Safe Areas: Handle the Notch - -Modern phones have notches, rounded corners, and home indicators. Use -`env()`: - -```css -body { - padding-top: env(safe-area-inset-top); - padding-bottom: env(safe-area-inset-bottom); - padding-left: env(safe-area-inset-left); - padding-right: env(safe-area-inset-right); -} - -/* With fallback */ -.footer { - padding-bottom: max(1rem, env(safe-area-inset-bottom)); -} -``` - -Enable `viewport-fit` in your meta tag: - -```html - -``` - -`apps/web/src/app/layout.tsx` sets a Next.js `viewport` object — align -additions there, not via manual meta tags. - -## Responsive Images: Get It Right - -### srcset with Width Descriptors - -```html -Hero image -``` - -How it works: - -- `srcset` lists available images with actual widths (`w` descriptors). -- `sizes` tells the browser how wide the image will display. -- Browser picks the best file based on viewport width AND device pixel - ratio. - -In Kilo, prefer Next.js `` — it produces correct srcset, sizes, -and lazy loading automatically. - -### Picture Element for Art Direction - -When you need different crops/compositions (not just resolutions): - -```html - - - - ... - -``` - -## Layout Adaptation Patterns - -- **Navigation.** Three stages — hamburger/sheet on mobile, horizontal - compact on tablet, full with labels on desktop. In Kilo, the - `Sidebar` primitive + `Sheet` covers this. -- **Tables.** Transform to cards on mobile using `display: block` and - `data-label` attributes. For simple tables, horizontal scroll with a - fade mask is acceptable — Kilo already uses this pattern in a few - billing/admin views. -- **Progressive disclosure.** Use `
/` or shadcn's - `Accordion` / `Collapsible` for content that can collapse on mobile. - -## Testing: Don't Trust DevTools Alone - -DevTools device emulation is useful for layout but misses: - -- Actual touch interactions. -- Real CPU/memory constraints. -- Network latency patterns. -- Font rendering differences. -- Browser chrome / keyboard appearances. - -Test on at least one real iPhone, one real Android, a tablet if relevant. -Cheap Android phones reveal performance issues you'll never see on -simulators. For Kilo's mobile app, use a dev build / dev client on a real -device before shipping significant UI changes. Do not use Expo Go; the app -does not support it. - ---- - -**Avoid**: Desktop-first design. Device detection instead of feature -detection. Separate mobile/desktop codebases grown by accident. Ignoring -tablet and landscape. Assuming all mobile devices are powerful. -Mobile-hostile `hidden` instead of reshaping content. diff --git a/.kilo/skills/kilo-design/reference/spatial-design.md b/.kilo/skills/kilo-design/reference/spatial-design.md deleted file mode 100644 index a412cf6ef6..0000000000 --- a/.kilo/skills/kilo-design/reference/spatial-design.md +++ /dev/null @@ -1,190 +0,0 @@ -# Spatial Design - -> Adapted from Impeccable's `spatial-design.md` (Apache 2.0). See -> `NOTICE.md` for attribution and upstream source. - -## Kilo application - -Kilo's product UI is **compact and task-oriented**. Do not redesign the -app shell with marketing-scale spacing. - -### Spacing - -- Use Tailwind's 4pt-aligned scale: `gap-1`, `gap-2`, `gap-3`, `gap-4`, - `gap-6`, `gap-8`. Avoid arbitrary `gap-[19px]`. -- Prefer `gap` over margins. It eliminates margin collapse and is - consistent with flex/grid in the codebase. -- Cards use `p-6` for header/content/footer, `gap-1.5` between card title - and description (`apps/web/src/components/ui/card.tsx`). -- App topbars run at `h-14`; avoid arbitrary topbar heights. -- Controls stay compact: `h-8` (sm), `h-control-default` / 36px (default), `h-10` (lg). Use `h-control-touch` or `size-control-touch` for 44px touch targets. -- Mobile (React Native) has its own safe-area behavior — use the tokens - in `apps/mobile/`, not web-only `env(safe-area-inset-*)`. - -### Radius - -Kilo defines a radius scale: - -| Token | Value | Use | -|---|---|---| -| `--radius-sm` | `4px` | Tight inline chips | -| `--radius-md` | `8px` | Buttons, inputs | -| `--radius-lg` | `10px` | Popovers, medium containers | -| `--radius-xl` | `14px` | Cards, dialogs | -| (full) | `rounded-full` | Badges, avatars, status pills | - -Do not introduce new radius values. - -### Hierarchy - -- **Never nest a Card inside a Card.** If you need sub-grouping, use - dividers, spacing, headings, or muted backgrounds — not another card. -- Use Kilo's sidebar tokens for sidebar-adjacent surfaces; don't hand-paint - a second sidebar. -- Use spacing + typography to build hierarchy before reaching for shadows. - Dark-mode depth comes from lighter surfaces, not shadows. - -### Absolute rejects in Kilo UI - -- Arbitrary spacing values outside Tailwind's scale. -- Nested cards. -- Uniform padding everywhere (variety creates rhythm). -- Hand-drawn z-index values like `z-[9999]`. Use semantic layering - (`z-10` for sticky, Radix overlays for modals/menus — Radix handles - stacking). -- Reintroducing one-off popover/tooltip/drawer positioning when Radix - primitives already exist in `apps/web/src/components/ui/`. - ---- - -## Spacing Systems - -### Use 4pt Base - -4pt systems give you 12px between 8 and 16. Tailwind's scale is 4pt-aligned; -use it. Name tokens semantically (`--space-sm`, `--space-lg`), not by value -(`--spacing-8`). In Kilo this usually means Tailwind utilities. - -## Grid Systems - -### The Self-Adjusting Grid - -Use `repeat(auto-fit, minmax(280px, 1fr))` for responsive grids without -breakpoints. Columns are at least 280px, as many as fit per row, leftovers -stretch. - -For complex layouts, use named `grid-template-areas` and redefine at -breakpoints. Kilo's app shell already uses sidebar + content layouts with -`sidebar-*` tokens; reuse those structural utilities before building new -ones. - -## Visual Hierarchy - -### The Squint Test - -Blur your eyes or screenshot + blur. Can you still identify: - -- The most important element? -- The second most important? -- Clear groupings? - -If everything looks the same weight blurred, you have a hierarchy problem. - -### Hierarchy Through Multiple Dimensions - -Do not rely on size alone. Combine: - -| Tool | Strong hierarchy | Weak hierarchy | -|---|---|---| -| **Size** | 3:1 ratio or more | <2:1 ratio | -| **Weight** | Bold vs Regular | Medium vs Regular | -| **Color** | High contrast | Similar tones | -| **Position** | Top / left (primary) | Bottom / right | -| **Space** | Surrounded by whitespace | Crowded | - -The best hierarchy uses 2–3 dimensions at once: a heading that's larger, -bolder, AND has more space above it. - -### Cards Are Not Required - -Cards are overused. Spacing and alignment create visual grouping naturally. -Use cards only when: - -- Content is truly distinct and actionable. -- Items need visual comparison in a grid. -- Content needs clear interaction boundaries. - -**Never nest cards inside cards.** Use spacing, typography, and subtle -dividers for hierarchy within a card. - -## Container Queries - -Viewport queries are for page layouts. **Container queries are for -components:** - -```css -.card-container { - container-type: inline-size; -} - -.card { - display: grid; - gap: var(--space-md); -} - -/* Card layout changes based on its container, not the viewport */ -@container (min-width: 400px) { - .card { - grid-template-columns: 120px 1fr; - } -} -``` - -A card in a narrow sidebar stays compact while the same card in a main -content area expands — automatically, no viewport hacks. - -## Optical Adjustments - -Text at `margin-left: 0` looks indented due to letterform whitespace; use -negative margin (`-0.05em`) to optically align. Geometrically centered -icons often look off-center; play icons shift right, arrows shift toward -their direction. - -### Touch Targets vs Visual Size - -Buttons can look small but need large touch targets (44px minimum). Use -padding or pseudo-elements: - -```css -.icon-button { - width: 24px; - height: 24px; - position: relative; -} - -.icon-button::before { - content: ''; - position: absolute; - inset: -10px; -} -``` - -In Kilo, `h-9 w-9` icon buttons (`button.tsx` `size: "icon"`) sit just -below the 44px touch target. On mobile-facing surfaces, stretch the tap -area via padding or `::before`, not by enlarging the visual control. - -## Depth & Elevation - -Create semantic z-index scales (`dropdown → sticky → modal-backdrop → -modal → toast → tooltip`) rather than arbitrary numbers. In Kilo, Radix -primitives already manage stacking for overlays — don't fight them with -`z-[99999]`. - -Shadows should be subtle — if you can clearly see them, they're too -strong. Dark-mode Kilo depth comes from surface elevation, not shadow. - ---- - -**Avoid**: Arbitrary spacing values outside your scale. Making all spacing -equal (variety creates hierarchy). Creating hierarchy through size alone. -Nested cards. Rewriting positioning for overlays when Radix already solves it. diff --git a/.kilo/skills/kilo-design/reference/typography.md b/.kilo/skills/kilo-design/reference/typography.md deleted file mode 100644 index 760f585cc0..0000000000 --- a/.kilo/skills/kilo-design/reference/typography.md +++ /dev/null @@ -1,180 +0,0 @@ -# Typography - -> Adapted from Impeccable's `typography.md` (Apache 2.0). See `NOTICE.md` for -> attribution and upstream source. - -## Kilo application - -Kilo's fonts are already chosen and loaded. Do not introduce new families. - -| Family | CSS variable | Use | -|---|---|---| -| Inter | `--font-sans` | Default product UI, buttons, labels, body | -| Roboto Mono | `--font-mono` | Code tokens, identifiers, metadata | -| JetBrains Mono | `--font-jetbrains` | Terminal and code-editor surfaces (class `font-jetbrains`) | - -Kilo-specific rules: - -- **Product UI uses a fixed type scale.** No fluid `clamp()` sizing inside - the app shell, dashboards, billing, settings, or Storybook components. - App UIs need spatial predictability. -- **Marketing/brand pages may use `clamp()` for hero headlines** only. Body - copy stays fixed. -- **Use `tabular-nums`** on anything numeric that aligns in columns: - billing, usage counters, tables, KPIs, timers. -- **Disable code ligatures** (`font-variant-ligatures: none;`) only on - surfaces where glyph-accurate code matters (terminals, diff views). -- **Use exact role metrics.** `type-title`, `type-heading`, `type-body-lg`, `type-body`, `type-label`, `type-eyebrow`, and `type-code` implement `DESIGN.md`; do not independently bump line-height or weight. -- Page titles use `type-title` (`1.5rem / 600 / 1.2`). Logo lockups may retain their existing brand-specific styling. -- `globals.css` maps `font-sans` and `font-mono` to the variables loaded by `layout.tsx`. Do not add per-component font fallbacks. - -Absolute rejects in Kilo product UI: - -- New font families outside the three listed above. -- Gradient text. -- ALL-CAPS body copy (short labels/eyebrows OK with added tracking). -- Font sizes outside canonical `type-*` utilities or an approved brand/marketing scale. -- Fluid `clamp()` in product UI. - ---- - -## Classic Typography Principles - -### Vertical Rhythm - -Your line-height should be the base unit for ALL vertical spacing. If body -text has `line-height: 1.5` on 16px type (24px), spacing values should be -multiples of 24px. This creates subconscious harmony between text and space. - -### Modular Scale & Hierarchy - -The common mistake: too many font sizes that are too close together (14, 15, -16, 18). Muddy hierarchy. - -**Use fewer sizes with more contrast.** A five-size system covers most -product UI: - -| Role | Typical ratio | Kilo Tailwind | Use case | -|---|---|---|---| -| xs | 0.75rem | `text-xs` | Captions, legal, helper | -| sm | 0.875rem | `text-sm` | Secondary UI, metadata | -| base | 1rem | `text-base` | Body text | -| lg | 1.125–1.25rem | `text-lg` | Subheadings, lead text | -| xl+ | 1.5rem and up | `text-xl`+ | Page titles, hero | - -Pick a ratio (1.25 major third, 1.333 perfect fourth, 1.5 perfect fifth) -and commit. Do not mix multiple scales. - -### Readability & Measure - -Cap body width in the 45–75ch band (`max-width: 65ch`). Narrow columns need -tighter leading; wide columns need more. - -**Dark mode compensation.** Light text on dark can read lighter than dark on light. Kilo's canonical type roles already account for product density. Do not alter their line-height, tracking, or weight per component; propose a contract change if readability testing shows a systemic issue. - -**Paragraph rhythm.** Use either space between paragraphs or first-line -indent. Never both. Product UI uses space. - -## Font Selection & Pairing - -Kilo does not select new fonts per project. If a brand surface justifies a -genuine display face for a hero, treat it as a design decision that needs -approval, not a reflex. - -### Pairing principles - -One well-chosen family in multiple weights usually beats two competing -typefaces. Kilo already runs Inter + Roboto Mono + JetBrains Mono; that is -enough. If a second typeface appears on a marketing page, it contrasts on -multiple axes (serif + sans, geometric + humanist, condensed + wide), never -two similar sans-serifs side by side. - -### Web font loading - -Fonts are loaded in `apps/web/src/app/layout.tsx` via `next/font/google`, -which handles `font-display: swap` and preload. Do not reintroduce manual -`@font-face` declarations or competing loaders. - -## Modern Web Typography - -### Fluid type — limited in Kilo - -`clamp(min, preferred, max)` is allowed on marketing hero headlines and -long-form content where the type dominates the layout. It is **not** used -for product UI, dashboards, tools, or tables. Material, Polaris, Primer, -and Carbon all use fixed scales for the same reason: spatial predictability -matters more than viewport-scaled type in dense surfaces. - -Bound your `clamp()`: `max-size ≤ ~2.5 × min-size`. - -### OpenType features - -```css -/* Tabular numbers for data alignment */ -.data-table { - font-variant-numeric: tabular-nums; -} - -/* Proper fractions */ -.recipe-amount { - font-variant-numeric: diagonal-fractions; -} - -/* Small caps for abbreviations */ -abbr { - font-variant-caps: all-small-caps; -} - -/* Disable ligatures in code */ -code, -.font-jetbrains { - font-variant-ligatures: none; -} - -/* Explicit kerning */ -body { - font-kerning: normal; -} -``` - -### Rendering polish - -```css -/* Even out heading line lengths */ -h1, -h2, -h3 { - text-wrap: balance; -} - -/* Reduce orphans and ragged endings in long prose */ -article p { - text-wrap: pretty; -} - -/* Pick the right optical-size master automatically */ -body { - font-optical-sizing: auto; -} -``` - -ALL-CAPS short labels need 5–12% letter-spacing (`letter-spacing: 0.05em` -to `0.12em`). - -## Typography System Architecture - -Name tokens semantically, not by value. In Kilo product UI, prefer canonical `type-*` utilities. Use `font-sans`, `font-mono`, or `.font-jetbrains` only when a complete role utility does not apply. - -## Accessibility - -- **Never disable zoom.** `user-scalable=no` breaks accessibility. -- **Use `rem`/`em` for font sizes.** Never `px` for body text. -- **Mobile readability.** Use the `type-body-lg` utility for long-form mobile reading. Keep form controls at 16px where needed to prevent browser zoom. The canonical compact product `body` role remains 14px. -- **Adequate touch targets.** Text links need padding or line-height that - yields a 44px+ tap target. - ---- - -**Avoid**: More than three font families (Kilo already uses three; no -fourth). Skipping fallback font definitions. Decorative fonts for body -text. Fluid type in product UI. diff --git a/.kilo/skills/kilo-design/reference/ux-writing.md b/.kilo/skills/kilo-design/reference/ux-writing.md deleted file mode 100644 index 7c1cc5ce62..0000000000 --- a/.kilo/skills/kilo-design/reference/ux-writing.md +++ /dev/null @@ -1,253 +0,0 @@ -# UX Writing - -> Adapted from Impeccable's `ux-writing.md` (Apache 2.0). See `NOTICE.md` -> for attribution and upstream source. - -## Kilo application - -Kilo voice is **clear, technical, calm, and direct**. Engineering-literate -audience. No hype, no cutesy error copy, no vague productivity slogans. - -### Kilo voice in one paragraph - -Kilo talks to developers and team leads. Say what the product does, what -the user needs to do next, and what will happen if they do it. Skip -adjectives like "powerful," "seamless," "effortless," and "revolutionary." -Prefer concrete verbs and specific nouns. - -### Terminology to pick and keep - -Pick one term per concept and hold it across web, mobile, docs, and UI: - -| Use | Not | -|---|---| -| Sign in / Sign out | Log in, Log out, Enter, Exit | -| Delete | Remove, Trash, Clear (for destructive ops) | -| Settings | Preferences, Options, Configuration | -| Create | Add, New (for creating a persistent thing) | -| Workspace | Team, Account, Org (if "workspace" is what the product calls it) | -| Kilo Code | KiloCode, kilo-code (product name) | - -If this repo has a newer glossary, prefer that. Do not invent synonyms -to add variety. - -### Button labels - -Use verb + object. Specific over generic. Kilo-flavored examples: - -| Bad | Good | -|---|---| -| OK | Save changes | -| Submit | Create workspace | -| Yes | Delete project | -| Cancel | Keep editing | -| Click here | View billing history | - -For destructive actions, name the destruction and the count: - -- "Delete 5 invites" -- "Delete workspace permanently" -- "Remove member from team" - -### Error copy - -Every error should answer: (1) what happened, (2) why (if knowable), -(3) what to try next. - -Kilo-flavored patterns: - -- `Can't reach Stripe. Check your connection and try again.` -- `Invalid token. Sign in again to refresh your session.` -- `Email must include an @ symbol. Example: you@example.com` -- `You don't have access to this workspace. Ask an admin for an invite.` -- `Something went wrong on our end. Our team has been notified. Try again in a minute.` - -Do **not**: - -- Blame the user: "You entered an invalid date" → "Please enter a date as - MM/DD/YYYY". -- Use humor in errors — users are already frustrated. -- Emit stack traces in user-facing copy. -- Use `Error: ` prefixes in user-facing messages (the UI treatment already - signals an error). - -### Empty states - -Acknowledge, explain value, provide a clear action. Examples: - -- `No workspaces yet. Create one to invite your team and start billing.` -- `No invoices yet. Your first invoice will appear after your trial ends.` -- `No API keys. Create one to connect Kilo Code to your IDE.` - -### Loading copy - -Be specific. `Creating workspace…` beats `Loading…`. For long waits, set -expectations: `Provisioning machine. This usually takes 30–60 seconds.` - -### Confirmation copy - -Confirm only for truly irreversible or high-stakes actions. Name the -action in both buttons: - -- `Delete workspace permanently?` - Primary: `Delete workspace` (destructive variant). - Secondary: `Keep workspace`. - -### Accessibility copy - -- Link text must stand alone: `View pricing plans`, not `Click here`. -- Alt text describes information, not the image: - `Revenue increased 40% in Q4`, not `Chart`. -- Use `alt=""` for decorative images. -- Icon-only buttons need `aria-label`. - -### Translation / i18n - -- German and Finnish can be ~30% longer than English. Plan layout for - expansion. -- Keep full sentences as single strings; word order changes between - languages. -- Avoid abbreviations (`5 minutes ago`, not `5m ago`) unless space is - actually constrained. -- When adding new strings, structure them to allow a translator context. - -### Absolute rejects in Kilo copy - -- "Submit" / "OK" / "Yes/No" as primary labels. -- "Oops!" / "Whoops" / "Uh oh" in any user-facing error. -- Emoji in error messages. -- Em dashes "—" in UI copy. Use commas, colons, semicolons, or - parentheses. Also not `--`. -- "Powerful," "seamless," "revolutionary," "unlock" as adjectives. -- Undifferentiated terminology: using `delete` / `remove` / `trash` - interchangeably in the same product surface. - ---- - -## The Button Label Problem - -Never use `OK`, `Submit`, or `Yes`/`No`. Use specific verb + object: - -| Bad | Good | Why | -|---|---|---| -| OK | Save changes | Says what will happen | -| Submit | Create account | Outcome-focused | -| Yes | Delete message | Confirms the action | -| Cancel | Keep editing | Clarifies what "cancel" means | -| Click here | Download PDF | Describes the destination | - -For destructive actions, name the destruction: - -- `Delete`, not `Remove` (delete is permanent; remove implies - recoverable). -- `Delete 5 items`, not `Delete selected` (show the count). - -## Error Messages: The Formula - -Every error should answer: (1) what happened, (2) why, (3) how to fix it. -`Email address isn't valid. Please include an @ symbol.` beats -`Invalid input`. - -### Error message templates - -| Situation | Template | -|---|---| -| Format error | "[Field] needs to be [format]. Example: [example]" | -| Missing required | "Please enter [what's missing]" | -| Permission denied | "You don't have access to [thing]. [What to do instead]" | -| Network error | "We couldn't reach [thing]. Check your connection and [action]" | -| Server error | "Something went wrong on our end. We're looking into it." | - -### Don't blame the user - -Reframe errors: `Please enter a date in MM/DD/YYYY format` not -`You entered an invalid date`. - -## Empty States Are Opportunities - -Empty states are onboarding moments: - -1. Acknowledge briefly. -2. Explain the value of filling it. -3. Provide a clear action. - -`No projects yet. Create your first one to get started.` not just -`No items`. - -## Voice vs Tone - -**Voice** is your brand's personality — consistent everywhere. **Tone** -adapts to the moment. - -| Moment | Tone shift | -|---|---| -| Success | Celebratory, brief: "Done! Your changes are live." | -| Error | Empathetic, helpful: "That didn't work. Here's what to try…" | -| Loading | Reassuring: "Saving your work…" | -| Destructive confirm | Serious, clear: "Delete this project? This can't be undone." | - -Never use humor for errors. - -## Writing for Accessibility - -- **Link text** must have standalone meaning — `View pricing plans`, not - `Click here`. -- **Alt text** describes information, not the image — `Revenue increased -40% in Q4`, not `Chart`. -- Use `alt=""` for decorative images. -- **Icon buttons** need `aria-label` for screen reader context. - -## Writing for Translation - -### Plan for expansion - -German text is ~30% longer than English. Allocate space: - -| Language | Expansion | -|---|---| -| German | +30% | -| French | +20% | -| Finnish | +30–40% | -| Chinese | -30% (fewer chars, same width) | - -### Translation-friendly patterns - -- Keep numbers separate (`New messages: 3`, not `You have 3 new -messages`). -- Use full sentences as single strings (word order varies by language). -- Avoid abbreviations (`5 minutes ago`, not `5 mins ago`). -- Give translators context about where strings appear. - -## Consistency: The Terminology Problem - -Pick one term and stick with it. Build a terminology glossary and -enforce it. Variety creates confusion. - -## Avoid Redundant Copy - -If the heading explains it, the intro is redundant. If the button is -clear, don't explain it again. Say it once, say it well. - -## Loading States - -Be specific: `Saving your draft…`, not `Loading…`. For long waits, set -expectations (`This usually takes 30 seconds`) or show progress. - -## Confirmation Dialogs: Use Sparingly - -Most confirmation dialogs are design failures — consider undo instead. -When you must confirm: name the action, explain consequences, use -specific button labels (`Delete project` / `Keep project`, not -`Yes` / `No`). - -## Form Instructions - -Show format with placeholders, not instructions. For non-obvious fields, -explain why you're asking. - ---- - -**Avoid**: Jargon without explanation. Blaming users -(`You made an error` → `This field is required`). Vague errors -(`Something went wrong`). Varying terminology for variety. Humor for -errors. diff --git a/.kilo/skills/repository-verification/SKILL.md b/.kilo/skills/repository-verification/SKILL.md index c0d9d84e1f..ac6f9b7922 100644 --- a/.kilo/skills/repository-verification/SKILL.md +++ b/.kilo/skills/repository-verification/SKILL.md @@ -13,7 +13,7 @@ Read root and relevant package `package.json` files before selecting commands. P |---|---| | `pnpm typecheck` | Runs `scripts/typecheck-all.sh`. | | `pnpm lint` | Runs `scripts/lint-all.sh`. | -| `pnpm test` | Runs web tests, then `test:web-env`; it does not run every package suite. | +| `pnpm test` | Runs web, `test:web-env`, and `test:dev-local`; it does not run every package suite. | | `pnpm validate` | Runs root typecheck, lint, and test scripts. | | `pnpm format` | Formats supported files with `oxfmt`. | | `pnpm format:check` | Lists supported files that differ from `oxfmt`. | diff --git a/.kilo_workflow/.e2e-slot-state.sh b/.kilo_workflow/.e2e-slot-state.sh new file mode 100755 index 0000000000..ea918f8776 --- /dev/null +++ b/.kilo_workflow/.e2e-slot-state.sh @@ -0,0 +1,144 @@ +#!/usr/bin/env bash +# Internal state engine. Agents use the five public E2E lifecycle scripts. +set -uo pipefail + +DIR="$HOME/.cache/kilo-e2e-slots" +TOTAL=3 +POLL=10 +ACQUIRE_DEADLINE=2700 +mkdir -p "$DIR" || { echo "cannot create slot state dir $DIR" >&2; exit 1; } +[ -w "$DIR" ] || { echo "slot state dir $DIR is not writable" >&2; exit 1; } +command -v tmux >/dev/null || { echo "tmux is required" >&2; exit 1; } + +self_session() { + [ -n "${TMUX_PANE:-}" ] || return 0 + tmux display-message -p -t "$TMUX_PANE" '#S' 2>/dev/null || true +} + +session_live() { + tmux has-session -t "=$1" 2>/dev/null +} + +reap() { + local now slot owner modified age + now=$(date +%s) + for slot in "$DIR"/slot-*; do + [ -d "$slot" ] || continue + owner=$(cat "$slot/owner" 2>/dev/null || true) + if [ -n "$owner" ]; then + if ! session_live "$owner"; then + rm -rf "$slot" + echo "reclaimed $(basename "$slot") from dead session $owner" >&2 + fi + continue + fi + + # mkdir wins the slot before acquire publishes its owner. Only clear an + # ownerless directory once it is old enough to be an interrupted acquire. + # GNU first: on GNU stat, `-f` means --file-system and exits 0 with mount + # info, so a BSD-first probe never falls through. BSD stat rejects `-c`. + modified=$(stat -c %Y "$slot" 2>/dev/null || stat -f %m "$slot" 2>/dev/null || echo "$now") + age=$((now - modified)) + [ "$age" -gt 60 ] && rm -rf "$slot" + done +} + +case "${1:?internal usage: $0 acquire|release|status|_held}" in + _held) + owner=$(self_session) + [ -n "$owner" ] || exit 1 + for slot in "$DIR"/slot-*; do + [ -d "$slot" ] || continue + [ "$(cat "$slot/owner" 2>/dev/null)" = "$owner" ] || continue + echo "$slot" + exit 0 + done + exit 1 + ;; + acquire) + [ -z "${2:-}" ] || { + echo "acquire takes no session name; run it inside the tmux session that owns the work" >&2 + exit 1 + } + owner=$(self_session) + [ -n "$owner" ] || { + echo "not inside tmux; a live tmux session must own the slot" >&2 + exit 1 + } + session_live "$owner" || { + echo "tmux session '$owner' is not live" >&2 + exit 1 + } + + for slot in "$DIR"/slot-*; do + [ -d "$slot" ] || continue + [ "$(cat "$slot/owner" 2>/dev/null)" = "$owner" ] || continue + echo "already holding $(basename "$slot")" + exit 0 + done + + deadline=$(($(date +%s) + ACQUIRE_DEADLINE)) + while :; do + reap + for number in $(seq 1 "$TOTAL"); do + slot="$DIR/slot-$number" + if mkdir "$slot" 2>/dev/null; then + # Resolve via this script's own location, never the caller's CWD: + # invoked by absolute path from a sibling repository (WORKFLOW.md), + # a bare rev-parse would record the sibling's root and break the + # status report's UNACCOUNTED matching. + worktree=$(git -C "$(dirname "$0")" rev-parse --show-toplevel 2>/dev/null || pwd -P) + if printf '%s' "$worktree" > "$slot/worktree" && + date -u +%Y-%m-%dT%H:%M:%SZ > "$slot/since" && + printf '%s' "$owner" > "$slot/owner"; then + echo "acquired slot-$number" + exit 0 + fi + rm -rf "$slot" + echo "failed to record slot ownership in $DIR" >&2 + exit 1 + fi + done + if [ "$(date +%s)" -ge "$deadline" ]; then + echo "no slot freed in ${ACQUIRE_DEADLINE}s; current holders:" >&2 + "$0" status >&2 || true + exit 1 + fi + echo "all $TOTAL E2E slots busy; retrying in ${POLL}s" >&2 + sleep "$POLL" + done + ;; + release) + [ -z "${2:-}" ] || { echo "release takes no arguments" >&2; exit 1; } + owner=$(self_session) + [ -n "$owner" ] || { echo "not inside tmux" >&2; exit 1; } + found=0 + for slot in "$DIR"/slot-*; do + [ -d "$slot" ] || continue + [ "$(cat "$slot/owner" 2>/dev/null)" = "$owner" ] || continue + name=$(basename "$slot") + rm -rf "$slot" + echo "released $name" + found=1 + done + [ "$found" -eq 1 ] || echo "no slot held by $owner" + ;; + status) + [ -z "${2:-}" ] || { echo "status takes no arguments" >&2; exit 1; } + reap + held=0 + for slot in "$DIR"/slot-*; do + [ -d "$slot" ] || continue + owner=$(cat "$slot/owner" 2>/dev/null || echo '') + since=$(cat "$slot/since" 2>/dev/null || echo '') + worktree=$(cat "$slot/worktree" 2>/dev/null || echo '') + echo "$(basename "$slot"): $owner since $since [$worktree]" + held=$((held + 1)) + done + echo "$held/$TOTAL held" + ;; + *) + echo "internal usage: $0 acquire|release|status|_held" >&2 + exit 1 + ;; +esac diff --git a/.kilo_workflow/README.md b/.kilo_workflow/README.md index 0288e5b1bd..ae7d970e1f 100644 --- a/.kilo_workflow/README.md +++ b/.kilo_workflow/README.md @@ -12,7 +12,7 @@ A multi-agent delivery workflow for this repository (and siblings like `~/Projec A run ends in one of two states: -- **Complete** — an open PR, CI green, Kilobot-reviewed, assigned to you, awaiting your review. The workflow never approves or merges its own PR; a PR waiting on human review is the deliverable, not a stall. +- **Complete** — an open PR, CI green, Kilobot-reviewed (or Kilobot's absence explicitly waived after two failed retriggers, noted on the PR), assigned to you, awaiting your review. The workflow never approves or merges its own PR; a PR waiting on human review is the deliverable, not a stall. - **BLOCKED** — a precise blocker report (in the PR or the section's final report) saying exactly what a human must do. It does not guess past blockers or fake completion. ## What happens inside @@ -27,26 +27,45 @@ Pipeline: **starter → planner → orchestrator → implementer/reviewer loops | Implementer / impl-reviewer | Cheap-model pairs: implement a slice, then a fresh reviewer re-derives the diff's correctness; loop until findings dry up | | E2E verifier | Boots the real local stack (simulator, browser, services — real LLM calls, no mocks) and verifies the plan's goals behave, not just compile | -Each section works in its own worktree under `~/Projects/.worktrees/` — never a primary checkout — and cleans up everything it started when it ends. +Each section works in its own worktree under `~/Projects/.worktrees/` — never a primary checkout — and cleans up everything it started when it ends; the worktree itself is the one local artifact that stays until its PR closes. -## The trade: wall time for correctness, at a good price +## Fast without trading correctness -The workflow is deliberately slow in wall-clock hours and cheap in both dollars and human minutes: +The workflow minimizes wall time while preserving independent review and live verification: - **Expensive models only where judgment concentrates** (planning); high-volume implementation and review runs on cheaper models that follow an explicit plan. +- **Independent work runs in parallel.** Slices, reviewers, checks, and iOS/Android E2E shards overlap when their files and resources do not conflict; synchronization gates only the points that need a complete diff. - **Nothing ships on one opinion.** Every artifact — plan, slice, cumulative diff, runtime behavior, PR — is checked by a *fresh* session with no memory of earlier rounds, so conclusions can't anchor. Loops repeat until a fresh reviewer finds nothing. - **Verification is empirical.** Bugs must be reproduced before they're fixed; features must pass a live E2E round against real services before the gate opens. +- **Doomed E2E rounds stop early.** A verifier stops at the first confirmed product failure; after the fix, it runs that case first, every same-area regression case, and every unproven case. Only proven cases with a concrete disjoint-impact reason carry forward. -A section routinely takes hours of unattended machine time. The human cost is minutes at the edges: state the request, optionally approve the plan, review the final PR. That is the intended trade — burn agent time and cheap tokens to make the one expensive resource (your review attention) arrive at an already-verified PR. +A section can still take hours of unattended machine time when builds or live E2E dominate. The human cost is minutes at the edges: state the request, optionally approve the plan, review the final PR. ## What's in this directory | Path | Purpose | |---|---| | [`WORKFLOW.md`](WORKFLOW.md) | The canonical spec — roles, loops, gates, dispatch commands | +| [`init-section.sh`](init-section.sh) | Creates a section or adds a mid-plan repository: run id, worktrees, cloud prepare, scratch directory — prints the manifest | | [`dispatch-role.sh`](dispatch-role.sh) | Launches a kilo role agent in tmux with a clean environment and logged exit code | +| [`await-role.sh`](await-role.sh) | Waits on a dispatched agent's log and reports the round's outcome: DONE with its verdict, VOID, STALLED, or RUNNING | +| [`launch-interactive.sh`](launch-interactive.sh) | Launches an interactive session (planner, orchestrator) in tmux with a clean environment and a live TTY | +| [`launch-gate.sh`](launch-gate.sh) | Spaces Kilo CLI startups through a recoverable machine-global lock | +| [`await-interactive.sh`](await-interactive.sh) | Watches an interactive session for the monitor: COMPLETED, BLOCKED, DEAD, QUIET, or RUNNING | | [`steer.sh`](steer.sh) | Delivers a message to a running interactive session (starter, planner, orchestrator) and confirms it was submitted | -| [`e2e-slot.sh`](e2e-slot.sh) | Machine-global semaphore (default 3) capping concurrent device/stack E2E phases; agents are never capped | +| [`e2e-take-slot.sh`](e2e-take-slot.sh) | Takes one of three machine-global E2E bundle slots (stack + iOS + Android + other resources) | +| [`e2e-start-resource.sh`](e2e-start-resource.sh) | Starts a stack, iOS simulator, Android emulator, or explicit custom resource after proving the caller holds a slot | +| [`e2e-stop-resource.sh`](e2e-stop-resource.sh) | Stops the matching resource through its repository wrapper | +| [`e2e-free-slot.sh`](e2e-free-slot.sh) | Frees the caller's slot after its resources are stopped | +| [`e2e-slot-status.sh`](e2e-slot-status.sh) | Reclaims dead owners and reports live slots plus known resources with no slot | +| [`slice-diff.sh`](slice-diff.sh) | Emits one slice's diff for review plus a snapshot fingerprint; `--check` judges the round for violations | +| [`baseline.sh`](baseline.sh) | Records a worktree's exact git state and later proves the E2E verifier's byte-identical restore | +| [`pr-gate.sh`](pr-gate.sh) | Checks the completion gate's mechanical items against one head SHA (CI, threads, assignee, bot summary) | +| [`pr-threads.sh`](pr-threads.sh) | Lists, replies to, and resolves PR review threads (GraphQL plumbing for the Kilobot loop) | +| [`pick-reviewers.sh`](pick-reviewers.sh) | Ranks reviewer candidates for a PR from file history and the requester's past reviewers | +| [`upload-pr-attachment.sh`](upload-pr-attachment.sh) | Uploads a screenshot to GitHub `user-attachments` via the checksum-pinned, security-reviewed `gh-image` binary | | [`learnings/`](learnings/) | Environment blockers and fixes, one file each, committed via PRs so every future run inherits them; `learnings/system/` is gitignored machine-local state | -Role definitions live in the repository root `.kilo/agent/` (the kilo CLI only discovers agents there). The workflow self-heals: when a run stumbles on something this documentation could have prevented, it fixes the documentation in the same PR. +A standing rule from the spec: **anything that can be automated away, should be automated away.** Agents' tokens go to the work, not to battling the workflow or the environment — when a run stumbles on something a script or a document could have prevented, the run fixes the script or the document in the same PR, and learnings that graduate into automation get deleted. + +Role definitions live in the repository root `.kilo/agent/` (the kilo CLI only discovers agents there). \ No newline at end of file diff --git a/.kilo_workflow/WORKFLOW.md b/.kilo_workflow/WORKFLOW.md index 98874ad592..8c0a4f8954 100644 --- a/.kilo_workflow/WORKFLOW.md +++ b/.kilo_workflow/WORKFLOW.md @@ -10,18 +10,19 @@ The definitions for every kilo CLI role live in the repository root `.kilo/agent These apply to every role. Later sections do not repeat them. -- Every long-lived process — starter, planner, orchestrator, dispatched role agents, local services — runs in tmux, with a unique descriptive window or session name. -- Section names are lowercase slugs (`[a-z0-9-]` only — they become branch, tmux, and path names) carrying a short random run id: `-$(openssl rand -hex 2)`, for example `billing-a7f3`. This keeps parallel runs from colliding on worktrees, branches, tmux names, or scratch paths. +- Every long-lived process — planner, orchestrator, dispatched role agents, local services — runs in tmux, with a unique descriptive window or session name; the launch scripts guarantee this. The one exception is the starter, which lives wherever the user invoked it (often a plain harness session outside tmux) — its launches still land in tmux via `launch-interactive.sh`. +- Section names are lowercase slugs (`[a-z0-9-]` only — they become branch, tmux, and path names). `init-section.sh` appends the four-hex run id, for example `billing-a7f3`, so parallel runs cannot collide. - All workflow tmux lives on the default tmux server — never a custom socket; slot reaping and monitoring key on the sessions one server can see. -- Work only in dedicated worktrees, in every repository the plan touches — one worktree per repository, `~/Projects/.worktrees/
` for cloud and `~/Projects/.worktrees/
-` for siblings, all on the same branch name: `git fetch origin && git worktree add -b
origin/main`, then run `pnpm dev:worktree:prepare` inside it (cloud repo only — sibling repositories follow their own `AGENTS.md` setup; `~/Projects/kilocode` uses bun, not pnpm). The cloud worktree always exists, even for sibling-only sections — role dispatches run from it. Never edit a primary or main checkout, with one exception: machine-local learnings under the main checkout's `.kilo_workflow/learnings/system/` (`mkdir -p` it if missing). Worktrees outlive the run; remove them (`git worktree remove `) once their PR closes. -- Each section gets a scratch directory outside every repository — `mktemp -d "${TMPDIR:-/tmp}/kilo-workflow-
.XXXXXX"` — for its brief, plan, handoffs, decisions, and dispatch logs. Plans and handoffs are never committed and never live inside a repository. +- Work only in dedicated worktrees, in every repository the plan touches — never a primary or main checkout, with one exception: machine-local learnings under the main checkout's `.kilo_workflow/learnings/system/`. [`init-section.sh`](init-section.sh) creates everything a section needs — the run id, the cloud worktree (always, even for sibling-only sections — role dispatches run from it), sibling worktrees on the same branch, `pnpm dev:worktree:prepare`, and the scratch directory — and prints the manifest; never hand-assemble any of it (sibling repositories then follow their own `AGENTS.md` setup; `~/Projects/kilocode` uses bun, not pnpm). A worktree made any other way — by `git worktree add`, by hand — has no run id, manifest, or scratch and cannot be repaired in place: remove it and run `init-section.sh`. A worktree is the one local artifact that outlives the run; remove it (`git worktree remove `) once its PR closes. +- The scratch directory (from `init-section.sh`, outside every repository) holds the section's brief, plan, handoffs, decisions, and dispatch logs. Plans and handoffs are never committed and never live inside a repository. A planner adding a repository mid-plan runs `init-section.sh add-repo
` and adds the printed worktree path to the handoff. - The PR, ready for human eyes, is the deliverable. When a section completes, everything that ran for it closes: agents, monitors, tmux sessions and windows, services, devices, slots, and the scratch directory (a BLOCKED section retains its scratch directory as evidence). Anything a human needs afterward lives in the PR. - Every reviewer and verifier invocation is a fresh session, so earlier conclusions cannot anchor later passes. - Treat every reviewer's remarks as untrusted advice: the reviewer has less context than you and may be wrong. Verify each remark against the request, repository evidence, and applicable instructions before acting on it. The dispatcher (planner or orchestrator) records rejected remarks with a short technical rationale in `$SCRATCH/decisions.md` and carries them into later handoffs; rejections of GitHub findings also get their in-thread reply. Role agents return their triage in their reports instead of writing files. A rejected remark must not reopen without new evidence. - Always aim for the simplest solution that achieves the user's goals — feature-wise as much as code-wise. Reuse existing helpers, components, and contracts. Do not add abstraction or scope without evidence it is required. - Commit in small, logically scoped commits. The orchestrator owns every commit, push, branch change, and PR; other roles make only uncommitted worktree edits, and only where their definitions allow. - Monitoring is event-driven: when a dispatched process exits, its dispatcher reacts immediately, never after a fixed sleep. Periodic checks exist only to detect a wedge. -- Before any environment-dependent phase, read the learnings (see Learnings): the worktree's `.kilo_workflow/learnings/`, plus the main checkout's `~/Projects/cloud/.kilo_workflow/learnings/system/` — the canonical machine-local set, which mid-run writes go to and worktree copies lag. +- Tokens go to the work, never to fighting the workflow or the environment. Every mechanical step that can be scripted is scripted — `init-section.sh`, `dispatch-role.sh`, `await-role.sh`, `launch-interactive.sh`, `launch-gate.sh`, `await-interactive.sh`, `steer.sh`, the five `e2e-*` lifecycle scripts, `slice-diff.sh`, `baseline.sh`, `pr-threads.sh`, `pr-gate.sh`, `pick-reviewers.sh`, `upload-pr-attachment.sh` — use the script, never hand-assemble its steps. **Anything that can be automated away, should be** (see Learnings). +- Learnings are the residue automation cannot reach. Before any environment-dependent phase, list both learnings directories — the worktree's `.kilo_workflow/learnings/` and the main checkout's `~/Projects/cloud/.kilo_workflow/learnings/system/` (the canonical machine-local set, which mid-run writes go to and worktree copies lag) — and read the entries whose names match your surface; filenames are symptom-keyed. When a tool or environment failure blocks you mid-run, grep both directories for the error text before debugging from scratch: a prior run has usually already paid for the answer. ### Models @@ -51,22 +52,38 @@ LOG=$(.kilo_workflow/dispatch-role.sh plan-reviewer
r1 ` (repeatable), never inlined with `"$(cat file)"`: dispatches routed through a tmux command string get re-parsed by another shell, and backticks inside the file then execute (see `learnings/kilo-run-shell-substitution-executes-backticks.md`). +The cwd/worktree is always the **cloud** worktree, even when the slice edits a sibling repository — the role definitions in root `.kilo/agent/` are only discovered there, and they pin the model, so worker dispatches never pass `--model`/`--variant`. The message is a short literal; file content — handoffs, plans, diffs — always travels via `--file ` (repeatable), never inlined with `"$(cat file)"`: dispatches routed through a tmux command string get re-parsed by another shell, and backticks inside the file then execute as shell commands. -What the script encodes (details in `learnings/`): +What the script encodes (details in its header comments): -- tmux wrapping — harness command timeouts kill bare long runs. The `e2e-verifier` gets its **own tmux session** (E2E slots are owned and auto-reclaimed by session name; a window-named owner leaks or shares slots); other roles run as windows in the dispatcher's session, resolved through `$TMUX_PANE`. A dispatcher that is not itself inside tmux has no such session, so its roles get their own sessions too — never a guessed one. Names are `
--