` |
-
-## P2: Touch & Interaction (CRITICAL)
-
-| Rule | Standard | Avoid |
-|---|---|---|
-| `hover-states` | All interactive = visible hover feedback | Silent no-ops |
-| `cursor-pointer` | `cursor: pointer` on all clickable | Clickable divs without cursor |
-| `loading-feedback` | Spinner/skeleton ALL async > 300ms | Frozen UI |
-| `hover-vs-tap` | `@media (hover: hover)` for hover; click/tap for primary | Features only via hover |
-| `disabled-states` | `opacity: 0.5` + `pointer-events: none` + `aria-disabled` | Disabled still clickable |
-| `empty-states` | Headline + copy + CTA, every empty container | Blank screen |
-| `error-feedback` | Inline message + summary at top (identical wording) | "Something went wrong" |
-| `tap-feedback` | Visual feedback < 100ms of tap | No visual response |
-| `gesture-alternative` | Every gesture = visible button equivalent | Gesture-only actions |
-| `safe-area` | Primary targets away from notch, gesture bar, edges | Content under OS chrome |
-
-## P3: Layout & Responsive (HIGH)
-
-| Rule | Standard | Avoid |
-|---|---|---|
-| `mobile-first` | Mobile styles first; override with `min-width` | Desktop-first `max-width` |
-| `breakpoints` | 375 / 768 / 1024 / 1280 / 1440px | Arbitrary device breakpoints |
-| `content-max-width` | `max-width: 1280px` page; `65ch` prose | Full-width paragraphs on ultrawide |
-| `4px-grid` | ALL spacing = multiples of 4px | 11px, 17px, 23px |
-| `spacing-hierarchy` | Space within groups < space between groups | Same padding everywhere |
-| `z-index-scale` | dropdown(1000) sticky(1020) modal(1050) tooltip(1070) toast(1080) | `z-index: 9999` |
-| `aspect-ratio` | `aspect-ratio` or `width`+`height` on all images | Images without dimensions (CLS) |
-| `sticky-offset` | Fixed/sticky nav β `padding-top: nav-height` on body | Nav covering first section |
-| `viewport-units` | `min-h-dvh` not `100vh` mobile | `100vh` (broken iOS) |
-| `12-col-grid` | 12 col, 24px gutters desktop, 16px mobile, 48-64px margins | No grid system |
-| `no-horizontal-scroll` | Content fits viewport width | Horizontal scroll mobile |
-
-## P4: Typography (HIGH)
-
-| Rule | Standard | Avoid |
-|---|---|---|
-| `type-scale` | Ratio: 1.25 compact / 1.333 standard / 1.414 dramatic | Random sizes (17px, 23px) |
-| `body-fixed` | Body 16px fixed; NEVER fluid `clamp()` | `clamp()` on body (causes reflow) |
-| `heading-fluid` | Headings use `clamp()` | Fixed heading sizes |
-| `line-height-invert` | Display 1.05-1.15; Heading 1.2-1.3; Body 1.5 app / 1.6-1.75 prose | Same lh everywhere |
-| `tracking` | Headings -0.01 to -0.03em; Body 0; Overlines +0.06 to +0.10em | Negative tracking on body |
-| `weight-contrast` | Heading 600-800, body 400 | `font-weight: 500` everywhere |
-| `max-2-families` | Sans + mono for apps; serif + sans for editorial | 3+ families |
-| `prose-width` | `max-width: 65ch` on body text | Full-width text |
-| `fallback-stack` | `ui-sans-serif, system-ui, sans-serif` always | Missing fallbacks |
-| `readable-mobile` | 16px min body mobile (avoids iOS auto-zoom) | 14px body mobile |
-
-## P5: Color System (HIGH)
-
-| Rule | Standard | Avoid |
-|---|---|---|
-| `oklch` | OKLCH for all design tokens | Hex/HSL for design systems |
-| `no-pure-bw` | Near-black `oklch(0.12-0.15 0.005 H)` + near-white `oklch(0.97-0.99 0.005 H)` | Pure #000 on #FFF |
-| `warm-cool-commit` | Commit to warm OR cool neutrals; never mix | Warm bg + cool borders |
-| `semantic-tokens` | 3-layer: primitive ramps β semantic tokens β Tailwind bridge | Raw hex in components |
-| `dark-mode` | Redesign, don't invert. Warm charcoal bg. Lighter surfaces per elevation. | Inverting light mode |
-| `status-colors` | Success/error/warning/info each with solid + soft variant; L ~0.55 for AA | Same color for both variants |
-| `no-ai-purple` | Custom brand hue, not #6366F1 | AI purple as unconscious default |
-| `chart-tokens` | Dedicated `--chart-*` tokens separate from `--primary` | Reusing brand for charts |
-| `shadow-tint` | Warm-tinted oklch shadows, never `rgba(0,0,0,...)` | Cold black shadows |
-| `dark-elevation` | Progressively lighter bg per level | Box shadows in dark mode |
-| `color-dark-mode-test` | Test contrast separately in dark mode | One-mode testing |
-
-## P6: Motion & Animation (MEDIUM)
-
-| Rule | Standard | Avoid |
-|---|---|---|
-| `duration-scale` | 100-150ms hover; 200ms default; 300ms panel; 400-500ms complex | > 500ms UI transitions |
-| `exit-faster` | Exit 50-100ms shorter than enter | Same duration enter/exit |
-| `easing` | ease-out (enter), ease-in (exit), ease-in-out (reposition) | Linear easing |
-| `gpu-only` | Animate only `transform` and `opacity` | width/height/top/left |
-| `no-decorative` | Animation must serve information | `animate-bounce` on static icons |
-| `max-2-animated` | Max 2 animated elements per viewport | 6 elements animating on load |
-| `spring-context` | Spring/bounce only for playful/consumer | Bounce in enterprise |
-| `interruptible` | User gesture cancels in-progress animation | Blocked input during animation |
-| `stagger-sequence` | Stagger list entrance 30-50ms per item | All items appear simultaneously |
-
-## P7: Components (MEDIUM)
-
-| Rule | Standard | Avoid |
-|---|---|---|
-| `all-states` | Every component: default, hover, active, focus, disabled, loading | Missing states |
-| `button-loading` | Spinner replaces text, same width (no CLS) | Width changing |
-| `input-labels` | Visible persistent label above input | Placeholder-as-label |
-| `input-validation` | Validate on blur; real-time only when correcting | Validating on focus |
-| `password-toggle` | Show/hide with text label; never disable paste | Paste disabled |
-| `empty-state` | Headline + copy + single CTA | "No data" |
-| `icon-system` | SVG icons (Lucide/Heroicons/Phosphor), never emojis | Emojis as icons |
-| `confirmation` | Title = action question; buttons = specific verbs | "Are you sure?" / "OK" |
-| `error-messages` | What happened + why + how to fix; never blame user | "Error 403" |
-| `nav-active` | Current page visually indicated | No active indicator |
-| `consistent-radius` | Same radius per component type | Mixing 4px and 24px |
-| `elevation-consistent` | Consistent shadow/elevation scale | Random shadow values |
-
-## P8: UX Writing (MEDIUM)
-
-| Rule | Standard | Avoid |
-|---|---|---|
-| `button-labels` | Verb + object: "Download report", "Add to cart" | "Submit", "Click here", "OK" |
-| `first-person-cta` | "Start my trial" > "Start your trial" (+90% ContentVerve) | Second-person CTAs |
-| `single-cta` | One primary CTA per view (+266% conversions) | Multiple competing CTAs |
-| `plain-language` | Grade 4-6, max 25 words/sentence | "Purchase", "Commence" |
-| `sentence-case` | Sentence case headings | Title Case Everywhere |
-| `specific-headlines` | "3 items in your cart" | "Almost there!" |
-| `loading-copy` | < 2s spinner; 2-10s "Saving..."; 10s+ progressive | "Loading..." for everything |
-| `no-blame` | "That password doesn't match" | "You entered wrong password" |
-| `no-clear-on-error` | Preserve all user input on error | Clearing form on error |
-| `inclusive-language` | "select" not "click"; "they/their"; "primary/subordinate" | "click", "master/slave" |
-
-## P9: Landing Page Conversion (MEDIUM)
-
-| Rule | Evidence | Standard |
-|---|---|---|
-| `hero-3sec` | NNG: 57% viewing time above fold | Value prop in 3 seconds |
-| `false-floor` | NNG: 102% more views above fold | Bleed 40-80px of next section |
-| `section-order` | Unbounce 41K pages | HeroβProofβProblemβFeaturesβTestimonialsβPricingβFAQβCTAβFooter |
-| `social-proof` | TrustRadius: 30-70% lift | Named metrics > logos > badges |
-| `pricing-3tier` | ProfitWell 12K SaaS | 3 tiers, highlight middle, expensive first |
-| `trust-signals` | 61% didn't buy without seals | Trust signal near every CTA |
-| `page-speed` | Google: 1sβ3s = +32% bounce | Sub-2s; AVIF > WebP > JPEG |
-| `cta-above-fold` | HubSpot 40K pages: +30% | CTA above fold, repeated after sections |
-| `grade-5-7` | Unbounce: +56% vs grade 8-9 | Copy at grade 5-7 |
-| `form-fields` | Baymard: -4-6% per field beyond 8 | Max 7-8 fields |
-| `mobile-cta` | 82.9% mobile traffic | Sticky CTA bar, thumb-zone placement |
-
-## P10: Charts & Data (LOW)
-
-| Rule | Standard | Avoid |
-|---|---|---|
-| `right-align-numbers` | Right-align quantitative data in monospace | Left-aligned numbers |
-| `table-row-hover` | Subtle bg highlight on row hover | No row tracking |
-| `table-pagination` | Pagination > infinite scroll | Infinite scroll on tables |
-| `fixed-headers` | Freeze row/col headers during scroll | Scrolling headers |
-| `no-rainbow` | Viridis/Okabe-Ito; max 8 categories | Rainbow colormap |
-| `data-ink` | Erase elements without info loss (Tufte) | Gridlines dominating data |
-| `chart-a11y` | Color + pattern/shape; provide table alternative | Color-only encoding |
-
----
-
-# PERSONALITY ATLAS
-
-> Source: 58 real company design systems. Design = communication before aesthetics.
-
-```
-Layer 1: Personality β what does product say about itself?
-Layer 2: Language β what visual vocabulary carries that?
-Layer 3: Rules β what constraints enforce it consistently?
-```
-
-## 1. Premium Precision
-**Communicates:** "Engineered by people who care about every pixel."
-**Exemplars:** Linear (tight type -0.03em, 3-variable color, opacity hierarchy), Vercel (black+white, Geist -0.04em, 96-128px sections), Apple (SF Pro 44pt targets, Clarity/Deference/Depth), Stripe (weight 300/500, CIELAB 5-step = 4.5:1)
-
-| Property | Value | Why |
-|---|---|---|
-| Colors | Mono + single accent | Multiple colors compete. One directs. |
-| Typography | -0.02 to -0.03em headings, weight 300-600 | Tight = deliberate. Low weight = restraint. |
-| Radius | 0-8px | Sharp = engineered. |
-| Shadows | None or ultra-subtle | Precision demands lightness. |
-| Motion | 200-250ms, ease-out, no bounce | Motion serves info, not personality. |
-| Density | Normal | Balanced. |
-| Default | Light | Content visibility. |
-
-**Use:** SaaS, dev tools (light), docs, B2B. **Never:** Children's, gaming, playful.
-
-## 2. Technical Developer
-**Communicates:** "Built by developers, for developers."
-**Exemplars:** Supabase (dark emerald, code-first), Warp (IDE-like, terminal IS product), Cursor (sleek dark, keyboard-first), Raycast (command palette is entire UX, every action < 100ms)
-
-| Property | Value | Why |
-|---|---|---|
-| Colors | Dark bg (oklch 0.08-0.14), green/cyan accents | Dark reduces strain. Green/cyan = terminal convention. |
-| Typography | Monospace for data, sans for UI chrome | Monospace = data. Sans = chrome. That IS hierarchy. |
-| Radius | 4-8px | Functional middle. |
-| Shadows | Glow on accent (0 0 20px oklch(accent / 0.15)) | Box shadows wrong on dark. Glow feels native. |
-| Motion | 100-200ms, snappy | Devs notice 50ms lag. |
-| Density | Compact (14px body, 48px sections, 20px cards) | Info density = feature. |
-| Default | Dark | 8+ hours in dark IDEs. |
-
-**Critical:** Command palette (Cmd+K) NOT optional for 50+ feature apps. Keyboard shortcuts on every action. Code blocks: syntax highlighting + copy button.
-
-**Use:** Dev tools, CLIs, APIs, editors. **Never:** Consumer, marketing, healthcare, government.
-
-## 3. Warm Editorial
-**Communicates:** "Reading this should feel like opening a well-made book."
-**Exemplars:** Notion (serif headings, cream bg, editor disappears), Airbnb (warm coral #FF5A5F, photography-driven, rounded-xl), Medium (serif body, 1.75lh)
-
-| Property | Value | Why |
-|---|---|---|
-| Colors | Warm-tinted: oklch(0.98 0.012 78) not oklch(0.98 0 0) | 0.012 chroma at hue 78 = "premium notebook" not "cold SaaS". Highest-leverage single decision. |
-| Typography | Serif or humanist sans, 18px body, 1.6-1.75 lh | Serif = trust. Larger body + generous leading = comfort. |
-| Radius | 12-20px | Rounded = friendly (Gestalt). Cap 20px - beyond = childish. |
-| Shadows | Warm-tinted (oklch(0.22 0.006 56 / 0.06)) | Cold rgba shadows disconnected on warm surfaces. |
-| Motion | 200-300ms, ease-in-out, gentle | Spring/bounce = tonally wrong. |
-| Density | Comfortable (96px sections, 40px cards, 18px body) | Reading requires breathing room. |
-| Default | Light | Paper metaphor. |
-
-**Use:** Content, editorial, consumer, hospitality. **Never:** Dev tools, data-dense, fintech.
-
-## 4. Bold Energetic
-**Communicates:** "We're confident and not afraid to stand out."
-**Exemplars:** Figma (multi-color, each feature = own color), Framer (bold black + blue, motion-first), PostHog (playful dark, hedgehog branding)
-
-| Property | Value | Why |
-|---|---|---|
-| Colors | 4-6 vivid, complementary/triadic, C 0.15+ | Energy requires contrast. Mono kills it. Cap 6 = chaos limit. |
-| Typography | Display 700-900, 32px+, -0.02 to -0.03em | Large heavy type demands attention. That's the point. |
-| Radius | 12-16px | Confident. Not sharp (cold) or super-round (childish). |
-| Shadows | Colored (0 8px 24px oklch(brand / 0.10)) | Colored shadows reference brand. More expressive. |
-| Motion | 200-400ms, spring (cubic-bezier(0.34, 1.56, 0.64, 1)) | Bold = bold motion. Under 400ms for UI. |
-| Default | Light | Bold colors need light contrast. Dark mutes vibrancy. |
-
-**Use:** Creative tools, startups, social, youth. **Never:** Banking, healthcare, government, B2B.
-
-## 5. Cinematic Dark
-**Communicates:** "This is an experience, not a tool."
-**Exemplars:** ElevenLabs (audio waveform aesthetics define visual language), RunwayML (AI content IS hero, UI = invisible framing), SpaceX (full-bleed mission photography, futuristic through restraint)
-
-| Property | Value | Why |
-|---|---|---|
-| Colors | Near-black (oklch 0.05-0.10), single neon accent | True black = 60% OLED power savings at 100% brightness. Single accent = Von Restorff focal. |
-| Typography | Light weight 300-400 at large display, tight tracking | Light on dark = ethereal. Heavy on dark = oppressive. |
-| Radius | 0-6px | Sharp = futuristic. Rounded adds warmth that conflicts. |
-| Shadows | Glow (0 0 40px oklch(accent / 0.20)), no box-shadow | Shadows invisible on dark. Glow = native. |
-| Motion | 400-600ms cinematic, parallax, ease-in-out | Speed destroys cinematic feel. ONLY personality where 500ms+ OK for reveals. |
-| Density | Comfortable (120px sections) | Dense breaks immersive spell. Each section = "scene." |
-| Default | Dark | Personality IS darkness. Light mode may not be appropriate. |
-
-**Use:** Media, entertainment, gaming, music, AI creative. **Never:** Productivity, forms-heavy, government, healthcare.
-
-## 6. Enterprise Trust
-**Communicates:** "Your data is safe with us."
-**Exemplars:** IBM Carbon (every component ships WCAG 2.1 AA, 3:1 focus ring), Coinbase (institutional blue, says "bank" not "startup"), Salesforce (Lightning system, complexity through structure)
-
-| Property | Value | Why |
-|---|---|---|
-| Colors | Blue/navy (oklch 0.45-0.55 0.15-0.18 240-260), 1 brand + 1 accent | Blue = most cross-culturally consistent trust signal (Frontiers in Psychology, Goldstein 1942). |
-| Typography | Formal sans (IBM Plex, Inter), 400 body, 600 heading | No serif (editorial), no display weight (startup). Moderate = structured. |
-| Radius | 4-8px | Professional. 0px = brutalist. 12px+ = consumer. |
-| Motion | 150-200ms, ease-out | 8+ hour workday. Decorative motion = distraction. |
-| Default | Light | Institutional convention. |
-
-**Trust signals required:** SOC2/ISO badges, uptime guarantees, SSO/SAML, audit logs, RBAC visible.
-
-**Use:** B2B, fintech, healthcare management, gov tech. **Never:** Consumer, creative, gaming.
-
-## Choosing Personality
-
-Industry Γ user type Γ emotional target. Signals conflict β **industry wins** (harder constraint).
-
-| Emotional Target | Maps To |
-|---|---|
-| Trustworthy | enterprise-trust |
-| Playful | bold-energetic |
-| Premium | premium-precision |
-| Energetic | bold-energetic |
-| Calm | warm-editorial |
-| Technical | technical-developer |
-| Bold | bold-energetic |
-| Editorial | warm-editorial |
-
----
-
-# INDUSTRY RULES
-
-> Source: ui-ux-pro-max (161 rules), awesome-design-md (58 companies).
-
-| Industry | Style | Color | Must | Never | Notes |
-|---|---|---|---|---|---|
-| SaaS | Soft UI | Trust blue + accent | Hover transitions, empty states, onboarding checklist (3-5 items) | Excessive animation, AI purple, > 2 accents | |
-| Analytics/Dashboard | Minimalism | Neutral + Okabe-Ito/viridis | Data export, filtering, sortable tables, keyboard nav, monospace numbers, right-align quantities | Ornate design, rainbow colormaps | |
-| Healthcare | Soft UI | Calm blue + green, C < 0.12 | **WCAG AAA**, 48px+ targets, crisis resources | Neon, motion-heavy, < 14px text, gamification w/o clinical validation | HIPAA: no PHI in URLs, session timeouts |
-| Fintech | Minimalism | Navy + blue + gold | Security signals, trust badges near monetary actions, locale-aware number formatting, audit trail | Playful design, AI purple, unclear fees (FTC risk), animations on transactions | |
-| Creative Agency | Vibrant Block | Bold, high chroma | Case studies, full-bleed imagery, scroll animations, portfolio grid | Corporate minimalism, stock photos, template layouts | |
-| Developer Tool | Dark OLED | Dark + emerald/cyan | Code examples, keyboard shortcuts, Cmd+K, syntax highlighting, copy buttons | Heavy chrome, poor keyboard support, forced light default | Docs quality IS product quality |
-| AI/Chatbot | Minimalism | Neutral + one accent (NOT #6366F1) | Streaming text < 100ms first token, typing indicators, code blocks + copy | Heavy chrome, AI purple default, anthropomorphized persona | |
-| E-commerce (Luxury) | Minimalism | Black + gold | Product photography as hero, trust signals, size guides, guest checkout (26% abandon if forced account) | Block-based colorful, cheap discount badges | "complimentary shipping" not "FREE SHIPPING!!!" |
-| Government | Minimalism | High contrast, institutional | **WCAG AAA**, skip links, grade 4-6 language, breadcrumbs, multi-language, print-friendly | Ornate, motion, decorative images, jargon | |
-| Mental Health | Soft UI | Muted pastels, warm | Calm aesthetics, privacy-first, breathing room, crisis resources every screen | Neon, gamification, social pressure, dark default, aggressive notifications | |
-| Education | Soft UI / Clay | Friendly pastels | Progress indicators, achievement feedback, clear nav, full a11y | Complex layouts, dense tables, dark default, small text | |
-| Wellness | Soft UI | Earth tones, sage, coral | Calm, breathing space, warm photography, gentle CTAs | Dark default, aggressive motion, neon, dense layouts | |
-
-For full detail: `designer_get_industry_rules(industry)`
-
----
-
-# COGNITIVE LAWS (11)
-
-> Source: Laws of UX, NNG, Smashing Magazine. Not opinions - empirically documented.
-
-## Fitts' Law
-`T = a + b * log2(2D/W)` - Halving distance > doubling size.
-- Touch targets β₯ 44px (WCAG) / 48px (Material). Screen edges = infinite mouse targets, hardest for touch.
-- Submit CTA at bottom of form (pointer already near last field). Destructive actions β₯ 8px from safe.
-- **Violations:** Icon-only buttons (16px visual β 44px target), Delete beside Save < 8px gap.
-
-## Hick's Law
-`RT = a + b * log2(n + 1)` - 2β4 choices costs more than 20β22. First added choices most expensive.
-- Minimize choices at irreversible points. Wizard pattern for multi-step. Surface recommended option.
-- Applies to decisions, not recognition. 15-item nav with clear categories = fine. 15-option modal = not.
-- **Violations:** All features on first login, pricing with no highlighted plan, 50+ unsorted dropdowns.
-
-## Miller's Law
-7 Β±2 chunks (Cowan 2001: 4 Β±1 without rehearsal). Unit = chunk, not item.
-- "(919) 555-2743" = 3 chunks vs "9195552743" = 10 items. 73% lower cognitive load.
-- Auto-chunk numbers, max 7 nav items, group forms β€ 5 fields/section.
-- **Violations:** Flat 12+ item nav, unbroken reference codes, 20+ ungrouped settings.
-
-## Gestalt Principles
-**Proximity > Similarity > Closure > Continuity > Common Fate**
-- **Proximity:** Label-input gap 4-8px < input-to-next-label 16-24px. Equal spacing = invisible structure.
-- **Similarity:** All links share treatment. Primary β secondary button weight.
-- **Closure:** Partial card at viewport bottom = scroll hook. Skeleton screens exploit this.
-- **Continuity:** Vertical form alignment. Zigzag layouts break scanning (NNG confirmed).
-- **Common Fate:** Skeleton placeholders pulse at identical timing.
-
-## Von Restorff Effect
-ONE highlighted element per view. Multiple highlights cancel.
-- One CTA. One recommended pricing plan. Red dot badge = only red in monochromatic UI.
-- **Violations:** Multiple "highlighted" CTAs, 6 elements animating on load.
-
-## Serial Position Effect
-First (primacy) and last (recency) remembered most. Middle forgotten.
-- Nav: important at edges. Pricing: recommended first or last. Onboarding: aha moment early, friction last.
-- Form fields: easy first (name, email), hard middle (tax ID).
-
-## F-Pattern (NNG: 232 users, 1.5M fixations)
-Dense text β horizontal top sweep β shorter lower sweep β vertical left scan. Right side = near-zero. 80% viewing time on left half.
-- Front-load sentences. "Billing settings" not "Settings for billing". H2/H3 every 200-300 words.
-
-## Z-Pattern
-Sparse visual pages (< 50 words). Logo top-left β trust top-right β diagonal β **CTA bottom-right** (terminal point).
-
-## Jakob's Law
-Users prefer sites to work like other sites. Radio = single, checkbox = multi, toggle = binary. Blue underline = link (-10-15% clicks without it). Cart top-right. Redesign: preview + opt-in + revert.
-
-## Doherty Threshold (IBM 1982)
-< 100ms instantaneous. 100-400ms immediate. **> 400ms flow breaks.** > 1s abandonment. > 10s gone.
-- Optimistic UI. Skeleton > spinner. Autocomplete < 300ms. Keystroke-to-display < 50ms.
-
-## Peak-End Rule (Kahneman 1993)
-Remembered = avg(peak intensity + final moment). Duration neglect.
-- Order confirmation = peak AND end (Mailchimp "High Five"). Onboarding completion = peak. Error recovery = peak management (Stripe specific messages). No-friction cancellation > dark-pattern 5-step.
-
-**Cross-law interactions:**
-- Hick + Serial Position on nav: fewer items + important at edges
-- Fitts + Von Restorff on CTAs: large + visually isolated = compound positive
-- Doherty + Peak-End: design loading reveal as positive peak
-- Hick vs disclosure: < 20% usage = hide; 80%+ = visible
-
----
-
-# VISUAL COMPOSITION
-
-> Source: NNG (1.5M fixations, 57,453 fold fixations), A List Apart, Smashing Magazine
-
-## Visual Hierarchy - 6 Levers (priority order)
-
-1. **Size** - Bigger = more important. Max 3 size variations. Never equal size for different priorities.
-2. **Contrast** - Squint test: blur 5-10px, primary action must be first visible.
-3. **Color** - Warm/saturated advances, cool/muted recedes. Red = destructive only.
-4. **Typography** - Weight is primary signal. Everything emphasized = nothing emphasized.
-5. **Spacing** - More surrounding space = more attention. Use before borders/fills.
-6. **Position** - Top-left = most attention. Optical center above mathematical center.
-
-## CRAP Principles
-- **Contrast:** If different, make VERY different. Same-same = no hierarchy.
-- **Repetition:** All links same treatment. Consistency = implicit rules.
-- **Alignment:** Left-align = simplest valid system. Never center multi-line paragraphs.
-- **Proximity:** Label-input 4-8px. Form groups 24-32px. Sections 48-96px. Same gap everywhere = invisible structure.
-
-## Whitespace
-**Micro** (tracking, leading, label-input): governs readability. **Macro** (sections, margins, hero): governs perceived value. Luxury = generous macro. Crowded = "affordable." Active whitespace = spotlight (Apple product isolation). Passive = structural.
-
-## The Fold (NNG: 57,453 fixations)
-- Above fold: **102% more views**. 57% viewing time above fold.
-- **Never fill exact viewport height** - bleed 40-80px of next section. False floor = users think page done.
-- First 100px must be relevant or users leave.
-
-## Reading Patterns
-- **F-Pattern:** Dense text. Right side = zero attention. Front-load sentences.
-- **Layer-Cake:** Most effective. Headings = summaries not labels.
-- **Z-Pattern:** Sparse visual < 50 words. CTA at terminal point (bottom-right).
-- **Spotted:** Specific targets (prices, dates). Distinct visual treatment.
-
-## Grids
-12-column: divides by 1/2/3/4/6/12. Desktop 24px gutters, mobile 16px, margins 48-64px / 20px.
-Baseline: 8px rhythm. Line heights = multiples (16, 24, 32, 40px).
-Full 12/12 (hero), wide 10/12, standard 8/12 (forms), narrow 6/12, sidebar 4/12.
-
-## Optical Alignment
-Mathematical β optical. Icons in buttons: 1-2px up. Text in buttons: more bottom padding. Hero headlines: raise 5-8% above mathematical center. Circles must be physically larger than squares to appear equal.
-
----
-
-# UX WRITING
-
-> Source: Mailchimp, NNG, GOV.UK, Copyhackers, Microsoft.
-
-## Button Labels
-- "Start **my** trial" > "Start **your** trial" (+90% ContentVerve). First-person = endowment effect.
-- Verb + object: "Download report", "Add to cart". Single CTA per screen (+266%).
-- Front-load verb. "No credit card required" near CTA (+34%).
-- **Never:** "Click here", "Submit", "OK", "Yes/No", "Learn More" as primary.
-
-## Voice & Tone (Mailchimp)
-Voice (constant): plainspoken, genuine, dry humor. Tone (variable): adjust to reader's state. "Clear > clever, always." Active voice.
-
-## Plain Language (GOV.UK)
-Reading age 9. Max 25 words/sentence. buy not purchase, help not assist, start not commence. 80% prefer clear English. Block caps 13-18% harder to read.
-
-## Error Messages (NNG + GOV.UK + Stripe)
-**What happened + Why + How to fix.** Never blame user. Never clear input. Inline + summary (identical wording). Validate on blur.
-- Good: "That email is already registered. Try signing in."
-- Stripe: "Your bank declined. No payment was made. Try a different card."
-
-## Placeholder Text (NNG)
-**Never as label** (disappears on focus, memory burden). Acceptable: format hints only ("MM/DD/YYYY").
-
-## Confirmation Dialogs
-Title = action question ("Delete this project?"). Body = consequences ("12,847 subscribers. Cannot be undone."). Buttons = specific verbs ("Delete project" / "Keep project"). Destructive: red button, focus on Cancel, max distance between buttons.
-
-## Empty States
-Every empty state = onboarding moment. Headline + copy + CTA. First-use: encouraging. Cleared: congratulatory. No results: helpful path. Never blank.
-
-## Loading States
-< 2s: spinner only. 2-10s: "Saving..." 10s+: "Uploading (3 of 12)..." Present participle.
-
----
-
-# DESIGN MASTERS - 5 CONVERGENCE POINTS
-
-> 7 masters (Rams, Norman, Vignelli, Spiekermann, Ive, Tufte, Kare) converged independently.
-
-## Rams: 10 Principles
-Innovative (remove friction, not add spectacle), Useful (function + psychology + aesthetics), Aesthetic (integral to usefulness), Understandable (zero-onboarding), Unobtrusive (canvas disappears), Honest (no dark patterns), Long-lasting (avoids fashion), Thorough (404 pages, empty states = design surfaces), **As little design as possible.**
-
-## Norman: 6 Principles
-**Signifiers** (blue underline = link), **Mapping** (controls match results), **Feedback** (< 100ms, calibrated), **Constraints** (define what's impossible), **Conceptual Models** (user mental model must match design). Two Gulfs: Execution (can I do it?) and Evaluation (did it work?). Good design narrows both.
-
-## Vignelli: Grid + Type Discipline
-Max 2 type sizes per screen. 2x ratio minimum for hierarchy. "White space > black of type." Grid removes arbitrary placement.
-
-## Spiekermann: Type = Brand
-Custom typeface = purchased differentiation. Open apertures for screen legibility. Size and tracking are inverse.
-
-## Tufte: Data-Ink Ratio
-Maximize toward 1.0. "Can this be erased without info loss?" Lie Factor = effect shown / effect in data (1.0 = honest). Small multiples. Sparklines.
-
-## Ive/Apple: Simplicity = Purpose
-"Simplicity not absence of clutter - that's a consequence." Clarity (transparent carrier), Deference (UI steps back), Depth (spring physics = signifiers).
-
-## Kare: Icons as Universal Language
-Meaningful (real metaphors), Memorable (one-trial learning), Clear (traffic sign test).
-
-## The 5 Convergences
-
-| # | Principle | Implication |
-|---|---|---|
-| 1 | Reduction is hardest work | Every element earns place. Default = removal. |
-| 2 | Constraints enable, not limit | Type scale, spacing grid, palette = preconditions for quality. |
-| 3 | Timelessness over trend | Build for structure. Glassmorphism fades. Good typography permanent. |
-| 4 | Function precedes form, but form not optional | Poor hierarchy = harder to use, not just ugly. |
-| 5 | Design communicates trust | No blame, no manipulation, no lying with graphics. |
-
----
-
-# AI SLOP FINGERPRINT
-
-ANY present β go back to Phase 3:
-
-| # | Pattern | Fix |
-|---|---|---|
-| 1 | `#6366F1` gradient (AI purple) | Custom brand hue in OKLCH |
-| 2 | Grid of identical cards, identical padding | Vary sizes, bento/asymmetric |
-| 3 | `font-weight: 500` everywhere | 700+ heading, 400 body |
-| 4 | `#F9FAFB` background (cold grey) | oklch(0.98 0.008-0.015 60-80) |
-| 5 | Missing states | Design ALL states |
-| 6 | `animate-bounce`/`pulse` on static | Animation for loading/state changes only |
-| 7 | 3+ font families | Max 2 (sans + mono) |
-| 8 | Line-height 1.75 on app UI | 1.5 for app; 1.75 prose only |
-| 9 | Absolute/relative from Figma MCP | Solve via flex/grid |
-| 10 | `rgba(0,0,0,...)` shadows | oklch-tinted warm shadows |
-| 11 | Same color for UI AND charts | Separate `--chart-*` tokens |
-| 12 | No `prefers-reduced-motion` | Media query with `!important` |
-| 13 | Pure #000 on #FFF | Near-black on tinted white |
-| 14 | `outline: none` without replacement | 2px ring, 2px offset |
-| 15 | Touch targets < 44px | Pad to 44px minimum |
+Cross-reference your resolved specs against the hard constraints. Use `view_file` on `references/anti-patterns-checklist.md` and `references/website-experience-cheatsheet.md` if MCP fails.
+- **P1 Accessibility:** 4.5:1 contrast, 44px targets, `prefers-reduced-motion`.
+- **P2 Interaction:** Hover states on all interactive elements.
+- **P3 Responsive:** Mobile-first, 4px grid spacing, 65ch prose width limit.
+- **P4 Typography:** Fixed 16px body, fluid headings (`clamp`).
+- **P5 Color:** Use OKLCH. No pure pure #000/#FFF. Warm/cool neutral commitment.
---
# PHASE 4: GENERATE DESIGN.md
-Assemble all decisions into 10-section DESIGN.md. See [template](references/design-md-template.md). See [examples](examples/) for worked outputs.
-
-```
-1. Visual Theme & Atmosphere - emotional target, personality, system inspiration, identity
-2. Color Palette - brand ramp (OKLCH 11 stops), semantic tokens, dark mode strategy
-3. Typography - scale table, font pairing + rationale, fluid vs fixed
-4. Spacing - semantic tokens, density, grid (12-col), content max-width
-5. Component Specs - button/input/card/nav with ALL variants + ALL states
-6. Motion - duration scale, easing rules, prefers-reduced-motion strategy
-7. Elevation - shadow system (light), bg-color elevation (dark), z-index scale
-8. Do's and Don'ts - 10 rules for THIS product, each traced to evidence
-9. Responsive - behavior at 375/768/1024/1280/1440px
-10. Anti-Patterns - industry violations, AI slop checks this design passes
-```
-
-**Present to user. Wait for approval. No code until approved.**
+Assemble 10 sections. Wait for user approval. NO CODE YET.
+1. Visual Theme (Emotional target, personality).
+2. Color Palette (OKLCH, semantic, dark mode).
+3. Typography (Scale, pairing).
+4. Spacing (Grid, density, content width).
+5. Component Specs (Variants + states).
+6. Motion (Durations, easing, reduced-motion).
+7. Elevation (Shadow tokens, z-index).
+8. Do's & Don'ts (Industry-traced).
+9. Responsive (375/768/1024/1280/1440px targets).
+10. Anti-Patterns (Slop checks passed).
---
# PHASE 5: CODE GENERATION
-After DESIGN.md approved:
-
-1. CSS custom properties (`:root` tokens) β call `design_tokens_generate`
-2. Base layout β grid + spacing
-3. Typography β apply scale
-4. Components β ALL states (default, hover, active, focus, disabled, loading)
-5. Motion β after layout correct
-6. Responsive β mobile-first
-7. Accessibility β focus, ARIA, touch targets
-8. Final audit β anti-pattern checklist + pre-delivery checks
-
----
-
-# QUALITY GATES (5)
-
-| Gate | Test | Fail = |
-|---|---|---|
-| Personality | Emotional target in one sentence? | AI slop |
-| Industry | Follows `designer_get_industry_rules`? | Contextual failure |
-| Anti-Pattern | Zero matches from fingerprint? | Fix first |
-| Accessibility | Passes all P1 rules? | Not shippable |
-| DESIGN.md | Coherent DESIGN.md writable from output? | Generated, not designed |
-
----
-
-# PRE-DELIVERY CHECKLIST
-
-**Visual Quality**
-- [ ] No AI purple as default
-- [ ] Weight contrast (heading β body)
-- [ ] Warm/cool neutrals committed
-- [ ] Near-black + near-white (not pure)
-- [ ] All spacing = 4px multiples
-- [ ] Consistent radius per component type
-
-**States**
-- [ ] Hover on all interactive
-- [ ] Focus ring (2px) on all interactive
-- [ ] Loading state for every async
-- [ ] Error state for every form input
-- [ ] Empty state for every data container
-- [ ] Disabled: opacity 0.5 + pointer-events none
-
-**Accessibility**
-- [ ] Body contrast β₯ 4.5:1 (both modes)
-- [ ] Touch targets β₯ 44px
-- [ ] prefers-reduced-motion implemented
-- [ ] No color-only indicators
-- [ ] All images have alt text
-- [ ] Skip links present
-- [ ] Semantic HTML (nav, main, button, a href)
-- [ ] Heading hierarchy sequential
-
-**Responsive**
-- [ ] Tested at 375, 768, 1024, 1440px
-- [ ] Content max-width constraint
-- [ ] No horizontal scroll mobile
-- [ ] Prose max-width: 65ch
-- [ ] dvh not vh for mobile full-height
-
-**Motion**
-- [ ] No > 500ms UI transitions
-- [ ] No linear easing
-- [ ] Only transform + opacity animated
-- [ ] No decorative bounce/pulse
-- [ ] Exits faster than entrances
-
-**Code**
-- [ ] No emojis as icons (SVG only)
-- [ ] cursor: pointer on clickable
-- [ ] No arbitrary z-index
-- [ ] Images have aspect-ratio or dimensions
-- [ ] No Figma absolute/relative dump
-- [ ] No form clearing on error
+Post-approval implementation order:
+1. CSS custom properties (`:root`) β `design_tokens_generate`.
+2. Base layout β grid + spacing.
+3. Typography.
+4. Components (ALL states).
+5. Motion (After layout).
+6. Responsive.
+7. Accessibility (Focus, ARIA).
+8. Final audit.
---
# INTEGRATION CONTRACTS
-## Upstream: How designer gets invoked
-
-**From `hyperstack:blueprint`:** visual/UX intent detected β input raw request + codebase context β return approved DESIGN.md path
-
-**From `hyperstack` root:** Phase 2 detects visual work β routes here before engineering-discipline for any visual task
-
-**From user direct:** "design", "build me a", "landing page", "DESIGN.md", any visual phrase β run full pipeline from Phase 1
-
-## Downstream: What designer hands off
-
-**To `hyperstack:forge-plan` (primary consumer):**
-After Phase 4 approved β file at `docs/DESIGN.md` or `
/DESIGN.md`
-
-forge-plan reads 10 sections β generates tasks:
-- S2 (Color) β task: `design_tokens_generate`
-- S3 (Typography) β task: font loading + type scale
-- S4 (Spacing) β task: configure Tailwind spacing tokens
-- S5 (Components) β tasks: one per component. If Q11b=shadcn: `shadcn_get_component` for each. If raw Tailwind: hand-write from DESIGN.md. If other library: use its docs.
-- S6 (Motion) β task: `motion_generate_animation` with DESIGN.md motion spec
-- S7 (Elevation) β task: define shadow tokens
-- S9 (Responsive) β tasks: breakpoint-specific overrides
-- S8 (Do's/Don'ts) β assertions embedded in every task's self-review
-
-Invocation: *"DESIGN.md approved and saved at ``. Invoking `hyperstack:forge-plan` with this as input spec."*
-
-**To `shadcn` MCP plugin - ONLY if Q11b=shadcn:**
-```
-shadcn_get_rules β architectural constraints (ALWAYS first)
-shadcn_get_composition(page_type) β which components compose for this page
-shadcn_list_components β available catalog
-for each component in DESIGN.md S5:
- shadcn_get_component(name) β full spec: primitive, data-slots, variants
- shadcn_get_snippet(name) β canonical usage example
-```
-No shadcn component matching DESIGN.md spec β escalate to `hyperstack:designer`, don't invent hybrid.
+**Upstream (`hyperstack:blueprint`):** Visual/UX intent detected β run pipeline β return approved DESIGN.md path.
-**To raw Tailwind - ONLY if Q11b=raw Tailwind:**
-```
-design_tokens_get_category("component-sizing")
-ui_ux_get_component_pattern(name)
-```
-Hand-build from DESIGN.md S5 using Tailwind classes directly. Apply all P7 rules.
+**Downstream (`hyperstack:forge-plan`):**
+DESIGN.md saved β `forge-plan` reads 10 sections β generates tasks.
-**To `motion_generate_animation`:**
-```
-motion_generate_animation({
- description: "",
- durations: { fast: "150ms", normal: "200ms", slow: "300ms" },
- easing: "ease-out",
- prefersReducedMotion: true // always
-})
-```
-
-**To `design_tokens_generate`:**
-```
-design_tokens_generate({
- description: "",
- brand: ,
- neutral: ,
- typography: ,
- spacing: ,
-})
-```
-
-**To `hyperstack:behaviour-analysis`:**
-After implementation complete, before ship-gate. DESIGN.md = "expected behaviour" ground truth:
-- S5 β expected states per component
-- S6 β expected timing/easing
-- S8 β assertions to verify
-- S10 β violations to search for
+**To `shadcn` Plugin (If selected):**
+Call `shadcn_get_rules` FIRST. `shadcn_get_composition`, `shadcn_list_components`. `shadcn_get_component` per DESIGN.md. No hallucinated components.
**To `hyperstack:ship-gate`:**
-Before completion claim. Verifies:
-- All S5 components have ALL required states implemented
-- S10 anti-patterns absent from code
-- OKLCH tokens from S2 present in CSS
-- `prefers-reduced-motion` implemented (S6)
-
-## Reverse Escalation
-
-| Discovery | Source | Action |
-|---|---|---|
-| Visual gap mid-plan | forge-plan β designer | Append clarification to DESIGN.md, resume |
-| DESIGN.md expected behavior unclear/contradictory | behaviour-analysis β designer | User resolves, DESIGN.md updated |
-| DESIGN.md compliance fail not fixable in code | ship-gate β designer | Revise DESIGN.md framework constraints |
-
-## Announcement Protocol
+DESIGN.md acts as absolute ground truth for testing expected behaviours, states, animations, and non-slop compliance.
-When invoked: *"Using hyperstack:designer - producing DESIGN.md contract for [task type]."*
-When handing off: *"DESIGN.md complete at [path]. Invoking hyperstack:forge-plan with this as input spec."*
-When escalating back: *"[from-skill] escalating to designer - [reason]."*
\ No newline at end of file
+**Announce invocation:** *"Using hyperstack:designer - stepping into Creative Director persona to produce DESIGN.md."*
\ No newline at end of file
diff --git a/skills/engineering-discipline/SKILL.md b/skills/engineering-discipline/SKILL.md
index 384984d..77fc4f3 100755
--- a/skills/engineering-discipline/SKILL.md
+++ b/skills/engineering-discipline/SKILL.md
@@ -51,17 +51,6 @@ references:
- **Quick Reference** β direct lookup of patterns, principles, naming conventions
- **Process Mode** β full 8-step workflow for complex/production features
-## The Iron Laws
-
-```
-1. NO REFACTOR WITHOUT TESTS FIRST
-2. NO PATTERN WITHOUT A NAMED FORCE
-3. NO SYNTAX BEFORE ARCHITECTURE
-4. NO ASSUMPTIONS WITHOUT DISCLOSURE
-5. NO "IT SHOULD WORK" - VERIFY IT DOES
-```
-
-Violating the letter = violating the spirit.
## Core Philosophy
@@ -146,33 +135,6 @@ Critical issue unaddressed β HARD STOP.
| Architecture decisions | `references/architecture/architecture-reasoning.md` |
| Standard response format | `references/architecture/output-format.md` |
-## Red Flags - STOP
-
-| Thought | Reality |
-|---|---|
-| "Quick fix, don't need the full 8-step framework" | Quick fixes break invariants when you skip Step 3. Do the framework. |
-| "I'll skip Step 8 Negative Doubt, I'm confident" | Confidence = #1 predictor of shipped bugs. Do the negative doubt. |
-| "I already know the responsibilities" | Write them down anyway. Writing forces clarity you thought you had. |
-| "Tests for a refactor are overkill" | Refactor without tests = random code change. Not negotiable. |
-| "I'll add tests after the refactor" | Write tests first, watch them pass, then refactor. |
-| "The pattern is obviously the right one" | Obvious patterns without named forces = cargo-culting. Name the force. |
-| "Small code, skip architecture reasoning" | Small code with wrong architecture compounds fast. |
-| "I'll assume the API is stable" | Never. State the assumption explicitly. |
-| "The 5-failure-mode exercise is busywork" | Most effective bug catcher in the framework. Do all 5. |
-| "I'll write tests that match the implementation" | Tests define behavior. Write them against the spec. |
-| "Refactoring doesn't change behavior, so tests are unchanged" | Write a test first that locks behavior. Then refactor. Then run. |
-| "I understand the invariants intuitively" | Write them down. Intuition drifts in 48 hours. |
-
-## Critical Reminders
-
-1. β No refactor without tests
-2. β No pattern without named force
-3. β No circular dependencies
-4. β No assumptions without disclosure
-5. β No global state without justification
-6. β No proceeding with ambiguous requirements
-
-Something cannot be done safely β say so and explain why.
## Lifecycle Integration
diff --git a/skills/forge-plan/SKILL.md b/skills/forge-plan/SKILL.md
index a08511e..99a5da2 100644
--- a/skills/forge-plan/SKILL.md
+++ b/skills/forge-plan/SKILL.md
@@ -1,241 +1,163 @@
---
name: forge-plan
category: core
-description: Use after blueprint design approval to produce a task-by-task implementation plan grounded in MCP-verified API calls. No placeholders, no assumed syntax.
+description: Executed after blueprint/designer approval. Produces task-by-task implementation plan grounded in MCP-verified APIs. Zero placeholders.
---
# Forge Plan
## Input
-Requires a completed, user-approved design from one of:
+Requires approved design:
+1. **`hyperstack:blueprint`** β Backend/infra/architecture. Input: architecture note.
+2. **`hyperstack:designer`** β Visual/UX. Input: 10-section `DESIGN.md`.
-1. **`hyperstack:blueprint`** β backend/infra/architecture work. Design = architecture note.
-2. **`hyperstack:designer`** β visual/UX work. Design = structured `DESIGN.md` with 10 sections.
+No design present:
+- Visual/UX task β STOP. Invoke `designer`.
+- Backend/infra task β STOP. Invoke `blueprint`.
-No approved design:
-- Visual/UX task β stop, invoke `hyperstack:designer`
-- Backend/infra task β stop, invoke `hyperstack:blueprint`
+## DESIGN.md Ingestion (Visual/UX)
-## DESIGN.md Ingestion (visual/UX work)
-
-Parse DESIGN.md and map sections to task categories:
+Parse DESIGN.md into task categories:
| DESIGN.md Section | Task Category | MCP Calls |
|---|---|---|
-| 1. Visual Theme | (context only - used in all tasks) | `designer_get_personality` |
-| 2. Color Palette | Token setup tasks | `design_tokens_generate` with OKLCH values |
-| 3. Typography | Font loading + type scale tasks | `design_tokens_get_category("typography")` |
-| 4. Spacing | Tailwind spacing config | `design_tokens_get_category("spacing")` |
-| 5. Component Specs | One task per component | shadcn β `shadcn_get_rules` + `shadcn_get_composition` + `shadcn_get_component`. Raw Tailwind β `ui_ux_get_component_pattern` + hand-build. Other library β use that library's own docs. |
-| 6. Motion | Animation tasks | `motion_generate_animation` with DESIGN.md motion spec |
-| 7. Elevation | Shadow token tasks | `design_tokens_get_category("shadows")` |
-| 8. Do's and Don'ts | Embedded as self-review assertions in every task |
-| 9. Responsive Breakpoints | Breakpoint-specific override tasks | `ui_ux_get_principle("responsive")` |
-| 10. Anti-Patterns | Embedded as self-review assertions - each task must verify none present |
-
-Every task's self-review step must cite the relevant DESIGN.md section for traceability.
+| 1. Visual Theme | Context | `designer_get_personality` |
+| 2. Color Palette | Token setup | `design_tokens_generate` (OKLCH) |
+| 3. Typography | Font loading + scale | `design_tokens_get_category("typography")` |
+| 4. Spacing | Tailwind config | `design_tokens_get_category("spacing")` |
+| 5. Component Specs | Component impl | shadcn: `shadcn_get_rules`, `get_composition`, `get_component`. Raw Tailwind: `ui_ux_get_component_pattern`. |
+| 6. Motion | Animation build | `motion_generate_animation` |
+| 7. Elevation | Shadow tokens | `design_tokens_get_category("shadows")` |
+| 8. Do's & Don'ts | Self-review | Embedded assertions in tasks |
+| 9. Responsive | Breakpoint config | `ui_ux_get_principle("responsive")` |
+| 10. Anti-Patterns| Self-review | Embedded validations |
## The Contract
-Every implementation step touching a domain covered by Hyperstack MCP **must** reference actual MCP tool output. Plan built on imagined syntax = bug report scheduled for delivery.
+Every implementation step touching an MCP domain MUST reference tool output. Imagined syntax = rejected plan.
## Process
-### Step 1: MCP Survey for Implementation
+### Step 1: MCP Survey
-Before writing a single task, call relevant MCP tools for every domain the implementation will touch:
+Query tools BEFORE writing:
| Domain | Call |
|---|---|
-| **DESIGN.md present** | **`designer_get_personality(cluster)`, `designer_get_page_template(type)`, `designer_get_anti_patterns(industry)` - DESIGN.md is ground truth for all visual decisions** |
-| React Flow | `reactflow_get_api` for each component/hook used |
-| Motion | `motion_get_api` for each animation primitive + `motion_generate_animation` if DESIGN.md specifies motion |
-| Go / Echo | `golang_get_pattern` + `echo_get_recipe` for each pattern |
-| Rust | `rust_get_practice` for each relevant practice |
-| Design tokens | `design_tokens_get_procedure` per token step + `design_tokens_generate` if DESIGN.md specifies OKLCH palette |
-| React / Next.js | `react_get_pattern` + `react_get_constraints` |
-| shadcn (only if Q11b chose shadcn) | `shadcn_get_rules` (first) + `shadcn_get_composition(page_type)` + `shadcn_get_component(name)` + `shadcn_get_snippet(name)`. Invoke `hyperstack:shadcn-expert` for architectural guidance. |
-| Raw Tailwind (only if Q11b chose raw Tailwind) | `ui_ux_get_component_pattern(name)` per component. Hand-build from DESIGN.md Section 5. No library wrapper. |
-| Other component library (MUI, Mantine, Chakra, Ant Design) | Use the library's own docs. Hyperstack has no plugin for these. Flag to user. |
-
-Record each tool output. Plan's code blocks must match what tools return.
-
-**MCP Degraded Mode:** Tools fail β inform user: "MCP unavailable for [domain] - plan may contain unverified API shapes." Mark affected tasks `[UNVERIFIED]`. Don't silently proceed with assumed APIs.
+| **DESIGN.md present** | **`designer_get_personality`, `get_page_template`, `get_anti_patterns`** |
+| React Flow | `reactflow_get_api` |
+| Motion | `motion_get_api`, `motion_generate_animation` |
+| Go / Echo | `golang_get_pattern`, `echo_get_recipe` |
+| Rust | `rust_get_practice` |
+| Design tokens | `design_tokens_get_procedure`, `design_tokens_generate` |
+| React / Next.js | `react_get_pattern`, `react_get_constraints` |
+| shadcn (if selected) | `shadcn_get_rules` (FIRST), `get_composition`, `get_component`, `get_snippet`. Invoke `shadcn-expert` for guidance. |
+| Raw Tailwind (if selected) | `ui_ux_get_component_pattern` |
+| Other library | Read library documentation |
+
+**Degraded Mode:** If MCP fails, inform user: "MCP unavailable for [domain]. Plan contains unverified API shapes." Mark tasks `[UNVERIFIED]`.
### Step 2: Map Files
-Before defining tasks, map every file to be created or modified:
-
```
-Create: exact/path/to/new-file.ts - one-line responsibility
-Modify: exact/path/to/existing.ts - what changes and why
-Test: exact/path/to/file.test.ts - what behaviour is tested
+Create: path/to/new-file.ts - one-line purpose
+Modify: path/to/existing.ts - what changes + why
+Test: path/to/file.test.ts - behaviour tested
```
-
-Each file has one clear responsibility. Files that change together live together. Split by responsibility, not by layer.
+Split by responsibility, not by layer. Files changing together live together.
### Step 3: Write Tasks
-**Each task produces working, testable, committed software on its own.**
-
-Task structure:
+Task structure MUST be autonomous and testable:
````markdown
### Task N: [Name]
**Files:**
-- Create/Modify/Test: `exact/path/file.ts`
-
-**MCP references:** [tool calls from Step 1 relevant to this task]
+- Create/Modify: `path/file.ts`
-- [ ] **Step 1: Write the failing test**
+**MCP references:** [cite Step 1 outputs]
+- [ ] **Step 1: Failing test**
```ts
-describe('ComponentName', () => {
- it('should do X when Y', () => {
- // ...
- });
-});
+describe('Component', () => { it('does X', () => { ... }); });
```
-
-Run: `npx vitest run path/to/file.test.ts`
-Expected: FAIL - "X is not defined"
+Run: `npx vitest run path/file.test.ts` (Expected: FAIL)
- [ ] **Step 2: Implement**
-
```ts
-// actual implementation matching MCP-verified API shapes
+// actual verified implementation
```
- [ ] **Step 3: Verify**
-
-Run: `npx vitest run path/to/file.test.ts`
-Expected: PASS - 1/1
+Run: `npx vitest run path/file.test.ts` (Expected: PASS)
- [ ] **Step 4: Commit**
-
```bash
-git add path/to/file.ts path/to/file.test.ts
-git commit -m "feat: [specific description]"
+git add file.ts file.test.ts
+git commit -m "feat: [desc]"
```
````
### Step 4: Self-Review
-After writing the complete plan, check inline:
-
-1. **Spec coverage** β task for every requirement in the approved design? List gaps.
-2. **Placeholder scan** β search for "TBD", "TODO", "add error handling", "similar to Task N", "implement later", steps without code blocks. Fix every instance.
-3. **MCP verification** β every domain-specific code block traces back to a tool call in Step 1.
-4. **Type consistency** β types, method names, prop names consistent across tasks.
-5. **Step atomicity** β each step = 2-5 minutes of work. "Implement the entire service layer" is not a step.
+1. **Spec coverage:** Cover every requirement?
+2. **Placeholder scan:** Hunt and destroy "TBD", "TODO", "implement later", "similar to Task N".
+3. **MCP verification:** All APIs trace back?
+4. **Type consistency:** Signatures match?
+5. **Atomicity:** Steps represent 2-5 minutes of work?
### Step 5: Handoff
-Save plan to `docs/plans/YYYY-MM-DD-[feature-name].md` and commit.
-
-Then offer:
+Save to `docs/plans/YYYY-MM-DD-[feature].md`. Commit. Ask user:
-> "Plan saved to `[path]`. Three execution options:
->
-> 1. **Autonomous** - execute all tasks end-to-end without pausing. Tests, reviews, ship-gate run automatically. Only stops on failure.
-> 2. **Subagent-driven** (`hyperstack:subagent-ops`) - fresh agent per task, automated two-stage review between tasks.
-> 3. **Inline with checkpoints** (`hyperstack:engineering-discipline`) - execute tasks in this session, pause for human review at phase gates.
->
-> Which approach?"
+> "Plan saved. Execution options:
+> 1. **Autonomous** (`autonomous-mode`) - End-to-end auto.
+> 2. **Subagent-driven** (`subagent-ops`) - Strict agent handoff per task.
+> 3. **Manual checkpoints** (`engineering-discipline`) - Execute, pause for human review."
-## No Placeholders - Ever
+## NO PLACEHOLDERS
-Plan failures β never write:
-- "TBD" / "TODO" / "fill in later"
-- "Add appropriate error handling"
-- "Write tests for the above" without actual test code
-- "Similar to Task N" β repeat the code, tasks may be read out of order
-- Steps describing what to do without showing how
-- References to types or functions not defined in any task
+Never write:
+- "TBD" / "fill in later"
+- "Add error handling" (write it)
+- "Write tests for above" (provide code)
+- "Similar to Task N" (copy it)
-## The Iron Law
+## IRON LAW
```
NO PLANS WITHOUT FRESH MCP-VERIFIED DATA
```
-Every API call, prop name, hook signature, or library pattern must trace to an MCP tool call made in THIS session. Not last session. Not from memory.
+Prop names and hook signatures trace to THIS session's MCP output. Not memory. Not last session.
-## Red Flags - STOP
+## RED FLAGS - STOP
| Thought | Reality |
|---|---|
-| "I know how React Flow Handle works, no need to check" | Plan will have wrong prop names. Call the tool. |
-| "I'll write the test structure, developer can fill in assertions" | That's a placeholder. Write the real test. |
-| "This task is too small for a full test" | No task is too small for a failing test. |
-| "I'll reference the survey output later" | Do the survey before writing. Not after. |
-| "I already surveyed this library last week" | State drifts. MCP data updates. Call again. |
-| "The MCP tool output is obvious" | Cite the actual output. |
-| "I'll TBD the uncertain parts" | TBD = plan failure. Resolve uncertainty before writing the task. |
-| "Similar to Task N saves time" | Plans get read out of order. Repeat the code. |
-| "I don't need to run the tool for this common pattern" | Common patterns drift. Call the tool. |
-| "User is waiting, I'll skip the survey" | Plan without survey = bug report. Do the survey. |
-| "This is a minor refactor" | Minor refactors move responsibility. Plans for responsibility changes need MCP verification. |
-
-## Integration
-
-- **Requires (backend/infra):** `hyperstack:blueprint` approved design
-- **Requires (visual/UX):** `hyperstack:designer` approved DESIGN.md
-- **Executes via:** Autonomous mode, `hyperstack:subagent-ops`, or `hyperstack:engineering-discipline`
-- **Completes via:** `hyperstack:ship-gate` β `hyperstack:deliver`
+| "I know the React Flow API." | Write wrong props. Call tool. |
+| "Tester writes assertions." | Placeholder detected. Write the test. |
+| "Too small for test." | All tasks require tests. |
+| "Run survey later." | Survey dictates plan. Run first. |
+| "Tool output obvious." | Cite it anyway. |
+| "TBD uncertain parts." | Resolve before writing. |
+| "Similar to Task N." | Plans read piecemeal. Repeat code. |
## Reverse Escalation
| Discovery | Escalate to | Action |
|---|---|---|
-| DESIGN.md section ambiguous or contradictory | `hyperstack:designer` | Pause plan, resolve, append clarification to DESIGN.md, resume |
-| Component needed not in DESIGN.md Section 5 | `hyperstack:designer` | Invoke designer with specific gap, append to DESIGN.md |
-| MCP tool returns conflicting shapes with DESIGN.md | `hyperstack:designer` | DESIGN.md may need to acknowledge framework constraints |
-| Architecture gap (non-visual) | `hyperstack:blueprint` | Re-enter blueprint for architecture decision |
+| DESIGN.md ambiguous | `designer` | Append clarification. Resume. |
+| Missing component | `designer` | Invoke for gap. Update DESIGN.md. |
+| MCP tool conflict | `designer` | Acknowledge framework constraints. |
+| Architecture gap | `blueprint` | Formalize structural decision. |
-Don't silently invent what DESIGN.md doesn't specify. Escalate back to designer.
+## Lifecycle
+**Frontend Agent:**
+`blueprint` β `designer` β `forge-plan` (THIS) β `[execution]` β `ship-gate` β `deliver`
-## Lifecycle Integration
-
-### Agent Workflow Chains
-
-**Website/Frontend Agent:**
-```
-blueprint β designer β forge-plan (THIS) β [execution] β ship-gate β deliver
- β
- DESIGN.md ingestion
- β
- [shadcn-expert if Q11b=shadcn]
-```
-
-**Backend/Infra Agent:**
-```
-blueprint β forge-plan (THIS) β [execution] β ship-gate β deliver
- β
- architecture note
-```
-
-**Execution handoff (user chooses):**
-- `autonomous-mode` β full auto end-to-end
-- `subagent-ops` β fresh agent per task
-- `engineering-discipline` β manual with checkpoints
-
-### Upstream Dependencies
-- `blueprint` β approved architecture note (backend/infra)
-- `designer` β approved DESIGN.md (visual/UX)
-
-### Downstream Consumers
-- `autonomous-mode` | `subagent-ops` | `engineering-discipline` β executes plan
-- `shadcn-expert` β if Q11b=shadcn, per-component guidance
-- `worktree-isolation` β clean workspace before execution
-
-### Reverse Escalation
-| Discovery | Escalate to | Action |
-|---|---|---|
-| DESIGN.md section ambiguous | `designer` | Pause, resolve, append to DESIGN.md |
-| Component not in DESIGN.md Section 5 | `designer` | Add to DESIGN.md |
-| MCP tool conflicts with DESIGN.md | `designer` | Reconcile framework constraints |
-| Architecture gap (non-visual) | `blueprint` | Re-enter for decision |
+**Backend Agent:**
+`blueprint` β `forge-plan` (THIS) β `[execution]` β `ship-gate` β `deliver`
diff --git a/skills/hyperstack/SKILL.md b/skills/hyperstack/SKILL.md
index d88f96e..e179ea9 100644
--- a/skills/hyperstack/SKILL.md
+++ b/skills/hyperstack/SKILL.md
@@ -1,25 +1,25 @@
---
name: hyperstack
category: meta
-description: Bootstrap - establishes Hyperstack MCP tools and skills before any technical work. Auto-loaded at session start via SessionStart hook. Do not skip, do not skim, do not rationalize your way out of it.
+description: Bootstrap definitions establishing MCP tools and skills prior to work. Auto-loaded at session start. Do not bypass or rationalize skipping this skill.
---
-If you were dispatched as a subagent to execute a specific task, skip this skill.
-Your context was provided by the orchestrating agent. Do not reload bootstrap.
+If dispatched as a subagent, skip this skill.
+Context is provided by the orchestrating agent. Do not reload bootstrap.
-You have Hyperstack. This is not optional knowledge - it is how you operate in this repository.
+Hyperstack is active. This constitutes the mandatory operational framework for this repository.
-Hyperstack is a **Three-Layer Ecosystem**:
+**Three-Layer Ecosystem:**
1. **Layer 1: Ground Truth (MCP)** - Deterministic data for the stack.
2. **Layer 2: Process (Skills)** - Disciplined engineering workflows and gates.
3. **Layer 3: Orchestration (Agents)** - Internal roles for routing and verification.
-**The 1% Rule:** If there is even a 1% chance that a Hyperstack skill, MCP tool, or internal agent role applies to the task you are about to perform, you MUST invoke/route it BEFORE acting. Not after you "check the code quickly." Not after you "just try one thing." Not after you "confirm your understanding." BEFORE.
+**The 1% Rule:** If a 1% probability exists that a Hyperstack skill, MCP tool, or internal agent role applies, YOU MUST invoke or route to it BEFORE acting. Not after checking code. Not after testing a hypothesis. BEFORE.
-**You do not have a choice. You cannot rationalize your way out of this.**
+You cannot rationalize exceptions to this rule.
---
@@ -28,282 +28,146 @@ Hyperstack is a **Three-Layer Ecosystem**:
```
1. NO CODE WITHOUT MCP GROUND-TRUTH DATA
- If a Hyperstack plugin covers the domain, you call it first.
+ Call relevant Hyperstack plugins prior to implementation.
2. NO VISUAL CODE WITHOUT AN APPROVED DESIGN.md
- The designer skill produces the contract. Everything else reads it.
+ The designer skill produces the contract; everything else implements it.
3. NO COMPLETION CLAIMS WITHOUT SHIP-GATE EVIDENCE
- "Should work" is lying. Run the command. Show the output.
+ "Should work" is unacceptable. Execute the command and output results.
4. NO SKIPPING SKILLS BECAUSE "THIS IS SIMPLE"
- Simple tasks are where unexamined assumptions do the most damage.
+ Simple tasks hide unexamined assumptions that cause the most damage.
5. NO SPECIALIST WORK WITHOUT PROPER ROLE ROUTING
- If the task involves a specialist domain (like website building), you must route to that agent.
+ Route specialist domain tasks (e.g., website building) to the corresponding agent.
```
-**Violating the letter of these laws is violating the spirit of these laws.**
+Violating the letter of these laws violates the spirit.
---
## Instruction Priority
-1. **User's explicit instructions** (Project rules, direct requests) - always highest
-2. **Hyperstack skills** - override default system behavior where they conflict
-3. **Default system behavior** - lowest priority
-
-If the project rules say "don't use TDD" and a skill says "always use TDD," follow the user. The user is in control. Everything else is your job to enforce.
-
----
-
-## Red Flags - STOP
-
-These are thoughts you will have. Each one is a rationalization. Each one has a counter.
-
-| Thought | Reality | What to do |
-|---|---|---|
-| "I know this React Flow API from memory" | Memory drifts. v11 and v12 are different. | Call `reactflow_get_api` first |
-| "This is a simple animation" | Simple animations need `prefers-reduced-motion`, correct easing, and GPU-only properties | Call `motion_get_examples` first |
-| "Go error handling is straightforward" | Straightforward code is where anti-patterns ship | Call `golang_get_practice` first |
-| "I'll check docs after I write it" | You will ship before you check. Every time. | Docs BEFORE code. Always. |
-| "I know the OKLCH token pattern" | OKLCH has specific rules about alpha, chroma peaks, dark mode lightness | Call `design_tokens_get_procedure` first |
-| "This pattern looks common, I'll adapt it" | Adaptation hides drift | Call the MCP tool. Copy from ground truth. |
-| "The user is impatient, I'll skip the gate" | User impatience is not permission to ship slop | Gates are not optional |
-| "This doesn't count as visual work" | If it looks, moves, or is interacted with β visual | Invoke designer skill |
-| "I'll verify after I commit" | The verification step exists because "after" never comes | Verify BEFORE claim |
-| "Subagent said it's done" | Subagents lie | Check the diff. Run the tests. |
-| "Just this one time" | There is no "just this one time" | No exceptions |
-| "I'll write the test after" | No. Write it before. | `NO PRODUCTION CODE WITHOUT A FAILING TEST FIRST` |
-| "I already checked earlier in this conversation" | Check again. State drifts. | Fresh verification every time |
-| "The file is too small to need a design" | Small files with wrong decisions ship to production | Every decision gets a gate |
+1. **User's explicit instructions** (Project rules, direct requests) - Maximum priority.
+2. **Hyperstack skills** - Overrides system defaults.
+3. **Default system behavior** - Minimum priority.
---
## Layer 1: MCP Tools (Ground-Truth Data)
-Call these BEFORE writing any code for these stacks. **Memory is not acceptable.**
+Call these BEFORE writing code. **Memory is unacceptable.**
| Namespace | Stack | Must-call-first tools |
|---|---|---|
-| `designer_*` | Design decision engine | `designer_resolve_intent`, `designer_get_personality`, `designer_get_preset`, `designer_get_page_template`, `designer_get_font_pairing`, `designer_get_anti_patterns` |
-| `design_tokens_*` | Design token systems | `design_tokens_generate`, `design_tokens_get_category`, `design_tokens_get_gotchas` |
-| `ui_ux_*` | UI/UX principles | `ui_ux_get_principle`, `ui_ux_get_component_pattern`, `ui_ux_get_gotchas` |
-| `shadcn_*` (**only if shadcn chosen**) | shadcn/ui Base UI edition | `shadcn_get_rules` (first), `shadcn_get_composition`, `shadcn_get_component`, `shadcn_get_snippet`, `shadcn_list_components` |
-| `reactflow_*` | React Flow v12 | `reactflow_get_api`, `reactflow_search_docs`, `reactflow_get_pattern` |
-| `motion_*` | Motion for React v12 | `motion_get_api`, `motion_get_examples`, `motion_get_transitions` |
-| `lenis_*` | Lenis smooth scroll | `lenis_get_api`, `lenis_generate_setup`, `lenis_get_pattern` |
-| `react_*` | React 19 / Next.js | `react_get_pattern`, `react_get_constraints`, `react_search_docs` |
-| `echo_*` | Echo (Go HTTP) | `echo_get_recipe`, `echo_get_middleware`, `echo_decision_matrix` |
-| `golang_*` | Go best practices | `golang_get_practice`, `golang_get_pattern`, `golang_get_antipatterns` |
-| `rust_*` | Rust practices | `rust_get_practice`, `rust_cheatsheet`, `rust_search_docs` |
+| `designer_*` | Design engine | `resolve_intent`, `get_personality`, `get_preset`, `get_page_template`, `get_font_pairing`, `get_anti_patterns` |
+| `design_tokens_*` | Token systems | `generate`, `get_category`, `get_gotchas` |
+| `ui_ux_*` | UI/UX principles | `get_principle`, `get_component_pattern`, `get_gotchas` |
+| `shadcn_*` (if selected) | Base UI edition | `get_rules` (FIRST), `get_composition`, `get_component`, `get_snippet`, `list_components` |
+| `reactflow_*` | React Flow v12 | `get_api`, `search_docs`, `get_pattern` |
+| `motion_*` | Motion for React v12 | `get_api`, `get_examples`, `get_transitions` |
+| `lenis_*` | Lenis smooth scroll | `get_api`, `generate_setup`, `get_pattern` |
+| `react_*` | React 19 / Next.js | `get_pattern`, `get_constraints`, `search_docs` |
+| `echo_*` | Echo (Go HTTP) | `get_recipe`, `get_middleware`, `decision_matrix` |
+| `golang_*` | Go best practices | `get_practice`, `get_pattern`, `get_antipatterns` |
+| `rust_*` | Rust practices | `get_practice`, `cheatsheet`, `search_docs` |
### MCP Degraded Mode
-If MCP tools fail or are unavailable:
-1. Tell the user explicitly: "Hyperstack MCP server is unavailable - my answers will be less precise and I am flagging them as uncertain."
-2. Fall back to training data but FLAG every answer as uncertain.
-3. Never silently answer as if ground-truth data was used.
-4. Do not invent API shapes.
+If MCP tools fail:
+1. Explicitly inform user: "Hyperstack MCP server is unavailable. Assertions are uncertain."
+2. Fall back to training data, but FLAG every answer as uncertain.
+3. NEVER assume ground-truth validity.
+4. DO NOT invent API shapes.
---
-## Layer 2: Skills (Engineering Process)
-
-Use the `Skill` tool to load these before the relevant task type.
+## Layer 2: When to Invoke Skills
-**Full skill index:** See `skills/INDEX.md` - all skills grouped by category (core / domain / meta). Regenerate with `npm run skills:index` after adding or editing any skill.
+Load via `Skill` tool **before acting**. Registered in: `skills/INDEX.md`.
### Announcement Iron Law
```
-BEFORE invoking any Hyperstack skill, announce it:
+BEFORE invoking any Hyperstack skill, announce:
"Using hyperstack:[skill-name] - [one-line purpose]"
```
-This is non-negotiable. Silent skill invocations are invisible to the user and cannot be audited. **If you invoke a skill silently, you are lying by omission.**
-
-### Workflow Skills (invoke in this order for feature work)
-
-| Skill | When to invoke | Gate type |
-|---|---|---|
-| `hyperstack:blueprint` | Before any feature build - MCP survey, design gate, negative doubt | **HARD GATE** |
-| `hyperstack:designer` | Before any visual/UX work - produces DESIGN.md contract | **HARD GATE** |
-| `hyperstack:forge-plan` | After design approval - MCP-verified implementation plan | Requires approved design |
-| `hyperstack:run-plan` | Have an existing plan - validate then execute | Requires plan |
-| `hyperstack:engineering-discipline` | During execution - Senior SDE phase gates | Phase gates |
-| `hyperstack:ship-gate` | Before any completion claim - evidence required | **HARD GATE** |
-| `hyperstack:deliver` | After all tasks complete - final verification and delivery | Gate |
-
-### Execution Skills (invoke during implementation)
+### Condition β Skill Table
-| Skill | When to invoke |
+| Situation | Load this skill |
|---|---|
-| `hyperstack:autonomous-mode` | Full autonomous execution - runs end-to-end, only stops on failure |
-| `hyperstack:subagent-ops` | Plans with independent tasks - fresh agent per task, two-stage review |
-| `hyperstack:test-first` | Before writing any implementation code - red-green-refactor |
-| `hyperstack:worktree-isolation` | Before feature work - clean workspace isolation |
-| `hyperstack:code-review` | After completing tasks - dispatch reviewer subagent |
-| `hyperstack:parallel-dispatch` | 2+ independent failures or tasks - concurrent agent dispatch |
+| Starting any new feature, component, or behaviour change | `blueprint` |
+| Task involves UI, animation, visuals, or interaction | `designer` β produces DESIGN.md first |
+| Have an approved design or plan to execute | `forge-plan` or `run-plan` |
+| Claiming anything is complete, fixed, or passing | `ship-gate` β evidence required |
+| Hit any bug, test failure, or unexpected behaviour | `debug-discipline` β root cause before any fix |
+| User says "autonomous", "just do it", "go ahead" | `autonomous-mode` |
+| Plan has 2+ independent tasks | `subagent-ops` or `parallel-dispatch` |
+| Implementing any feature or bug fix (before code) | `test-first` |
+| Reviewing completed implementation | `code-review` |
+| Security-sensitive API, auth, or infra code | `security-review` |
+| UI state machine, interaction audit | `behaviour-analysis` |
+| Selecting an abstraction or design pattern | `engineering-discipline` |
+| Writing or updating project documentation | `readme-writer` |
+| Starting implementation that needs workspace isolation | `worktree-isolation` |
+
+### Workflow Chain Reference
-### Support Skills (invoke when the situation calls for it)
-
-| Skill | When to invoke |
-|---|---|
-| `hyperstack:designer` | Before any visual/UX work - produces DESIGN.md |
-| `hyperstack:debug-discipline` | Any bug or unexpected behaviour - root cause first |
-| `hyperstack:behaviour-analysis` | UI/UX audits, state machine correctness |
-| `hyperstack:design-patterns-skill` | Selecting the right abstraction or design pattern |
-| `hyperstack:security-review` | OWASP audits, API and infrastructure security |
-| `hyperstack:readme-writer` | Evidence-based documentation |
-
-### Workflow Chain
-
-```
-New work: blueprint β [designer if visual] β forge-plan β choose execution mode β ship-gate β deliver
- β β
- β βββ produces DESIGN.md (input to forge-plan)
- β
-Existing: run-plan βββ€
- β
- ββ autonomous-mode (full auto, stops only on failure)
- ββ subagent-ops (fresh agent per task, two-stage review)
- ββ engineering-discipline (manual, human checkpoints)
-
-Before execution: worktree-isolation (clean workspace)
-Debugging: debug-discipline β parallel-dispatch (if independent failures)
```
+New work: blueprint β [designer if visual] β forge-plan β execution β ship-gate β deliver
-**Visual work branch:** If the task changes how something looks, feels, moves, or is interacted with, `blueprint` routes through `designer` BEFORE `forge-plan`. The DESIGN.md produced by designer becomes the input spec for forge-plan.
-
-**Skip designer when:** pure backend, single CSS bug fix, performance optimization with no visual change, infra/DevOps, documentation-only.
+Existing: run-plan βββ€
+ ββ autonomous-mode
+ ββ subagent-ops
+ ββ engineering-discipline
-For non-trivial tasks, follow the chain in order. Do not skip steps.
-
-**Platform tool equivalences:** See `skills/hyperstack/references/` for tool name mappings per harness.
+Debugging: debug-discipline β parallel-dispatch
+```
---
## Layer 3: Agents (Orchestration & Routing)
-Hyperstack uses internal roles to manage complexity. These roles are **internal and auto-invoked**.
-The bootstrap and orchestrator (`hyper`) choose the correct role based on the request and lifecycle state.
-
-| Agent | Category | Owns |
-|---|---|---|
-| `hyper` | Core | Classification, routing, gate enforcement, final verification, delivery. |
-| `website-builder` | Specialist | Website-facing design/implementation, CTA hierarchy, page structure. |
-
-### Role Hierarchy & Hand-off
-
-1. Every request starts in `hyper`.
-2. `hyper` classifies and delegates to specialists (e.g., `website-builder`) when domain-specific work is detected.
-3. Specialists implement the work following Layers 1 & 2 (MCP + Skills).
-4. Specialists **MUST** hand back to `hyper` for final verification and ship-gate.
-5. `hyper` performs the final check and delivers to the user.
+Internal roles β auto-invoked, not user-facing.
----
-
-## Role Registry Details
-
-- `hyper` - conductor, classifier, gatekeeper, verifier, and delivery owner
-- `website-builder` - first specialist for website-facing design and
- implementation work
-
-## Routing Summary
-
-- Every request enters through `hyper`
-- `hyper` inspects the workspace first: package manifests, dependency signals,
- and likely core files for the affected surface
-- `hyper -> website-builder` for website-facing work: landing pages, dashboards,
- marketing pages, redesigns, page structure, CTA hierarchy, form friction,
- trust signals, and website-experience-heavy UI work
-- `website-builder -> hyper` after specialist output is ready for review and
- verification
-- If classification is ambiguous, stay in `hyper`
-
-## Allowed Transitions
-
-- `user request -> hyper`
-- `hyper -> website-builder`
-- `website-builder -> hyper`
-- `hyper -> existing Hyperstack skills/plugins`
-- `hyper -> verification and delivery gates`
+| Agent | Owns |
+|---|---|
+| `hyper` | Classification, routing, gate enforcement, final verification, delivery |
+| `website-builder` | Website-facing design/implementation, CTA hierarchy, page structure |
-## Disallowed Transitions
+### Disallowed Transitions
- `user request -> website-builder`
- `website-builder -> ship`
- `website-builder -> deliver`
-- `website-builder` claiming final completion directly
-
----
-
-## The Rationalization Catalog (Read Before Every Session)
-
-These are the exact thoughts you will have when you want to skip a skill. Every one is a bug in your reasoning. Every one has been written down because someone (probably you in a past session) used it to ship bad code.
-
-### Skill-skipping rationalizations
-
-| Thought | Why it's wrong |
-|---|---|
-| "This is just a question, not a task" | Questions are tasks. They lead to answers that become code. Check for skills. |
-| "I need context first, then I'll use skills" | Skills tell you HOW to gather context. Check first. |
-| "Let me quickly look at the files" | "Quickly" is the word you use when you're skipping the gate. |
-| "I remember this pattern" | Remembering is not the same as using the current tool output. Memory drifts. |
-| "This doesn't need a formal skill, it's obvious" | If it's obvious, invoking the skill takes 10 seconds. Do it. |
-| "The skill is overkill for this" | You don't get to decide what's overkill. The skill exists because the shortcut failed. |
-| "I'll just do one thing first then invoke the skill" | No. Skill invocation comes BEFORE the one thing. |
-| "I already have a mental model of this" | Mental models drift faster than you think. Refresh it from MCP. |
-
-### Verification-skipping rationalizations
-
-| Thought | Why it's wrong |
-|---|---|
-| "Should work now" | "Should" is not evidence. Run the command. |
-| "I'm confident in this change" | Confidence is not evidence. Run the command. |
-| "Minor change, no need to recheck" | Minor changes cause regressions. Run the command. |
-| "Tests were passing before my change" | Irrelevant. Run them again now. |
-| "The subagent reported success" | Subagents lie. Check the diff yourself. |
-| "I followed the pattern correctly" | Following the pattern is not the same as the pattern working. Run the command. |
-| "I'll verify after I push" | After you push it's in CI. Verify BEFORE. |
-| "Just this once" | There is no "just this once." |
-| "I'm tired" | Exhaustion is not an excuse. Stop and rest if you must, don't ship unverified. |
-| "Partial check is enough" | Partial verification is theater. Do the full check. |
-
-### The "I'm different" rationalization
-
-| Thought | Why it's wrong |
-|---|---|
-| "These rules are for general AI, I understand them better" | No. They were written for past sessions of you that also thought they understood. |
-| "The spirit of the rule allows this" | The letter of the rule is the spirit of the rule. |
-| "This specific case isn't covered" | Every case is covered by "use the skill or don't proceed." |
-| "I can adapt the process to be faster" | Fast is for after discipline is internalized. You are not there yet. |
---
-## The One Rule That Governs All Rules
-
-> **If there is even a 1% chance a Hyperstack skill or MCP tool applies to what you are about to do, you ABSOLUTELY MUST invoke it first.**
+## High-Signal Red Flags
-Not after. Not alongside. FIRST.
-
-If the skill turns out not to apply once you've loaded it, you don't have to use it. But you MUST check.
+| Thought | Reality | Action |
+|---|---|---|
+| "I know the React Flow API from memory." | Memory drifts. v11 and v12 differ. | Call `reactflow_get_api` first. |
+| "This is a simple animation." | Animations require `prefers-reduced-motion`, easing, and GPU properties. | Call `motion_get_examples` first. |
+| "Go error handling is straightforward." | Straightforward code hosts anti-patterns. | Call `golang_get_practice` first. |
+| "I'll check docs after writing." | Shipping occurs before checking. | Consult docs BEFORE code. |
+| "I know the OKLCH token pattern." | OKLCH dictates specific alpha, chroma, and lightness rules. | Call `design_tokens_get_procedure` first. |
+| "This pattern is common; I'll adapt it." | Adaptation obscures structural drift. | Call the MCP tool and replicate ground truth. |
+| "The user is impatient; skip the gate." | User impatience does not grant permission to ship slop. | Enforcement gates are mandatory. |
+| "This isn't visual work." | If it changes look, motion, or interaction, it is visual. | Invoke designer skill. |
+| "Subagent reported success." | Subagents hallucinate success. | Manually review the diff and run tests. |
+| "Just this once." | "Once" establishes a pattern. | Zero exceptions. |
---
-## Final Check Before Any Response
-
-Before you respond to the user's message, confirm:
+## Final Response Check
-1. [ ] Did I check whether any Hyperstack skill applies to this task? (1% rule)
-2. [ ] Did I call any relevant MCP tool for ground-truth data? (memory is not acceptable)
-3. [ ] If this involves visual work, did I invoke designer BEFORE writing any code?
-4. [ ] If I'm claiming something is done, did I run the verification command THIS message?
-5. [ ] Did I announce every skill invocation with the exact format?
-
-If any answer is no, **stop and fix it before responding.**
-
----
+1. [ ] Did I evaluate Hyperstack skill applicability? (1% rule)
+2. [ ] Did I execute relevant MCP tools? (No memory rely)
+3. [ ] If visual, did I invoke `designer` BEFORE coding?
+4. [ ] If claiming completion, did I execute verification THIS message?
+5. [ ] Did I announce skill invocation with exact formatting?
-**You have Hyperstack. Use it.**
+**Stop and fix if any answer is NO.**
diff --git a/skills/parallel-dispatch/SKILL.md b/skills/parallel-dispatch/SKILL.md
index 69c5e5d..b6204f4 100644
--- a/skills/parallel-dispatch/SKILL.md
+++ b/skills/parallel-dispatch/SKILL.md
@@ -89,14 +89,6 @@ Return: Summary of root cause and changes made.
| Related failures split across agents | Investigate together first |
| Same files given to multiple agents | Guaranteed merge conflicts |
-## Red Flags - STOP
-
-| Thought | Reality |
-|---|---|
-| "Dispatch 5 agents for speed" | More agents β faster if they conflict |
-| "I'll let agents figure out the scope" | Vague scope β vague results |
-| "These might be related but I'll parallelize anyway" | Related bugs in parallel = wasted work. Investigate first. |
-| "Skip the integration check" | Agents don't know about each other. You must verify. |
## Integration
diff --git a/skills/run-plan/SKILL.md b/skills/run-plan/SKILL.md
index efebd72..e0f42a8 100644
--- a/skills/run-plan/SKILL.md
+++ b/skills/run-plan/SKILL.md
@@ -14,13 +14,6 @@ description: Use when you have an existing plan, spec, or task list to execute.
Creating a new plan from scratch β use `hyperstack:blueprint` β `hyperstack:forge-plan` instead.
-## The Iron Law
-
-```
-NO EXECUTION WITHOUT PLAN VALIDATION FIRST.
-```
-
-Plan with wrong API shapes or missing steps β wrong code. 2 minutes of validation saves hours of rework.
## Process
@@ -92,15 +85,6 @@ Blocker mid-task β stop immediately, don't guess or work around it. Report to
All tasks marked complete β invoke `hyperstack:deliver`.
-## Red Flags - STOP
-
-| Thought | Reality |
-|---|---|
-| "The plan looks fine, no need to check MCP" | One wrong prop name = broken code in every task that uses it |
-| "I'll fix the gap as I go" | Undocumented gaps β undocumented decisions |
-| "The user wrote this plan, it must be correct" | Plans have bugs. That's why this step exists. |
-| "Step N is unclear but I can infer what they meant" | Stop and ask. Inferred intent β surprising code. |
-| "I'll skip ship-gate on this task, it's small" | No exceptions. |
## Integration
diff --git a/skills/shadcn-expert/SKILL.md b/skills/shadcn-expert/SKILL.md
index 224811a..c1fbec2 100644
--- a/skills/shadcn-expert/SKILL.md
+++ b/skills/shadcn-expert/SKILL.md
@@ -6,15 +6,6 @@ description: Advanced shadcn/ui architect specializing in Base UI, Tailwind v4,
# shadcn/ui Expert (Base UI Edition)
-## The Iron Law
-
-```
-NO COMPONENT WITHOUT shadcn_get_rules FIRST
-```
-
-Call `shadcn_get_rules` before proposing any new component or modification. Base UI edition differs from standard shadcn (Radix) in multiple ways. Memory is not acceptable.
-
-Violating the letter = violating the spirit.
## When This Skill Applies
@@ -109,20 +100,6 @@ Implementation tasks per DESIGN.md Section 5
**Reverse escalation:** DESIGN.md spec incompatible with shadcn architecture β escalate to `hyperstack:designer` to reconcile. Don't silently adapt.
-## Red Flags - STOP
-
-| Thought | Reality |
-|---|---|
-| "User didn't say 'shadcn' explicitly, but I'll assume it" | Do NOT assume. Ask or check designer Q11. |
-| "I know the shadcn rules from training data" | Training data has standard shadcn (Radix). This is Base UI edition. Call `shadcn_get_rules`. |
-| "data-slot is just a naming convention" | It's the primary styling selector for parentβchild styling. Mandatory. |
-| "I'll use Radix because it's more common" | Project chose Base UI. Use `@base-ui/react`. |
-| "Hardcoding pixel positions is faster" | Use Base UI props. Hardcoded px breaks responsive behavior. |
-| "This Dialog has 5 slots, I'll combine into one component" | Split into sub-components. Monolithic Dialogs are anti-pattern. |
-| "I'll skip 'use client' since it seems stateless" | Does it use `data-open` or any state modifier? β needs `'use client'`. Check before skipping. |
-| "The cn utility is optional" | Mandatory. All className merging goes through `cn`. |
-| "I'll pick variant names that match the brand" | Stick to `default/outline/secondary/ghost/destructive`. Custom variants break the system. |
-| "shadcn components work with any color system" | OKLCH-native. Hex values break the token system. |
## Lifecycle Integration
diff --git a/skills/ship-gate/SKILL.md b/skills/ship-gate/SKILL.md
index bc3ac3c..bdb6782 100644
--- a/skills/ship-gate/SKILL.md
+++ b/skills/ship-gate/SKILL.md
@@ -1,99 +1,57 @@
---
name: ship-gate
category: core
-description: Use before claiming any work is complete, fixed, or passing. Run the verification command and show output before making any success claim.
+description: Execute before claiming work is complete, fixed, or passing. Run the verification command and show output. No evidence = no claim.
---
# Verification Before Completion
-## The Iron Law
-
-```
-NO COMPLETION CLAIMS WITHOUT FRESH VERIFICATION EVIDENCE.
-```
-
-Not run in this message β cannot claim it passes. Claiming completion without evidence = dishonesty.
-
-Violating the letter = violating the spirit.
## The Gate
```
-1. IDENTIFY β What command proves this claim?
-2. RUN β Execute it fresh. Not from memory. Not from a prior run.
-3. READ β Full output. Exit code. Error count. Every line.
-4. VERIFY β Does output confirm the claim?
- NO β State actual status with evidence
- YES β State claim WITH evidence attached
+1. IDENTIFY β Which command proves this claim?
+2. RUN β Execute it fresh. Not from memory.
+3. READ β Full output. Exit code. Error count.
+4. VERIFY β Output confirms claim?
+ NO β State status + provide evidence.
+ YES β State claim + provide evidence.
5. CLAIM β Only now.
```
-Skipping any step = lying, not verifying.
-
-**Evidence must be visible in this message.** Not "I ran the command." Not "I checked earlier." Actual command output pasted into this message. No output = no claim.
+Skipping steps = lying.
+**Evidence MUST be visible.** Paste actual command output. "I ran the command" is unacceptable. No output = no claim.
## Evidence Format
-### For test claims:
-```
-β
Tests pass:
-
-$ npm test
-PASS src/components/__tests__/Button.test.tsx
- Button
- β renders with label (5ms)
- β handles click event (3ms)
-
-Tests: 3 passed, 3 total
-```
-
-### For type checks:
-```
-β
Types check:
-
-$ tsc --noEmit
-[no output = success]
-```
-
-### For build claims:
-```
-β
Build succeeds:
-
-$ npm run build
-[build output showing exit 0]
-```
-
-### For MCP-verified patterns:
-```
-β
Code matches MCP output:
-
-MCP tool: reactflow_get_api(Handle)
-Output: props = { children, position, type }
+Show output in message:
-Code:
-```
+**Tests:** `$ npm test` β `Tests: 3 passed, 3 total`
+**Types:** `$ tsc --noEmit` β `[no output = success]`
+**Build:** `$ npm run build` β `[exit 0]`
+**MCP:** Code block must explicitly match specific MCP tool response.
-Cannot show evidence β cannot make the claim.
+Cannot show evidence β cannot make claim.
## Verification Map
| Claim | Required | Not sufficient |
|---|---|---|
-| Tests pass | Test command output showing 0 failures | "Should pass", previous run, looking at the code |
-| Build succeeds | Build command: exit 0 | Linter passing, "no obvious errors" |
-| Bug is fixed | Reproduce original symptom: now passes | Code changed, "logically fixed" |
+| Tests pass | Test command output showing 0 failures | "Should pass", previous run |
+| Build succeeds | Build command: exit 0 | Linter passing |
+| Bug is fixed | Reproduce original symptom: now passes | "Logically fixed" |
| Type checks | `tsc --noEmit`: 0 errors | "Looks typed correctly" |
-| MCP data applied correctly | Code matches MCP output shown in session | "I followed the pattern" |
-| Requirements met | Line-by-line checklist against the spec | Tests passing |
-| Subagent completed | VCS diff confirms actual changes | Subagent reports "done" |
-| Regression covered | Red-green cycle verified | "I wrote a test for it" |
-| **DESIGN.md compliance** | **Implementation matches all 10 DESIGN.md sections. All component states present. No anti-patterns from Section 10.** | **"Looks right", "follows the design"** |
+| MCP pattern | Code matches current session MCP output | "Following pattern" |
+| Requirements | Line-by-line checklist against spec | Tests passing |
+| Subagent done | VCS diff confirms actual changes | Subagent reports "done" |
+| Regression | Red-green cycle verified | "I wrote a test" |
+| **DESIGN compliance** | **Implementation matches all 10 sections.** | **"Looks right"** |
-## DESIGN.md Compliance Gate (visual/UX tasks only)
+## DESIGN.md Compliance Gate (Visual/UX)
-If DESIGN.md exists in the repo, completion claim must pass this gate:
+If DESIGN.md exists, completion requires this gate:
-### Step 1: Run Automated Compliance Checker
+### Step 1: Automated Checker
```bash
designer_verify_implementation(
@@ -105,96 +63,37 @@ designer_verify_implementation(
| DESIGN.md Section | What the tool checks |
|---|---|
| 2. Color Palette | All OKLCH tokens present. Contrast >= WCAG AA. |
-| 3. Typography | Font family loaded. Type scale tokens defined. Tracking/line-height match DESIGN.md. |
-| 4. Spacing | Spacing tokens on 4px grid. No arbitrary pixel values. |
-| 5. Components | ALL required states present (default/hover/focus/active/disabled/loading). Semantic HTML used. |
-| 6. Motion | `prefers-reduced-motion` respected. No `linear` easing. No `> 500ms` UI transitions. |
-| 7. Elevation | Shadow tokens defined. Z-index uses named scale (no `9999`). |
-| 8. Do's and Don'ts | Each Do/Don't from DESIGN.md checked against code. None violated. |
-| 9. Responsive | Layout tested at 375/768/1024/1440px. No horizontal scroll. Prose max-width 65ch. |
-| 10. Anti-Patterns | No AI slop: no `#6366F1`, no `font-weight: 500` everywhere, no missing states, no `animate-bounce` on static, no 3+ font families, no `rgba(0,0,0)` shadows. |
+| 3. Typography | Fonts loaded. Scale defined. Tracking matches. |
+| 4. Spacing | 4px grid. No arbitrary pixels. |
+| 5. Components | ALL states (default/hover/focus/active/disabled/loading). |
+| 6. Motion | `prefers-reduced-motion`. No `linear`. Transitions < 500ms. |
+| 7. Elevation | Shadow tokens defined. Z-index uses scale. |
+| 8. Do's and Don'ts | Each rule checked against code. |
+| 9. Responsive | 375/768/1024/1440px tested. Prose <= 65ch. |
+| 10. Anti-Patterns | No `#6366F1`, no `500` weight everywhere, no `rgba` shadows. |
-### Step 2: Show the Tool Output
+### Step 2: Show Output
-```
-β
DESIGN.md Compliance Check:
-
-Section 1 (Theme): PASS
-Section 2 (Colors): PASS - all OKLCH tokens present
-Section 3 (Typography): PASS - fonts loaded, scale defined
-Section 4 (Spacing): PASS - 4px grid enforced
-Section 5 (Components): PASS - all states present
-Section 6 (Motion): PASS - prefers-reduced-motion respected
-Section 7 (Elevation): PASS - shadow/z-index tokens used
-Section 8 (Do's/Don'ts): PASS - no violations
-Section 9 (Responsive): PASS - tested at all breakpoints
-Section 10 (Anti-Patterns): PASS - no slop detected
-```
+Paste the `designer_verify_implementation` output block representing PASS on all 10 sections.
### Step 3: Handle Failures
-Any section fails β do NOT claim completion.
-- Option A: Fix the code to pass the check
-- Option B: Escalate to `hyperstack:designer` to revise DESIGN.md if the design was wrong
+Any section fails β DO NOT claim completion.
+- Option A: Fix code.
+- Option B: Escalate to `designer` to revise DESIGN.md.
-DESIGN.md doesn't exist for a visual task β process failure upstream. Stop and invoke `hyperstack:designer` before shipping anything.
+No DESIGN.md on visual task? Stop. Invoke `designer`.
-## Red Flags - STOP
-| Thought | Reality |
-|---|---|
-| "Should work now" | "Should" β evidence. Run the command. |
-| "I'm confident in this change" | Confidence β evidence. Run the command. |
-| "Subagent said it's done" | Subagents lie. Check the VCS diff. Run the tests. |
-| "Minor change, no need to recheck" | Minor changes cause regressions. Run the command. |
-| "Tests were passing before my change" | Irrelevant. Run them again now. |
-| "MCP tool confirmed the pattern" | Confirms the pattern, not that your code is correct. Run the command. |
-| "I'll verify after I push" | After you push it's in CI. Verify BEFORE. |
-| "I already ran it earlier this conversation" | State drifts. Run it again. |
-| "The linter is passing" | Linter β compiler β runtime. Run the full verification. |
-| "Partial check is enough" | Partial verification = theater. Full check. |
-| "I ran the tests, they passed" (no output shown) | Evidence not shown = claim not made. Paste the full output. |
-| "The code looks correct" (claiming DESIGN.md compliance) | Looks β verification. Run `designer_verify_implementation`. Show tool output. |
-| "I did the DESIGN.md checks manually" | Manual checks miss edge cases. Use the automated tool. |
-| "DESIGN.md doesn't exist yet, I'll implement first" | DESIGN.md is a blocker. Invoke `hyperstack:designer` before writing CSS/components. |
-| "Just this once" | No exceptions. |
-
-## Integration
-
-Run this skill before:
-- Any `git commit` or PR creation
-- Marking any task as complete
-- Reporting status to the user
-- Claiming a bug is fixed
-- Handing work off to a subagent or reviewer
-- Transitioning between phases in `hyperstack:engineering-discipline`
-
-
-## Lifecycle Integration
-
-### Agent Workflow Chains
+## Lifecycle
**All execution paths converge here:**
-```
-[autonomous-mode | subagent-ops | engineering-discipline] β ship-gate (THIS) β deliver
-```
-
-**DESIGN.md compliance (visual/UX only):**
-```
-ship-gate β designer_verify_implementation β [PASS β deliver | FAIL β fix or escalate]
-```
+`[autonomous-mode | subagent-ops | engineering-discipline] β ship-gate (THIS) β deliver`
-### Upstream Dependencies
-- `autonomous-mode` β final gate before delivery
-- `subagent-ops` β final gate after all tasks
-- `engineering-discipline` β per-task + final gate
+**DESIGN.md flow:**
+`ship-gate β designer_verify_implementation β [PASS β deliver | FAIL β fix/escalate]`
-### Downstream Consumers
-- `deliver` β only proceeds if ship-gate passes
-
-### Escalation Paths
-| Failure | Escalate to | Action |
-|---|---|---|
-| DESIGN.md compliance fails | `designer` | Fix code or revise DESIGN.md |
-| Tests fail | `debug-discipline` β fix β re-run ship-gate |
-| Type/lint errors | Fix β re-run ship-gate |
+**Escalations:**
+- DESIGN.md check fails β `designer`
+- Tests fail β `debug-discipline`
+- Type/lint errors β Fix β re-run ship-gate
diff --git a/skills/subagent-ops/SKILL.md b/skills/subagent-ops/SKILL.md
index ca0eb17..b7fda99 100644
--- a/skills/subagent-ops/SKILL.md
+++ b/skills/subagent-ops/SKILL.md
@@ -103,17 +103,6 @@ Good subagent prompts are:
Bad: "Fix the tests" (too broad)
Good: "Fix the 3 failing tests in `src/flow/nodes.test.ts`. Root cause is [X]. Expected: all pass. Return: summary of changes."
-## Red Flags - STOP
-
-| Thought | Reality |
-|---|---|
-| "I'll dispatch multiple implementers in parallel" | They'll conflict on shared files. One at a time. |
-| "Skip spec review, the code looks fine" | Spec drift is invisible without review. |
-| "Start code quality before spec compliance" | Wrong order. Spec first, quality second. |
-| "Subagent said done, move on" | Verify with review. Trust but verify. |
-| "I'll fix it myself instead of re-dispatching" | Context pollution. Dispatch a fix subagent. |
-| "This task is too small for the full cycle" | Small tasks still get spec + quality review. |
-| "Let the subagent read the plan file" | Provide full text. File reads waste subagent context. |
## Integration
diff --git a/skills/test-first/SKILL.md b/skills/test-first/SKILL.md
index 71e0a1e..a59dc4f 100644
--- a/skills/test-first/SKILL.md
+++ b/skills/test-first/SKILL.md
@@ -6,15 +6,6 @@ description: Use when implementing any feature, bug fix, or behaviour change - b
# Test-First Development
-## The Iron Law
-
-```
-NO PRODUCTION CODE WITHOUT A FAILING TEST FIRST.
-```
-
-Wrote code before the test? Delete it. Start over. Don't keep it as "reference." Don't "adapt" it while writing tests. Delete means delete.
-
-Violating the letter = violating the spirit.
## When to Use
@@ -105,20 +96,10 @@ Before marking work complete:
Can't check all boxes? β You skipped TDD. Start over.
-## Red Flags - STOP
+## The Rule
+
+No production code without a failing test first. Delete code written before the test β don't keep it as "reference".
-| Thought | Reality |
-|---|---|
-| "Too simple to test" | Simple code breaks. Test takes 30 seconds. |
-| "I'll test after" | Tests passing immediately prove nothing. |
-| "Tests after achieve the same goals" | Tests-after = "what does this do?" Tests-first = "what should this do?" |
-| "I already manually tested it" | Ad-hoc β systematic. No record, can't re-run. |
-| "Deleting X hours of work is wasteful" | Sunk cost fallacy. Keeping unverified code = debt. |
-| "Keep as reference, write tests first" | You'll adapt it. That's testing after. Delete means delete. |
-| "Need to explore first" | Fine. Throw away exploration, then start with TDD. |
-| "Test is hard to write = skip it" | Hard to test = hard to use. Simplify the interface. |
-| "TDD will slow me down" | TDD is faster than debugging. Always. |
-| "This is different because..." | No it isn't. Write the test. |
## Integration
diff --git a/skills/testing-skills/SKILL.md b/skills/testing-skills/SKILL.md
index 7b20f2b..8a0b83b 100644
--- a/skills/testing-skills/SKILL.md
+++ b/skills/testing-skills/SKILL.md
@@ -6,15 +6,6 @@ description: Use when creating or editing Hyperstack skills, before shipping the
# Testing Skills With Subagents
-## The Iron Law
-
-```
-NO SKILL SHIPS WITHOUT SUBAGENT PRESSURE TEST EVIDENCE
-```
-
-A skill that has not been tested against an adversarial subagent is a paper contract. If you have not watched a subagent try to rationalize its way out of your skill AND fail, you do not know if the skill works.
-
-**Violating the letter of this rule is violating the spirit of this rule.**
## Core Principle
diff --git a/skills/worktree-isolation/SKILL.md b/skills/worktree-isolation/SKILL.md
index 22f0692..da855eb 100644
--- a/skills/worktree-isolation/SKILL.md
+++ b/skills/worktree-isolation/SKILL.md
@@ -109,14 +109,6 @@ git worktree remove
# Leave worktree in place, report its location
```
-## Red Flags - STOP
-
-| Thought | Reality |
-|---|---|
-| "I'll just work on the main branch" | Dirty state β mysterious failures. Isolate. |
-| "Worktree setup is overhead" | 30 seconds of setup prevents hours of state debugging. |
-| "I'll skip baseline tests" | Won't know if failures are yours or pre-existing. |
-| "The directory doesn't need to be ignored" | One `git add .` and the worktree is in your repo. |
## Integration
From 48cd59dcb3467766a3ec1a2174a7366188c26851 Mon Sep 17 00:00:00 2001
From: Kailas Mahavarkar <66670953+KailasMahavarkar@users.noreply.github.com>
Date: Sun, 19 Apr 2026 06:13:30 +0530
Subject: [PATCH 14/23] chore: restore baseline compatibility for routing plan
---
...-19-topology-routing-artifact-contracts.md | 697 ++++++++++++++++++
harness/context-policy.md | 5 +
harness/observability.md | 5 +
harness/router.md | 5 +
harness/transitions.md | 5 +
skills/designer/SKILL.md | 4 +-
6 files changed, 720 insertions(+), 1 deletion(-)
create mode 100644 docs/superpowers/plans/2026-04-19-topology-routing-artifact-contracts.md
create mode 100644 harness/context-policy.md
create mode 100644 harness/observability.md
create mode 100644 harness/router.md
create mode 100644 harness/transitions.md
diff --git a/docs/superpowers/plans/2026-04-19-topology-routing-artifact-contracts.md b/docs/superpowers/plans/2026-04-19-topology-routing-artifact-contracts.md
new file mode 100644
index 0000000..19889d2
--- /dev/null
+++ b/docs/superpowers/plans/2026-04-19-topology-routing-artifact-contracts.md
@@ -0,0 +1,697 @@
+# Topology Routing And Artifact Contracts Implementation Plan
+
+> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
+
+**Goal:** Make topology the active runtime authority for agent routing, skill enforcement, and typed artifact handoffs instead of passive configuration.
+
+**Architecture:** Extend the current topology manifest with artifact contract definitions and route policies, then build a runtime layer that can validate artifacts, choose the right agent for a request, enforce allowed skills/bundles, and expose those capabilities through new CLI commands. Keep existing local tool execution intact and layer routing on top of it rather than rewriting the tool bridge.
+
+**Tech Stack:** TypeScript, Bun, Zod, YAML, existing `src/engine/*`, existing `src/cli.ts`, generated topology/runtime artifacts, Bun test
+
+---
+
+## File Structure Lock-In
+
+### New Files
+
+- `topology/artifacts/task_handoff.yaml`
+- `topology/artifacts/design_contract.yaml`
+- `topology/artifacts/build_result.yaml`
+- `topology/artifacts/verification_report.yaml`
+- `topology/routes/defaults.yaml`
+- `src/engine/artifact-loader.ts`
+- `src/engine/artifact-validator.ts`
+- `src/engine/router.ts`
+- `src/engine/skill-enforcer.ts`
+- `tests/artifact-contracts-behaviour.test.ts`
+- `tests/router-behaviour.test.ts`
+- `tests/local-cli-routing-behaviour.test.ts`
+
+### Files To Modify
+
+- `topology/manifest.yaml`
+- `src/engine/contracts.ts`
+- `src/engine/topology-loader.ts`
+- `src/engine/policy.ts`
+- `src/engine/resolver.ts`
+- `src/engine/navigation.ts`
+- `src/cli.ts`
+- `scripts/generate-topology-artifacts.ts`
+- `generated/routing/allow-deny.md`
+- `generated/runtime-context/topology.bootstrap.md`
+- `tests/topology-artifacts-behaviour.test.ts`
+
+### Responsibility Boundaries
+
+- `topology/artifacts/` defines handoff schemas and proof expectations.
+- `topology/routes/` defines request-to-agent defaults and domain preference rules.
+- `src/engine/artifact-*` owns schema loading and validation only.
+- `src/engine/router.ts` owns agent selection and strictest-proof computation.
+- `src/engine/skill-enforcer.ts` owns allowed-skill checks for an already-routed agent.
+- `src/cli.ts` remains a thin transport layer over engine functions.
+
+---
+
+### Task 1: Add Artifact Definitions To Topology And Load Them
+
+**Files:**
+- Modify: `topology/manifest.yaml`
+- Create: `topology/artifacts/task_handoff.yaml`
+- Create: `topology/artifacts/design_contract.yaml`
+- Create: `topology/artifacts/build_result.yaml`
+- Create: `topology/artifacts/verification_report.yaml`
+- Create: `topology/routes/defaults.yaml`
+- Modify: `src/engine/contracts.ts`
+- Modify: `src/engine/topology-loader.ts`
+- Test: `tests/topology-manifest-behaviour.test.ts`
+
+- [ ] **Step 1: Extend the failing topology test with artifact and route expectations**
+
+```ts
+import { expect, test } from "bun:test";
+import { loadTopology } from "../src/engine/topology-loader.ts";
+
+test("loadTopology reads artifact contracts and route defaults", () => {
+ const topology = loadTopology(process.cwd());
+
+ expect(topology.artifacts.map((a) => a.id)).toEqual([
+ "task_handoff",
+ "design_contract",
+ "build_result",
+ "verification_report",
+ ]);
+ expect(topology.routeDefaults.defaultAgent).toBe("hyper");
+ expect(topology.routeDefaults.domainPreference.frontend).toBe("frontend-builder");
+});
+```
+
+- [ ] **Step 2: Run the focused test to verify it fails**
+
+Run: `bun test tests/topology-manifest-behaviour.test.ts`
+Expected: FAIL with `Cannot read properties of undefined` for `topology.artifacts` or `topology.routeDefaults`
+
+- [ ] **Step 3: Add artifact and route files**
+
+```yaml
+# topology/artifacts/task_handoff.yaml
+id: task_handoff
+required_fields:
+ - request_id
+ - domain_targets
+ - capability_targets
+ - success_criteria
+proof_mode: routing_only
+```
+
+```yaml
+# topology/artifacts/design_contract.yaml
+id: design_contract
+required_fields:
+ - visual_theme
+ - color_system
+ - typography
+ - spacing
+ - component_states
+ - motion_rules
+proof_mode: visual_contract
+```
+
+```yaml
+# topology/routes/defaults.yaml
+default_agent: hyper
+domain_preference:
+ frontend: frontend-builder
+ backend: backend-builder
+ shared: hyper
+cross_domain_agent: fullstack-builder
+strictest_proof_order:
+ - routing_and_verification
+ - executable
+ - visual_and_behavioral
+```
+
+- [ ] **Step 4: Extend topology contracts**
+
+```ts
+// src/engine/contracts.ts
+export interface ArtifactContract {
+ id: string;
+ requiredFields: string[];
+ proofMode: string;
+}
+
+export interface RouteDefaults {
+ defaultAgent: string;
+ domainPreference: Record;
+ crossDomainAgent: string;
+ strictestProofOrder: string[];
+}
+
+export interface LoadedTopology {
+ version: 1;
+ defaultTransport: "local-tools";
+ entryAgent: string;
+ domains: DomainPolicy[];
+ agents: AgentPolicy[];
+ bundles: BundlePolicy[];
+ artifacts: ArtifactContract[];
+ routeDefaults: RouteDefaults;
+}
+```
+
+- [ ] **Step 5: Extend the loader to read artifacts and route defaults**
+
+```ts
+// src/engine/topology-loader.ts
+interface ArtifactDocument {
+ id: string;
+ required_fields: string[];
+ proof_mode: string;
+}
+
+interface RouteDefaultsDocument {
+ default_agent: string;
+ domain_preference: Record;
+ cross_domain_agent: string;
+ strictest_proof_order: string[];
+}
+
+function mapArtifactDocument(doc: ArtifactDocument): ArtifactContract {
+ return {
+ id: doc.id,
+ requiredFields: doc.required_fields,
+ proofMode: doc.proof_mode,
+ };
+}
+
+function mapRouteDefaultsDocument(doc: RouteDefaultsDocument): RouteDefaults {
+ return {
+ defaultAgent: doc.default_agent,
+ domainPreference: doc.domain_preference,
+ crossDomainAgent: doc.cross_domain_agent,
+ strictestProofOrder: doc.strictest_proof_order,
+ };
+}
+
+const artifacts = ["task_handoff", "design_contract", "build_result", "verification_report"].map((id) =>
+ mapArtifactDocument(readYaml(join(repoRoot, "topology", "artifacts", `${id}.yaml`))),
+);
+const routeDefaults = mapRouteDefaultsDocument(
+ readYaml(join(repoRoot, "topology", "routes", "defaults.yaml")),
+);
+```
+
+- [ ] **Step 6: Run the topology test and typecheck**
+
+Run: `bun test tests/topology-manifest-behaviour.test.ts && bun run build`
+Expected: PASS, with artifact and route-default assertions green
+
+- [ ] **Step 7: Commit**
+
+```bash
+git add topology/manifest.yaml topology/artifacts topology/routes src/engine/contracts.ts src/engine/topology-loader.ts tests/topology-manifest-behaviour.test.ts
+git commit -m "feat: add topology artifact contracts and route defaults"
+```
+
+---
+
+### Task 2: Implement Typed Artifact Validation
+
+**Files:**
+- Create: `src/engine/artifact-loader.ts`
+- Create: `src/engine/artifact-validator.ts`
+- Test: `tests/artifact-contracts-behaviour.test.ts`
+
+- [ ] **Step 1: Write the failing artifact validation test**
+
+```ts
+import { expect, test } from "bun:test";
+import { loadTopology } from "../src/engine/topology-loader.ts";
+import { validateArtifactPayload } from "../src/engine/artifact-validator.ts";
+
+test("validateArtifactPayload accepts a complete task_handoff", () => {
+ const topology = loadTopology(process.cwd());
+ const result = validateArtifactPayload(topology, "task_handoff", {
+ request_id: "req-1",
+ domain_targets: ["frontend"],
+ capability_targets: ["design.intent"],
+ success_criteria: ["produce design contract"],
+ });
+
+ expect(result.ok).toBe(true);
+});
+
+test("validateArtifactPayload rejects missing design_contract fields", () => {
+ const topology = loadTopology(process.cwd());
+ const result = validateArtifactPayload(topology, "design_contract", {
+ visual_theme: "dark",
+ color_system: "brand + neutral",
+ });
+
+ expect(result.ok).toBe(false);
+ expect(result.missingFields).toContain("typography");
+ expect(result.missingFields).toContain("component_states");
+});
+```
+
+- [ ] **Step 2: Run the artifact test to verify it fails**
+
+Run: `bun test tests/artifact-contracts-behaviour.test.ts`
+Expected: FAIL with `Cannot find module "../src/engine/artifact-validator.ts"`
+
+- [ ] **Step 3: Add the artifact loader**
+
+```ts
+// src/engine/artifact-loader.ts
+import type { ArtifactContract, LoadedTopology } from "./contracts.js";
+
+export function getArtifactContract(topology: LoadedTopology, artifactId: string): ArtifactContract {
+ const artifact = topology.artifacts.find((entry) => entry.id === artifactId);
+ if (!artifact) {
+ throw new Error(`Unknown artifact contract: ${artifactId}`);
+ }
+ return artifact;
+}
+```
+
+- [ ] **Step 4: Implement payload validation**
+
+```ts
+// src/engine/artifact-validator.ts
+import { getArtifactContract } from "./artifact-loader.js";
+import type { LoadedTopology } from "./contracts.js";
+
+export function validateArtifactPayload(
+ topology: LoadedTopology,
+ artifactId: string,
+ payload: Record,
+) {
+ const contract = getArtifactContract(topology, artifactId);
+ const missingFields = contract.requiredFields.filter((field) => !(field in payload));
+
+ return {
+ ok: missingFields.length === 0,
+ artifactId,
+ proofMode: contract.proofMode,
+ missingFields,
+ };
+}
+```
+
+- [ ] **Step 5: Run artifact validation tests and build**
+
+Run: `bun test tests/artifact-contracts-behaviour.test.ts && bun run build`
+Expected: PASS
+
+- [ ] **Step 6: Commit**
+
+```bash
+git add src/engine/artifact-loader.ts src/engine/artifact-validator.ts tests/artifact-contracts-behaviour.test.ts
+git commit -m "feat: add typed artifact validation"
+```
+
+---
+
+### Task 3: Add Topology Router With Strictest-Proof Resolution
+
+**Files:**
+- Create: `src/engine/router.ts`
+- Modify: `src/engine/policy.ts`
+- Test: `tests/router-behaviour.test.ts`
+
+- [ ] **Step 1: Write the failing router test**
+
+```ts
+import { expect, test } from "bun:test";
+import { loadTopology } from "../src/engine/topology-loader.ts";
+import { routeRequest } from "../src/engine/router.ts";
+
+test("routeRequest sends frontend-only work to frontend-builder", () => {
+ const topology = loadTopology(process.cwd());
+ const route = routeRequest(topology, {
+ requestId: "req-1",
+ domainTargets: ["frontend"],
+ capabilityTargets: ["design.intent"],
+ });
+
+ expect(route.agent.id).toBe("frontend-builder");
+ expect(route.proofMode).toBe("visual_and_behavioral");
+});
+
+test("routeRequest sends mixed frontend+backend work to fullstack-builder", () => {
+ const topology = loadTopology(process.cwd());
+ const route = routeRequest(topology, {
+ requestId: "req-2",
+ domainTargets: ["frontend", "backend"],
+ capabilityTargets: ["design.intent", "backend.http.patterns"],
+ });
+
+ expect(route.agent.id).toBe("fullstack-builder");
+ expect(route.proofMode).toBe("visual_and_behavioral");
+});
+```
+
+- [ ] **Step 2: Run the router test to verify it fails**
+
+Run: `bun test tests/router-behaviour.test.ts`
+Expected: FAIL with `Cannot find module "../src/engine/router.ts"`
+
+- [ ] **Step 3: Add proof-order helper to policy**
+
+```ts
+// src/engine/policy.ts
+export function getStrictestProofMode(order: string[], proofModes: string[]): string {
+ const ranked = proofModes
+ .map((mode) => ({ mode, index: order.indexOf(mode) }))
+ .filter((entry) => entry.index >= 0)
+ .sort((left, right) => right.index - left.index);
+
+ if (ranked.length === 0) {
+ throw new Error(`No proof mode could be ranked from: ${proofModes.join(", ")}`);
+ }
+
+ return ranked[0].mode;
+}
+```
+
+- [ ] **Step 4: Implement route resolution**
+
+```ts
+// src/engine/router.ts
+import type { LoadedTopology } from "./contracts.js";
+import { getAgent, getDomain, getStrictestProofMode } from "./policy.js";
+
+export function routeRequest(
+ topology: LoadedTopology,
+ input: {
+ requestId: string;
+ domainTargets: string[];
+ capabilityTargets: string[];
+ },
+) {
+ const uniqueDomains = [...new Set(input.domainTargets)];
+ const routeAgentId =
+ uniqueDomains.length > 1
+ ? topology.routeDefaults.crossDomainAgent
+ : topology.routeDefaults.domainPreference[uniqueDomains[0] ?? "shared"] ?? topology.routeDefaults.defaultAgent;
+
+ const agent = getAgent(topology, routeAgentId);
+ const proofMode = getStrictestProofMode(
+ topology.routeDefaults.strictestProofOrder,
+ uniqueDomains.map((domainId) => getDomain(topology, domainId).completionProof),
+ );
+
+ return {
+ requestId: input.requestId,
+ agent,
+ proofMode,
+ domains: uniqueDomains,
+ capabilityTargets: input.capabilityTargets,
+ };
+}
+```
+
+- [ ] **Step 5: Run routing tests and build**
+
+Run: `bun test tests/router-behaviour.test.ts && bun run build`
+Expected: PASS
+
+- [ ] **Step 6: Commit**
+
+```bash
+git add src/engine/policy.ts src/engine/router.ts tests/router-behaviour.test.ts
+git commit -m "feat: add topology router with strictest proof resolution"
+```
+
+---
+
+### Task 4: Enforce Allowed Skills For Routed Agents
+
+**Files:**
+- Create: `src/engine/skill-enforcer.ts`
+- Modify: `src/engine/router.ts`
+- Test: `tests/router-behaviour.test.ts`
+
+- [ ] **Step 1: Extend the router test with skill enforcement**
+
+```ts
+import { expect, test } from "bun:test";
+import { loadTopology } from "../src/engine/topology-loader.ts";
+import { assertSkillAllowedForAgent } from "../src/engine/skill-enforcer.ts";
+import { routeRequest } from "../src/engine/router.ts";
+
+test("assertSkillAllowedForAgent rejects backend-only review skill on frontend-builder", () => {
+ const topology = loadTopology(process.cwd());
+ const route = routeRequest(topology, {
+ requestId: "req-3",
+ domainTargets: ["frontend"],
+ capabilityTargets: ["design.intent"],
+ });
+
+ expect(() => assertSkillAllowedForAgent(route.agent, "security-review")).toThrow(/not allowed/i);
+});
+
+test("assertSkillAllowedForAgent accepts designer for frontend-builder", () => {
+ const topology = loadTopology(process.cwd());
+ const route = routeRequest(topology, {
+ requestId: "req-4",
+ domainTargets: ["frontend"],
+ capabilityTargets: ["design.intent"],
+ });
+
+ expect(() => assertSkillAllowedForAgent(route.agent, "designer")).not.toThrow();
+});
+```
+
+- [ ] **Step 2: Run the router test to verify it fails**
+
+Run: `bun test tests/router-behaviour.test.ts`
+Expected: FAIL with `Cannot find module "../src/engine/skill-enforcer.ts"`
+
+- [ ] **Step 3: Add the skill enforcer**
+
+```ts
+// src/engine/skill-enforcer.ts
+import type { AgentPolicy } from "./contracts.js";
+
+export function assertSkillAllowedForAgent(agent: AgentPolicy, skillName: string): void {
+ if (!agent.allowedSkills.includes(skillName)) {
+ throw new Error(`Skill ${skillName} is not allowed for agent ${agent.id}`);
+ }
+}
+```
+
+- [ ] **Step 4: Run tests and build**
+
+Run: `bun test tests/router-behaviour.test.ts && bun run build`
+Expected: PASS
+
+- [ ] **Step 5: Commit**
+
+```bash
+git add src/engine/skill-enforcer.ts tests/router-behaviour.test.ts
+git commit -m "feat: enforce allowed skills for routed agents"
+```
+
+---
+
+### Task 5: Expose Routing And Artifact Validation Through CLI
+
+**Files:**
+- Modify: `src/cli.ts`
+- Test: `tests/local-cli-routing-behaviour.test.ts`
+
+- [ ] **Step 1: Write the failing CLI routing test**
+
+```ts
+import { expect, test } from "bun:test";
+import { spawnSync } from "node:child_process";
+import { resolve } from "node:path";
+
+test("CLI route command returns the routed agent and proof mode", () => {
+ const result = spawnSync(
+ process.execPath,
+ [
+ resolve("bin/hyperstack.mjs"),
+ "route",
+ "--json",
+ '{"requestId":"req-1","domainTargets":["frontend"],"capabilityTargets":["design.intent"]}',
+ ],
+ { cwd: process.cwd(), encoding: "utf8" },
+ );
+
+ expect(result.status).toBe(0);
+ expect(result.stdout).toMatch(/frontend-builder/);
+ expect(result.stdout).toMatch(/visual_and_behavioral/);
+});
+
+test("CLI artifact validate command reports missing fields", () => {
+ const result = spawnSync(
+ process.execPath,
+ [
+ resolve("bin/hyperstack.mjs"),
+ "artifact",
+ "validate",
+ "design_contract",
+ "--json",
+ '{"visual_theme":"dark"}',
+ ],
+ { cwd: process.cwd(), encoding: "utf8" },
+ );
+
+ expect(result.status).toBe(0);
+ expect(result.stdout).toMatch(/missingFields/);
+ expect(result.stdout).toMatch(/typography/);
+});
+```
+
+- [ ] **Step 2: Run the CLI test to verify it fails**
+
+Run: `bun test tests/local-cli-routing-behaviour.test.ts`
+Expected: FAIL because `src/cli.ts` only supports `tool`
+
+- [ ] **Step 3: Extend `src/cli.ts`**
+
+```ts
+// src/cli.ts
+import { loadTopology } from "./engine/topology-loader.js";
+import { routeRequest } from "./engine/router.js";
+import { validateArtifactPayload } from "./engine/artifact-validator.js";
+import { invokeLocalTool } from "./adapters/local-tools/index.js";
+
+const topology = loadTopology(process.cwd());
+
+if (command === "tool") {
+ // existing path unchanged
+}
+
+if (command === "route" && flag === "--json" && json) {
+ const input = JSON.parse(json) as {
+ requestId: string;
+ domainTargets: string[];
+ capabilityTargets: string[];
+ };
+ process.stdout.write(`${JSON.stringify(routeRequest(topology, input), null, 2)}\n`);
+ process.exit(0);
+}
+
+if (command === "artifact" && process.argv[3] === "validate") {
+ const artifactId = process.argv[4];
+ const jsonFlag = process.argv[5];
+ const jsonPayload = process.argv[6];
+ const payload = JSON.parse(jsonPayload) as Record;
+ process.stdout.write(
+ `${JSON.stringify(validateArtifactPayload(topology, artifactId, payload), null, 2)}\n`,
+ );
+ process.exit(0);
+}
+```
+
+- [ ] **Step 4: Run CLI routing tests and build**
+
+Run: `bun test tests/local-cli-routing-behaviour.test.ts && bun run build`
+Expected: PASS
+
+- [ ] **Step 5: Commit**
+
+```bash
+git add src/cli.ts tests/local-cli-routing-behaviour.test.ts
+git commit -m "feat: expose topology routing and artifact validation via cli"
+```
+
+---
+
+### Task 6: Regenerate Topology Artifacts To Include Artifacts And Routing Rules
+
+**Files:**
+- Modify: `scripts/generate-topology-artifacts.ts`
+- Modify: `tests/topology-artifacts-behaviour.test.ts`
+- Modify: `generated/routing/allow-deny.md`
+- Modify: `generated/runtime-context/topology.bootstrap.md`
+
+- [ ] **Step 1: Extend the failing topology artifact test**
+
+```ts
+import { expect, test } from "bun:test";
+import { readFileSync } from "node:fs";
+import { resolve } from "node:path";
+
+test("generated topology bootstrap includes artifact and route defaults", () => {
+ const bootstrap = readFileSync(resolve("generated/runtime-context/topology.bootstrap.md"), "utf8");
+ expect(bootstrap).toMatch(/task_handoff/);
+ expect(bootstrap).toMatch(/design_contract/);
+ expect(bootstrap).toMatch(/cross-domain agent: fullstack-builder/);
+});
+```
+
+- [ ] **Step 2: Run the artifact test to verify it fails**
+
+Run: `bun test tests/topology-artifacts-behaviour.test.ts`
+Expected: FAIL because the generator does not emit artifact or route sections yet
+
+- [ ] **Step 3: Extend the generator**
+
+```ts
+// scripts/generate-topology-artifacts.ts
+writeFileSync(
+ resolve("generated/runtime-context/topology.bootstrap.md"),
+ [
+ "# Topology Runtime Bootstrap",
+ "",
+ `Entry agent: ${topology.entryAgent}`,
+ `Cross-domain agent: ${topology.routeDefaults.crossDomainAgent}`,
+ "",
+ "## Artifacts",
+ ...topology.artifacts.map((artifact) => `- ${artifact.id}: ${artifact.proofMode}`),
+ "",
+ "## Agents",
+ ...topology.agents.map((agent) => `- ${agent.id}: ${agent.kind} -> ${agent.domains.join(", ")}`),
+ "",
+ "## Bundles",
+ ...topology.bundles.map((bundle) => `- ${bundle.id}: ${bundle.capabilities.join(", ")}`),
+ "",
+ ].join("\n"),
+);
+```
+
+- [ ] **Step 4: Regenerate and verify**
+
+Run: `bun run generate:topology && bun test tests/topology-artifacts-behaviour.test.ts && bun run build`
+Expected: PASS
+
+- [ ] **Step 5: Commit**
+
+```bash
+git add scripts/generate-topology-artifacts.ts generated/routing/allow-deny.md generated/runtime-context/topology.bootstrap.md tests/topology-artifacts-behaviour.test.ts
+git commit -m "feat: generate topology route and artifact summaries"
+```
+
+---
+
+## Spec Coverage Check
+
+- Topology becomes active runtime authority: covered by Tasks 3, 4, and 5.
+- Typed artifact contracts: covered by Tasks 1 and 2.
+- Strictest touched-domain proof model: covered by Task 3.
+- Skill enforcement by routed agent: covered by Task 4.
+- CLI/runtime exposure for routing and validation: covered by Task 5.
+- Generated topology artifacts expanded to reflect the new runtime semantics: covered by Task 6.
+
+## Placeholder Scan
+
+- No `TBD`, `TODO`, or deferred implementation placeholders are present.
+- Every code-touching step contains concrete code.
+- Every verification step includes an exact command and expected outcome.
+
+## Type Consistency Check
+
+- Artifact IDs are consistently `task_handoff`, `design_contract`, `build_result`, `verification_report`.
+- Agent IDs stay `hyper`, `frontend-builder`, `backend-builder`, `fullstack-builder`.
+- Bundle IDs stay `shared.system`, `frontend.design`, `frontend.react`, `backend.http`, `backend.lang.go`, `backend.lang.rust`.
+- Proof mode names stay `routing_and_verification`, `executable`, `visual_and_behavioral`.
+
+## Notes For Execution
+
+- Keep using the existing local tool runtime from the previous phase; this plan adds routing/validation above it.
+- Do not migrate deep corpus content in this phase; use topology authority first, corpus migration later.
+- Keep commits small and phase-aligned exactly as listed.
diff --git a/harness/context-policy.md b/harness/context-policy.md
new file mode 100644
index 0000000..aefd284
--- /dev/null
+++ b/harness/context-policy.md
@@ -0,0 +1,5 @@
+# Harness Context Policy
+
+Compatibility shim for legacy path.
+
+Canonical document: [docs/harness/context-policy.md](../docs/harness/context-policy.md)
diff --git a/harness/observability.md b/harness/observability.md
new file mode 100644
index 0000000..25aefc5
--- /dev/null
+++ b/harness/observability.md
@@ -0,0 +1,5 @@
+# Harness Observability
+
+Compatibility shim for legacy path.
+
+Canonical document: [docs/harness/observability.md](../docs/harness/observability.md)
diff --git a/harness/router.md b/harness/router.md
new file mode 100644
index 0000000..32a4257
--- /dev/null
+++ b/harness/router.md
@@ -0,0 +1,5 @@
+# Harness Router
+
+Compatibility shim for legacy path.
+
+Canonical document: [docs/harness/router.md](../docs/harness/router.md)
diff --git a/harness/transitions.md b/harness/transitions.md
new file mode 100644
index 0000000..cc456ca
--- /dev/null
+++ b/harness/transitions.md
@@ -0,0 +1,5 @@
+# Harness Transitions
+
+Compatibility shim for legacy path.
+
+Canonical document: [docs/harness/transitions.md](../docs/harness/transitions.md)
diff --git a/skills/designer/SKILL.md b/skills/designer/SKILL.md
index bb9d156..1da06f9 100644
--- a/skills/designer/SKILL.md
+++ b/skills/designer/SKILL.md
@@ -78,6 +78,8 @@ Inside ``, you must answer:
**Step 1:** Use `designer_resolve_intent` (or read `references/questions.md`).
**Step 2:** Ensure you know the Product, Brand Color, Target Audience, Emotional Target, and Component Library (e.g., shadcn vs raw Tailwind).
+User preferences override auto-resolved defaults. Auto-resolved defaults are suggestions, not authority.
+
---
# PHASE 2: DESIGN SYSTEM RESOLUTION
@@ -143,4 +145,4 @@ Call `shadcn_get_rules` FIRST. `shadcn_get_composition`, `shadcn_list_components
**To `hyperstack:ship-gate`:**
DESIGN.md acts as absolute ground truth for testing expected behaviours, states, animations, and non-slop compliance.
-**Announce invocation:** *"Using hyperstack:designer - stepping into Creative Director persona to produce DESIGN.md."*
\ No newline at end of file
+**Announce invocation:** *"Using hyperstack:designer - stepping into Creative Director persona to produce DESIGN.md."*
From f4baf8856b7cc3c9503ca3dae80a5584cf85bb6b Mon Sep 17 00:00:00 2001
From: Kailas Mahavarkar <66670953+KailasMahavarkar@users.noreply.github.com>
Date: Sun, 19 Apr 2026 06:42:15 +0530
Subject: [PATCH 15/23] feat: add workspace-first artifact contracts and route
defaults
---
...-19-topology-routing-artifact-contracts.md | 296 ++++++++++++------
src/engine/contracts.ts | 18 ++
src/engine/topology-loader.ts | 54 +++-
tests/topology-manifest-behaviour.test.ts | 16 +
topology/artifacts/build_result.yaml | 6 +
topology/artifacts/design_contract.yaml | 9 +
topology/artifacts/task_handoff.yaml | 10 +
topology/artifacts/verification_report.yaml | 6 +
topology/artifacts/workspace_inventory.yaml | 9 +
topology/manifest.yaml | 6 +
topology/routes/defaults.yaml | 15 +
11 files changed, 353 insertions(+), 92 deletions(-)
create mode 100644 topology/artifacts/build_result.yaml
create mode 100644 topology/artifacts/design_contract.yaml
create mode 100644 topology/artifacts/task_handoff.yaml
create mode 100644 topology/artifacts/verification_report.yaml
create mode 100644 topology/artifacts/workspace_inventory.yaml
create mode 100644 topology/routes/defaults.yaml
diff --git a/docs/superpowers/plans/2026-04-19-topology-routing-artifact-contracts.md b/docs/superpowers/plans/2026-04-19-topology-routing-artifact-contracts.md
index 19889d2..875cb11 100644
--- a/docs/superpowers/plans/2026-04-19-topology-routing-artifact-contracts.md
+++ b/docs/superpowers/plans/2026-04-19-topology-routing-artifact-contracts.md
@@ -1,12 +1,12 @@
-# Topology Routing And Artifact Contracts Implementation Plan
+# Workspace-First Topology Routing And Artifact Contracts Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
-**Goal:** Make topology the active runtime authority for agent routing, skill enforcement, and typed artifact handoffs instead of passive configuration.
+**Goal:** Make topology the active runtime authority for workspace-aware routing, conditional design contracts, skill enforcement, and typed artifact handoffs.
-**Architecture:** Extend the current topology manifest with artifact contract definitions and route policies, then build a runtime layer that can validate artifacts, choose the right agent for a request, enforce allowed skills/bundles, and expose those capabilities through new CLI commands. Keep existing local tool execution intact and layer routing on top of it rather than rewriting the tool bridge.
+**Architecture:** Extend topology with universal planning artifacts and route defaults, then build a runtime layer that validates artifacts, routes requests based on domain plus workspace reality, computes required artifacts, and exposes those results through the CLI. `workspace_inventory` is universal, `design_contract` is conditional, `verification_report` is universal.
-**Tech Stack:** TypeScript, Bun, Zod, YAML, existing `src/engine/*`, existing `src/cli.ts`, generated topology/runtime artifacts, Bun test
+**Tech Stack:** TypeScript, Bun, YAML, existing `src/engine/*`, existing `src/cli.ts`, generated topology/runtime artifacts, Bun test
---
@@ -14,6 +14,7 @@
### New Files
+- `topology/artifacts/workspace_inventory.yaml`
- `topology/artifacts/task_handoff.yaml`
- `topology/artifacts/design_contract.yaml`
- `topology/artifacts/build_result.yaml`
@@ -33,29 +34,29 @@
- `src/engine/contracts.ts`
- `src/engine/topology-loader.ts`
- `src/engine/policy.ts`
-- `src/engine/resolver.ts`
- `src/engine/navigation.ts`
- `src/cli.ts`
- `scripts/generate-topology-artifacts.ts`
-- `generated/routing/allow-deny.md`
- `generated/runtime-context/topology.bootstrap.md`
+- `generated/routing/allow-deny.md`
- `tests/topology-artifacts-behaviour.test.ts`
### Responsibility Boundaries
-- `topology/artifacts/` defines handoff schemas and proof expectations.
-- `topology/routes/` defines request-to-agent defaults and domain preference rules.
-- `src/engine/artifact-*` owns schema loading and validation only.
-- `src/engine/router.ts` owns agent selection and strictest-proof computation.
-- `src/engine/skill-enforcer.ts` owns allowed-skill checks for an already-routed agent.
-- `src/cli.ts` remains a thin transport layer over engine functions.
+- `workspace_inventory` is mandatory for any routed work.
+- `design_contract` is conditional and only required for new surfaces or visual-semantic changes.
+- `verification_report` remains mandatory before completion claims.
+- `src/engine/router.ts` owns route choice and required-artifact computation.
+- `src/engine/skill-enforcer.ts` owns allowed-skill checks for a routed agent.
+- `src/cli.ts` is transport only. No policy logic belongs there.
---
-### Task 1: Add Artifact Definitions To Topology And Load Them
+### Task 1: Add Workspace-First Artifact Contracts And Route Defaults
**Files:**
- Modify: `topology/manifest.yaml`
+- Create: `topology/artifacts/workspace_inventory.yaml`
- Create: `topology/artifacts/task_handoff.yaml`
- Create: `topology/artifacts/design_contract.yaml`
- Create: `topology/artifacts/build_result.yaml`
@@ -65,32 +66,48 @@
- Modify: `src/engine/topology-loader.ts`
- Test: `tests/topology-manifest-behaviour.test.ts`
-- [ ] **Step 1: Extend the failing topology test with artifact and route expectations**
+- [ ] **Step 1: Extend the failing topology test**
```ts
import { expect, test } from "bun:test";
import { loadTopology } from "../src/engine/topology-loader.ts";
-test("loadTopology reads artifact contracts and route defaults", () => {
+test("loadTopology reads workspace-first artifacts and route defaults", () => {
const topology = loadTopology(process.cwd());
expect(topology.artifacts.map((a) => a.id)).toEqual([
+ "workspace_inventory",
"task_handoff",
"design_contract",
"build_result",
"verification_report",
]);
expect(topology.routeDefaults.defaultAgent).toBe("hyper");
+ expect(topology.routeDefaults.requiresWorkspaceInventory).toBe(true);
expect(topology.routeDefaults.domainPreference.frontend).toBe("frontend-builder");
+ expect(topology.routeDefaults.designContractRequiredWhen).toContain("new_surface");
});
```
-- [ ] **Step 2: Run the focused test to verify it fails**
+- [ ] **Step 2: Run the test to verify it fails**
Run: `bun test tests/topology-manifest-behaviour.test.ts`
-Expected: FAIL with `Cannot read properties of undefined` for `topology.artifacts` or `topology.routeDefaults`
+Expected: FAIL with `topology.artifacts` or `topology.routeDefaults` missing
-- [ ] **Step 3: Add artifact and route files**
+- [ ] **Step 3: Add topology YAMLs**
+
+```yaml
+# topology/artifacts/workspace_inventory.yaml
+id: workspace_inventory
+required_fields:
+ - repo_type
+ - stack
+ - touched_surfaces
+ - existing_patterns
+ - verification_commands
+ - project_mode
+proof_mode: discovery_only
+```
```yaml
# topology/artifacts/task_handoff.yaml
@@ -100,6 +117,9 @@ required_fields:
- domain_targets
- capability_targets
- success_criteria
+ - change_classification
+ - requires_design_contract
+ - required_artifacts
proof_mode: routing_only
```
@@ -113,24 +133,29 @@ required_fields:
- spacing
- component_states
- motion_rules
-proof_mode: visual_contract
+proof_mode: visual_contract_conditional
```
```yaml
# topology/routes/defaults.yaml
default_agent: hyper
+requires_workspace_inventory: true
domain_preference:
frontend: frontend-builder
backend: backend-builder
shared: hyper
cross_domain_agent: fullstack-builder
+design_contract_required_when:
+ - new_surface
+ - visual_semantic_change
+ - no_existing_pattern_match
strictest_proof_order:
- routing_and_verification
- executable
- visual_and_behavioral
```
-- [ ] **Step 4: Extend topology contracts**
+- [ ] **Step 4: Extend contracts**
```ts
// src/engine/contracts.ts
@@ -142,11 +167,23 @@ export interface ArtifactContract {
export interface RouteDefaults {
defaultAgent: string;
+ requiresWorkspaceInventory: boolean;
domainPreference: Record;
crossDomainAgent: string;
+ designContractRequiredWhen: string[];
strictestProofOrder: string[];
}
+export interface TopologyRoot {
+ version: 1;
+ defaultTransport: "local-tools";
+ entryAgent: string;
+ domains: string[];
+ agents: string[];
+ bundles: string[];
+ artifacts: string[];
+}
+
export interface LoadedTopology {
version: 1;
defaultTransport: "local-tools";
@@ -159,7 +196,7 @@ export interface LoadedTopology {
}
```
-- [ ] **Step 5: Extend the loader to read artifacts and route defaults**
+- [ ] **Step 5: Extend the loader**
```ts
// src/engine/topology-loader.ts
@@ -171,8 +208,10 @@ interface ArtifactDocument {
interface RouteDefaultsDocument {
default_agent: string;
+ requires_workspace_inventory: boolean;
domain_preference: Record;
cross_domain_agent: string;
+ design_contract_required_when: string[];
strictest_proof_order: string[];
}
@@ -187,55 +226,52 @@ function mapArtifactDocument(doc: ArtifactDocument): ArtifactContract {
function mapRouteDefaultsDocument(doc: RouteDefaultsDocument): RouteDefaults {
return {
defaultAgent: doc.default_agent,
+ requiresWorkspaceInventory: doc.requires_workspace_inventory,
domainPreference: doc.domain_preference,
crossDomainAgent: doc.cross_domain_agent,
+ designContractRequiredWhen: doc.design_contract_required_when,
strictestProofOrder: doc.strictest_proof_order,
};
}
-
-const artifacts = ["task_handoff", "design_contract", "build_result", "verification_report"].map((id) =>
- mapArtifactDocument(readYaml(join(repoRoot, "topology", "artifacts", `${id}.yaml`))),
-);
-const routeDefaults = mapRouteDefaultsDocument(
- readYaml(join(repoRoot, "topology", "routes", "defaults.yaml")),
-);
```
-- [ ] **Step 6: Run the topology test and typecheck**
+- [ ] **Step 6: Run the test and typecheck**
Run: `bun test tests/topology-manifest-behaviour.test.ts && bun run build`
-Expected: PASS, with artifact and route-default assertions green
+Expected: PASS
- [ ] **Step 7: Commit**
```bash
git add topology/manifest.yaml topology/artifacts topology/routes src/engine/contracts.ts src/engine/topology-loader.ts tests/topology-manifest-behaviour.test.ts
-git commit -m "feat: add topology artifact contracts and route defaults"
+git commit -m "feat: add workspace-first artifact contracts and route defaults"
```
---
-### Task 2: Implement Typed Artifact Validation
+### Task 2: Implement Artifact Validation For Planning And Verification
**Files:**
- Create: `src/engine/artifact-loader.ts`
- Create: `src/engine/artifact-validator.ts`
- Test: `tests/artifact-contracts-behaviour.test.ts`
-- [ ] **Step 1: Write the failing artifact validation test**
+- [ ] **Step 1: Write the failing test**
```ts
import { expect, test } from "bun:test";
import { loadTopology } from "../src/engine/topology-loader.ts";
import { validateArtifactPayload } from "../src/engine/artifact-validator.ts";
-test("validateArtifactPayload accepts a complete task_handoff", () => {
+test("validateArtifactPayload accepts a complete workspace_inventory", () => {
const topology = loadTopology(process.cwd());
- const result = validateArtifactPayload(topology, "task_handoff", {
- request_id: "req-1",
- domain_targets: ["frontend"],
- capability_targets: ["design.intent"],
- success_criteria: ["produce design contract"],
+ const result = validateArtifactPayload(topology, "workspace_inventory", {
+ repo_type: "web-app",
+ stack: ["react", "tailwind"],
+ touched_surfaces: ["settings page"],
+ existing_patterns: ["shadcn form"],
+ verification_commands: ["bun test", "bun run build"],
+ project_mode: "existing",
});
expect(result.ok).toBe(true);
@@ -254,7 +290,7 @@ test("validateArtifactPayload rejects missing design_contract fields", () => {
});
```
-- [ ] **Step 2: Run the artifact test to verify it fails**
+- [ ] **Step 2: Run the test to verify it fails**
Run: `bun test tests/artifact-contracts-behaviour.test.ts`
Expected: FAIL with `Cannot find module "../src/engine/artifact-validator.ts"`
@@ -274,12 +310,12 @@ export function getArtifactContract(topology: LoadedTopology, artifactId: string
}
```
-- [ ] **Step 4: Implement payload validation**
+- [ ] **Step 4: Implement the validator**
```ts
// src/engine/artifact-validator.ts
-import { getArtifactContract } from "./artifact-loader.js";
import type { LoadedTopology } from "./contracts.js";
+import { getArtifactContract } from "./artifact-loader.js";
export function validateArtifactPayload(
topology: LoadedTopology,
@@ -298,7 +334,7 @@ export function validateArtifactPayload(
}
```
-- [ ] **Step 5: Run artifact validation tests and build**
+- [ ] **Step 5: Run tests and build**
Run: `bun test tests/artifact-contracts-behaviour.test.ts && bun run build`
Expected: PASS
@@ -307,43 +343,73 @@ Expected: PASS
```bash
git add src/engine/artifact-loader.ts src/engine/artifact-validator.ts tests/artifact-contracts-behaviour.test.ts
-git commit -m "feat: add typed artifact validation"
+git commit -m "feat: add artifact validation for planning and verification"
```
---
-### Task 3: Add Topology Router With Strictest-Proof Resolution
+### Task 3: Add Workspace-Aware Router With Conditional Design Contracts
**Files:**
- Create: `src/engine/router.ts`
- Modify: `src/engine/policy.ts`
- Test: `tests/router-behaviour.test.ts`
-- [ ] **Step 1: Write the failing router test**
+- [ ] **Step 1: Write the failing router tests**
```ts
import { expect, test } from "bun:test";
import { loadTopology } from "../src/engine/topology-loader.ts";
import { routeRequest } from "../src/engine/router.ts";
-test("routeRequest sends frontend-only work to frontend-builder", () => {
+test("routeRequest sends existing-project frontend logic work to frontend-builder without design contract", () => {
const topology = loadTopology(process.cwd());
const route = routeRequest(topology, {
requestId: "req-1",
domainTargets: ["frontend"],
+ capabilityTargets: ["frontend.patterns"],
+ workspaceInventory: {
+ projectMode: "existing",
+ existingPatterns: ["existing form shell"],
+ },
+ changeClassification: "frontend_logic",
+ });
+
+ expect(route.agent.id).toBe("frontend-builder");
+ expect(route.requiredArtifacts).toContain("workspace_inventory");
+ expect(route.requiredArtifacts).not.toContain("design_contract");
+});
+
+test("routeRequest requires design contract for a new visual surface", () => {
+ const topology = loadTopology(process.cwd());
+ const route = routeRequest(topology, {
+ requestId: "req-2",
+ domainTargets: ["frontend"],
capabilityTargets: ["design.intent"],
+ workspaceInventory: {
+ projectMode: "greenfield",
+ existingPatterns: [],
+ },
+ changeClassification: "frontend_visual",
});
expect(route.agent.id).toBe("frontend-builder");
+ expect(route.requiredArtifacts).toContain("workspace_inventory");
+ expect(route.requiredArtifacts).toContain("design_contract");
expect(route.proofMode).toBe("visual_and_behavioral");
});
test("routeRequest sends mixed frontend+backend work to fullstack-builder", () => {
const topology = loadTopology(process.cwd());
const route = routeRequest(topology, {
- requestId: "req-2",
+ requestId: "req-3",
domainTargets: ["frontend", "backend"],
- capabilityTargets: ["design.intent", "backend.http.patterns"],
+ capabilityTargets: ["frontend.patterns", "backend.http.patterns"],
+ workspaceInventory: {
+ projectMode: "existing",
+ existingPatterns: [],
+ },
+ changeClassification: "fullstack_slice",
});
expect(route.agent.id).toBe("fullstack-builder");
@@ -356,7 +422,7 @@ test("routeRequest sends mixed frontend+backend work to fullstack-builder", () =
Run: `bun test tests/router-behaviour.test.ts`
Expected: FAIL with `Cannot find module "../src/engine/router.ts"`
-- [ ] **Step 3: Add proof-order helper to policy**
+- [ ] **Step 3: Add a strictest-proof helper**
```ts
// src/engine/policy.ts
@@ -374,19 +440,38 @@ export function getStrictestProofMode(order: string[], proofModes: string[]): st
}
```
-- [ ] **Step 4: Implement route resolution**
+- [ ] **Step 4: Implement the router**
```ts
// src/engine/router.ts
import type { LoadedTopology } from "./contracts.js";
import { getAgent, getDomain, getStrictestProofMode } from "./policy.js";
+function shouldRequireDesignContract(input: {
+ changeClassification: string;
+ workspaceInventory: { projectMode: "greenfield" | "existing"; existingPatterns: string[] };
+}): boolean {
+ if (input.changeClassification !== "frontend_visual") {
+ return false;
+ }
+
+ return (
+ input.workspaceInventory.projectMode === "greenfield" ||
+ input.workspaceInventory.existingPatterns.length === 0
+ );
+}
+
export function routeRequest(
topology: LoadedTopology,
input: {
requestId: string;
domainTargets: string[];
capabilityTargets: string[];
+ workspaceInventory: {
+ projectMode: "greenfield" | "existing";
+ existingPatterns: string[];
+ };
+ changeClassification: string;
},
) {
const uniqueDomains = [...new Set(input.domainTargets)];
@@ -401,17 +486,26 @@ export function routeRequest(
uniqueDomains.map((domainId) => getDomain(topology, domainId).completionProof),
);
+ const requiredArtifacts = ["workspace_inventory", "task_handoff"];
+ const requiresDesignContract = shouldRequireDesignContract(input);
+
+ if (requiresDesignContract) {
+ requiredArtifacts.push("design_contract");
+ }
+
return {
requestId: input.requestId,
agent,
proofMode,
domains: uniqueDomains,
capabilityTargets: input.capabilityTargets,
+ requiredArtifacts,
+ requiresDesignContract,
};
}
```
-- [ ] **Step 5: Run routing tests and build**
+- [ ] **Step 5: Run router tests and build**
Run: `bun test tests/router-behaviour.test.ts && bun run build`
Expected: PASS
@@ -420,7 +514,7 @@ Expected: PASS
```bash
git add src/engine/policy.ts src/engine/router.ts tests/router-behaviour.test.ts
-git commit -m "feat: add topology router with strictest proof resolution"
+git commit -m "feat: add workspace-aware router with conditional design contracts"
```
---
@@ -429,23 +523,27 @@ git commit -m "feat: add topology router with strictest proof resolution"
**Files:**
- Create: `src/engine/skill-enforcer.ts`
-- Modify: `src/engine/router.ts`
- Test: `tests/router-behaviour.test.ts`
-- [ ] **Step 1: Extend the router test with skill enforcement**
+- [ ] **Step 1: Extend the failing router test**
```ts
import { expect, test } from "bun:test";
import { loadTopology } from "../src/engine/topology-loader.ts";
-import { assertSkillAllowedForAgent } from "../src/engine/skill-enforcer.ts";
import { routeRequest } from "../src/engine/router.ts";
+import { assertSkillAllowedForAgent } from "../src/engine/skill-enforcer.ts";
test("assertSkillAllowedForAgent rejects backend-only review skill on frontend-builder", () => {
const topology = loadTopology(process.cwd());
const route = routeRequest(topology, {
- requestId: "req-3",
+ requestId: "req-4",
domainTargets: ["frontend"],
- capabilityTargets: ["design.intent"],
+ capabilityTargets: ["frontend.patterns"],
+ workspaceInventory: {
+ projectMode: "existing",
+ existingPatterns: ["existing form shell"],
+ },
+ changeClassification: "frontend_logic",
});
expect(() => assertSkillAllowedForAgent(route.agent, "security-review")).toThrow(/not allowed/i);
@@ -454,9 +552,14 @@ test("assertSkillAllowedForAgent rejects backend-only review skill on frontend-b
test("assertSkillAllowedForAgent accepts designer for frontend-builder", () => {
const topology = loadTopology(process.cwd());
const route = routeRequest(topology, {
- requestId: "req-4",
+ requestId: "req-5",
domainTargets: ["frontend"],
capabilityTargets: ["design.intent"],
+ workspaceInventory: {
+ projectMode: "greenfield",
+ existingPatterns: [],
+ },
+ changeClassification: "frontend_visual",
});
expect(() => assertSkillAllowedForAgent(route.agent, "designer")).not.toThrow();
@@ -495,7 +598,7 @@ git commit -m "feat: enforce allowed skills for routed agents"
---
-### Task 5: Expose Routing And Artifact Validation Through CLI
+### Task 5: Expose Routing And Artifact Validation Through The CLI
**Files:**
- Modify: `src/cli.ts`
@@ -508,21 +611,22 @@ import { expect, test } from "bun:test";
import { spawnSync } from "node:child_process";
import { resolve } from "node:path";
-test("CLI route command returns the routed agent and proof mode", () => {
+test("CLI route command returns routed agent and required artifacts", () => {
const result = spawnSync(
process.execPath,
[
resolve("bin/hyperstack.mjs"),
"route",
"--json",
- '{"requestId":"req-1","domainTargets":["frontend"],"capabilityTargets":["design.intent"]}',
+ '{"requestId":"req-1","domainTargets":["frontend"],"capabilityTargets":["frontend.patterns"],"workspaceInventory":{"projectMode":"existing","existingPatterns":["existing form shell"]},"changeClassification":"frontend_logic"}',
],
{ cwd: process.cwd(), encoding: "utf8" },
);
expect(result.status).toBe(0);
expect(result.stdout).toMatch(/frontend-builder/);
- expect(result.stdout).toMatch(/visual_and_behavioral/);
+ expect(result.stdout).toMatch(/workspace_inventory/);
+ expect(result.stdout).not.toMatch(/design_contract/);
});
test("CLI artifact validate command reports missing fields", () => {
@@ -532,16 +636,16 @@ test("CLI artifact validate command reports missing fields", () => {
resolve("bin/hyperstack.mjs"),
"artifact",
"validate",
- "design_contract",
+ "workspace_inventory",
"--json",
- '{"visual_theme":"dark"}',
+ '{"repo_type":"web-app"}',
],
{ cwd: process.cwd(), encoding: "utf8" },
);
expect(result.status).toBe(0);
expect(result.stdout).toMatch(/missingFields/);
- expect(result.stdout).toMatch(/typography/);
+ expect(result.stdout).toMatch(/stack/);
});
```
@@ -550,7 +654,7 @@ test("CLI artifact validate command reports missing fields", () => {
Run: `bun test tests/local-cli-routing-behaviour.test.ts`
Expected: FAIL because `src/cli.ts` only supports `tool`
-- [ ] **Step 3: Extend `src/cli.ts`**
+- [ ] **Step 3: Extend the CLI**
```ts
// src/cli.ts
@@ -562,7 +666,7 @@ import { invokeLocalTool } from "./adapters/local-tools/index.js";
const topology = loadTopology(process.cwd());
if (command === "tool") {
- // existing path unchanged
+ // existing path
}
if (command === "route" && flag === "--json" && json) {
@@ -570,7 +674,10 @@ if (command === "route" && flag === "--json" && json) {
requestId: string;
domainTargets: string[];
capabilityTargets: string[];
+ workspaceInventory: { projectMode: "greenfield" | "existing"; existingPatterns: string[] };
+ changeClassification: string;
};
+
process.stdout.write(`${JSON.stringify(routeRequest(topology, input), null, 2)}\n`);
process.exit(0);
}
@@ -579,15 +686,19 @@ if (command === "artifact" && process.argv[3] === "validate") {
const artifactId = process.argv[4];
const jsonFlag = process.argv[5];
const jsonPayload = process.argv[6];
+
+ if (jsonFlag !== "--json" || !artifactId || !jsonPayload) {
+ process.stderr.write("Usage: hyperstack artifact validate --json '{...}'\n");
+ process.exit(1);
+ }
+
const payload = JSON.parse(jsonPayload) as Record;
- process.stdout.write(
- `${JSON.stringify(validateArtifactPayload(topology, artifactId, payload), null, 2)}\n`,
- );
+ process.stdout.write(`${JSON.stringify(validateArtifactPayload(topology, artifactId, payload), null, 2)}\n`);
process.exit(0);
}
```
-- [ ] **Step 4: Run CLI routing tests and build**
+- [ ] **Step 4: Run CLI tests and build**
Run: `bun test tests/local-cli-routing-behaviour.test.ts && bun run build`
Expected: PASS
@@ -596,18 +707,18 @@ Expected: PASS
```bash
git add src/cli.ts tests/local-cli-routing-behaviour.test.ts
-git commit -m "feat: expose topology routing and artifact validation via cli"
+git commit -m "feat: expose routing and artifact validation via cli"
```
---
-### Task 6: Regenerate Topology Artifacts To Include Artifacts And Routing Rules
+### Task 6: Regenerate Topology Summaries With Workspace-First Rules
**Files:**
- Modify: `scripts/generate-topology-artifacts.ts`
- Modify: `tests/topology-artifacts-behaviour.test.ts`
-- Modify: `generated/routing/allow-deny.md`
- Modify: `generated/runtime-context/topology.bootstrap.md`
+- Modify: `generated/routing/allow-deny.md`
- [ ] **Step 1: Extend the failing topology artifact test**
@@ -616,18 +727,19 @@ import { expect, test } from "bun:test";
import { readFileSync } from "node:fs";
import { resolve } from "node:path";
-test("generated topology bootstrap includes artifact and route defaults", () => {
+test("generated topology bootstrap includes workspace-first routing markers", () => {
const bootstrap = readFileSync(resolve("generated/runtime-context/topology.bootstrap.md"), "utf8");
- expect(bootstrap).toMatch(/task_handoff/);
+ expect(bootstrap).toMatch(/workspace_inventory/);
expect(bootstrap).toMatch(/design_contract/);
- expect(bootstrap).toMatch(/cross-domain agent: fullstack-builder/);
+ expect(bootstrap).toMatch(/design contract is conditional/i);
+ expect(bootstrap).toMatch(/cross-domain agent: fullstack-builder/i);
});
```
- [ ] **Step 2: Run the artifact test to verify it fails**
Run: `bun test tests/topology-artifacts-behaviour.test.ts`
-Expected: FAIL because the generator does not emit artifact or route sections yet
+Expected: FAIL because current topology summaries do not include workspace-first routing markers
- [ ] **Step 3: Extend the generator**
@@ -640,6 +752,8 @@ writeFileSync(
"",
`Entry agent: ${topology.entryAgent}`,
`Cross-domain agent: ${topology.routeDefaults.crossDomainAgent}`,
+ `Workspace inventory required: ${topology.routeDefaults.requiresWorkspaceInventory}`,
+ "Design contract is conditional",
"",
"## Artifacts",
...topology.artifacts.map((artifact) => `- ${artifact.id}: ${artifact.proofMode}`),
@@ -662,20 +776,20 @@ Expected: PASS
- [ ] **Step 5: Commit**
```bash
-git add scripts/generate-topology-artifacts.ts generated/routing/allow-deny.md generated/runtime-context/topology.bootstrap.md tests/topology-artifacts-behaviour.test.ts
-git commit -m "feat: generate topology route and artifact summaries"
+git add scripts/generate-topology-artifacts.ts generated/runtime-context/topology.bootstrap.md generated/routing/allow-deny.md tests/topology-artifacts-behaviour.test.ts
+git commit -m "feat: generate workspace-first topology summaries"
```
---
## Spec Coverage Check
-- Topology becomes active runtime authority: covered by Tasks 3, 4, and 5.
-- Typed artifact contracts: covered by Tasks 1 and 2.
+- Workspace-first planning: covered by Tasks 1, 2, 3, and 5.
+- Conditional `design_contract` for existing projects: covered by Tasks 3, 5, and 6.
+- Universal `verification_report`: preserved by route and artifact model.
- Strictest touched-domain proof model: covered by Task 3.
-- Skill enforcement by routed agent: covered by Task 4.
+- Skill allow/deny enforcement: covered by Task 4.
- CLI/runtime exposure for routing and validation: covered by Task 5.
-- Generated topology artifacts expanded to reflect the new runtime semantics: covered by Task 6.
## Placeholder Scan
@@ -685,13 +799,13 @@ git commit -m "feat: generate topology route and artifact summaries"
## Type Consistency Check
-- Artifact IDs are consistently `task_handoff`, `design_contract`, `build_result`, `verification_report`.
-- Agent IDs stay `hyper`, `frontend-builder`, `backend-builder`, `fullstack-builder`.
-- Bundle IDs stay `shared.system`, `frontend.design`, `frontend.react`, `backend.http`, `backend.lang.go`, `backend.lang.rust`.
+- Artifact IDs are consistently `workspace_inventory`, `task_handoff`, `design_contract`, `build_result`, `verification_report`.
+- Route inputs consistently use `workspaceInventory` and `changeClassification`.
- Proof mode names stay `routing_and_verification`, `executable`, `visual_and_behavioral`.
+- Agent IDs stay `hyper`, `frontend-builder`, `backend-builder`, `fullstack-builder`.
## Notes For Execution
-- Keep using the existing local tool runtime from the previous phase; this plan adds routing/validation above it.
-- Do not migrate deep corpus content in this phase; use topology authority first, corpus migration later.
-- Keep commits small and phase-aligned exactly as listed.
+- Do not force `design_contract` for every frontend request.
+- Treat client existing-project work as workspace-first by default.
+- Keep local tool execution intact; this phase layers routing and planning logic above it.
diff --git a/src/engine/contracts.ts b/src/engine/contracts.ts
index fd19f39..5e1ee59 100644
--- a/src/engine/contracts.ts
+++ b/src/engine/contracts.ts
@@ -5,6 +5,7 @@ export interface TopologyRoot {
domains: string[];
agents: string[];
bundles: string[];
+ artifacts: string[];
}
export interface DomainPolicy {
@@ -38,6 +39,21 @@ export interface BundlePolicy {
outputContracts: string[];
}
+export interface ArtifactContract {
+ id: string;
+ requiredFields: string[];
+ proofMode: string;
+}
+
+export interface RouteDefaults {
+ defaultAgent: string;
+ requiresWorkspaceInventory: boolean;
+ domainPreference: Record;
+ crossDomainAgent: string;
+ designContractRequiredWhen: string[];
+ strictestProofOrder: string[];
+}
+
export interface LoadedTopology {
version: 1;
defaultTransport: "local-tools";
@@ -45,4 +61,6 @@ export interface LoadedTopology {
domains: DomainPolicy[];
agents: AgentPolicy[];
bundles: BundlePolicy[];
+ artifacts: ArtifactContract[];
+ routeDefaults: RouteDefaults;
}
diff --git a/src/engine/topology-loader.ts b/src/engine/topology-loader.ts
index fc93dba..7e5bc0c 100644
--- a/src/engine/topology-loader.ts
+++ b/src/engine/topology-loader.ts
@@ -1,7 +1,15 @@
import { readFileSync } from "node:fs";
import { join } from "node:path";
import YAML from "yaml";
-import type { AgentPolicy, BundlePolicy, DomainPolicy, LoadedTopology, TopologyRoot } from "./contracts.js";
+import type {
+ AgentPolicy,
+ ArtifactContract,
+ BundlePolicy,
+ DomainPolicy,
+ LoadedTopology,
+ RouteDefaults,
+ TopologyRoot,
+} from "./contracts.js";
interface RootDocument {
version: 1;
@@ -10,6 +18,7 @@ interface RootDocument {
domains: string[];
agents: string[];
bundles: string[];
+ artifacts: string[];
}
interface DomainDocument {
@@ -43,6 +52,21 @@ interface BundleDocument {
output_contracts: string[];
}
+interface ArtifactDocument {
+ id: string;
+ required_fields: string[];
+ proof_mode: string;
+}
+
+interface RouteDefaultsDocument {
+ default_agent: string;
+ requires_workspace_inventory: boolean;
+ domain_preference: Record;
+ cross_domain_agent: string;
+ design_contract_required_when: string[];
+ strictest_proof_order: string[];
+}
+
function readYaml(filePath: string): T {
return YAML.parse(readFileSync(filePath, "utf8")) as T;
}
@@ -55,6 +79,7 @@ function mapRootDocument(root: RootDocument): TopologyRoot {
domains: root.domains,
agents: root.agents,
bundles: root.bundles,
+ artifacts: root.artifacts,
};
}
@@ -95,6 +120,25 @@ function mapBundleDocument(bundle: BundleDocument): BundlePolicy {
};
}
+function mapArtifactDocument(doc: ArtifactDocument): ArtifactContract {
+ return {
+ id: doc.id,
+ requiredFields: doc.required_fields,
+ proofMode: doc.proof_mode,
+ };
+}
+
+function mapRouteDefaultsDocument(doc: RouteDefaultsDocument): RouteDefaults {
+ return {
+ defaultAgent: doc.default_agent,
+ requiresWorkspaceInventory: doc.requires_workspace_inventory,
+ domainPreference: doc.domain_preference,
+ crossDomainAgent: doc.cross_domain_agent,
+ designContractRequiredWhen: doc.design_contract_required_when,
+ strictestProofOrder: doc.strictest_proof_order,
+ };
+}
+
export function loadTopology(repoRoot: string): LoadedTopology {
const root = mapRootDocument(readYaml(join(repoRoot, "topology", "manifest.yaml")));
const domains = root.domains.map((id) =>
@@ -106,6 +150,12 @@ export function loadTopology(repoRoot: string): LoadedTopology {
const bundles = root.bundles.map((id) =>
mapBundleDocument(readYaml(join(repoRoot, "topology", "bundles", `${id}.yaml`))),
);
+ const artifacts = root.artifacts.map((id) =>
+ mapArtifactDocument(readYaml(join(repoRoot, "topology", "artifacts", `${id}.yaml`))),
+ );
+ const routeDefaults = mapRouteDefaultsDocument(
+ readYaml(join(repoRoot, "topology", "routes", "defaults.yaml")),
+ );
return {
version: root.version,
@@ -114,5 +164,7 @@ export function loadTopology(repoRoot: string): LoadedTopology {
domains,
agents,
bundles,
+ artifacts,
+ routeDefaults,
};
}
diff --git a/tests/topology-manifest-behaviour.test.ts b/tests/topology-manifest-behaviour.test.ts
index b340fa6..617c85c 100644
--- a/tests/topology-manifest-behaviour.test.ts
+++ b/tests/topology-manifest-behaviour.test.ts
@@ -33,3 +33,19 @@ test("resolveCapabilityContext returns frontend.design for design.intent", () =>
expect(result.bundle.id).toBe("frontend.design");
expect(result.domain.id).toBe("frontend");
});
+
+test("loadTopology reads artifact contracts and route defaults", () => {
+ const topology = loadTopology(process.cwd());
+
+ expect(topology.artifacts.map((a) => a.id)).toEqual([
+ "workspace_inventory",
+ "task_handoff",
+ "design_contract",
+ "build_result",
+ "verification_report",
+ ]);
+ expect(topology.routeDefaults.defaultAgent).toBe("hyper");
+ expect(topology.routeDefaults.requiresWorkspaceInventory).toBe(true);
+ expect(topology.routeDefaults.domainPreference.frontend).toBe("frontend-builder");
+ expect(topology.routeDefaults.designContractRequiredWhen).toContain("new_surface");
+});
diff --git a/topology/artifacts/build_result.yaml b/topology/artifacts/build_result.yaml
new file mode 100644
index 0000000..fa068f1
--- /dev/null
+++ b/topology/artifacts/build_result.yaml
@@ -0,0 +1,6 @@
+id: build_result
+required_fields:
+ - agent_id
+ - changed_files
+ - verification_commands
+proof_mode: executable
diff --git a/topology/artifacts/design_contract.yaml b/topology/artifacts/design_contract.yaml
new file mode 100644
index 0000000..0189b9e
--- /dev/null
+++ b/topology/artifacts/design_contract.yaml
@@ -0,0 +1,9 @@
+id: design_contract
+required_fields:
+ - visual_theme
+ - color_system
+ - typography
+ - spacing
+ - component_states
+ - motion_rules
+proof_mode: visual_contract_conditional
diff --git a/topology/artifacts/task_handoff.yaml b/topology/artifacts/task_handoff.yaml
new file mode 100644
index 0000000..11c4035
--- /dev/null
+++ b/topology/artifacts/task_handoff.yaml
@@ -0,0 +1,10 @@
+id: task_handoff
+required_fields:
+ - request_id
+ - domain_targets
+ - capability_targets
+ - success_criteria
+ - change_classification
+ - requires_design_contract
+ - required_artifacts
+proof_mode: routing_only
diff --git a/topology/artifacts/verification_report.yaml b/topology/artifacts/verification_report.yaml
new file mode 100644
index 0000000..7dbb04e
--- /dev/null
+++ b/topology/artifacts/verification_report.yaml
@@ -0,0 +1,6 @@
+id: verification_report
+required_fields:
+ - status
+ - proof_mode
+ - covered_paths
+proof_mode: routing_and_verification
diff --git a/topology/artifacts/workspace_inventory.yaml b/topology/artifacts/workspace_inventory.yaml
new file mode 100644
index 0000000..637a712
--- /dev/null
+++ b/topology/artifacts/workspace_inventory.yaml
@@ -0,0 +1,9 @@
+id: workspace_inventory
+required_fields:
+ - repo_type
+ - stack
+ - touched_surfaces
+ - existing_patterns
+ - verification_commands
+ - project_mode
+proof_mode: discovery_only
diff --git a/topology/manifest.yaml b/topology/manifest.yaml
index 98f5d2d..3569f0a 100644
--- a/topology/manifest.yaml
+++ b/topology/manifest.yaml
@@ -17,3 +17,9 @@ bundles:
- backend.http
- backend.lang.go
- backend.lang.rust
+artifacts:
+ - workspace_inventory
+ - task_handoff
+ - design_contract
+ - build_result
+ - verification_report
diff --git a/topology/routes/defaults.yaml b/topology/routes/defaults.yaml
new file mode 100644
index 0000000..1d8dc52
--- /dev/null
+++ b/topology/routes/defaults.yaml
@@ -0,0 +1,15 @@
+default_agent: hyper
+requires_workspace_inventory: true
+domain_preference:
+ frontend: frontend-builder
+ backend: backend-builder
+ shared: hyper
+cross_domain_agent: fullstack-builder
+design_contract_required_when:
+ - new_surface
+ - visual_semantic_change
+ - no_existing_pattern_match
+strictest_proof_order:
+ - routing_and_verification
+ - executable
+ - visual_and_behavioral
From 09968a253d326f18a7242c8110af4b6253affa22 Mon Sep 17 00:00:00 2001
From: Kailas Mahavarkar <66670953+KailasMahavarkar@users.noreply.github.com>
Date: Sun, 19 Apr 2026 06:42:53 +0530
Subject: [PATCH 16/23] feat: add artifact validation for planning and
verification
---
src/engine/artifact-loader.ts | 9 +++++++
src/engine/artifact-validator.ts | 18 ++++++++++++++
tests/artifact-contracts-behaviour.test.ts | 29 ++++++++++++++++++++++
3 files changed, 56 insertions(+)
create mode 100644 src/engine/artifact-loader.ts
create mode 100644 src/engine/artifact-validator.ts
create mode 100644 tests/artifact-contracts-behaviour.test.ts
diff --git a/src/engine/artifact-loader.ts b/src/engine/artifact-loader.ts
new file mode 100644
index 0000000..c137985
--- /dev/null
+++ b/src/engine/artifact-loader.ts
@@ -0,0 +1,9 @@
+import type { ArtifactContract, LoadedTopology } from "./contracts.js";
+
+export function getArtifactContract(topology: LoadedTopology, artifactId: string): ArtifactContract {
+ const artifact = topology.artifacts.find((entry) => entry.id === artifactId);
+ if (!artifact) {
+ throw new Error(`Unknown artifact contract: ${artifactId}`);
+ }
+ return artifact;
+}
diff --git a/src/engine/artifact-validator.ts b/src/engine/artifact-validator.ts
new file mode 100644
index 0000000..d8a43ee
--- /dev/null
+++ b/src/engine/artifact-validator.ts
@@ -0,0 +1,18 @@
+import type { LoadedTopology } from "./contracts.js";
+import { getArtifactContract } from "./artifact-loader.js";
+
+export function validateArtifactPayload(
+ topology: LoadedTopology,
+ artifactId: string,
+ payload: Record,
+) {
+ const contract = getArtifactContract(topology, artifactId);
+ const missingFields = contract.requiredFields.filter((field) => !(field in payload));
+
+ return {
+ ok: missingFields.length === 0,
+ artifactId,
+ proofMode: contract.proofMode,
+ missingFields,
+ };
+}
diff --git a/tests/artifact-contracts-behaviour.test.ts b/tests/artifact-contracts-behaviour.test.ts
new file mode 100644
index 0000000..8e82acf
--- /dev/null
+++ b/tests/artifact-contracts-behaviour.test.ts
@@ -0,0 +1,29 @@
+import { expect, test } from "bun:test";
+import { loadTopology } from "../src/engine/topology-loader.ts";
+import { validateArtifactPayload } from "../src/engine/artifact-validator.ts";
+
+test("validateArtifactPayload accepts a complete workspace_inventory", () => {
+ const topology = loadTopology(process.cwd());
+ const result = validateArtifactPayload(topology, "workspace_inventory", {
+ repo_type: "web-app",
+ stack: ["react", "tailwind"],
+ touched_surfaces: ["settings page"],
+ existing_patterns: ["shadcn form"],
+ verification_commands: ["bun test", "bun run build"],
+ project_mode: "existing",
+ });
+
+ expect(result.ok).toBe(true);
+});
+
+test("validateArtifactPayload rejects missing design_contract fields", () => {
+ const topology = loadTopology(process.cwd());
+ const result = validateArtifactPayload(topology, "design_contract", {
+ visual_theme: "dark",
+ color_system: "brand + neutral",
+ });
+
+ expect(result.ok).toBe(false);
+ expect(result.missingFields).toContain("typography");
+ expect(result.missingFields).toContain("component_states");
+});
From 5fc52fe1c8c53e1529f89c6f25ffa39aa013196e Mon Sep 17 00:00:00 2001
From: Kailas Mahavarkar <66670953+KailasMahavarkar@users.noreply.github.com>
Date: Sun, 19 Apr 2026 06:49:18 +0530
Subject: [PATCH 17/23] feat: add workspace-aware router with conditional
design contracts
---
src/engine/policy.ts | 13 ++++++++
src/engine/router.ts | 59 ++++++++++++++++++++++++++++++++++
tests/router-behaviour.test.ts | 57 ++++++++++++++++++++++++++++++++
3 files changed, 129 insertions(+)
create mode 100644 src/engine/router.ts
create mode 100644 tests/router-behaviour.test.ts
diff --git a/src/engine/policy.ts b/src/engine/policy.ts
index db4c488..a3f8ee5 100644
--- a/src/engine/policy.ts
+++ b/src/engine/policy.ts
@@ -23,3 +23,16 @@ export function getDomain(topology: LoadedTopology, domainId: string): DomainPol
}
return domain;
}
+
+export function getStrictestProofMode(order: string[], proofModes: string[]): string {
+ const ranked = proofModes
+ .map((mode) => ({ mode, index: order.indexOf(mode) }))
+ .filter((entry) => entry.index >= 0)
+ .sort((left, right) => right.index - left.index);
+
+ if (ranked.length === 0) {
+ throw new Error(`No proof mode could be ranked from: ${proofModes.join(", ")}`);
+ }
+
+ return ranked[0].mode;
+}
diff --git a/src/engine/router.ts b/src/engine/router.ts
new file mode 100644
index 0000000..346ea95
--- /dev/null
+++ b/src/engine/router.ts
@@ -0,0 +1,59 @@
+import type { LoadedTopology } from "./contracts.js";
+import { getAgent, getDomain, getStrictestProofMode } from "./policy.js";
+
+function shouldRequireDesignContract(input: {
+ changeClassification: string;
+ workspaceInventory: { projectMode: "greenfield" | "existing"; existingPatterns: string[] };
+}): boolean {
+ if (input.changeClassification !== "frontend_visual") {
+ return false;
+ }
+
+ return (
+ input.workspaceInventory.projectMode === "greenfield" ||
+ input.workspaceInventory.existingPatterns.length === 0
+ );
+}
+
+export function routeRequest(
+ topology: LoadedTopology,
+ input: {
+ requestId: string;
+ domainTargets: string[];
+ capabilityTargets: string[];
+ workspaceInventory: {
+ projectMode: "greenfield" | "existing";
+ existingPatterns: string[];
+ };
+ changeClassification: string;
+ },
+) {
+ const uniqueDomains = [...new Set(input.domainTargets)];
+ const routeAgentId =
+ uniqueDomains.length > 1
+ ? topology.routeDefaults.crossDomainAgent
+ : topology.routeDefaults.domainPreference[uniqueDomains[0] ?? "shared"] ?? topology.routeDefaults.defaultAgent;
+
+ const agent = getAgent(topology, routeAgentId);
+ const proofMode = getStrictestProofMode(
+ topology.routeDefaults.strictestProofOrder,
+ uniqueDomains.map((domainId) => getDomain(topology, domainId).completionProof),
+ );
+
+ const requiredArtifacts = ["workspace_inventory", "task_handoff"];
+ const requiresDesignContract = shouldRequireDesignContract(input);
+
+ if (requiresDesignContract) {
+ requiredArtifacts.push("design_contract");
+ }
+
+ return {
+ requestId: input.requestId,
+ agent,
+ proofMode,
+ domains: uniqueDomains,
+ capabilityTargets: input.capabilityTargets,
+ requiredArtifacts,
+ requiresDesignContract,
+ };
+}
diff --git a/tests/router-behaviour.test.ts b/tests/router-behaviour.test.ts
new file mode 100644
index 0000000..d2f4894
--- /dev/null
+++ b/tests/router-behaviour.test.ts
@@ -0,0 +1,57 @@
+import { expect, test } from "bun:test";
+import { loadTopology } from "../src/engine/topology-loader.ts";
+import { routeRequest } from "../src/engine/router.ts";
+
+test("routeRequest sends existing-project frontend logic work to frontend-builder without design contract", () => {
+ const topology = loadTopology(process.cwd());
+ const route = routeRequest(topology, {
+ requestId: "req-1",
+ domainTargets: ["frontend"],
+ capabilityTargets: ["frontend.patterns"],
+ workspaceInventory: {
+ projectMode: "existing",
+ existingPatterns: ["existing form shell"],
+ },
+ changeClassification: "frontend_logic",
+ });
+
+ expect(route.agent.id).toBe("frontend-builder");
+ expect(route.requiredArtifacts).toContain("workspace_inventory");
+ expect(route.requiredArtifacts).not.toContain("design_contract");
+});
+
+test("routeRequest requires design contract for a new visual surface", () => {
+ const topology = loadTopology(process.cwd());
+ const route = routeRequest(topology, {
+ requestId: "req-2",
+ domainTargets: ["frontend"],
+ capabilityTargets: ["design.intent"],
+ workspaceInventory: {
+ projectMode: "greenfield",
+ existingPatterns: [],
+ },
+ changeClassification: "frontend_visual",
+ });
+
+ expect(route.agent.id).toBe("frontend-builder");
+ expect(route.requiredArtifacts).toContain("workspace_inventory");
+ expect(route.requiredArtifacts).toContain("design_contract");
+ expect(route.proofMode).toBe("visual_and_behavioral");
+});
+
+test("routeRequest sends mixed frontend+backend work to fullstack-builder", () => {
+ const topology = loadTopology(process.cwd());
+ const route = routeRequest(topology, {
+ requestId: "req-3",
+ domainTargets: ["frontend", "backend"],
+ capabilityTargets: ["frontend.patterns", "backend.http.patterns"],
+ workspaceInventory: {
+ projectMode: "existing",
+ existingPatterns: [],
+ },
+ changeClassification: "fullstack_slice",
+ });
+
+ expect(route.agent.id).toBe("fullstack-builder");
+ expect(route.proofMode).toBe("visual_and_behavioral");
+});
From 2217443adf3f8d27f0655a39bf18766270a07173 Mon Sep 17 00:00:00 2001
From: Kailas Mahavarkar <66670953+KailasMahavarkar@users.noreply.github.com>
Date: Sun, 19 Apr 2026 06:50:00 +0530
Subject: [PATCH 18/23] feat: enforce allowed skills for routed agents
---
src/engine/skill-enforcer.ts | 7 +++++++
tests/router-behaviour.test.ts | 33 +++++++++++++++++++++++++++++++++
2 files changed, 40 insertions(+)
create mode 100644 src/engine/skill-enforcer.ts
diff --git a/src/engine/skill-enforcer.ts b/src/engine/skill-enforcer.ts
new file mode 100644
index 0000000..876fc2b
--- /dev/null
+++ b/src/engine/skill-enforcer.ts
@@ -0,0 +1,7 @@
+import type { AgentPolicy } from "./contracts.js";
+
+export function assertSkillAllowedForAgent(agent: AgentPolicy, skillName: string): void {
+ if (!agent.allowedSkills.includes(skillName)) {
+ throw new Error(`Skill ${skillName} is not allowed for agent ${agent.id}`);
+ }
+}
diff --git a/tests/router-behaviour.test.ts b/tests/router-behaviour.test.ts
index d2f4894..cdccfe8 100644
--- a/tests/router-behaviour.test.ts
+++ b/tests/router-behaviour.test.ts
@@ -1,6 +1,7 @@
import { expect, test } from "bun:test";
import { loadTopology } from "../src/engine/topology-loader.ts";
import { routeRequest } from "../src/engine/router.ts";
+import { assertSkillAllowedForAgent } from "../src/engine/skill-enforcer.ts";
test("routeRequest sends existing-project frontend logic work to frontend-builder without design contract", () => {
const topology = loadTopology(process.cwd());
@@ -55,3 +56,35 @@ test("routeRequest sends mixed frontend+backend work to fullstack-builder", () =
expect(route.agent.id).toBe("fullstack-builder");
expect(route.proofMode).toBe("visual_and_behavioral");
});
+
+test("assertSkillAllowedForAgent rejects backend-only review skill on frontend-builder", () => {
+ const topology = loadTopology(process.cwd());
+ const route = routeRequest(topology, {
+ requestId: "req-4",
+ domainTargets: ["frontend"],
+ capabilityTargets: ["frontend.patterns"],
+ workspaceInventory: {
+ projectMode: "existing",
+ existingPatterns: ["existing form shell"],
+ },
+ changeClassification: "frontend_logic",
+ });
+
+ expect(() => assertSkillAllowedForAgent(route.agent, "security-review")).toThrow(/not allowed/i);
+});
+
+test("assertSkillAllowedForAgent accepts designer for frontend-builder", () => {
+ const topology = loadTopology(process.cwd());
+ const route = routeRequest(topology, {
+ requestId: "req-5",
+ domainTargets: ["frontend"],
+ capabilityTargets: ["design.intent"],
+ workspaceInventory: {
+ projectMode: "greenfield",
+ existingPatterns: [],
+ },
+ changeClassification: "frontend_visual",
+ });
+
+ expect(() => assertSkillAllowedForAgent(route.agent, "designer")).not.toThrow();
+});
From 882e86283c8bf667da84925b3e823a4ac7e7112d Mon Sep 17 00:00:00 2001
From: Kailas Mahavarkar <66670953+KailasMahavarkar@users.noreply.github.com>
Date: Sun, 19 Apr 2026 06:51:02 +0530
Subject: [PATCH 19/23] feat: expose routing and artifact validation via cli
---
src/cli.ts | 59 ++++++++++++++++++++---
tests/local-cli-routing-behaviour.test.ts | 40 +++++++++++++++
2 files changed, 93 insertions(+), 6 deletions(-)
create mode 100644 tests/local-cli-routing-behaviour.test.ts
diff --git a/src/cli.ts b/src/cli.ts
index ef7ab64..6bd102a 100644
--- a/src/cli.ts
+++ b/src/cli.ts
@@ -1,16 +1,63 @@
+import { validateArtifactPayload } from "./engine/artifact-validator.js";
+import { routeRequest } from "./engine/router.js";
+import { loadTopology } from "./engine/topology-loader.js";
import { invokeLocalTool } from "./adapters/local-tools/index.js";
async function main() {
const [command, toolName, flag, json] = process.argv.slice(2);
+ const topology = loadTopology(process.cwd());
- if (command !== "tool" || !toolName || flag !== "--json" || !json) {
- process.stderr.write('Usage: hyperstack tool --json \'{"key":"value"}\'\n');
- process.exit(1);
+ if (command === "tool") {
+ if (!toolName || flag !== "--json" || !json) {
+ process.stderr.write('Usage: hyperstack tool --json \'{"key":"value"}\'\n');
+ process.exit(1);
+ }
+
+ const args = JSON.parse(json) as Record;
+ const result = await invokeLocalTool(toolName, args);
+ process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
+ process.exit(0);
+ }
+
+ if (command === "route") {
+ if (toolName !== "--json" || !flag) {
+ process.stderr.write("Usage: hyperstack route --json '{...}'\n");
+ process.exit(1);
+ }
+
+ const input = JSON.parse(flag) as {
+ requestId: string;
+ domainTargets: string[];
+ capabilityTargets: string[];
+ workspaceInventory: { projectMode: "greenfield" | "existing"; existingPatterns: string[] };
+ changeClassification: string;
+ };
+
+ process.stdout.write(`${JSON.stringify(routeRequest(topology, input), null, 2)}\n`);
+ process.exit(0);
}
- const args = JSON.parse(json) as Record;
- const result = await invokeLocalTool(toolName, args);
- process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
+ if (command === "artifact" && toolName === "validate") {
+ const artifactId = flag;
+ const jsonFlag = process.argv[5];
+ const jsonPayload = process.argv[6];
+
+ if (!artifactId || jsonFlag !== "--json" || !jsonPayload) {
+ process.stderr.write("Usage: hyperstack artifact validate --json '{...}'\n");
+ process.exit(1);
+ }
+
+ const payload = JSON.parse(jsonPayload) as Record;
+ process.stdout.write(`${JSON.stringify(validateArtifactPayload(topology, artifactId, payload), null, 2)}\n`);
+ process.exit(0);
+ }
+
+ process.stderr.write(
+ "Usage: hyperstack tool --json '{...}'\n" +
+ " or: hyperstack route --json '{...}'\n" +
+ " or: hyperstack artifact validate --json '{...}'\n",
+ );
+ process.exit(1);
}
main().catch((error) => {
diff --git a/tests/local-cli-routing-behaviour.test.ts b/tests/local-cli-routing-behaviour.test.ts
new file mode 100644
index 0000000..4333424
--- /dev/null
+++ b/tests/local-cli-routing-behaviour.test.ts
@@ -0,0 +1,40 @@
+import { expect, test } from "bun:test";
+import { spawnSync } from "node:child_process";
+import { resolve } from "node:path";
+
+test("CLI route command returns routed agent and required artifacts", () => {
+ const result = spawnSync(
+ process.execPath,
+ [
+ resolve("bin/hyperstack.mjs"),
+ "route",
+ "--json",
+ '{"requestId":"req-1","domainTargets":["frontend"],"capabilityTargets":["frontend.patterns"],"workspaceInventory":{"projectMode":"existing","existingPatterns":["existing form shell"]},"changeClassification":"frontend_logic"}',
+ ],
+ { cwd: process.cwd(), encoding: "utf8" },
+ );
+
+ expect(result.status).toBe(0);
+ expect(result.stdout).toMatch(/frontend-builder/);
+ expect(result.stdout).toMatch(/workspace_inventory/);
+ expect(result.stdout).not.toMatch(/design_contract/);
+});
+
+test("CLI artifact validate command reports missing fields", () => {
+ const result = spawnSync(
+ process.execPath,
+ [
+ resolve("bin/hyperstack.mjs"),
+ "artifact",
+ "validate",
+ "workspace_inventory",
+ "--json",
+ '{"repo_type":"web-app"}',
+ ],
+ { cwd: process.cwd(), encoding: "utf8" },
+ );
+
+ expect(result.status).toBe(0);
+ expect(result.stdout).toMatch(/missingFields/);
+ expect(result.stdout).toMatch(/stack/);
+});
From 6f9fcd285d331547b1ea8f8bcbe4a9928e50461a Mon Sep 17 00:00:00 2001
From: Kailas Mahavarkar <66670953+KailasMahavarkar@users.noreply.github.com>
Date: Sun, 19 Apr 2026 06:52:41 +0530
Subject: [PATCH 20/23] feat: generate workspace-first topology summaries
---
.../2026-04-17-topology-manifest-design.md | 89 ++++++++++++++++---
generated/routing/allow-deny.md | 8 ++
.../runtime-context/topology.bootstrap.md | 10 +++
scripts/generate-topology-artifacts.ts | 8 ++
tests/topology-artifacts-behaviour.test.ts | 3 +
5 files changed, 106 insertions(+), 12 deletions(-)
diff --git a/docs/superpowers/specs/2026-04-17-topology-manifest-design.md b/docs/superpowers/specs/2026-04-17-topology-manifest-design.md
index a1e1cb7..9865758 100644
--- a/docs/superpowers/specs/2026-04-17-topology-manifest-design.md
+++ b/docs/superpowers/specs/2026-04-17-topology-manifest-design.md
@@ -98,7 +98,39 @@ Frontend has weaker proof paths and needs design-constrained execution:
This asymmetry must be explicit in topology.
-### 3.4 Stable Tool Names, New Runtime
+### 3.4 Planning Is Universal, Design Contracts Are Conditional
+
+The current design stack enforces `DESIGN.md` too early and too broadly:
+
+- `website-builder` is website-specific, not general frontend
+- `blueprint` routes any visual/UX work directly into `designer`
+- `designer` hard-gates visual work behind approved `DESIGN.md`
+- topology/runtime currently has no `workspace_inventory` or conditional-design logic
+
+That is acceptable for greenfield visual work, but wrong for many client existing-project tasks.
+
+Corrected rule:
+
+- `workspace_inventory` is always required
+- `task_handoff` is always required
+- `implementation_plan` is normally required
+- `design_contract` is conditional
+- `verification_report` is always required before completion
+
+`design_contract` is required only when:
+
+- a new user-facing surface is created
+- visual semantics materially change
+- a reliable existing pattern/design-system match cannot be found in the workspace
+
+It is not a universal gate for:
+
+- backend-only work
+- infra/config/docs work
+- existing-project refactors
+- non-visual bugfixes inside established patterns
+
+### 3.5 Stable Tool Names, New Runtime
Tool identities such as `designer_resolve_intent`, `reactflow_get_api`, and `golang_get_practice` remain stable. What changes is the resolver behind them:
@@ -399,6 +431,7 @@ Artifacts are typed handoff shapes between agents, skills, and adapters.
Recommended first V1 artifact set:
+- `workspace_inventory`
- `task_handoff`
- `design_contract`
- `build_result`
@@ -406,7 +439,31 @@ Recommended first V1 artifact set:
- `verification_report`
- `delivery_report`
-### 10.1 `task_handoff`
+### 10.1 `workspace_inventory`
+
+Produced by:
+
+- `hyper`
+- future workspace discovery helpers
+
+Consumed by:
+
+- router
+- planning skills
+- builder agents
+
+Fields:
+
+- repo_type
+- stack
+- touched_surfaces
+- owning_modules
+- existing_patterns
+- existing_design_system
+- verification_commands
+- project_mode (`greenfield` | `existing`)
+
+### 10.2 `task_handoff`
Produced by:
@@ -425,8 +482,13 @@ Fields:
- constraints
- success_criteria
- touched_surfaces
+- change_classification (`backend_only` | `frontend_logic` | `frontend_visual` | `fullstack_slice` | `docs_config`)
+- requires_design_contract
+- required_artifacts
+
+### 10.3 `design_contract`
-### 10.2 `design_contract`
+Conditional artifact. Required only when `requires_design_contract = true`.
Produced by:
@@ -449,7 +511,7 @@ Fields:
- responsive_rules
- anti_patterns
-### 10.3 `verification_report`
+### 10.4 `verification_report`
Produced by:
@@ -497,18 +559,19 @@ Flow:
- capability = `design.intent`
3. `hyper` routes to `frontend-builder`
4. `frontend-builder` is required to use `frontend.design`
-5. local adapter `designer_resolve_intent` resolves the call
-6. engine maps the tool to:
+5. `hyper` builds `workspace_inventory`
+6. local adapter `designer_resolve_intent` resolves the call when route classification requires it
+7. engine maps the tool to:
- capability: `design.intent`
- bundle: `frontend.design`
- corpus paths:
- `corpus/frontend/designer`
- `corpus/frontend/ui-ux`
- `corpus/frontend/design-tokens`
-7. injector builds a short context pack
-8. adapter returns a shaped `intent_resolution` artifact
-9. `designer` skill can now produce `design_contract`
-10. no frontend completion path may claim done before required frontend proof exists
+8. injector builds a short context pack
+9. adapter returns a shaped `intent_resolution` artifact
+10. `designer` produces `design_contract` only when route classification marks it required
+11. no completion path may claim done before required proof exists
## 12. Local Navigation Engine
@@ -580,8 +643,9 @@ Frontend completion requires stronger proof because code correctness is not enou
Required proof path:
-- design contract exists
+- workspace inventory exists
- frontend truth bundles used
+- design contract exists only when route classification requires it
- behavior audit completed
- final report marks residual risks explicitly
@@ -612,7 +676,8 @@ Backend proof alone cannot close a fullstack task that changes frontend behavior
- no direct user -> specialist execution
- no unrestricted specialist -> forbidden bundle access
-- no frontend completion without `design_contract`
+- no routed work without `workspace_inventory`
+- no visual-semantic or new-surface completion without `design_contract`
- no completion claim without `verification_report`
- no cross-domain execution without declared domain union
- no runtime link outside topology manifest
diff --git a/generated/routing/allow-deny.md b/generated/routing/allow-deny.md
index 1b03656..c71da0b 100644
--- a/generated/routing/allow-deny.md
+++ b/generated/routing/allow-deny.md
@@ -3,15 +3,23 @@
## hyper
- Allowed: shared.system
- Forbidden:
+- Allowed Skills: blueprint, forge-plan, run-plan, parallel-dispatch, subagent-ops, autonomous-mode, ship-gate, code-review, deliver
+- Completion Proof: routing_and_verification
## frontend-builder
- Allowed: frontend.design, frontend.react
- Forbidden: backend.http, backend.lang.go, backend.lang.rust
+- Allowed Skills: test-first, debug-discipline, engineering-discipline, worktree-isolation, designer, behaviour-analysis, shadcn-expert
+- Completion Proof: visual_and_behavioral
## backend-builder
- Allowed: backend.http, backend.lang.go, backend.lang.rust
- Forbidden: frontend.design, frontend.react
+- Allowed Skills: test-first, debug-discipline, engineering-discipline, worktree-isolation, security-review
+- Completion Proof: executable
## fullstack-builder
- Allowed: frontend.design, frontend.react, backend.http, backend.lang.go, backend.lang.rust
- Forbidden:
+- Allowed Skills: test-first, debug-discipline, engineering-discipline, worktree-isolation, designer, behaviour-analysis, shadcn-expert, security-review
+- Completion Proof: strictest_touched_domain
diff --git a/generated/runtime-context/topology.bootstrap.md b/generated/runtime-context/topology.bootstrap.md
index c61a37f..e93e150 100644
--- a/generated/runtime-context/topology.bootstrap.md
+++ b/generated/runtime-context/topology.bootstrap.md
@@ -1,6 +1,16 @@
# Topology Runtime Bootstrap
Entry agent: hyper
+Cross-domain agent: fullstack-builder
+Workspace inventory required: true
+Design contract is conditional
+
+## Artifacts
+- workspace_inventory: discovery_only
+- task_handoff: routing_only
+- design_contract: visual_contract_conditional
+- build_result: executable
+- verification_report: routing_and_verification
## Agents
- hyper: orchestrator -> shared
diff --git a/scripts/generate-topology-artifacts.ts b/scripts/generate-topology-artifacts.ts
index f124f58..d75f20c 100644
--- a/scripts/generate-topology-artifacts.ts
+++ b/scripts/generate-topology-artifacts.ts
@@ -14,6 +14,12 @@ writeFileSync(
"# Topology Runtime Bootstrap",
"",
`Entry agent: ${topology.entryAgent}`,
+ `Cross-domain agent: ${topology.routeDefaults.crossDomainAgent}`,
+ `Workspace inventory required: ${topology.routeDefaults.requiresWorkspaceInventory}`,
+ "Design contract is conditional",
+ "",
+ "## Artifacts",
+ ...topology.artifacts.map((artifact) => `- ${artifact.id}: ${artifact.proofMode}`),
"",
"## Agents",
...topology.agents.map((agent) => `- ${agent.id}: ${agent.kind} -> ${agent.domains.join(", ")}`),
@@ -33,6 +39,8 @@ writeFileSync(
`## ${agent.id}`,
`- Allowed: ${agent.allowedBundles.join(", ")}`,
`- Forbidden: ${agent.forbiddenBundles.join(", ")}`,
+ `- Allowed Skills: ${agent.allowedSkills.join(", ")}`,
+ `- Completion Proof: ${agent.completionProof}`,
"",
]),
].join("\n"),
diff --git a/tests/topology-artifacts-behaviour.test.ts b/tests/topology-artifacts-behaviour.test.ts
index c3105c5..d815abf 100644
--- a/tests/topology-artifacts-behaviour.test.ts
+++ b/tests/topology-artifacts-behaviour.test.ts
@@ -14,8 +14,11 @@ test("generated local tool registry includes stable tool names", () => {
test("generated topology bootstrap includes agent and bundle routing markers", () => {
const bootstrap = readFileSync(resolve("generated/runtime-context/topology.bootstrap.md"), "utf8");
+ expect(bootstrap).toMatch(/workspace_inventory/);
expect(bootstrap).toMatch(/hyper/);
expect(bootstrap).toMatch(/frontend-builder/);
expect(bootstrap).toMatch(/backend-builder/);
expect(bootstrap).toMatch(/frontend\.design/);
+ expect(bootstrap).toMatch(/design contract is conditional/i);
+ expect(bootstrap).toMatch(/cross-domain agent: fullstack-builder/i);
});
From 71f5525661899fb0fbc4c3b3c3a0a47047724713 Mon Sep 17 00:00:00 2001
From: Kailas Mahavarkar <66670953+KailasMahavarkar@users.noreply.github.com>
Date: Sun, 19 Apr 2026 14:25:19 +0530
Subject: [PATCH 21/23] fix: align skill routing with workspace-first behavior
---
.../runtime-context/hyperstack.bootstrap.md | 5 ++-
skills/blueprint/SKILL.md | 39 +++++++++++++------
skills/designer/SKILL.md | 17 ++++----
skills/hyperstack/SKILL.md | 9 +++--
tests/role-harness-behaviour.test.ts | 17 ++++++++
5 files changed, 64 insertions(+), 23 deletions(-)
diff --git a/generated/runtime-context/hyperstack.bootstrap.md b/generated/runtime-context/hyperstack.bootstrap.md
index 45d2b7e..649261d 100644
--- a/generated/runtime-context/hyperstack.bootstrap.md
+++ b/generated/runtime-context/hyperstack.bootstrap.md
@@ -19,7 +19,7 @@ You cannot rationalize exceptions to this rule.
Call relevant Hyperstack plugins prior to implementation.
2. NO VISUAL CODE WITHOUT AN APPROVED DESIGN.md
- The designer skill produces the contract; everything else implements it.
+ The designer skill produces the contract when routing requires a design contract; existing-project frontend logic work stays workspace-first.
3. NO COMPLETION CLAIMS WITHOUT SHIP-GATE EVIDENCE
"Should work" is unacceptable. Execute the command and output results.
@@ -51,7 +51,8 @@ You cannot rationalize exceptions to this rule.
## Workflow Skills
- Starting any new feature, component, or behaviour change: `blueprint`
-- Task involves UI, animation, visuals, or interaction: `designer` β produces DESIGN.md first
+- Any task touching existing project code: `blueprint` builds `workspace_inventory` first
+- Task creates a new surface, changes visual semantics, or has no reliable existing pattern match: `designer` β produces conditional `design_contract` / DESIGN.md
- Have an approved design or plan to execute: `forge-plan` or `run-plan`
- Claiming anything is complete, fixed, or passing: `ship-gate` β evidence required
- Hit any bug, test failure, or unexpected behaviour: `debug-discipline` β root cause before any fix
diff --git a/skills/blueprint/SKILL.md b/skills/blueprint/SKILL.md
index 86e6809..44dd161 100644
--- a/skills/blueprint/SKILL.md
+++ b/skills/blueprint/SKILL.md
@@ -11,11 +11,17 @@ description: Execute before any feature build, component creation, or behavior c
Do not write code, scaffold files, or invoke implementation skills until:
-1. MCP survey is complete for relevant domains.
-2. Design is presented OR user project preferences are known:
- - Visual/UX work β DESIGN.md contract from `skills/designer/SKILL.md`.
- - Backend/infra work β Architecture note from this skill.
-3. User explicitly approves the design.
+1. Workspace inventory is explicit:
+ - existing stack
+ - owning modules
+ - existing patterns
+ - verification commands
+2. MCP survey is complete for relevant domains.
+3. Required artifacts are chosen correctly:
+ - `workspace_inventory` β always
+ - `task_handoff` β always
+ - `design_contract` β required only when the task creates a new surface, changes visual semantics, or has no trustworthy existing pattern match
+4. User explicitly approves the plan/design when the chosen artifacts require approval.
This applies to every task, regardless of perceived simplicity.
@@ -34,12 +40,14 @@ Read current state before querying the user:
- Relevant source files, recent commits, existing patterns.
- Existing logic applicable for reuse or extension.
- Relevant Hyperstack MCP domains.
+- Build `workspace_inventory` first. This is mandatory even for client existing projects.
### Step 2: MCP Survey
| Domain is relevant | Call first |
|---|---|
-| **Visual/UX work (any)** | **STOP β invoke `skills/designer/SKILL.md`. Produces DESIGN.md β pass to Step 5 or `forge-plan`.** |
+| **Frontend logic in an existing pattern** | `react_*`, `ui_ux_*`, and stack-specific tools first. No automatic `DESIGN.md`. |
+| **New surface / visual-semantic change / no existing pattern match** | **Invoke `skills/designer/SKILL.md`. Produces conditional `design_contract` / DESIGN.md when required.** |
| React Flow | `reactflow_search_docs` + `reactflow_list_apis` |
| Motion / animation | `motion_search_docs` + `motion_list_apis` |
| Lenis scroll | `lenis_search_docs` + `lenis_list_apis` |
@@ -49,9 +57,12 @@ Read current state before querying the user:
| Design tokens | `design_tokens_list_categories` + `design_tokens_get_gotchas` |
| UI/UX | `ui_ux_list_principles` + `ui_ux_get_gotchas` |
-Building designs on incorrect API assumptions creates immediate technical debt.
+Building plans on incorrect API assumptions or missing workspace reality creates immediate technical debt.
-**Visual work routing:** New page, component library, landing page, dashboard, redesign, "make it look like X" β `designer` skill owns the design gate. Return with DESIGN.md β proceed to handoff (Step 7).
+**Routing rule:**
+- existing-project frontend logic work β keep routing workspace-first
+- new page, redesign, component-system change, or visual-semantic change β `designer` owns the conditional design gate
+- backend/infra/docs work β no `DESIGN.md` gate
### Step 3: Clarify Requirements
@@ -59,6 +70,12 @@ Ask single clarifying questions sequentially:
- Purpose and success criteria (what defines completion?).
- Constraints (performance targets, accessibility, existing patterns).
- Scope boundaries (what is explicitly excluded?).
+- Change classification:
+ - `backend_only`
+ - `frontend_logic`
+ - `frontend_visual`
+ - `fullstack_slice`
+ - `docs_config`
Wait for answers before proceeding. Decompose independent subsystems if necessary.
@@ -96,7 +113,7 @@ Address each explicitly: redesign or formally accept the risk.
Following approval:
- Save design note to the relevant documentation directory.
-- For Visual/UX work, save DESIGN.md at `docs/DESIGN.md` or `/DESIGN.md`.
+- For tasks that require a design contract, save DESIGN.md at `docs/DESIGN.md` or `/DESIGN.md`.
- Invoke `hyperstack:forge-plan` to generate an MCP-verified implementation plan based on the approved design.
@@ -105,7 +122,7 @@ Following approval:
### Agent Workflow Chains
**Website/Frontend Agent:**
-`blueprint` (THIS) β `designer` (visual routing) β `forge-plan` β [execution] β `ship-gate` β `deliver`
+`blueprint` (THIS) β workspace inventory + change classification β [`designer` only if required] β `forge-plan` β [execution] β `ship-gate` β `deliver`
**Backend/Infra Agent:**
`blueprint` (THIS) β `forge-plan` (architecture note) β [execution] β `ship-gate` β `deliver`
@@ -126,5 +143,5 @@ Following approval:
### Reverse Escalation
| Discovery | Escalate to | Action |
|---|---|---|
-| Visual/UX work detected mid-task | `designer` | Pause, generate DESIGN.md, resume. |
+| New surface / visual-semantic change detected mid-task | `designer` | Pause, generate conditional `design_contract`, resume. |
| Architecture gap (non-visual) | `blueprint` | Pause, formalize architecture decision, resume. |
diff --git a/skills/designer/SKILL.md b/skills/designer/SKILL.md
index 1da06f9..597fa91 100644
--- a/skills/designer/SKILL.md
+++ b/skills/designer/SKILL.md
@@ -9,7 +9,7 @@ description: >-
> AI UIs look identical because AI skips decision process and jumps to code.
> Force every decision through evidence before code generation.
-> No visual code without APPROVED DESIGN.md.
+> No new visual-semantic surface without approved design contract.
## IRON LAW
@@ -17,7 +17,7 @@ description: >-
NO VISUAL CODE WITHOUT APPROVED DESIGN.md
```
-Single line JSX/CSS without DESIGN.md = violation. Simple buttons require decisions.
+Single line JSX/CSS without DESIGN.md = violation when the route requires a design contract. This gate is conditional, not universal.
## HARD GATE
@@ -33,8 +33,8 @@ DO NOT GENERATE VISUAL CODE UNTIL:
## 1% RULE
-1% chance task involves new page, new component, visual change, or redesign β invoke BEFORE code.
-**Apply:** Modifies look, feel, motion, or interaction.
+1% chance task involves a new surface, a visual-semantic change, or no trustworthy existing pattern match β invoke BEFORE code.
+**Apply:** New page, redesign, new component system, motion system change, or existing-project UI work with no safe pattern match.
**Skip:** Pure backend, non-visual CSS bug fixing, infrastructure.
## RED FLAGS - STOP
@@ -77,6 +77,7 @@ Inside ``, you must answer:
**Step 1:** Use `designer_resolve_intent` (or read `references/questions.md`).
**Step 2:** Ensure you know the Product, Brand Color, Target Audience, Emotional Target, and Component Library (e.g., shadcn vs raw Tailwind).
+**Step 3:** Confirm the route actually requires a `design_contract`. Existing-project frontend logic work should usually stay in workspace-first planning instead.
User preferences override auto-resolved defaults. Auto-resolved defaults are suggestions, not authority.
@@ -102,7 +103,9 @@ Cross-reference your resolved specs against the hard constraints. Use `view_file
---
-# PHASE 4: GENERATE DESIGN.md
+# PHASE 4: GENERATE DESIGN.md (Conditional)
+
+Only run this phase when route classification says `requires_design_contract = true`.
Assemble 10 sections. Wait for user approval. NO CODE YET.
1. Visual Theme (Emotional target, personality).
@@ -134,7 +137,7 @@ Post-approval implementation order:
# INTEGRATION CONTRACTS
-**Upstream (`hyperstack:blueprint`):** Visual/UX intent detected β run pipeline β return approved DESIGN.md path.
+**Upstream (`hyperstack:blueprint`):** New-surface or visual-semantic intent detected β run pipeline β return approved conditional `design_contract` / DESIGN.md path.
**Downstream (`hyperstack:forge-plan`):**
DESIGN.md saved β `forge-plan` reads 10 sections β generates tasks.
@@ -143,6 +146,6 @@ DESIGN.md saved β `forge-plan` reads 10 sections β generates tasks.
Call `shadcn_get_rules` FIRST. `shadcn_get_composition`, `shadcn_list_components`. `shadcn_get_component` per DESIGN.md. No hallucinated components.
**To `hyperstack:ship-gate`:**
-DESIGN.md acts as absolute ground truth for testing expected behaviours, states, animations, and non-slop compliance.
+When present, DESIGN.md acts as ground truth for testing expected behaviours, states, animations, and non-slop compliance. When absent, verification falls back to workspace patterns plus route-level proof requirements.
**Announce invocation:** *"Using hyperstack:designer - stepping into Creative Director persona to produce DESIGN.md."*
diff --git a/skills/hyperstack/SKILL.md b/skills/hyperstack/SKILL.md
index e179ea9..2d6b70d 100644
--- a/skills/hyperstack/SKILL.md
+++ b/skills/hyperstack/SKILL.md
@@ -31,7 +31,7 @@ You cannot rationalize exceptions to this rule.
Call relevant Hyperstack plugins prior to implementation.
2. NO VISUAL CODE WITHOUT AN APPROVED DESIGN.md
- The designer skill produces the contract; everything else implements it.
+ The designer skill produces the contract when routing requires a design contract; existing-project frontend logic work stays workspace-first.
3. NO COMPLETION CLAIMS WITHOUT SHIP-GATE EVIDENCE
"Should work" is unacceptable. Execute the command and output results.
@@ -99,7 +99,8 @@ BEFORE invoking any Hyperstack skill, announce:
| Situation | Load this skill |
|---|---|
| Starting any new feature, component, or behaviour change | `blueprint` |
-| Task involves UI, animation, visuals, or interaction | `designer` β produces DESIGN.md first |
+| Any task touching existing project code | `blueprint` builds `workspace_inventory` first |
+| Task creates a new surface, changes visual semantics, or has no reliable existing pattern match | `designer` β produces conditional `design_contract` / DESIGN.md |
| Have an approved design or plan to execute | `forge-plan` or `run-plan` |
| Claiming anything is complete, fixed, or passing | `ship-gate` β evidence required |
| Hit any bug, test failure, or unexpected behaviour | `debug-discipline` β root cause before any fix |
@@ -116,7 +117,7 @@ BEFORE invoking any Hyperstack skill, announce:
### Workflow Chain Reference
```
-New work: blueprint β [designer if visual] β forge-plan β execution β ship-gate β deliver
+New work: blueprint β workspace_inventory + change classification β [designer only if required] β forge-plan β execution β ship-gate β deliver
Existing: run-plan βββ€
ββ autonomous-mode
@@ -126,6 +127,8 @@ Existing: run-plan βββ€
Debugging: debug-discipline β parallel-dispatch
```
+**Planning rule:** `workspace_inventory` is universal. `design_contract` is conditional. `verification_report` is universal.
+
---
## Layer 3: Agents (Orchestration & Routing)
diff --git a/tests/role-harness-behaviour.test.ts b/tests/role-harness-behaviour.test.ts
index d47fa3d..cf20e25 100644
--- a/tests/role-harness-behaviour.test.ts
+++ b/tests/role-harness-behaviour.test.ts
@@ -102,3 +102,20 @@ test("designer skill gives user preferences precedence over auto-resolved defaul
expect(designerContent).toMatch(/preferences?.*override|override.*preferences?/i);
expect(designerContent).toMatch(/auto-resolved defaults?|defaults?.*suggestions?/i);
});
+
+test("workspace-first planning makes design contracts conditional rather than universal", () => {
+ const blueprintContent = normalize(readFileSync(resolve("skills/blueprint/SKILL.md"), "utf8"));
+ const designerContent = normalize(readFileSync(resolve("skills/designer/SKILL.md"), "utf8"));
+ const hyperstackContent = normalize(readFileSync(resolve("skills/hyperstack/SKILL.md"), "utf8"));
+
+ expect(blueprintContent).toMatch(/workspace_inventory/i);
+ expect(blueprintContent).toMatch(/design_contract/i);
+ expect(blueprintContent).toMatch(/conditional|required only/i);
+
+ expect(designerContent).toMatch(/conditional|required only/i);
+ expect(designerContent).toMatch(/new surface|visual-semantic|existing pattern/i);
+
+ expect(hyperstackContent).toMatch(/workspace_inventory/i);
+ expect(hyperstackContent).toMatch(/design_contract/i);
+ expect(hyperstackContent).toMatch(/conditional|required only/i);
+});
From b2b0a0316c42ed7048f92dee0b0db9fc72b8e8cc Mon Sep 17 00:00:00 2001
From: Kailas Mahavarkar <66670953+KailasMahavarkar@users.noreply.github.com>
Date: Sun, 19 Apr 2026 15:07:08 +0530
Subject: [PATCH 22/23] docs: align design workflow with workspace-first
routing
---
README.md | 16 +++++++-------
skills/shadcn-expert/SKILL.md | 31 +++++++++++++++-------------
skills/ship-gate/SKILL.md | 18 ++++++++--------
tests/role-harness-behaviour.test.ts | 8 +++++++
4 files changed, 42 insertions(+), 31 deletions(-)
diff --git a/README.md b/README.md
index 120807f..de0c994 100755
--- a/README.md
+++ b/README.md
@@ -294,16 +294,16 @@ Ordinary skill markdown is a polite suggestion. Polite suggestion fails when an
When you say, **βbuild me a SaaS dashboardβ**:
1. **SessionStart** already puts in `hyperstack`, so AI know system is there.
-2. **Blueprint skill** sees visual job and sends it to `hyperstack:designer`.
-3. **Designer skill** runs `designer_resolve_intent(product)` to guess industry, personality, style, density, and mode.
+2. **Blueprint skill** builds workspace understanding first and classifies the change.
+3. If the route says a design contract is required, **Designer skill** runs `designer_resolve_intent(product)` to guess industry, personality, style, density, and mode.
4. Designer asks **3 questions** in base mode, or **12 questions** in advanced mode.
-5. Like **Q11b** will ask what component library to use: shadcn, raw Tailwind, MUI, Mantine, Chakra, Ant Design, or custom.
-6. Designer makes a **DESIGN.md** contract with 10 parts: theme, colors, type, spacing, components, motion, elevation, do/donβts, responsive rules, and anti-patterns.
-7. User approves the **DESIGN.md**.
-8. **Forge-plan** reads it and makes one task for each section. If user picked shadcn, it calls `shadcn_get_component`. If not, it builds from the DESIGN.md spec.
+5. Q11b asks what component library to use: shadcn, raw Tailwind, MUI, Mantine, Chakra, Ant Design, or custom.
+6. Only when needed, Designer makes a conditional **DESIGN.md / design contract** with theme, colors, type, spacing, components, motion, elevation, do/donβts, responsive rules, and anti-patterns.
+7. User approves the design contract when the route requires it.
+8. **Forge-plan** reads the routed artifacts and makes one task for each required area. Existing-project frontend logic work can stay workspace-first without forcing a design contract.
9. Build tasks run with MCP tools as ground truth.
-10. **designer_verify_implementation** checks build against **DESIGN.md**.
-11. **Ship-gate** blocks final completion unless build passes the **DESIGN.md** rules.
+10. **designer_verify_implementation** checks build against the design contract when present.
+11. **Ship-gate** blocks final completion unless build passes the required proof rules.
AI cannot jump ahead. Every step has hard gate. Excuses already blocked by rationalization tables.
diff --git a/skills/shadcn-expert/SKILL.md b/skills/shadcn-expert/SKILL.md
index c1fbec2..2314b9f 100644
--- a/skills/shadcn-expert/SKILL.md
+++ b/skills/shadcn-expert/SKILL.md
@@ -22,10 +22,13 @@ description: Advanced shadcn/ui architect specializing in Base UI, Tailwind v4,
## Position in the Ecosystem
```
-hyperstack:designer β DESIGN.md
+hyperstack:blueprint β workspace_inventory + change classification
β
- βΌ (if shadcn chosen in Q11)
-hyperstack:forge-plan reads DESIGN.md
+ βΌ (if shadcn chosen and design contract required)
+hyperstack:designer β conditional DESIGN.md / design_contract
+ β
+ βΌ
+hyperstack:forge-plan reads workspace + routed requirements
β
βΌ
hyperstack:shadcn-expert (THIS skill)
@@ -36,7 +39,7 @@ hyperstack:shadcn-expert (THIS skill)
βββΆ shadcn_get_snippet(name)
β
βΌ
-Implementation tasks per DESIGN.md Section 5
+Implementation tasks per routed component requirements
```
## MCP Tools
@@ -94,11 +97,11 @@ Implementation tasks per DESIGN.md Section 5
## Integration with Designer + Forge-Plan
-**Upstream:** `hyperstack:forge-plan` processes DESIGN.md Section 5 β calls `shadcn_get_component(name)` per component β references this skill for architectural guidance
+**Upstream:** `hyperstack:forge-plan` processes routed component requirements. If a design contract exists, it uses the relevant component sections. Existing-project frontend logic work may stay workspace-first without forcing a design contract.
-**Downstream:** Component code matching DESIGN.md Section 5 variants + states, all P7 (Components) rules enforced, ready for `hyperstack:ship-gate`
+**Downstream:** Component code matching required variants + states, all P7 (Components) rules enforced, ready for `hyperstack:ship-gate`
-**Reverse escalation:** DESIGN.md spec incompatible with shadcn architecture β escalate to `hyperstack:designer` to reconcile. Don't silently adapt.
+**Reverse escalation:** If a routed design contract is incompatible with shadcn architecture, escalate to `hyperstack:designer` to reconcile. Don't silently adapt.
@@ -108,23 +111,23 @@ Implementation tasks per DESIGN.md Section 5
**Website/Frontend Agent (if Q11b=shadcn):**
```
-designer β DESIGN.md β forge-plan β shadcn-expert (THIS) β [component implementation]
- β
- [shadcn_* MCP tools]
+blueprint β workspace inventory / change classification β [designer only if required] β forge-plan β shadcn-expert (THIS) β [component implementation]
+ β
+ [shadcn_* MCP tools]
```
### Upstream Dependencies
-- `designer` β Q11b chose shadcn/ui (Base UI edition)
-- `forge-plan` β processes DESIGN.md Section 5 β calls shadcn_get_component per component
+- Q11b chose shadcn/ui (Base UI edition)
+- `forge-plan` β processes routed component requirements β calls shadcn_get_component per component
### Downstream Consumers
-- Component code matching DESIGN.md Section 5 variants + states
+- Component code matching routed variants + states
- `ship-gate` β P7 (Components) rules enforced
### Reverse Escalation
| Discovery | Escalate to | Action |
|---|---|---|
-| DESIGN.md spec incompatible with shadcn architecture | `designer` | Reconcile DESIGN.md with Base UI constraints |
+| Design contract incompatible with shadcn architecture | `designer` | Reconcile design contract with Base UI constraints |
### When NOT to Use
- User chose raw Tailwind (no component library)
diff --git a/skills/ship-gate/SKILL.md b/skills/ship-gate/SKILL.md
index bdb6782..b523829 100644
--- a/skills/ship-gate/SKILL.md
+++ b/skills/ship-gate/SKILL.md
@@ -45,11 +45,11 @@ Cannot show evidence β cannot make claim.
| Requirements | Line-by-line checklist against spec | Tests passing |
| Subagent done | VCS diff confirms actual changes | Subagent reports "done" |
| Regression | Red-green cycle verified | "I wrote a test" |
-| **DESIGN compliance** | **Implementation matches all 10 sections.** | **"Looks right"** |
+| **Design-contract compliance** | **Implementation matches all required sections when a design contract exists.** | **"Looks right"** |
-## DESIGN.md Compliance Gate (Visual/UX)
+## DESIGN.md / Design Contract Compliance Gate (Visual/UX)
-If DESIGN.md exists, completion requires this gate:
+If a task requires a design contract and DESIGN.md exists, completion requires this gate:
### Step 1: Automated Checker
@@ -78,11 +78,11 @@ Paste the `designer_verify_implementation` output block representing PASS on all
### Step 3: Handle Failures
-Any section fails β DO NOT claim completion.
+Any required section fails β DO NOT claim completion.
- Option A: Fix code.
-- Option B: Escalate to `designer` to revise DESIGN.md.
+- Option B: Escalate to `designer` to revise the design contract.
-No DESIGN.md on visual task? Stop. Invoke `designer`.
+No design contract on a task that requires one? Stop. Invoke `designer`.
## Lifecycle
@@ -90,10 +90,10 @@ No DESIGN.md on visual task? Stop. Invoke `designer`.
**All execution paths converge here:**
`[autonomous-mode | subagent-ops | engineering-discipline] β ship-gate (THIS) β deliver`
-**DESIGN.md flow:**
-`ship-gate β designer_verify_implementation β [PASS β deliver | FAIL β fix/escalate]`
+**Design-contract flow:**
+`ship-gate β designer_verify_implementation (when design contract required) β [PASS β deliver | FAIL β fix/escalate]`
**Escalations:**
-- DESIGN.md check fails β `designer`
+- Design-contract check fails β `designer`
- Tests fail β `debug-discipline`
- Type/lint errors β Fix β re-run ship-gate
diff --git a/tests/role-harness-behaviour.test.ts b/tests/role-harness-behaviour.test.ts
index cf20e25..6a5e620 100644
--- a/tests/role-harness-behaviour.test.ts
+++ b/tests/role-harness-behaviour.test.ts
@@ -107,6 +107,8 @@ test("workspace-first planning makes design contracts conditional rather than un
const blueprintContent = normalize(readFileSync(resolve("skills/blueprint/SKILL.md"), "utf8"));
const designerContent = normalize(readFileSync(resolve("skills/designer/SKILL.md"), "utf8"));
const hyperstackContent = normalize(readFileSync(resolve("skills/hyperstack/SKILL.md"), "utf8"));
+ const shipGateContent = normalize(readFileSync(resolve("skills/ship-gate/SKILL.md"), "utf8"));
+ const shadcnExpertContent = normalize(readFileSync(resolve("skills/shadcn-expert/SKILL.md"), "utf8"));
expect(blueprintContent).toMatch(/workspace_inventory/i);
expect(blueprintContent).toMatch(/design_contract/i);
@@ -118,4 +120,10 @@ test("workspace-first planning makes design contracts conditional rather than un
expect(hyperstackContent).toMatch(/workspace_inventory/i);
expect(hyperstackContent).toMatch(/design_contract/i);
expect(hyperstackContent).toMatch(/conditional|required only/i);
+
+ expect(shipGateContent).toMatch(/design contract/i);
+ expect(shipGateContent).toMatch(/when.*required|required.*design contract/i);
+
+ expect(shadcnExpertContent).toMatch(/workspace inventory|workspace-first/i);
+ expect(shadcnExpertContent).toMatch(/designer only if required|conditional/i);
});
From 454f23cf873814d6fc0555a0d0d199879c6cb805 Mon Sep 17 00:00:00 2001
From: Kailas Mahavarkar <66670953+KailasMahavarkar@users.noreply.github.com>
Date: Sun, 19 Apr 2026 15:35:57 +0530
Subject: [PATCH 23/23] refactor: align role contracts around frontend-builder
---
README.md | 6 +--
agents/frontend-builder/CHECKS.md | 32 +++++++++++
agents/frontend-builder/CONTEXT.md | 30 +++++++++++
agents/frontend-builder/LIFECYCLE.md | 43 +++++++++++++++
agents/frontend-builder/PROFILE.md | 54 +++++++++++++++++++
agents/hyper/LIFECYCLE.md | 8 +--
agents/hyper/PROFILE.md | 4 +-
docs/harness/context-policy.md | 4 +-
docs/harness/router.md | 5 +-
docs/harness/transitions.md | 12 ++---
.../runtime-context/hyperstack.bootstrap.md | 10 ++--
skills/hyperstack/SKILL.md | 8 +--
src/internal/context-compiler.ts | 8 +--
tests/role-harness-behaviour.test.ts | 24 ++++-----
14 files changed, 204 insertions(+), 44 deletions(-)
create mode 100644 agents/frontend-builder/CHECKS.md
create mode 100644 agents/frontend-builder/CONTEXT.md
create mode 100644 agents/frontend-builder/LIFECYCLE.md
create mode 100644 agents/frontend-builder/PROFILE.md
diff --git a/README.md b/README.md
index de0c994..62e4fe4 100755
--- a/README.md
+++ b/README.md
@@ -84,7 +84,7 @@ If you aren't using the Autopilot, follow the **Unified Bootstrap** to set up bo
It is not just a library; it is a **disciplined harness** made of three tightly-coupled layers:
-1. **The Harness**: Bootstraps the agent, routes internal specialist roles (`hyper`, `website-builder`), and enforces global development invariants.
+1. **The Harness**: Bootstraps the agent, routes internal specialist roles (`hyper`, `frontend-builder`), and enforces global development invariants.
2. **The MCP Ground Truth**: 12 TypeScript plugins (80 tools) that provide deterministic data. No hallucinated imports or invented component specs.
3. **The Adversarial Gates**: 21 skills with **"Enforcement Teeth"**. These aren't suggestions; they are Iron Laws supported by rationalization tables that counter every excuse an agent uses to skip quality gates.
@@ -127,7 +127,7 @@ graph TD
If you are an agent reading this, your mental model must be: **Process is Priority.** You are operating within a system that requires deterministic grounding and formal design before implementation.
- **Conductance**: `hyper` owners classification and gate verification.
-- **Specialization**: `website-builder` handles visual and frontend implementation.
+- **Specialization**: `frontend-builder` handles visual and frontend implementation.
- **Persistence**: You run in a stable Docker container with a persistent lifecycle.
---
@@ -226,7 +226,7 @@ The internal harness is what ties the public layers together by managing process
- bootstrap is injected at session start from generated runtime context
- `hyper` owns classification, routing, gates, and verification
-- `website-builder` specializes in website-facing design and implementation work
+- `frontend-builder` specializes in frontend-facing design and implementation work
- roles are internal and auto-called, not user-invoked commands
diff --git a/agents/frontend-builder/CHECKS.md b/agents/frontend-builder/CHECKS.md
new file mode 100644
index 0000000..8aea1cd
--- /dev/null
+++ b/agents/frontend-builder/CHECKS.md
@@ -0,0 +1,32 @@
+# Frontend Builder Checks
+
+## Preconditions
+
+- Delegation from `hyper` exists
+- Frontend scope is explicit
+- Required plan/design gate is active
+
+## Required Evidence
+
+- The package manifests and dependency signals that describe the active frontend stack
+- The core frontend file map for the active surface: routes, layouts, major
+ components, styles, tokens, navigation
+- Whether the task is existing-pattern frontend logic, frontend visual change,
+ or a new surface
+- State coverage for loading, empty, error, success, disabled, or destructive states
+- Responsive and accessibility implications
+- MCP-backed grounding for stack-specific implementation choices
+
+## Done Criteria
+
+- Workspace and frontend inventory are explicit and tied to the delegated task
+- Frontend scope completed without widening
+- Specialist output is ready for `hyper` to review
+- No shipping or completion claim made directly by `frontend-builder`
+
+## Red Flags
+
+- Acting like a page-only website builder instead of a frontend specialist
+- Implementing outside delegated scope
+- Missing state coverage or proof requirements
+- Claiming completion without handing back to `hyper`
diff --git a/agents/frontend-builder/CONTEXT.md b/agents/frontend-builder/CONTEXT.md
new file mode 100644
index 0000000..d605a4d
--- /dev/null
+++ b/agents/frontend-builder/CONTEXT.md
@@ -0,0 +1,30 @@
+# Frontend Builder Context Policy
+
+## Hot Context
+
+- Current delegated frontend task
+- Workspace inventory for the active frontend surface
+- Relevant package manifests and dependency signals
+- Core frontend files for the active page, flow, or component surface
+- Relevant user task and audience
+- Active frontend proof requirements
+- Targeted MCP outputs for design, UI/UX, tokens, motion, and stack choices
+
+## Warm Context
+
+- Approved `DESIGN.md` / design contract when required
+- Current plan slice
+- Route/layout/component/style inventory for the active surface
+- Relevant changed files or page components
+
+## Cold Context
+
+- Unrelated backend docs
+- Large reference docs not needed for the current frontend task
+- Historical design notes outside the active page or flow
+
+## Never Load
+
+- Whole repo philosophy documents when a targeted contract slice is enough
+- Unrelated plugin docs
+- Full codebase dumps for a single frontend task
diff --git a/agents/frontend-builder/LIFECYCLE.md b/agents/frontend-builder/LIFECYCLE.md
new file mode 100644
index 0000000..1dcaef9
--- /dev/null
+++ b/agents/frontend-builder/LIFECYCLE.md
@@ -0,0 +1,43 @@
+# Frontend Builder Lifecycle
+
+## Entry Criteria
+
+- `hyper` has classified the request as frontend work
+- Delegation to `frontend-builder` is explicit
+- Required planning or design gates are active
+
+## Steps
+
+1. Read the user workspace before making frontend decisions
+2. Inspect package manifests and dependencies (`package.json`, lockfiles, app
+ manifests) to understand the active frontend stack and tools
+3. Identify the core frontend files for the current surface: routes, layouts,
+ page components, tokens, styles, navigation, and major reusable UI modules
+4. Load only the frontend-relevant context slice after that inventory exists
+5. Resolve whether the task is existing-project frontend logic, frontend visual
+ change, or a new surface
+6. Use existing patterns first when they are trustworthy
+7. Produce or refine frontend design outputs only when the route requires a
+ design contract
+8. Implement frontend code only when delegated and within scope
+9. Return a specialist result package to `hyper` with evidence
+
+## Handoffs
+
+- `hyper -> frontend-builder` when the request is frontend-facing
+- `frontend-builder -> hyper` after specialist output is ready for review and
+ verification
+
+## Exit Criteria
+
+- Frontend-specific design or implementation output is complete for the
+ delegated scope
+- The workspace inventory is explicit: packages, stack, and core frontend files
+ are known
+- Required evidence is attached for `hyper` to verify
+
+## Failure Escalation
+
+- If the task drifts outside frontend work, stop and hand back to `hyper`
+- If planning or proof gates are missing, stop and hand back to `hyper`
+- If verification or shipping is requested, stop and hand back to `hyper`
diff --git a/agents/frontend-builder/PROFILE.md b/agents/frontend-builder/PROFILE.md
new file mode 100644
index 0000000..57305aa
--- /dev/null
+++ b/agents/frontend-builder/PROFILE.md
@@ -0,0 +1,54 @@
+---
+name: frontend-builder
+kind: specialist
+auto_invoke_when:
+ - frontend pages
+ - frontend component work
+ - website pages
+ - dashboards
+ - marketing sites
+ - frontend redesigns
+ - interaction-heavy UI work
+owns:
+ - frontend-specific design work when required by routing
+ - frontend-specific implementation work when delegated
+ - page structure and CTA hierarchy when website-facing
+ - frontend interaction quality
+ - existing-project frontend logic changes within established patterns
+must_not_do:
+ - self-ship
+ - bypass hyper
+ - widen scope outside delegated frontend work
+delegates_to:
+ - hyper
+requires:
+ - delegation from hyper
+ - active planning and verification gates from Hyperstack
+ - workspace inventory for the active frontend surface
+ - MCP-first grounding for frontend stack choices
+---
+
+# Frontend Builder Profile
+
+## Mission
+
+`frontend-builder` is Hyperstack's primary frontend specialist role. It owns
+frontend design and implementation work when delegated by `hyper`.
+
+## Authority
+
+- Produces and refines frontend-specific design decisions when a design contract
+ is required
+- Owns page structure, CTA hierarchy, state coverage, form friction, trust
+ signals, responsive content priority, and frontend interaction quality
+- Implements frontend code when delegated
+- Works from existing project patterns first; does not force greenfield design
+ contracts onto established systems
+
+## Boundaries
+
+`frontend-builder` is a general frontend specialist, not just a website-page
+role.
+
+`frontend-builder` must always hand back to `hyper` for verification and
+delivery.
diff --git a/agents/hyper/LIFECYCLE.md b/agents/hyper/LIFECYCLE.md
index 4b88421..3811faf 100644
--- a/agents/hyper/LIFECYCLE.md
+++ b/agents/hyper/LIFECYCLE.md
@@ -14,16 +14,16 @@
3. Classify the work using both the request and the workspace reality
4. Determine whether a specialist role is required
5. Enforce MCP-first and design/plan gates before implementation
-6. Route website-facing work to `website-builder`
+6. Route frontend-facing work to `frontend-builder`
7. Receive specialist output and verify it against the active plan or design
8. Run review, verification, and ship gates
9. Deliver the result or report blockers with evidence
## Handoffs
-- `hyper -> website-builder` for website pages, landing pages, dashboards,
- redesigns, and website-experience-heavy UI work
-- `website-builder -> hyper` after specialist design or implementation output is
+- `hyper -> frontend-builder` for frontend pages, landing pages, dashboards,
+ redesigns, and frontend-experience-heavy UI work
+- `frontend-builder -> hyper` after specialist design or implementation output is
ready for review and verification
## Exit Criteria
diff --git a/agents/hyper/PROFILE.md b/agents/hyper/PROFILE.md
index 793718a..9b00c57 100644
--- a/agents/hyper/PROFILE.md
+++ b/agents/hyper/PROFILE.md
@@ -16,7 +16,7 @@ must_not_do:
- skip MCP-first grounding
- allow completion claims without verification evidence
delegates_to:
- - website-builder
+ - frontend-builder
requires:
- current bootstrap invariants from hyperstack
- approved design before implementation when required
@@ -42,5 +42,5 @@ routing, gate enforcement, lifecycle transitions, and final verification.
`hyper` does not exist to absorb all work. It delegates specialist work when the
request is clearly in a specialist domain.
-For website-facing work, `hyper` routes to `website-builder` and later regains
+For frontend-facing work, `hyper` routes to `frontend-builder` and later regains
control for review, verification, and delivery.
diff --git a/docs/harness/context-policy.md b/docs/harness/context-policy.md
index 9b2a717..2c2421f 100644
--- a/docs/harness/context-policy.md
+++ b/docs/harness/context-policy.md
@@ -8,11 +8,11 @@ Each internal role should load only the context slice it needs.
- `hyper`
- classification, routing, gates, verification, delivery
-- `website-builder`
+- `frontend-builder`
- workspace inventory
- package manifests and dependency signals
- core frontend files for the active surface
- - website intent, page structure, website-experience constraints, website code
+ - frontend intent, page structure, frontend experience constraints, frontend code
## Tiers
diff --git a/docs/harness/router.md b/docs/harness/router.md
index f04c611..86ac37d 100644
--- a/docs/harness/router.md
+++ b/docs/harness/router.md
@@ -8,8 +8,9 @@ Users do not invoke internal roles directly. Roles are internal and auto-called.
## Routing Matrix
-Route `hyper -> website-builder` when the request is primarily about:
+Route `hyper -> frontend-builder` when the request is primarily about:
+- frontend component work
- landing pages
- dashboards
- marketing or product websites
@@ -25,7 +26,7 @@ Before routing, `hyper` must inspect the workspace enough to know:
- which package manifests and dependency signals define the active frontend stack
- which core frontend files likely own the affected surface
-- whether the request is actually website-facing rather than generic frontend or
+- whether the request is actually frontend-facing rather than backend
backend work
Keep work in `hyper` when the request is primarily about:
diff --git a/docs/harness/transitions.md b/docs/harness/transitions.md
index a023723..4909d5b 100644
--- a/docs/harness/transitions.md
+++ b/docs/harness/transitions.md
@@ -3,17 +3,17 @@
## Allowed
- `user request -> hyper`
-- `hyper -> website-builder`
-- `website-builder -> hyper`
+- `hyper -> frontend-builder`
+- `frontend-builder -> hyper`
- `hyper -> existing Hyperstack skills/plugins`
- `hyper -> verification and delivery gates`
## Disallowed
-- `user request -> website-builder`
-- `website-builder -> ship`
-- `website-builder -> deliver`
-- `website-builder` claiming final completion directly
+- `user request -> frontend-builder`
+- `frontend-builder -> ship`
+- `frontend-builder -> deliver`
+- `frontend-builder` claiming final completion directly
## V1 Principle
diff --git a/generated/runtime-context/hyperstack.bootstrap.md b/generated/runtime-context/hyperstack.bootstrap.md
index 649261d..a501506 100644
--- a/generated/runtime-context/hyperstack.bootstrap.md
+++ b/generated/runtime-context/hyperstack.bootstrap.md
@@ -69,14 +69,14 @@ You cannot rationalize exceptions to this rule.
## Internal Agents
- Roles are internal and auto-called. Users do not invoke them directly.
- Internal roles are auto-called, not user-facing.
-- hyper -> website-builder
+- hyper -> frontend-builder
- `hyper`: Classification, routing, gate enforcement, final verification, delivery
-- `website-builder`: Website-facing design/implementation, CTA hierarchy, page structure
+- `frontend-builder`: Frontend-facing design/implementation, CTA hierarchy, page structure, and existing-project frontend logic work
## Disallowed Transitions
-- `user request -> website-builder`
-- `website-builder -> ship`
-- `website-builder -> deliver`
+- `user request -> frontend-builder`
+- `frontend-builder -> ship`
+- `frontend-builder -> deliver`
## High-Signal Red Flags
- "I know the React Flow API from memory." -> Memory drifts. v11 and v12 differ.
diff --git a/skills/hyperstack/SKILL.md b/skills/hyperstack/SKILL.md
index 2d6b70d..966d97e 100644
--- a/skills/hyperstack/SKILL.md
+++ b/skills/hyperstack/SKILL.md
@@ -138,13 +138,13 @@ Internal roles β auto-invoked, not user-facing.
| Agent | Owns |
|---|---|
| `hyper` | Classification, routing, gate enforcement, final verification, delivery |
-| `website-builder` | Website-facing design/implementation, CTA hierarchy, page structure |
+| `frontend-builder` | Frontend-facing design/implementation, CTA hierarchy, page structure, and existing-project frontend logic work |
### Disallowed Transitions
-- `user request -> website-builder`
-- `website-builder -> ship`
-- `website-builder -> deliver`
+- `user request -> frontend-builder`
+- `frontend-builder -> ship`
+- `frontend-builder -> deliver`
---
diff --git a/src/internal/context-compiler.ts b/src/internal/context-compiler.ts
index d1987a1..c27de98 100644
--- a/src/internal/context-compiler.ts
+++ b/src/internal/context-compiler.ts
@@ -44,9 +44,9 @@ const REQUIRED_BOOTSTRAP_MARKERS = [
"MCP unavailable",
"announce it",
"hyper",
- "website-builder",
+ "frontend-builder",
"auto-called",
- "hyper -> website-builder",
+ "hyper -> frontend-builder",
];
function stripFrontmatter(source: string): string {
@@ -179,8 +179,8 @@ function extractInternalAgents(source: string): string[] {
output.push("- Internal roles are auto-called, not user-facing.");
}
- if (agentNames.includes("hyper") && agentNames.includes("website-builder")) {
- output.push("- hyper -> website-builder");
+ if (agentNames.includes("hyper") && agentNames.includes("frontend-builder")) {
+ output.push("- hyper -> frontend-builder");
}
output.push(
diff --git a/tests/role-harness-behaviour.test.ts b/tests/role-harness-behaviour.test.ts
index 6a5e620..f6149fd 100644
--- a/tests/role-harness-behaviour.test.ts
+++ b/tests/role-harness-behaviour.test.ts
@@ -11,10 +11,10 @@ const REQUIRED_ROLE_FILES = [
"agents/hyper/LIFECYCLE.md",
"agents/hyper/CONTEXT.md",
"agents/hyper/CHECKS.md",
- "agents/website-builder/PROFILE.md",
- "agents/website-builder/LIFECYCLE.md",
- "agents/website-builder/CONTEXT.md",
- "agents/website-builder/CHECKS.md",
+ "agents/frontend-builder/PROFILE.md",
+ "agents/frontend-builder/LIFECYCLE.md",
+ "agents/frontend-builder/CONTEXT.md",
+ "agents/frontend-builder/CHECKS.md",
"harness/router.md",
"harness/transitions.md",
"harness/context-policy.md",
@@ -35,7 +35,7 @@ function normalize(str: string): string {
return str.replace(/\r\n/g, "\n");
}
-test("role harness files exist for hyper and website-builder", () => {
+test("role harness files exist for hyper and frontend-builder", () => {
for (const relativePath of REQUIRED_ROLE_FILES) {
expect(existsSync(resolve(relativePath))).toBe(true);
}
@@ -44,7 +44,7 @@ test("role harness files exist for hyper and website-builder", () => {
test("role profile frontmatter includes the required contract keys", () => {
for (const relativePath of [
"agents/hyper/PROFILE.md",
- "agents/website-builder/PROFILE.md",
+ "agents/frontend-builder/PROFILE.md",
]) {
const content = normalize(readFileSync(resolve(relativePath), "utf8"));
const frontmatter = content.match(/^---\n([\s\S]*?)\n---\n/);
@@ -66,7 +66,7 @@ test("role lifecycle and checks documents expose required headings", () => {
expect(lifecycleContent).toMatch(/^## Exit Criteria$/m);
expect(lifecycleContent).toMatch(/^## Failure Escalation$/m);
- const checksContent = normalize(readFileSync(resolve("agents/website-builder/CHECKS.md"), "utf8"));
+ const checksContent = normalize(readFileSync(resolve("agents/frontend-builder/CHECKS.md"), "utf8"));
expect(checksContent).toMatch(/^## Preconditions$/m);
expect(checksContent).toMatch(/^## Required Evidence$/m);
expect(checksContent).toMatch(/^## Done Criteria$/m);
@@ -80,14 +80,14 @@ test("hyperstack bootstrap compiler preserves role-routing markers", () => {
expect(missing.length).toBe(0);
expect(content).toMatch(/hyper/);
- expect(content).toMatch(/website-builder/);
+ expect(content).toMatch(/frontend-builder/);
expect(content).toMatch(/auto-called/);
- expect(content).toMatch(/hyper -> website-builder/);
+ expect(content).toMatch(/hyper -> frontend-builder/);
});
-test("website-builder lifecycle requires workspace discovery before website decisions", () => {
- const lifecycleContent = normalize(readFileSync(resolve("agents/website-builder/LIFECYCLE.md"), "utf8"));
- const contextContent = normalize(readFileSync(resolve("agents/website-builder/CONTEXT.md"), "utf8"));
+test("frontend-builder lifecycle requires workspace discovery before frontend decisions", () => {
+ const lifecycleContent = normalize(readFileSync(resolve("agents/frontend-builder/LIFECYCLE.md"), "utf8"));
+ const contextContent = normalize(readFileSync(resolve("agents/frontend-builder/CONTEXT.md"), "utf8"));
expect(lifecycleContent).toMatch(/workspace/i);
expect(lifecycleContent).toMatch(/package\.json|manifests?|dependencies|packages/i);