Imported from sharp-pixel/LaTrouvaille (
retail-search-prototype/AGENTS.md). Install upstream withnpx skills add sharp-pixel/LaTrouvaille --skill retail-search-prototype. Copyright stays with the author.
Prototype Instructions
Run the local server yourself and open the preview in the in-app browser. Do not give the user server-start instructions when you can run it.
Before making substantial visual changes, use the Product Design plugin's get-context skill when the visual source is unclear or no longer matches the current goal. When the user gives durable prototype-specific design feedback, preferences, or decisions, record them in AGENTS.md.
When implementing from a selected generated mock, treat that image as the source of truth for layout, component anatomy, density, spacing, color, typography, visible content, and hierarchy.
The demo login action is a persona selector. Keep Anonymous as the default, show each persona's background and mental model, make the selector available on desktop and mobile, and attach the active persona to UBI query and event records. Persona selection intentionally personalizes the native query rewrite and softly boosts close OpenSearch matches; changing persona must refetch the active results, and the personalized rewrite is exposed in the query strip. The browser sends only personaId to search. Resolve that ID server-side to the allowlisted search context (personaId, version, archetype, background, mental model, and a query expansion capped at 120 characters); never transmit persona names, demographics, or images as model context. Store the effective rewrite once in UBI plus only the compact personalization status/identity summary. Persona portraits are original fictional assets in a warm cartoonish 3D render style; keep Anonymous deliberately faceless and non-demographic.
La Trouvaille's visual identity is a private discovery salon rather than a generic luxury marketplace: use deep mineral green, warm parchment, muted leaf, and clay accents; favor confident sans-serif typography, rounded asymmetric geometry, and collection-led language. Do not reproduce Vestiaire Collective's centered serif wordmark, seller promo strip, category-heavy navigation, or discount-led hierarchy. Keep the primary discovery navigation limited to New arrivals, Bags, Watches, Jewellery, Clothing, and Shoes; avoid customer-facing labels such as We Love, Sale, Inside, Express Delivery, and Direct Shipping.
Keep the homepage deliberately reduced: one search affordance, one responsive navigation model at a time, two hero products, a compact varied discovery rail, 20px card radii, 10px control radii, and support text no smaller than 12px. Do not restore hero suggestion chips, marketplace statistics, an empty cart count, or repeated hero imagery in the discovery section.
Persona search preferences may specialize the bounded query expansion by understood category. For watch intent, Camille and Sofia softly favor bracelet, jewellery, sculptural, coil, mini, and oval watches; Julien softly favors traditional dress, automatic, manual-wind, leather-strap, and heritage watches. Apply these only as optional ranking signals after watch intent or a Watches facet is established, never as filters or overrides of explicit shopper text, and keep Anonymous unprofiled. In the OpenSearch GenAI prompt, interpret dress watch, formal watch, and suit watch as gender-neutral watch-style phrases: filter to Watches, use watch as the broad required candidate text, and let the optional persona clause reorder that candidate set.
Catalogue listings carry a lowercase gender_affinity of women, men, or unisex. Review affinity as product metadata using size, silhouette, and styling; every watch must be explicitly classified rather than inheriting the catalogue baseline. The native OpenSearch GenAI planner owns gender-intent and budget translation: give it raw shopper text, the explicit UI ceiling, and an optional trusted persona.strict_max_price, then have its registered prompt emit the final price and gender_affinity filters. Explicit women's or men's intent includes the corresponding affinity plus unisex; never infer it from persona demographics. Do not precompute or inject these two filters in the search API or shopper-controlled lexical bypass.
Keep the Query understanding toggle available on desktop and mobile and enabled by default. Disabling it must refetch active results and skip the native LLM pipeline, deterministic intent/facet/control extraction, Tier-2 rewrite rules, and persona behavior. The OpenSearch bypass query must be one unboosted multi_match over the literal shopper text with OR semantics and only title, brand, canonical_text, and description; do not add phrase queries, rank features, rewrites, or Boolean scoring recipes. Apply explicit UI filters and price separately through post_filter, retain the selected UI sort, and do not render an inferred-intent strip.
Catalog content belongs to a fictional luxury universe. Do not introduce real brand or model names in listings, search suggestions, query rules, fixtures, screenshots, or documentation. Keep each fictional house consistent across categories and reuse its established model vocabulary; French maisons use French house/model language, Italian fashion houses use Italianate names, Swiss watchmakers use horological/Geneva language, and Anglo-American labels use English names.
Cart listings are unique: the cart has no quantity controls, cannot contain the same listing twice, and starts empty on each fresh app load.
The customer-facing UBI summary is scoped to the active query ID. Show the current query and only interactions linked to it; do not expose internal search-enhancement implementation details such as Querqy or Agentic Search status. Hovering or keyboard-focusing the current UBI query must reveal the actual OpenSearch DSL in a readable popup.
Customer natural-language queries use the native OpenSearch Agentic Search pipeline configured by scripts/configure-agentic-search.mjs. Prefer the served fine-tuned model alias and fall back to the pinned base model alias during provisioning. Agentic execution fails closed: if the pipeline, model inference, generated DSL, or runtime validation is unavailable or invalid, return an explicit error and no catalogue results. Never retry an agentic request with lexical DSL. The only lexical path is the shopper-controlled Query understanding bypass; it is not an outage fallback. Also fail closed when the search API or OpenSearch itself is unavailable, with no browser-side or API-side local result fallback.
The Docker Compose app must reach search through the same-origin /api nginx proxy backed by the healthy search-api service. Keep search-api pointed at the Compose opensearch service, published on port 8790 for diagnostics, and configured with a health check plus restart: unless-stopped; do not require a separately started host process for normal Docker operation. Its container startup must wait for OpenSearch and automatically create any missing catalogue alias or UBI indexes before launching the API.
Optional SageMaker serving is managed by scripts/sagemaker-ministral.mjs and defaults to one ml.g5.2xlarge in eu-west-1, the pinned BF16 model revision, language-only loading, a 4,096-token context, and the base model alias. Keep endpoint creation and deletion explicit because the real-time endpoint is billable while active. The SageMaker OpenSearch path must use a SigV4 connector and static model selection; do not reuse OpenAI /v1/models discovery, the active AWS CLI profile, broad generic AWS credentials, or a short-lived SageMaker bearer token. Keep the deployment-script revision synchronized with query-understanding-training/configs/qlora-5090.yaml.
The planner owns the full generated body except service-owned _source. Keep its exact size, total-hit, hard-filter, text-intent, field/type, clause-budget, and sort contract synchronized across the shared prompts, training policy, and runtime response validator. The agentic_context check is post-execution correctness validation, not a security sandbox; production safeguards belong in OpenSearch-side permissions and resource limits.
Keep the composed native query_text at or below OpenSearch's 1,000-character limit. The local OpenAI-compatible connector enables JSON-schema output by default; set AGENTIC_STRUCTURED_OUTPUT=false only for a provider that does not implement OpenAI response_format: json_schema.
OpenSearch 3.7's native planner prompt passes a _doc-wrapped mapping source and serializes the mapping and query-field array as JSON string literals. Keep training fixtures and the offline prompt renderer faithful to that captured representation when changing mappings or OpenSearch versions.