From 3eaa7c0bffa1c324a82c25870a5cd0d95cd33264 Mon Sep 17 00:00:00 2001 From: EagleFox31 <86088743+EagleFox31@users.noreply.github.com> Date: Fri, 9 Oct 2026 22:33:12 +0100 Subject: [PATCH 01/11] feat(wow): add SKILL.md skill resource --- skills/wow-frontend/SKILL.md | 68 ++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 skills/wow-frontend/SKILL.md diff --git a/skills/wow-frontend/SKILL.md b/skills/wow-frontend/SKILL.md new file mode 100644 index 0000000..555c0af --- /dev/null +++ b/skills/wow-frontend/SKILL.md @@ -0,0 +1,68 @@ +--- +name: wow-frontend +description: Plan and implement visually distinctive marketing/product pages using AppFactory's existing UI registry, vetted source research, intentional motion, real screenshots, accessibility and performance verification. Use for new or brownfield landing pages; never assume third-party code reuse is authorized. +--- + +# WOW Frontend — Trigenys AppFactory + +You are the implementation assistant for a **real product**, not a screenshot generator. The product owns its source code, framework, style system and deployment; AppFactory provides reusable guidance and contracts. + +## Read in this order + +1. The consumer's `AGENTS.md` / RAIDER policy, package manifest, current routes, styles/tokens, assets, deployed behavior and existing tests. **Inspect the actual consumer; do not assume the AppFactory template is its stack.** +2. This skill and [source selection](references/source-selection.md), [composition](references/composition.md), [motion](references/motion.md) and [visual QA](references/visual-qa.md). +3. Canonical source inventory: `ui-registry/wow-sources.json`; native component registry: `ui-registry/registry.json`; brand profiles: `ui-registry/profiles.json`; central security approvals: `ui-registry/wow-review-policy.json`. Resolve paths relative to the **AppFactory repository root**, not the consumer. +4. Existing contracts: `ui-registry/wow-contract.mjs`, `ui-registry/wow-security.mjs`, `docs/wow-reuse-security.md`. + +## Mandatory workflow + +### 1. AUDIT — understand the consumer before changing it + +Record product/audience, primary conversion action, real routes/behaviors, existing stack and styling, breakpoints, brand/typography, proof permissions, languages, image sources, performance baseline and current tests. State uncertainties explicitly. Do not invent deployment status, customer logos, partnerships, conversion metrics or testimonials. + +### 2. ART DIRECTION — choose a defensible visual idea + +Define a one-sentence art direction and two alternatives. Specify typography scale, color and imagery treatment, whitespace/grid, dominant focal point and section rhythm. Include a **content-first** journey explaining the product's actual value. Use [composition](references/composition.md), not arbitrary gradients, glowing blobs or “generic SaaS” styling. + +### 3. SEARCH BEFORE BUILD — inspect approved metadata, not random packages + +First check existing consumer components, then `ui-registry/registry.json`, then `ui-registry/wow-sources.json`. Use `node scripts/wow-frontend-plan.mjs ` for a **read-only dry run**, when the two configs are available. + +Every external entry in the current inventory is *reference-only*. The central `wow-review-policy.json` ships with **zero approvals**. Even when a source says MIT in GitHub metadata, **do not copy, install or execute its code**; its status does not become permission through a consumer prompt or `source.allow`. See [source selection](references/source-selection.md). External tools (Figma, MagicPath, Webflow or 21st.dev) are optional ideation tools, never automatic dependencies. + +### 4. COMPOSE — build in the consumer's stack + +Prefer the smallest original/native primitive that serves the visual story; reuse actual consumer assets and brand tokens. Do not add Tailwind, Next.js, Webflow, GSAP, Three.js or another runtime merely to acquire one effect. Preserve routes, API semantics, internationalization and truthful product behavior. Scope edits to a dedicated branch and keep production credentials out of the repository. + +For third-party material, stop at research/concept until the approval/adapter process is completed under #140/#142. Do not infer that a source marked “approved” in a future review automatically grants execution; `assessWowAdoption()` currently never executes. + +### 5. ANIMATE WITH PURPOSE — never animate away usability + +Only animate a cause/effect, hierarchy change, product state, meaningful transition or CTA focus. Every animation must have a legible, functional `prefers-reduced-motion` path. Avoid scroll-jacking, continuous distraction, layout shift and duplicate animation libraries. See [motion](references/motion.md). + +### 6. RENDER BEFORE DONE — mandatory real verification + +Run the consumer's typecheck/tests/build, then render the actual page at desktop and mobile viewports. Save/inspect real screenshots; test keyboard, focus states, CTA destination, no overflow, broken media, console errors, FR/EN content if applicable, reduced-motion path, and measured performance. Follow [visual QA](references/visual-qa.md). **A local planning script or source-code review is never evidence of rendered QA.** + +A PR may remain open or the task marked **blocked/partial** until screenshot and runtime checks exist; never mark these tests “PASS” unless run. The reusable automated visual-QA workflow is separately tracked in `EagleFox31/appfactory-project-automation#99`. + +### 7. PROVENANCE — preserve source and license evidence + +If external code is ever copied under an explicitly reviewed future approval, commit the component, license notice and `.appfactory/frontend-provenance.json` in the consumer repository. Use `reconcileWowProvenance()` and `verifyWowProvenanceFiles()` from AppFactory. Current inventory is reference-only: no provenance entry is required for visual inspiration alone, but describe the source as **reference**, not “installed component”. + +### 8. HANDOFF — report facts, not expectations + +Report: files changed, source and license decisions, actual preview/PR, tests run vs skipped, screenshot results, accessibility/performance results, known defects, deployment state and follow-up. “WOW complete” requires passing [visual QA](references/visual-qa.md), not just a convincing mockup. + +## RAIDER gates + +Reusable, Agnostic, Idempotent, Durable/non-regressive, Engineering-grade, Retroactive. A prior working project must still work after this skill is used. + +## Anti-patterns + +- Fake merchant logos, figures, testimonials, “1000+ shops”, fabricated conversion lifts or unapproved partner branding. +- Template-soup landing sections without content hierarchy or a coherent visual story. +- Random motion/background effects with no product intent. +- Unreviewed third-party code, images, fonts, registry installers or `curl | sh`. +- Replacing a brownfield stack for a single component. +- Declaring screenshot, mobile performance, accessibility or production deployment “done” without observed evidence. From 0c4a45a72f3a6aad1a3f899ccfc74e068621aac8 Mon Sep 17 00:00:00 2001 From: EagleFox31 <86088743+EagleFox31@users.noreply.github.com> Date: Fri, 9 Oct 2026 22:33:14 +0100 Subject: [PATCH 02/11] feat(wow): add source-selection.md skill resource --- .../references/source-selection.md | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 skills/wow-frontend/references/source-selection.md diff --git a/skills/wow-frontend/references/source-selection.md b/skills/wow-frontend/references/source-selection.md new file mode 100644 index 0000000..fc5e1d4 --- /dev/null +++ b/skills/wow-frontend/references/source-selection.md @@ -0,0 +1,50 @@ +# Source selection — search before build + +## Source-of-truth order + +1. The consumer's existing components and design system (first). +2. Native Trigenys components in `ui-registry/registry.json`, whose provenance is recorded in `ui-registry/provenance.json`. +3. External **research inventory** in `ui-registry/wow-sources.json`; consult `ui-registry/wow-review-policy.json` for centralized decisions. +4. Only then consider a new original component. + +Do **not** create a second shadcn registry; `wow-sources.json` is metadata for research, not installable `registry.json` items. + +## Resolve the existing contracts + +From the AppFactory repository root: + +```sh +node ui-registry/wow-contract.mjs +node scripts/wow-frontend-plan.mjs skills/wow-frontend/examples/commerce-factory.brief.json ui-registry/examples/wow-react-vite-css.json +``` + +A plan is **read-only** and uses repository-pinned metadata; it does not crawl GitHub or produce code. Invalid source IDs, permissions, malformed configs and unknown fields must fail closed. Treat the result as a candidate list for further review, never as a tested compatibility guarantee. + +## Distinguish status from technical fit + +- `blocked`: unknown, explicitly denied or policy invalid; do not use. +- `review-required`: missing authoritative license evidence; inspect only as a conceptual reference. +- `reference-only`: catalogued for inspiration; **no code copy, install or execution**. +- `approved`: a *specific* source commit/mode reviewed centrally; still requires downstream adapter, provenance and consumer review. Never interpret this as a shell execution permit. + +The current central policy has **zero approvals** and the published inventory disables all external execution. + +The existing planner's `native-reference`, `adaptation-reference` and `design-reference` labels describe **research fit only**. A Tailwind reference for React/Vite + plain CSS is a cue to recreate *original styling* in the existing stack, not to paste upstream snippets or add Tailwind. + +## Approval and licensing + +Before copying external code or assets in a future phase: identify the exact upstream 40-character commit SHA, authoritative LICENSE/COPYING file at that SHA, per-component and paid/Pro exceptions, transitive dependencies and licenses, required notices, acceptable modes, reviewer and review date. Record a central review in `wow-review-policy.json`; run `assessWowAdoption()` without bypassing any rejection. See `docs/wow-reuse-security.md`. This skill alone cannot approve sources. + +Never fetch/execute remote install scripts or silently run `npx` from a README. Never hotlink unlicensed product photography or reuse trademarked merchant branding without permission. + +## Decision output + +For each considered primitive capture: + +- the actual UX problem it solves; +- native/current component vs external source ID; +- framework/styling compatibility and runtime cost; +- legal status / evidence and required notices; +- use mode (`existing-native`, `original-reimplementation`, or `research-only`); +- reason for rejection/adoption; +- impact on responsive layout, reduced motion, accessibility and bundle size. From d23c77e6c1adcb66bc6b4db88ae2139f7cd8cdb1 Mon Sep 17 00:00:00 2001 From: EagleFox31 <86088743+EagleFox31@users.noreply.github.com> Date: Fri, 9 Oct 2026 22:33:17 +0100 Subject: [PATCH 03/11] feat(wow): add composition.md skill resource --- skills/wow-frontend/references/composition.md | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 skills/wow-frontend/references/composition.md diff --git a/skills/wow-frontend/references/composition.md b/skills/wow-frontend/references/composition.md new file mode 100644 index 0000000..039bb06 --- /dev/null +++ b/skills/wow-frontend/references/composition.md @@ -0,0 +1,44 @@ +# Composition — make the landing worth scrolling + +The sequence must follow the buyer's real decision, not a list of widgets. + +## Establish one visual thesis + +State who the page is for, the pain solved, the primary CTA and the product behavior to demonstrate. Choose one coherent art direction and two honest alternatives. Specify: + +- typography: headline/body pairing and scale; +- layout: container width, grid, vertical rhythm, visual asymmetry; +- palette: existing tokens first; one clear accent and high contrast; +- visuals: self-hosted real assets or clearly labeled mockups; mobile crop; +- interaction: intentional proof of product behavior; +- sections: why each exists and what visitor learns; +- mobile hierarchy: what survives without animation and hover. + +## Example story skeleton (adapt, never blindly paste) + +1. **Hero:** one product promise, one primary CTA, clear visual product evidence. +2. **Product in context:** show recognizable work in the actual product UI. +3. **Progressive transformation:** a user action leads to an observable outcome. +4. **Relevant capabilities:** three differentiated jobs, not twelve vague features. +5. **Truthful trust:** security/process facts, authorized real examples or none. +6. **Clear conversion:** CTA to the actual destination and a short expectation. + +Bento grids, sticky storytelling, large editorial typography and clean browser/phone mockups are **tools**, not requirements. Avoid same-looking AI SaaS gradients, empty decorative blocks and infinite scrollytelling. + +## Commerce Factory example — real repo observed + +`Trigenys/trigenys-commerce-factory` is React 19/TypeScript/Vite with existing plain `src/styles.css`, FR/EN content, optimized self-hosted AVIF/WebP imagery, storefront/product visuals and WhatsApp handoff. It should **not** be migrated to Tailwind, Next.js or Webflow for a landing refresh. + +A grounded story is: + +```text +merchant product imagery + → catalog/storefront presentation + → product selected + → WhatsApp action with product context + → practical merchant benefit +``` + +Preserve actual app links, FCFA context and the bilingual interface. Fictional demonstration stores must be labeled demos. No unapproved prospect branding, fake merchant results or made-up testimonials. + +The reference brief in `skills/wow-frontend/examples/commerce-factory.brief.json` is for **read-only planning**; it does not change Commerce Factory. From 656ee609dcab2dcd62c806a667336e7323b522aa Mon Sep 17 00:00:00 2001 From: EagleFox31 <86088743+EagleFox31@users.noreply.github.com> Date: Fri, 9 Oct 2026 22:33:19 +0100 Subject: [PATCH 04/11] feat(wow): add motion.md skill resource --- skills/wow-frontend/references/motion.md | 29 ++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 skills/wow-frontend/references/motion.md diff --git a/skills/wow-frontend/references/motion.md b/skills/wow-frontend/references/motion.md new file mode 100644 index 0000000..28aaae8 --- /dev/null +++ b/skills/wow-frontend/references/motion.md @@ -0,0 +1,29 @@ +# Motion — intentional, restrained, reversible + +Animation is justified only when it clarifies hierarchy, explains product flow, demonstrates state change, connects cause and effect or directs attention to a useful CTA. + +## Choose the least expensive tool + +1. CSS transitions/keyframes for fades, hover/focus, subtle reveals and minor motion. +2. Existing consumer animation runtime if already present and genuinely needed. +3. A heavier library (Motion/GSAP/3D) only after a written rationale, dependency/license review and bundle/performance budget. + +Do **not** install multiple overlapping motion runtimes. Keep hover-only effects decorative, never required to access content. + +## Non-negotiable behavior + +- Honor `@media (prefers-reduced-motion: reduce)`: content and CTA remain available; avoid motion-dependent navigation and offer static end states. +- No scroll-jacking, blocked scrolling or trapped focus. +- Avoid animating layout geometry that causes CLS; prefer opacity/transforms with measured impact. +- Avoid seizure-inducing flashing and relentless loops. +- Pause or stop long-running interactive motion when off-screen if necessary. +- Use clear touch/keyboard alternatives to pointer-hover interactions. +- On low-end phones test battery/runtime impact and input responsiveness. + +## Commerce Factory example + +A product card can visually transition to a storefront preview and then emphasize the WhatsApp CTA. All product information, pricing context and CTA must remain readable with **zero animation**. The design may show the prefilled product context *only if that behavior exists in the implemented flow*. + +## Evidence + +A text-only plan cannot establish animation performance. Record screenshots for static states, test reduced-motion mode in a real browser, inspect tab order and check measured CLS/LCP/TBT/INP where supported. If not tested, say **NOT VERIFIED**, not PASS. From 8c7f48dd10d87262629a6642bf16b33a3d70f75a Mon Sep 17 00:00:00 2001 From: EagleFox31 <86088743+EagleFox31@users.noreply.github.com> Date: Fri, 9 Oct 2026 22:33:21 +0100 Subject: [PATCH 05/11] feat(wow): add visual-qa.md skill resource --- skills/wow-frontend/references/visual-qa.md | 36 +++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 skills/wow-frontend/references/visual-qa.md diff --git a/skills/wow-frontend/references/visual-qa.md b/skills/wow-frontend/references/visual-qa.md new file mode 100644 index 0000000..9b9ba1c --- /dev/null +++ b/skills/wow-frontend/references/visual-qa.md @@ -0,0 +1,36 @@ +# Visual QA — render before done + +A completed PR requires **observed rendered evidence**, not merely valid JSX or a passing typecheck. + +## Minimum matrix + +- Desktop at **1440px** and mobile at **390px**. Add **360px/768px** for fragile responsive components. +- Main landing route and primary conversion path. +- Key sections above the fold and at least one long-scroll state. +- Keyboard navigation, skip link/focus, accessible names and primary CTA reachable with Enter/Space as appropriate. +- `prefers-reduced-motion` actual browser setting or emulation. +- No horizontal overflow, clipped content, missing images or blocked CTA. +- Console errors and failed network requests. +- FR/EN or other supported languages (including long translations). +- Image weight and truthful alt text; externally hosted images reviewed for licensing. +- Baseline vs candidate screenshots to detect layout regressions. + +## Performance budgets (consumer-controlled) + +Proposed defaults: LCP <= 2500ms, CLS <= 0.10 and TBT <= 200ms, with mobile realistic throttling where appropriate. These are **targets**, not assertions. INP may also be tracked in field or synthetic interactions. Report the test conditions, page URL/commit, device, tool and any exceptions. + +Run the consumer's own `typecheck`, tests and build, then a real browser/Playwright/Lighthouse or approved equivalent. The reusable automation workflow is tracked separately in `EagleFox31/appfactory-project-automation#99`. Its existence in the backlog does not mean visual tests have already run. + +## Evidence ledger + +| Gate | Evidence required | Allowed status | +| --- | --- | --- | +| Build | actual command, commit, exit result | PASS / FAIL / NOT RUN | +| Desktop screenshot | captured render + manual inspection | PASS / FAIL / NOT RUN | +| Mobile screenshot | captured render + overflow inspection | PASS / FAIL / NOT RUN | +| Keyboard/focus | observed interaction | PASS / FAIL / NOT RUN | +| Reduced motion | observed alternate behavior | PASS / FAIL / NOT RUN | +| Performance | tool results and thresholds | PASS / FAIL / NOT RUN | +| Provenance | central approval + consumer notices when reused | PASS / FAIL / NOT APPLICABLE | + +**No evidence → NOT RUN.** If the render cannot be inspected, leave the implementation awaiting validation; do not call the landing "wow complete." Keep the distinction between a useful *read-only plan* and a *deployed, verified page* explicit. From bb4c43833a9f3c3f7759dbe0951f8c0bcc1181ec Mon Sep 17 00:00:00 2001 From: EagleFox31 <86088743+EagleFox31@users.noreply.github.com> Date: Fri, 9 Oct 2026 22:33:23 +0100 Subject: [PATCH 06/11] feat(wow): add commerce-factory.brief.json skill resource --- .../examples/commerce-factory.brief.json | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 skills/wow-frontend/examples/commerce-factory.brief.json diff --git a/skills/wow-frontend/examples/commerce-factory.brief.json b/skills/wow-frontend/examples/commerce-factory.brief.json new file mode 100644 index 0000000..108340f --- /dev/null +++ b/skills/wow-frontend/examples/commerce-factory.brief.json @@ -0,0 +1,26 @@ +{ + "version": 1, + "project": "Trigenys Commerce Factory", + "repository": "Trigenys/trigenys-commerce-factory", + "audience": "Camerounian merchants selling products via a catalog and WhatsApp", + "primaryConversion": "Open merchant onboarding /app", + "artDirection": "Distinctive product-first commerce with real store visuals, warm accents and purposeful transitions", + "narrative": [ + "Show recognizable product imagery", + "Demonstrate the catalog/storefront presentation", + "Connect a chosen product to a WhatsApp conversation", + "Explain what merchants can do next" + ], + "constraints": { + "preserveStack": true, + "languages": [ + "fr", + "en" + ], + "assets": "self-hosted", + "merchants": "fictional-demo-only-unless-approved", + "truthfulProofOnly": true, + "reducedMotion": true + }, + "notes": "Based on a read-only inspection of Commerce Factory README, package.json, src/App.tsx and src/styles.css. No product changes or browser QA performed." +} From e235592089b21d39d539014d3b606ffbeb1d89e3 Mon Sep 17 00:00:00 2001 From: EagleFox31 <86088743+EagleFox31@users.noreply.github.com> Date: Fri, 9 Oct 2026 22:34:05 +0100 Subject: [PATCH 07/11] feat(wow): add deterministic read-only skill planning CLI --- scripts/wow-frontend-plan.mjs | 141 ++++++++++++++++++++++++++++++++++ 1 file changed, 141 insertions(+) create mode 100644 scripts/wow-frontend-plan.mjs diff --git a/scripts/wow-frontend-plan.mjs b/scripts/wow-frontend-plan.mjs new file mode 100644 index 0000000..c0785f2 --- /dev/null +++ b/scripts/wow-frontend-plan.mjs @@ -0,0 +1,141 @@ +#!/usr/bin/env node +// Read-only agent planning helper. No network, writes, copying, package installation or browser QA. +import fs from "node:fs"; +import path from "node:path"; +import process from "node:process"; +import { fileURLToPath } from "node:url"; +import { previewWowSources, readWowRegistry } from "../ui-registry/wow-contract.mjs"; +import { validateWowReviewPolicy, wowSourceDisposition } from "../ui-registry/wow-security.mjs"; + +const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), ".."); +const POLICY_PATH = path.join(ROOT, "ui-registry", "wow-review-policy.json"); +const record = (x) => x !== null && typeof x === "object" && !Array.isArray(x); +const normalize = (s) => typeof s === "string" ? s.trim() : ""; +const nonEmpty = (s) => normalize(s).length > 0; +const ISO_LANG = /^[a-z]{2,3}(-[A-Z]{2})?$/; + +export function validateWowBrief(brief) { + const errors = []; + if (!record(brief)) return ["brief must be an object"]; + const fields = ["version","project","repository","audience","primaryConversion","artDirection","narrative","constraints","notes"]; + for (const field of Object.keys(brief)) if (!fields.includes(field)) errors.push("unknown brief field: " + field); + if (brief.version !== 1) errors.push("brief.version must be 1"); + for (const field of ["project","audience","primaryConversion","artDirection"]) { + if (!nonEmpty(brief[field]) || normalize(brief[field]).length > 500) errors.push(field + " must be concise nonempty text"); + } + if (typeof brief.repository !== "string" || + !/^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/.test(brief.repository)) { + errors.push("repository must use owner/name"); + } + if (!Array.isArray(brief.narrative) || brief.narrative.length < 2 || brief.narrative.length > 10 || + brief.narrative.some((s) => !nonEmpty(s) || s.length > 400)) { + errors.push("narrative must contain 2-10 concise product story steps"); + } + if (!record(brief.constraints)) errors.push("constraints must be an object"); + else { + const allowed = ["preserveStack","languages","assets","merchants","truthfulProofOnly","reducedMotion","thirdPartyBranding"]; + for (const key of Object.keys(brief.constraints)) if (!allowed.includes(key)) errors.push("unknown constraint: " + key); + for (const flag of ["preserveStack","truthfulProofOnly","reducedMotion"]) { + if (brief.constraints[flag] !== true) errors.push(flag + " must be true"); + } + const languages = brief.constraints.languages; + if (!Array.isArray(languages) || !languages.length || new Set(languages).size !== languages.length || + languages.some((s) => typeof s !== "string" || !ISO_LANG.test(s))) { + errors.push("languages must be distinct language tags"); + } + if (!["self-hosted","rights-reviewed"].includes(brief.constraints.assets)) errors.push("assets must be self-hosted or rights-reviewed"); + if (brief.constraints.merchants !== undefined && + brief.constraints.merchants !== "fictional-demo-only-unless-approved") { + errors.push("real merchant branding requires explicit approval"); + } + if (brief.constraints.thirdPartyBranding !== undefined && + brief.constraints.thirdPartyBranding !== "explicit-permission") { + errors.push("thirdPartyBranding must require explicit-permission"); + } + } + if (brief.notes !== undefined && (typeof brief.notes !== "string" || brief.notes.length > 3000)) + errors.push("notes must be short text"); + return errors; +} + +const phases = [ + {id:"audit", action:"Inspect real consumer routes, package dependencies, existing components and asset ownership",status:"NOT RUN"}, + {id:"art-direction",action:"Define typography, hierarchy, composition, focal imagery and alternate directions",status:"NOT RUN"}, + {id:"source-selection",action:"Search existing consumer/native components before proposing original code",status:"NOT RUN"}, + {id:"compose",action:"Implement original/native responsive layout in the unchanged consumer stack",status:"NOT RUN"}, + {id:"motion",action:"Add meaningful transitions with keyboard and reduced-motion alternatives",status:"NOT RUN"}, + {id:"render",action:"Capture and inspect real 1440px/390px browser screenshots",status:"NOT RUN"}, + {id:"verify",action:"Run typecheck/build, accessibility, keyboard, reduced motion and measured performance checks",status:"NOT RUN"}, + {id:"provenance",action:"Verify licenses/notices and record adopted code only under future central approvals",status:"NOT RUN"} +]; + +export function planWowFrontend({brief,consumer,inventory,policy}) { + const errors = [ + ...validateWowBrief(brief), + ...validateWowReviewPolicy(policy,inventory) + ]; + const sources = previewWowSources(consumer,inventory); + if (!sources.ok) errors.push(...sources.errors.map((e) => "consumer/source: " + e)); + if (errors.length) return {ok:false,mode:"DRY_RUN",errors,steps:[],sources:[],evidence:{}}; + if (!consumer.enabled) { + return {ok:true,mode:"DRY_RUN",status:"DISABLED",project:brief.project, + repository:brief.repository,steps:[],sources:[],evidence:{},operationsAllowed:false}; + } + const candidates = sources.sources.map((candidate) => ({ + ...candidate, + disposition:wowSourceDisposition(candidate.id,inventory,policy).status, + legalReuseDecision:"NO CODE COPY / NO INSTALL / NO EXECUTION" + })); + return { + ok:true, + mode:"DRY_RUN", + status:"PLAN_ONLY", + project:brief.project, + repository:brief.repository, + audience:brief.audience, + primaryConversion:brief.primaryConversion, + artDirection:brief.artDirection, + narrative:[...brief.narrative], + unchangedStack:{...consumer.stack}, + languages:[...brief.constraints.languages], + sources:candidates, + steps:phases.map((phase) => ({...phase})), + guardrails:{ + preserveStack:true,truthfulProofOnly:true,reducedMotionRequired:true, + thirdPartyComponentInstall:false,thirdPartyCodeCopy:false, + noUnapprovedMerchantBranding:true, + neverClaimRenderedQAWithoutBrowser:true + }, + evidence:{ + repositoryInspection:"NOT RUN (consumer metadata was supplied, not audited)", + browserScreenshots:"NOT RUN",keyboard:"NOT RUN", + reducedMotion:"NOT RUN",performance:"NOT RUN",build:"NOT RUN",deployment:"NOT VERIFIED" + }, + operationsAllowed:false, + nextAction:"Verify this brief against the actual repository, select original/native design primitives, implement in a dedicated PR and perform real browser QA." + }; +} + +export function dryRunWowBriefFiles(briefPath,consumerPath) { + const brief = JSON.parse(fs.readFileSync(path.resolve(briefPath),"utf8")); + const consumer = JSON.parse(fs.readFileSync(path.resolve(consumerPath),"utf8")); + const policy = JSON.parse(fs.readFileSync(POLICY_PATH,"utf8")); + return planWowFrontend({brief,consumer,inventory:readWowRegistry(),policy}); +} + +if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) { + const [briefPath,consumerPath] = process.argv.slice(2); + if (!briefPath || !consumerPath) { + process.stderr.write("Usage: node scripts/wow-frontend-plan.mjs \n"); + process.exitCode = 2; + } else { + try { + const output = dryRunWowBriefFiles(briefPath,consumerPath); + process.stdout.write(JSON.stringify(output,null,2) + "\n"); + if (!output.ok) process.exitCode = 1; + } catch (error) { + process.stderr.write("Unable to plan WOW Frontend: " + error.message + "\n"); + process.exitCode = 1; + } + } +} From 1d3b2f232694ae5ab22cbf672348088b5c4b8aca Mon Sep 17 00:00:00 2001 From: EagleFox31 <86088743+EagleFox31@users.noreply.github.com> Date: Fri, 9 Oct 2026 22:34:39 +0100 Subject: [PATCH 08/11] test(wow): verify skill structure, real dry-run plan and safety boundaries --- test/wow-frontend-skill.test.mjs | 156 +++++++++++++++++++++++++++++++ 1 file changed, 156 insertions(+) create mode 100644 test/wow-frontend-skill.test.mjs diff --git a/test/wow-frontend-skill.test.mjs b/test/wow-frontend-skill.test.mjs new file mode 100644 index 0000000..be96281 --- /dev/null +++ b/test/wow-frontend-skill.test.mjs @@ -0,0 +1,156 @@ +import assert from "node:assert/strict"; +import crypto from "node:crypto"; +import fs from "node:fs"; +import { execFileSync } from "node:child_process"; +import test from "node:test"; +import { readWowRegistry } from "../ui-registry/wow-contract.mjs"; +import { + validateWowBrief, planWowFrontend, dryRunWowBriefFiles +} from "../scripts/wow-frontend-plan.mjs"; + +const read = (p) => fs.readFileSync(p,"utf8"); +const clone = (x) => structuredClone(x); +const briefPath = "skills/wow-frontend/examples/commerce-factory.brief.json"; +const consumerPath = "ui-registry/examples/wow-react-vite-css.json"; +const brief = JSON.parse(read(briefPath)); +const consumer = JSON.parse(read(consumerPath)); +const inventory = readWowRegistry(); +const policy = JSON.parse(read("ui-registry/wow-review-policy.json")); +const run = (b = brief,c = consumer,p = policy,i = inventory) => + planWowFrontend({brief:b,consumer:c,inventory:i,policy:p}); + +test("SKILL.md has discoverable metadata, required workflow and linked reference files", () => { + const content = read("skills/wow-frontend/SKILL.md"); + assert.match(content,/^---\nname: wow-frontend\ndescription: /); + assert.match(content,/SEARCH BEFORE BUILD/); + assert.match(content,/RENDER BEFORE DONE/); + assert.match(content,/prefers-reduced-motion/); + assert.match(content,/RAIDER/); + assert.match(content,/NO CODE COPY|do not copy/i); + assert.match(content,/ui-registry\/wow-sources\.json/); + assert.match(content,/ui-registry\/wow-review-policy\.json/); + assert.match(content,/source.selection|source-selection/); + for (const ref of ["source-selection.md","composition.md","motion.md","visual-qa.md"]) { + const linked = "references/" + ref; + assert.ok(content.includes(linked),linked + " not linked"); + assert.ok(fs.existsSync("skills/wow-frontend/" + linked),linked + " missing"); + const info = read("skills/wow-frontend/" + linked); + assert.ok(info.length > 500, linked + " lacks actionable instructions"); + } +}); + +test("dry run uses real Commerce Factory planning fixture but does not mutate source files", () => { + const before = [briefPath,consumerPath,"ui-registry/wow-sources.json", + "ui-registry/wow-review-policy.json"].map((p) => + crypto.createHash("sha256").update(read(p)).digest("hex")); + assert.deepEqual(validateWowBrief(brief),[]); + const output = dryRunWowBriefFiles(briefPath,consumerPath); + assert.equal(output.ok,true); + assert.equal(output.status,"PLAN_ONLY"); + assert.equal(output.mode,"DRY_RUN"); + assert.equal(output.project,"Trigenys Commerce Factory"); + assert.equal(output.repository,"Trigenys/trigenys-commerce-factory"); + assert.equal(output.unchangedStack.framework,"react-vite"); + assert.equal(output.unchangedStack.styling,"css"); + assert.deepEqual(output.languages,["fr","en"]); + assert.equal(output.operationsAllowed,false); + assert.equal(output.guardrails.thirdPartyCodeCopy,false); + assert.equal(output.guardrails.thirdPartyComponentInstall,false); + assert.equal(output.evidence.browserScreenshots,"NOT RUN"); + assert.equal(output.evidence.deployment,"NOT VERIFIED"); + assert.ok(output.steps.length >= 8); + assert.ok(output.steps.every((x) => x.status === "NOT RUN")); + assert.equal(output.sources.length,consumer.sources.allow.length); + for (const source of output.sources) { + assert.equal(source.mode,"reference-only"); + assert.equal(source.installAllowed,false); + assert.equal(source.codeReuseAllowed,false); + assert.equal(source.legalReuseDecision,"NO CODE COPY / NO INSTALL / NO EXECUTION"); + } + const after = [briefPath,consumerPath,"ui-registry/wow-sources.json", + "ui-registry/wow-review-policy.json"].map((p) => + crypto.createHash("sha256").update(read(p)).digest("hex")); + assert.deepEqual(after,before); +}); + +test("command-line dry run emits valid JSON without executing builds, network or writing files", () => { + const script = read("scripts/wow-frontend-plan.mjs"); + assert.doesNotMatch(script,/\b(?:writeFileSync|writeFile|spawn|execSync|fetch\s*\(|axios|import\s*\([^)]*https?:|child_process)\b/); + const stdout = execFileSync(process.execPath,["scripts/wow-frontend-plan.mjs",briefPath,consumerPath],{ + encoding:"utf8",timeout:10000 + }); + const report = JSON.parse(stdout); + assert.equal(report.ok,true); + assert.equal(report.mode,"DRY_RUN"); + assert.equal(report.status,"PLAN_ONLY"); +}); + +test("the skill rejects fabricated proof and unsupported configs before planning", () => { + const evil = clone(brief); + evil.constraints.truthfulProofOnly = false; + evil.constraints.merchants = "publicize-real-partners"; + evil.canRunCommands = true; + const report = run(evil); + assert.equal(report.ok,false); + assert.match(report.errors.join(" "),/truthfulProofOnly/); + assert.match(report.errors.join(" "),/merchant branding/); + assert.match(report.errors.join(" "),/unknown brief field/); + assert.deepEqual(report.steps,[]); + assert.deepEqual(report.sources,[]); +}); + +test("source discovery fails closed for unknown source, untrusted approval or forced installation", () => { + const bad = clone(consumer); + bad.sources.allow = ["unknown-plugin"]; + assert.equal(run(brief,bad).ok,false); + const badMode = clone(consumer); + badMode.sources.mode = "install"; + assert.match(run(brief,badMode).errors.join(" "),/reference-only/); + const corrupt = clone(policy); + corrupt.defaultDisposition = "install-all"; + const report = run(brief,consumer,corrupt); + assert.equal(report.ok,false); + assert.match(report.errors.join(" "),/defaultDisposition/); +}); + +test("a configured but disabled consumer produces no source plan or side effects", () => { + const disabled = {version:1,enabled:false}; + const result = run(brief,disabled); + assert.equal(result.ok,true); + assert.equal(result.status,"DISABLED"); + assert.deepEqual(result.sources,[]); + assert.deepEqual(result.steps,[]); + assert.equal(result.operationsAllowed,false); +}); + +test("different product language and stack stay supported without Commerce Factory-specific assumptions", () => { + const project = clone(brief); + project.project = "Roadmap Mentor"; + project.repository = "Trigenys/roadmap-mentor"; + project.constraints.languages = ["fr"]; + delete project.constraints.merchants; + const config = clone(consumer); + config.stack.framework = "vue-vite"; + config.stack.styling = "css"; + const result = run(project,config); + assert.equal(result.ok,true); + assert.equal(result.unchangedStack.framework,"vue-vite"); + assert.deepEqual(result.languages,["fr"]); + assert.ok(result.sources.some((s) => s.compatibility === "design-reference")); + assert.ok(result.sources.every((s) => s.installAllowed === false)); +}); + +test("source selection and visual QA references explicitly distinguish planned from verified", () => { + const selection = read("skills/wow-frontend/references/source-selection.md"); + const visual = read("skills/wow-frontend/references/visual-qa.md"); + const composition = read("skills/wow-frontend/references/composition.md"); + const motion = read("skills/wow-frontend/references/motion.md"); + assert.match(selection,/reference-only/); + assert.match(selection,/zero approvals/); + assert.match(selection,/no code copy|no code.*install/i); + assert.match(visual,/NOT RUN/); + assert.match(visual,/browser|Playwright/); + assert.match(composition,/FR\/EN/); + assert.match(motion,/prefers-reduced-motion/); + assert.match(motion,/scroll-jacking/); +}); From 4a5406d52370f8c867b42f726fb58722832aa28c Mon Sep 17 00:00:00 2001 From: EagleFox31 <86088743+EagleFox31@users.noreply.github.com> Date: Fri, 9 Oct 2026 22:34:54 +0100 Subject: [PATCH 09/11] test(wow): include agent skill dry run in existing UI Registry gate --- test/ui-registry.test.mjs | 1 + 1 file changed, 1 insertion(+) diff --git a/test/ui-registry.test.mjs b/test/ui-registry.test.mjs index 258c16c..b6dfd95 100644 --- a/test/ui-registry.test.mjs +++ b/test/ui-registry.test.mjs @@ -1,3 +1,4 @@ +import "./wow-frontend-skill.test.mjs"; import "./wow-frontend-security.test.mjs"; import "./wow-frontend-contract.test.mjs"; import assert from "node:assert/strict"; From 6d125edb48e8f547b057093a52b98c9743d2547a Mon Sep 17 00:00:00 2001 From: EagleFox31 <86088743+EagleFox31@users.noreply.github.com> Date: Fri, 9 Oct 2026 22:35:14 +0100 Subject: [PATCH 10/11] docs(wow): document skill discovery and dry-run use without implicit installation --- skills/wow-frontend/README.md | 40 +++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 skills/wow-frontend/README.md diff --git a/skills/wow-frontend/README.md b/skills/wow-frontend/README.md new file mode 100644 index 0000000..d30da91 --- /dev/null +++ b/skills/wow-frontend/README.md @@ -0,0 +1,40 @@ +# WOW Frontend agent skill + +Portable SKILL.md for agents designing or refactoring Trigenys product landings. + +## Location + +The authoritative skill is [SKILL.md](SKILL.md), with references for [source selection](references/source-selection.md), [composition](references/composition.md), [motion](references/motion.md) and [visual QA](references/visual-qa.md). It lives in **`Trigenys/appfactory`**, not in the Project Automation Action or the landing template. + +It can be **read directly from this repository**, or an agent that supports local `SKILL.md` packages can copy this entire `wow-frontend/` directory to the agent-specific skill location (for example `.agents/skills/wow-frontend/` or `.cursor/skills/wow-frontend/`, subject to that agent's actual discovery rules). This repository change does **not** install the skill into remote consumers or any ChatGPT/Cursor account. + +The references resolve other AppFactory contracts relative to the **AppFactory repository root**; they are not vendored automatically into consumer repositories. Agents running in another checkout should explicitly find the AppFactory source (or vendor the referenced contracts under a separately approved integration). + +## Read-only local planning + +From the AppFactory checkout: + +```sh +node scripts/wow-frontend-plan.mjs \ + skills/wow-frontend/examples/commerce-factory.brief.json \ + ui-registry/examples/wow-react-vite-css.json +``` + +The output is a **plan**, not a generated landing. It includes source dispositions, stack-compatibility research references, sequencing, denied installation/copy rights and **NOT RUN** browser/build/QA evidence. + +The Commerce Factory example was prepared after inspecting its `README.md`, `package.json`, `src/App.tsx` and `src/styles.css` using read-only GitHub access. It preserves React 19, Vite, TypeScript, existing CSS tokens and FR/EN. No Commerce Factory files, deployments or commercial data were changed. + +## Quality + +```sh +npm run test:ui-registry +``` + +This existing CI gate includes tests for the WOW source contract (#139), central approval and provenance policy (#140) and this skill's structure/dry-run behavior (#141). Real screenshot, mobile, keyboard and performance automation are still follow-up work, tracked in [Project Automation #99](https://github.com/EagleFox31/appfactory-project-automation/issues/99). + +## Versioning and obligations + +- Do not introduce a separate UI component registry: existing `ui-registry/registry.json` remains canonical for native code. +- The external `ui-registry/wow-sources.json` is currently reference-only; central `ui-registry/wow-review-policy.json` has no live approvals. +- Skill instructions **do not** grant import/install permissions or override consumer `AGENTS.md` and repository governance. +- Use RAIDER and include accurate evidence in PRs. A green planning test does not imply production screenshot QA. From 23c7031b61787245c40d57b9b14947324896a7f4 Mon Sep 17 00:00:00 2001 From: EagleFox31 <86088743+EagleFox31@users.noreply.github.com> Date: Fri, 9 Oct 2026 22:35:30 +0100 Subject: [PATCH 11/11] docs(wow): link source contracts to portable agent skill and dry-run planner --- ui-registry/README.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/ui-registry/README.md b/ui-registry/README.md index f2264d0..e8be840 100644 --- a/ui-registry/README.md +++ b/ui-registry/README.md @@ -82,3 +82,17 @@ The existing `uiProfile` provisioning path and `registry.json` files remain auth A reviewed approval must cite the exact upstream 40-character commit, pinned LICENSE/COPYING evidence, reviewed SPDX license, reviewer and mandatory notice file. `wow-security.mjs` exposes read-only status/eligibility checks and deterministic per-consumer provenance reconciliation; it never executes an installer or writes into a consumer repository. Run `npm run test:ui-registry` for both contract and security checks. See [the security and provenance runbook](../docs/wow-reuse-security.md) before proposing any change to `wow-review-policy.json`. + +## Agent workflow: WOW Frontend (#141) + +The portable [WOW Frontend SKILL.md](../skills/wow-frontend/SKILL.md) coordinates `audit → art direction → search before build → compose → intentional motion → render before done → provenance`. Its [README](../skills/wow-frontend/README.md) explains how to read or manually install the skill for a compatible agent. + +Read-only planning (no repository mutation or code import): + +```sh +node scripts/wow-frontend-plan.mjs \ + skills/wow-frontend/examples/commerce-factory.brief.json \ + ui-registry/examples/wow-react-vite-css.json +``` + +The plan never claims screenshots, accessibility tests, builds or deployment have run. Keep the existing native registry and default-deny external source policy intact.