optimizations

This commit is contained in:
2026-03-28 19:15:39 +01:00
parent 0b25d9570a
commit cab4fbd83e
509 changed files with 1016804 additions and 1605 deletions

View File

@@ -33,6 +33,14 @@ php artisan migrate
We provide an example Supervisor config at `deploy/supervisor/skinbase-queue.conf`.
The example worker listens on the application queues currently used by Skinbase features, including AI and discovery jobs:
```text
forum-security,forum-moderation,vision,recommendations,discovery,mail,default
```
If you split workloads across dedicated workers, make sure any queues configured through `VISION_QUEUE`, `RECOMMENDATIONS_QUEUE`, or `DISCOVERY_QUEUE` are explicitly covered by at least one worker process.
To use it on a Debian/Ubuntu server:
```bash
@@ -100,5 +108,18 @@ php artisan queue:flush
- Ensure `QUEUE_CONNECTION` in `.env` matches the driver you've configured.
- If using `database` driver, the `jobs` and `failed_jobs` tables must exist.
- The mailable used for contact submissions is queued; if the queue worker is not running mails will accumulate in the queue table (or Redis).
- AI auto-tagging, embedding generation, vector index repair, and recommendation cache regeneration are all queued. If you move them onto dedicated queues, the shipped example worker commands must be updated to consume those queue names.
8) AI and discovery queue checklist
-----------------------------------
If you are enabling the recommendation AI stack in production, verify all of the following:
- `QUEUE_CONNECTION` is backed by a real worker-capable driver such as `redis` or `database`
- `VISION_QUEUE`, `RECOMMENDATIONS_QUEUE`, and `DISCOVERY_QUEUE` either stay on `default` or are present in a worker `--queue=` list
- `UPLOAD_QUEUE_DERIVATIVES=true` has workers online before you enable it, otherwise upload post-processing will stall
- `php artisan queue:restart` is run after deploys so workers pick up new code and config
See `docs/recommendation-ai-production.md` for a stack-specific runbook.
Questions or prefer a different process manager? Tell me your target host and I can produce exact commands tailored to it.

View File

@@ -0,0 +1,49 @@
# Collections V3 Implementation Summary
Collections v3 is broadly implemented across the Laravel backend, Inertia pages, moderation flows, AI helpers, saved collections, editorial/community discovery surfaces, and scheduled lifecycle publishing.
Implemented areas:
- public collection pages, profile collection tabs, featured/trending/editorial/community/seasonal discovery routes
- collection studio management for metadata, artworks, collaborators, submissions, discussion, smart rules, layout modules, and editorial ownership
- engagement flows for likes, follows, saves, shares, comments, and submissions
- admin moderation and report handling for collections, collection comments, and collection submissions
- AI-assisted curation endpoints for title, summary, cover, grouping, related works, tags, SEO, and smart-rule explanations
- lifecycle scheduling through `published_at`, `unpublished_at`, and the `collections:sync-lifecycle` command
Gap closure completed during this audit pass:
- added campaign banner metadata support with `banner_text` and `spotlight_style`
- exposed `event_key`, `season_key`, `banner_text`, and `spotlight_style` in collection management payloads and UI
- rendered spotlight banner metadata on the public collection hero
- added focused feature coverage for campaign metadata persistence and rendering
Remaining work should be incremental polish rather than foundational implementation.# Collections v3 Implementation Summary
## Implemented
- Collaboration roles for owner, editor, contributor, and viewer
- Invite flow with pending, accepted, and declined or revoked handling
- Community collections with submission, approval, rejection, and withdrawal flows
- Collection saves distinct from likes and follows, including a saved collections page
- Lightweight collection comments with deletion and reporting support
- Public discovery surfaces for featured, trending, editorial, community, and seasonal collections
- Homepage collection surfacing for featured or trending, editorial, community, and recent collection strips
- Editorial and community collection types with publish and unpublish windows, event metadata, and badge labels
- AI-assisted collection helpers for title, summary, cover, grouping, related artworks, tags, SEO description, smart-rule explanations, split suggestions, and merge or spin-out ideas
- Related collection recommendations using bounded heuristic scoring
- Reporting support for collections, collection comments, and collection submissions
- Admin moderation actions for collection status changes, interaction toggles, unfeature actions, and collaborator removal
- Tabbed collection studio layout for details, artworks, members, submissions, settings, discussion, AI suggestions, and moderation
- Focused feature coverage for core permissions, discovery, AI endpoints, saves, submissions, comments, recommendations, and reporting
## Not Fully Implemented Yet
- Distinct invite lifecycle states for expired and declined as first-class states in the schema
- Homepage AI-curated or personalized collection modules beyond the new curated strips
- Expanded browser or end-to-end coverage for collaborative management flows
## Validation Snapshot
- Focused suite: `php artisan test tests/Feature/Collections/CollectionsFeatureTest.php`
- Current status: `42 passed (200 assertions)`

View File

@@ -0,0 +1,118 @@
# Collections v4 Implementation Summary
## Scope completed
- Added collection lifecycle, premium presentation, series, campaign, analytics, saved-library, and staff surface foundations on the existing collections stack.
- Reused the current Laravel + Inertia collections architecture rather than introducing a parallel system.
- Kept public safety constraints intact by continuing to route recommendations and surfaces through public-only collection queries.
## Backend
- v4 schema is backed by the collections platform migration that adds lifecycle, scoring, presentation, series, and campaign fields plus supporting tables for:
- collection history
- collection daily stats
- collection surface definitions
- collection surface placements
- collection saved lists and list items
- Fixed the attachment history regression in `CollectionService` so artwork attach actions correctly record the acting owner.
- Aligned collection surface placement storage with the actual database schema by persisting:
- `placement_type`
- `campaign_key`
- `notes`
- `created_by_user_id`
- Added `automatic` surface mode support so rule-driven surfaces can resolve purely from eligible public collections without depending on manual placements.
- Broadened automatic surface rules so staff can filter by owner, presentation style, theme token, collaboration mode, score thresholds, analytics/commercial flags, and explicit include/exclude collection IDs.
- Added definition-level surface scheduling and fallback behavior so staff surfaces can activate on schedule and hand off cleanly to fallback keys when inactive or empty.
- Added staff surface cleanup support so placements can be deleted directly, definitions can be deleted once their placements are cleared, and overlapping active placement windows can be flagged for staff review.
- Preserved `saved_at` timestamps in saved collection queries so v4 saved-library sorting works consistently.
- Added dedicated owner workflow endpoints for presentation, campaign, and lifecycle updates so the v4 API surface matches the studios scoped editing responsibilities instead of relying only on the generic collection update route.
- Added manual linked-collection support with persisted ordering, owner studio controls, and public-page rendering that prioritizes curated links while still filtering out non-public targets.
- Added first-class series title and description metadata so series landing pages and in-page sequence callouts no longer have to infer copy from keys or campaign labels.
## Owner and staff UI
- Added missing Inertia pages:
- `CollectionDashboard`
- `CollectionAnalytics`
- `CollectionHistory`
- `CollectionStaffSurfaces`
- Expanded the staff surfaces studio so definitions and placements can both be hydrated back into the form and updated through explicit staff routes.
- Added staff surface deletion controls plus conflict callouts for overlapping scheduled placements on the same surface.
- Expanded staff surface rule guidance so broader automatic filters and `quality_score` ranking are discoverable from the studio.
- Expanded the staff surfaces studio to manage definition-level activation windows and fallback surface keys.
- Added batch editorial tooling to the staff surfaces studio so staff can preview and apply campaign metadata updates across multiple collections while optionally planning surface placements in one pass.
- Upgraded the collection manage studio to expose v4 metadata and insight links:
- lifecycle state
- analytics toggle
- presentation style and emphasis
- theme token
- series key and order
- campaign key and label
- series title and description
- sponsorship and partner labels
- monetization and brand-safety notes
- archive and expiry scheduling
- AI quality review output
- Added linked-collection controls in the manage studio so owners can curate manual related strips alongside series and campaign metadata.
- Added dashboard, analytics, history, and staff-surface shortcuts directly in the collection studio.
## Public and saved-library UI
- Upgraded the public collection page with:
- owner-only analytics/history shortcuts
- campaign and series badges
- premium presentation and score callouts
- intro-block and featured-artworks presentation toggles driven by persisted layout modules
- series navigation and sibling collection links
- series titles and descriptions where owners provide them
- manual linked collections merged ahead of recommendation-driven related collections
- Added a dedicated public series landing route so related collection sequences can be browsed as ordered standalone pages.
- Rebuilt the saved collections page into a v4 library surface with:
- saved-list creation
- add-to-list actions
- dedicated saved-list detail routes
- saved-list order preservation on dedicated list pages
- saved-list reorder actions for active lists
- remove-from-list actions
- unsave cleanup that also removes related saved-list items
- filter and sort controls
- recommended next collections
## Testing added
- Added focused feature coverage for:
- premium presentation layout modules hiding intro copy while enabling a featured-artworks strip on public collection pages
- staff surface placement creation with v4 placement fields
- staff surface definition and placement updates
- automatic surface resolution respecting public eligibility rules
- broader automatic surface filtering using owner, presentation, score, and include/exclude rules
- surface definition fallback behavior when scheduled windows are inactive or a surface resolves no items
- placement assignment history entries being recorded for affected collections
- deleting staff surface placements while recording placement removal history
- preventing surface definition deletion until attached placements are cleared
- flagging overlapping active placement windows as staff-visible conflicts
- previewing batch editorial campaign and placement changes without persisting them
- applying batch editorial campaign metadata while skipping ineligible public-surface placements safely
- public series landing pages honoring series order while excluding private and restricted entries
- series title and description metadata flowing through series landing pages and collection page sequence callouts
- dashboard summaries counting lifecycle buckets, pending submissions, attention queues, and expiring campaigns from the owning curator's collections only
- collection analytics payloads returning totals, range deltas, timeline points, and ranked top artworks for owners
- allowing active collection editors to access analytics and history while blocking unrelated viewers
- dedicated presentation, campaign, and lifecycle workflow routes persisting the expected scoped collection metadata while preserving owner-only authorization
- syncing manual linked collections, hydrating them back into the manage studio, and preventing public pages from leaking private linked targets
- saved-list creation and adding saved collections to lists
- browsing a saved-list route and removing a collection from that list
- preserving saved-list item order on dedicated list routes
- reordering saved-list items
- unsaving a collection clearing that user's saved-list memberships
## Verification status
- The focused Collections v4 feature coverage is passing in `tests/Feature/Collections/CollectionsFeatureTest.php`.
- Current verification includes analytics, history, lifecycle, presentation, campaign, series, linked collections, saved-library, recommendation safety, public discovery, surface automation, placements, and staff batch editorial tooling.
## Follow-up candidates
- Add pagination controls for long history timelines beyond previous/next.
- Expand saved-library UX with drag-and-drop reorder flows.
- Add richer staff planning ergonomics on top of the current batch editorial tools if editorial operations need more campaign-specific scheduling views later.

View File

@@ -0,0 +1,138 @@
# Collections v5 Implementation Summary
## Scope
Collections v5 extends the existing collections platform with operational metadata, workflow controls, health scoring, search, canonicalization, merge support, programming assignments, and snapshot-based observability.
## Schema additions
The collections table now carries v5 state for:
- workflow and readiness
- health state and health flags
- canonical and duplicate metadata
- program, partner, trust, sponsorship, governance, and experiment metadata
- ranking and search boost tiers
- health component scores and refresh timestamps
- placement eligibility
Supporting tables were added for:
- program assignments
- daily quality snapshots
- recommendation snapshots
- merge actions
- cross-entity links
- saved notes
## New services
- CollectionHealthService: evaluates metadata completeness, freshness, engagement, readiness, health state, eligibility, and daily snapshots
- CollectionRankingService: computes recommendation tier, ranking bucket, and search boost tier
- CollectionWorkflowService: validates workflow transitions and runs quality refresh flows
- CollectionSearchService: public and owner/staff search across collection metadata
- CollectionCanonicalService: assigns canonical targets safely
- CollectionMergeService: merges source collections into canonical targets without affecting artwork ownership
- CollectionProgrammingService: manages assignments, previews, eligibility refresh, duplicate scans, and recommendation refreshes
- CollectionBackgroundJobService: dispatches queued health, quality, recommendation, and duplicate maintenance jobs
- CollectionPartnerProgramService: isolates protected partner/program metadata updates
- CollectionObservabilityService: cache keys and collection diagnostics
- CollectionLinkService: manages generic creator, story, and category links for collection context modules
## Route coverage
Public:
- GET /collections/search
Owner/staff:
- GET /settings/collections/search
- GET /settings/collections/{collection}/health
- POST /settings/collections/{collection}/workflow
- POST /settings/collections/{collection}/quality-refresh
- POST /settings/collections/{collection}/canonicalize
- POST /settings/collections/{collection}/merge
Staff programming:
- GET /staff/collections/programming
- POST /staff/collections/programs
- PATCH /staff/collections/programs/{program}
- POST /staff/collections/surfaces/preview
- POST /staff/collections/eligibility/refresh
- POST /staff/collections/duplicate-scan
- POST /staff/collections/recommendation-refresh
Scheduled maintenance:
- php artisan collections:dispatch-maintenance
## Payload changes
Collection card and detail payloads now expose v5 metadata so dashboard, search, programming, and health tooling can consume the same core shape without custom adapters.
## Dashboard changes
The owner dashboard now includes health-oriented summary counts and warning payloads alongside the existing lifecycle, campaign, analytics, and attention views.
It also includes an internal search and filtering panel for workflow, lifecycle, health, visibility, and placement readiness.
## Staff programming UI
The staff programming route now renders a dedicated programming studio with:
- assignment management
- live program pool preview
- queued eligibility diagnostics
- queued duplicate scan tools
- queued recommendation refresh tools
- internal experiment and partner/program governance controls with observability diagnostics for the selected collection, including treatment, placement, ranking, pool-version, ownership, sponsorship, and review metadata
- staff merge queue for pending duplicate review and recent merge decisions, including direct canonicalize, merge, and reject actions in the studio
## Background jobs
Collections v5 now dispatches queued jobs for:
- owner quality refreshes
- staff eligibility refreshes
- staff recommendation refreshes
- staff duplicate scans
- scheduled maintenance sweeps for stale health, recommendation, and duplicate work
## Merge review workflow
Collection management now includes an internal merge-review surface with:
- duplicate candidate comparison cards
- canonical target designation
- direct merge actions for manual targets
- not-duplicate dismissal that suppresses rejected pairs from future review payloads
## Saved library changes
The saved collections area now supports lightweight private notes per saved collection.
## Cross-entity linking
Collections can now link to creators, public artworks, published stories, and active categories through a generic entity-link flow exposed in collection management and rendered on the public detail page.
## Test coverage
Existing collection feature coverage still passes after v5 integration.
Additional focused tests now cover:
- owner-only health access
- owner search scoping
- protected workflow/programming fields
- canonicalization and merge flows
- public canonical redirects for canonicalized collections
- staff programming assignments and previews
- staff programming studio access
- public search safety
- workflow transition validation
- saved collection notes
- collection entity links on owner and public pages, including artwork and tag links with public-only filtering
- public program landing pages with explicit partner and sponsor surfacing on discovery cards and headers
- dashboard search/filter wiring

View File

@@ -2,6 +2,8 @@
Covers the trending system, following feed, personalized homepage, similar artworks, unified activity feed, and all input signal collection that powers the ranking formula.
This document also covers the v3 AI discovery layer: vision metadata extraction, vector indexing, AI similar-artwork search, reverse image search, and the hybrid feed section controls.
---
## Table of Contents
@@ -19,13 +21,14 @@ Covers the trending system, following feed, personalized homepage, similar artwo
11. [Caching Strategy](#11-caching-strategy)
12. [Scheduled Jobs](#12-scheduled-jobs)
13. [Testing](#13-testing)
14. [Operational Runbook](#14-operational-runbook)
14. [AI Discovery v3](#14-ai-discovery-v3)
15. [Operational Runbook](#15-operational-runbook)
---
## 1. Architecture Overview
```
```text
Browser
├─ POST /api/art/{id}/view → ArtworkViewController
@@ -74,7 +77,7 @@ Browser
**Deduplication (layered):**
| Layer | Mechanism | Scope |
|---|---|---|
| --- | --- | --- |
| Client-side | `sessionStorage` key `sb_viewed_{id}` set before the request | Browser tab lifetime |
| Server-side | `$request->session()->put('art_viewed.{id}', true)` | Laravel session lifetime |
| Throttle | `throttle:5,10` route middleware | Per-IP per-artwork |
@@ -83,7 +86,7 @@ The React component `ArtworkActions.jsx` fires a `useEffect` on mount that check
**What gets incremented:**
```
```text
artwork_stats.views +1 (all-time)
artwork_stats.views_24h +1 (zeroed nightly)
artwork_stats.views_7d +1 (zeroed weekly)
@@ -101,6 +104,7 @@ Via `ArtworkStatsService::incrementViews()` with `defer: true` (Redis when avail
**Throttle:** 10 requests per minute per IP
The endpoint:
1. Inserts a row in `artwork_downloads` (persistent event log with `created_at`)
2. Increments `artwork_stats.downloads`, `downloads_24h`, `downloads_7d`
3. Returns `{"ok": true, "url": "<highest-res thumbnail URL>"}` for the native browser download
@@ -109,7 +113,7 @@ The `<a download>` buttons in `ArtworkActions.jsx` call `trackDownload()` on cli
**What gets incremented:**
```
```text
artwork_downloads INSERT (event log, persisted forever)
artwork_stats.downloads +1 (all-time)
artwork_stats.downloads_24h +1 (recomputed from log nightly)
@@ -124,7 +128,7 @@ Via `ArtworkStatsService::incrementDownloads()` with `defer: true`.
### 2.3 Other signals (already existed)
| Signal | Endpoint / Service | Written to |
|---|---|---|
| --- | --- | --- |
| Favorite toggle | `POST /api/artworks/{id}/favorite` | `user_favorites`, `artwork_stats.favorites` |
| Reaction toggle | `POST /api/artworks/{id}/reactions` | `artwork_reactions` |
| Award | `ArtworkAwardController` | `artwork_award_stats.score_total` |
@@ -156,7 +160,7 @@ The trending formula needs _recent_ activity, not all-time totals. `artwork_stat
The solution is four cached window columns refreshed on a schedule:
| Column | Meaning | Reset cadence |
|---|---|---|
| --- | --- | --- |
| `views_24h` | Views since last midnight reset | Nightly at 03:30 |
| `views_7d` | Views since last Monday reset | Weekly (Mon) at 03:30 |
| `downloads_24h` | Downloads in last 24 h | Nightly at 03:30 (recomputed from log) |
@@ -194,7 +198,7 @@ Uses chunked PHP loop (no `GREATEST()` / `INTERVAL` MySQL syntax) → works in b
### 4.1 Formula
```
```text
score = (award_score × 5.0)
+ (favorites × 3.0)
+ (reactions × 2.0)
@@ -210,7 +214,7 @@ Weights are constants in `TrendingService` (`W_AWARD`, `W_FAVORITE`, etc.) — a
### 4.2 Output columns
| Artworks column | Meaning |
|---|---|
| --- | --- |
| `trending_score_24h` | Score using `views_24h` + `downloads_24h`; targets artworks ≤ 7 days old |
| `trending_score_7d` | Score using `views_7d` + `downloads_7d`; targets artworks ≤ 30 days old |
| `last_trending_calculated_at` | Timestamp of last calculation |
@@ -244,7 +248,7 @@ php artisan skinbase:recalculate-trending --chunk=500 # smaller DB
All routes under `/discover/*` are registered in `routes/web.php` and handled by `App\Http\Controllers\Web\DiscoverController`. All use **Meilisearch sorting** — no SQL `ORDER BY` in the hot path.
| Route | Name | Sort key | Auth |
|---|---|---|---|
| --- | --- | --- | --- |
| `/discover/trending` | `discover.trending` | `trending_score_7d:desc` | No |
| `/discover/fresh` | `discover.fresh` | `created_at:desc` | No |
| `/discover/top-rated` | `discover.top-rated` | `likes:desc` | No |
@@ -260,7 +264,7 @@ All routes under `/discover/*` are registered in `routes/web.php` and handled by
### Logic
```
```text
1. Get user's following IDs from user_followers
2. If empty → show empty state (see below)
3. If present → Artwork::whereIn('user_id', $followingIds)
@@ -321,7 +325,7 @@ When the user follows nobody:
Computes preferences from the user's **favourited artworks**:
| Output key | Source |
|---|---|
| --- | --- |
| `top_tags` (up to 5) | Tags on artworks in `artwork_favourites` |
| `top_categories` (up to 3) | Categories on artworks in `artwork_favourites` |
| `followed_creators` | IDs from `user_followers` |
@@ -354,7 +358,7 @@ Falls back to `getTrendingFromDb()` — `orderByDesc('trending_score_7d')` with
Meilisearch filters are built in priority order:
```
```text
is_public = true
is_approved = true
id != {source_id}
@@ -377,7 +381,7 @@ Meilisearch's own ranking then sorts by relevance within those filters. Results
### `activity_events` schema
| Column | Type | Notes |
|---|---|---|
| --- | --- | --- |
| `id` | bigint PK | |
| `actor_id` | bigint FK users | Who did the action |
| `type` | varchar | `upload` `comment` `favorite` `award` `follow` |
@@ -389,7 +393,7 @@ Meilisearch's own ranking then sorts by relevance within those filters. Results
### Where events are recorded
| Event type | Recording point |
|---|---|
| --- | --- |
| `upload` | `UploadController::finish()` on publish |
| `follow` | `FollowService::follow()` |
| `award` | `ArtworkAwardController::store()` |
@@ -412,6 +416,7 @@ The controller enriches each event batch with its target objects in a single que
Configured in `config/scout.php` under `meilisearch.index-settings`.
Push settings to a running instance:
```bash
php artisan scout:sync-index-settings
```
@@ -419,6 +424,7 @@ php artisan scout:sync-index-settings
### Artworks index settings
**Searchable attributes** (ranked in order):
1. `title`
2. `tags`
3. `author_name`
@@ -451,7 +457,7 @@ php artisan scout:sync-index-settings
## 11. Caching Strategy
| Data | Cache key | TTL | Driver |
|---|---|---|---|
| --- | --- | --- | --- |
| Homepage trending | `homepage.trending.{limit}` | 5 min | Redis/file |
| Homepage fresh | `homepage.fresh.{limit}` | 5 min | Redis/file |
| Homepage hero | `homepage.hero` | 5 min | Redis/file |
@@ -461,6 +467,7 @@ php artisan scout:sync-index-settings
| Similar artworks | `api.similar.{artwork_id}` | 5 min | Redis/file |
**Rules:**
- Personalized data (`from_following`, `by_tags`, `by_categories`) is **not** independently cached — it falls inside `allForUser()` which is called fresh per request.
- Long-running cache busting: the trending command and reset command do not explicitly clear cache — the TTL is short enough that stale data self-expires within one trending cycle.
@@ -471,7 +478,7 @@ php artisan scout:sync-index-settings
All registered in `routes/console.php` via `Schedule::command()`.
| Time | Command | Purpose |
|---|---|---|
| --- | --- | --- |
| Every 30 min | `skinbase:recalculate-trending --period=24h` | Update `trending_score_24h` |
| Every 30 min | `skinbase:recalculate-trending --period=7d --skip-index` | Update `trending_score_7d` (background) |
| 03:00 daily | `uploads:cleanup` | Remove stale draft uploads |
@@ -489,7 +496,7 @@ All registered in `routes/console.php` via `Schedule::command()`.
All tests live under `tests/Feature/Discovery/`.
| Test file | Coverage |
|---|---|
| --- | --- |
| `ActivityEventRecordingTest.php` | `ActivityEvent::record()`, all 5 types, actor relation, meta, route smoke tests for the activity feed |
| `FollowingFeedTest.php` | Auth redirect, empty state fallback, pagination, creator exclusion |
| `HomepagePersonalizationTest.php` | Guest vs auth homepage sections, preferences shape, 200 responses |
@@ -499,11 +506,13 @@ All tests live under `tests/Feature/Discovery/`.
| `WindowedStatsTest.php` | `incrementViews/Downloads` update all 3 columns, reset command zeros views, recomputes downloads from log, window boundary correctness |
Run all discovery tests:
```bash
php artisan test tests/Feature/Discovery/
```
Run specific suite:
```bash
php artisan test tests/Feature/Discovery/SignalTrackingTest.php
```
@@ -512,7 +521,74 @@ php artisan test tests/Feature/Discovery/SignalTrackingTest.php
---
## 14. Operational Runbook
## 14. AI Discovery v3
### 15.1 Overview
The v3 layer augments the existing recommendation engine with:
- CLIP-derived embeddings and tags
- BLIP captions
- YOLO object detections
- vector-gateway similarity search
- hybrid feed reranking and section generation
Primary request paths:
- `GET /api/art/{id}/similar-ai`
- `POST /api/search/image`
- `POST /api/uploads/{id}/vision-suggest`
Primary async jobs:
- `AutoTagArtworkJob`
- `GenerateArtworkEmbeddingJob`
- `SyncArtworkVectorIndexJob`
- `BackfillArtworkVectorIndexJob`
### 15.2 Core configuration
Vision gateway:
- `VISION_ENABLED`
- `VISION_GATEWAY_URL`
- `VISION_GATEWAY_TIMEOUT`
- `VISION_GATEWAY_CONNECT_TIMEOUT`
Vector gateway:
- `VISION_VECTOR_GATEWAY_ENABLED`
- `VISION_VECTOR_GATEWAY_URL`
- `VISION_VECTOR_GATEWAY_API_KEY`
- `VISION_VECTOR_GATEWAY_COLLECTION`
- `VISION_VECTOR_GATEWAY_UPSERT_ENDPOINT`
- `VISION_VECTOR_GATEWAY_SEARCH_ENDPOINT`
Hybrid feed:
- `DISCOVERY_V3_ENABLED`
- `DISCOVERY_V3_CACHE_TTL_MINUTES`
- `DISCOVERY_V3_VECTOR_SIMILARITY_WEIGHT`
- `DISCOVERY_V3_VECTOR_BASE_SCORE`
- `DISCOVERY_V3_MAX_SEED_ARTWORKS`
- `DISCOVERY_V3_VECTOR_CANDIDATE_POOL`
AI section sizing:
- `DISCOVERY_V3_SECTION_SIMILAR_STYLE_LIMIT`
- `DISCOVERY_V3_SECTION_YOU_MAY_ALSO_LIKE_LIMIT`
- `DISCOVERY_V3_SECTION_VISUALLY_RELATED_LIMIT`
### 15.3 Behavior notes
- Upload publish remains non-blocking for AI processing; derivatives can complete and the AI jobs are queued after the upload is finalized.
- The synchronous `vision-suggest` endpoint is only for immediate upload-step prefill and does not replace the queued persistence path.
- `similar-ai` and reverse image search return vector-gateway results only when the gateway is configured; otherwise they fail closed with explicit JSON reasons.
- Discovery sections are now tunable from config rather than fixed in code, which makes production adjustments safe without service edits.
---
## 15. Operational Runbook
### Trending scores are stuck / not updating

View File

@@ -0,0 +1,219 @@
# Nova Cards v3 Audit Checklist
Audit date: 2026-03-28
Source of truth reviewed:
- `.vscode/agents/skinbase-nova-cards-system_v3.md`
- Nova Cards controllers, services, models, routes, React Studio UI, migrations, and feature tests
Validation status:
- Verified with `php artisan test tests/Feature/NovaCards`
- Result: 72 passing tests, 489 assertions
Follow-up roadmap:
- `docs/nova-cards-v3-priority-roadmap.md`
Status legend:
- `[x]` Implemented end to end or clearly present
- `[-]` Partially implemented or scaffolded
- `[ ]` No clear implementation found during audit
Important note:
- The v3 agent file is a roadmap/spec, not a strict shipping checklist. Several sections describe target-state product direction rather than features that are already expected to exist in full.
## 1. v3 schema versioning and normalization
- [x] `schema_version` is stored and normalized for v3 cards
- [x] New projects normalize to v3 shape
- [x] Legacy v1/v2 projects are detected and upgraded
- [x] Save flow rewrites cards into the newer project structure
- [x] Compatibility behavior is covered by feature tests
- [-] Explicit admin rerender/backfill tooling for migrated cards was not found
Notes:
- Implemented via migration, `NovaCardProjectNormalizer`, and v3 tests.
## 2. Advanced editor architecture improvements
- [x] Structured project JSON exists with major v3 sections like `canvas`, `background`, `text_blocks`, `frame`, `effects`, `export_preferences`, and `source_context`
- [x] Multiple text blocks are supported
- [x] Additional body and caption blocks can be added and edited
- [x] Layout presets, alignment, position, padding, max width, typography, frame, effects, background modes, overlays, focal position, and packs are exposed in the Studio UI
- [x] Background upload works through the draft API
- [x] Mobile step-based flow exists for Studio
- [x] Version history and version restore exist
- [x] Block reordering UI now exists for text blocks
- [x] Compare versions UI now exists at a useful summary level
- [x] Dedicated quick mode versus advanced mode switch now exists
- [-] The editor is structured and block-based, but not a full layer tool
- [-] Visibility toggles exist for text blocks through the `enabled` flag, but not as a broader layer system
- [ ] Snap guides were not found
- [ ] Safe-zone editing helpers beyond stored config were not found
- [ ] Lock/unlock controls for editable elements were not found
Notes:
- This area is materially beyond MVP, and the recent Studio usability pass closed the highest-value gaps around quick/full mode, block reorder, and version compare. It still does not match the full “advanced studio” vision in the spec.
## 3. Creator presets
- [x] Creator presets table and model exist
- [x] Preset CRUD API exists
- [x] Presets can be captured from an existing card
- [x] Presets can be applied back to a card as project patches
- [x] Default preset behavior exists
- [x] Studio UI exposes preset browsing, apply, capture, and delete actions
- [x] Preset logic is covered by tests
## 4. Discovery and ranking surfaces
- [x] Public cards index includes featured, trending, latest, and rising content
- [x] Rising service exists and is tested
- [x] Related cards service exists and is tested
- [x] Remixed cards page exists
- [x] Lineage page exists
- [x] Challenge listing and challenge detail pages exist
- [x] Template packs page exists
- [x] Creator page exists
- [x] Dedicated style-family feed now exists
- [x] Dedicated palette-family feed now exists
- [x] Best-remixes discovery surface now exists
- [x] Dedicated mood feed now exists through config-backed tag mappings
- [x] Dedicated editorial landing page now exists
- [x] Dedicated seasonal landing page now exists
- [-] Discovery includes several meaningful surfaces, but not the full matrix described by the spec
- [ ] Remix-tree browsing surface beyond lineage was not found
Notes:
- Discovery is solid for core launch surfaces, but it is not yet the full “discovery intelligence” product outlined in the spec.
## 5. Creator identity and profile integration
- [x] Creator-specific public page exists for cards by user
- [x] Creator page now exposes public summary stats and creator highlight cards
- [x] Creator page now exposes featured works and featured collections
- [x] Top categories and top tags are surfaced on creator pages
- [x] Studio analytics page exists for a creators own card with views, likes, saves, remixes, shares, downloads, and related counters
- [x] Style family and palette family are stored on cards
- [-] Creator identity exists at the card/creator listing level, but richer creator-card identity features are not complete
- [x] Featured card rail now exists on creator pages as featured works
- [x] Featured collection rail now exists on creator pages
- [x] Dedicated Nova Cards creator portfolio page now exists
- [x] Creator pages now surface signature themes, challenge history, most remixed works, most liked works, remix branch activity, a remix graph summary, creator preference signals, and a recent creator timeline
- [-] Deeper creator identity modules are still incomplete beyond the current public portfolio summary; stronger interactive remix graphing and richer persistent preference identity are still missing
- [x] Creator spotlight eligibility/featured creators now exist for Nova Cards editorial surfacing
## 6. Social, remix, collection, challenge, and editorial support
- [x] Like, favorite, save, remix, duplicate, and challenge submission flows exist
- [x] Remix lineage is preserved and visible
- [x] Public collection detail page exists
- [x] Official collections and admin management for Nova Cards exist
- [x] Challenge admin management exists
- [x] Challenge entry visibility rules are covered by tests
- [x] Best-remixes public surface exists
- [x] Nova Cards editorial landing surfaces exist
- [x] Seasonal or themed card hubs specific to Nova Cards exist
- [x] Featured creators workflow specific to Nova Cards now exists
- [-] Editorial and community support is present, but the richer “ecosystem” layer remains incomplete
## 7. AI assistance hooks and optional UI
- [x] AI assist endpoint exists
- [x] AI assist service exists
- [x] Studio UI exposes AI suggestion requests
- [x] Suggestions include tags, mood, layout suggestions, and readability fixes
- [x] Suggestions are optional and creator-controlled
- [-] The AI assist layer appears primarily rule-based/fallback-driven rather than a deep external AI composition system
- [ ] More advanced assist actions from the spec, such as “convert to story format” or “create wallpaper version” as explicit AI actions, were not found
## 8. Export system improvements
- [x] Export request API exists
- [x] Export status polling exists
- [x] Export queue job exists
- [x] Multiple export formats exist: preview, hires, square, story, wallpaper, and OG
- [x] Export permissions are enforced via `allow_export`
- [x] Studio UI exposes export requests
- [-] Core export foundation is implemented, but richer policy/output features remain open
- [ ] Watermark policy controls were not found
- [ ] Advanced export preset management beyond format choice was not found
## 9. Trust, moderation, and rights
- [x] Card moderation status exists on the model
- [x] Reporting supports cards, comments, challenges, and challenge entries
- [x] Moderation queue/report summary integration exists
- [x] Ownership and remix-related rights flags exist, including `allow_remix`, `allow_background_reuse`, and `allow_export`
- [x] Background upload validation is enforced
- [x] API throttles and write-protection middleware are wired on key Nova Cards endpoints
- [-] Trust/moderation foundations are real, but the full anti-abuse roadmap is not complete
- [x] Publish-time duplicate-content heuristic flagging now exists for Nova Cards
- [x] Publish-time self-remix-loop heuristic flagging now exists for Nova Cards
- [x] Staff admin/reporting surfaces now expose persisted Nova Card publish heuristic reasons
- [x] Staff moderation overrides now persist actor/source metadata on Nova Cards
- [x] Staff overrides now persist moderation disposition codes like cleared/escalated/rejected
- [x] Staff moderation UI now allows selecting custom review dispositions per action
- [ ] Challenge branch freeze / remix-branch intervention tooling was not found
## 10. Backward-compatible migration strategy and rerender tooling
- [x] Migration for v3 schema additions exists
- [x] Legacy project JSON is normalized at load/use time
- [x] Older cards remain editable through normalization paths
- [x] Tests verify upgrade behavior
- [-] Compatibility is present, but operational migration tooling is incomplete
- [ ] Admin rerender tool for migrated cards was not found
- [ ] Backfill job for schema versions was not found
## 11. Acceptance criteria summary
### Studio/editor
- [x] Structured multi-block project model exists
- [x] Creator presets exist and can be reused
- [x] Versioned schema and normalization work
- [x] Exports are functional
- [x] Mobile Studio flow is usable
- [x] Studio usability pass now covers quick/full mode, text-block reorder, and version compare summaries
- [-] Full advanced editor capability set from the spec is not complete
### Social/community
- [x] Remix chains are preserved and visible
- [x] Collections are integrated into card flows
- [x] Challenge flows exist
- [-] Stronger creator identity exists only in a limited form
### Discovery
- [x] Rising and related content work
- [x] Creator, collection, challenge, and template public surfaces exist
- [-] Broader discovery matrix and editorial surfacing are incomplete
### AI assistance
- [x] Optional assistive suggestions exist
- [x] Creator remains in control
- [-] AI assistance is limited compared with the long-term vision
### Moderation/trust
- [x] Reporting and moderation hooks are in place
- [x] Attribution and basic rights controls are preserved
- [-] Anti-abuse depth from the spec is incomplete
### Technical
- [x] v1 and v2 content remain compatible through normalization
- [x] Schema migration is safe and test-covered
- [x] Render/export pipeline supports v3 features currently in use
- [-] Future-ready operational tooling is only partially present
## 12. Bottom line
- [x] Nova Cards v3 foundation is implemented
- [x] The core shipping slice is real: schema versioning, Studio improvements, presets, AI assist, exports, rising, related cards, remix lineage, challenge integration, moderation/reporting, and public browsing
- [-] Several roadmap areas are only partially implemented
- [ ] The full spec in `.vscode/agents/skinbase-nova-cards-system_v3.md` is not fully implemented end to end
## 13. Highest-value missing areas
- [ ] Advanced editor depth beyond the recent usability pass: lock/unlock, snap guides, safe-zone helpers, and broader layer controls
- [-] Rich creator identity surfaces: featured works, featured collections, and featured creators now exist, but portfolio depth and creator-history surfaces are still missing
- [x] Broader discovery surfaces now include style, palette, mood, best-remix, editorial, and seasonal pages
- [-] Stronger editorial tooling exists for cards, collections, challenges, and creators, but broader packaging and workflow depth are still limited
- [ ] Operational rerender/backfill tooling for long-term schema evolution

View File

@@ -0,0 +1,229 @@
# Nova Cards v3 Gap Matrix
Audit date: 2026-03-28
Primary spec:
- `.vscode/agents/skinbase-nova-cards-system_v3.md`
Validation baseline:
- Targeted verification passed with `php artisan test tests/Feature/NovaCards/NovaCardAdminTest.php tests/Feature/NovaCards/NovaCardPublicPagesTest.php`
- Result: 19 passing tests, 194 assertions
How to read this document:
- `Implemented` means there is direct repo evidence for the pillar's core shipping behavior.
- `Partial` means meaningful work exists, but the pillar still falls short of the v3 spec's target-state behavior.
- `Missing` means no clear implementation was found for that item during this audit.
Important note:
- The v3 agent file is a roadmap-level spec, not a literal definition of what must already be fully shipped. This matrix measures current repo reality against that target state.
## 1. Advanced studio
Status:
- Partial
Implemented evidence:
- Structured v3 schema with `canvas`, `background`, `text_blocks`, `frame`, `effects`, `export_preferences`, and `source_context` in `app/Services/NovaCards/NovaCardProjectNormalizer.php`
- Stored v3 canvas flags for safe zones and snap guides in `app/Services/NovaCards/NovaCardProjectNormalizer.php`
- Quick versus advanced editor modes in `resources/js/Pages/Studio/StudioCardEditor.jsx`
- Text-block reorder, enable/disable toggles, remove controls, and multi-block editing in `resources/js/Pages/Studio/StudioCardEditor.jsx`
- Version restore and compare-summary UI in `resources/js/Pages/Studio/StudioCardEditor.jsx`
- Advanced frame/effect/quote-mark/text-panel controls in `resources/js/Pages/Studio/StudioCardEditor.jsx`
Still missing or clearly incomplete:
- No visible snap-guide UI or guide interactions were found; only stored schema flags exist.
- No broader lock/unlock controls for editable elements were found.
- No full layer list with layer-level controls beyond text-block ordering was found.
- No drag-based canvas editing or anchor-point manipulation UI was found.
- Safe-zone support appears schema-level, not an exposed editing aid.
Verdict:
- The Studio is materially beyond MVP and has a credible v3 foundation, but it is not yet the full advanced layer/block studio described in the spec.
## 2. Creator identity
Status:
- Partial
Implemented evidence:
- Public creator page and dedicated creator portfolio page exist in `app/Http/Controllers/Web/NovaCardsController.php` and `routes/web.php`
- Creator summary stats, top categories, top tags, top moods, featured works, featured collections, creator highlights, most remixed works, most liked works, challenge history, signature themes, remix-branch activity, remix graph visualization, creator preference signals, and a recent creator timeline are rendered through `app/Http/Controllers/Web/NovaCardsController.php` and `resources/views/cards/index.blade.php`
- Public coverage for featured works, challenge history, signature themes, and creator portfolio depth exists in `tests/Feature/NovaCards/NovaCardPublicPagesTest.php`
- Staff-facing featured creator control exists in `app/Http/Controllers/Settings/NovaCardAdminController.php`, `resources/js/Pages/Collection/NovaCardsAdminIndex.jsx`, and `routes/web.php`
- Editorial featured-creators surface is wired in `app/Http/Controllers/Web/NovaCardsController.php` and `resources/views/cards/index.blade.php`
Still missing or clearly incomplete:
- No richer creator identity controls such as public template favorites or stronger persistent style identity tools were found beyond preference signals, presets, and stored style metadata.
- No true interactive remix graph visualization was found beyond the current branch graph summary.
Verdict:
- Creator identity is materially stronger than the older audit suggested, but it still falls short of the spec's broader portfolio, timeline, and persistent identity vision.
## 3. Social and remix culture
Status:
- Partial
Implemented evidence:
- Remix lineage is preserved in model/project state and exposed on card pages in `app/Services/NovaCards/NovaCardPresenter.php`, `resources/views/cards/show.blade.php`, and `resources/views/cards/lineage.blade.php`
- Dedicated lineage route and controller action exist in `app/Http/Controllers/Web/NovaCardsController.php` and `routes/web.php`
- Best-remixes and remixed-card discovery surfaces exist in `app/Http/Controllers/Web/NovaCardsController.php`
- Public lineage and remix coverage exists in `tests/Feature/NovaCards/NovaCardPublicPagesTest.php`
- Likes, saves, collections, and challenge participation are integrated into Studio and public surfaces in `resources/js/Pages/Studio/StudioCardEditor.jsx`
Still missing or clearly incomplete:
- No richer remix-tree browser beyond lineage/family views was found.
- No moderation action to freeze a remix branch was found.
- No explicit remix-abuse or spam-loop intervention workflow was found.
Verdict:
- Core remix culture is implemented, but deeper moderation and exploration around remix networks remain unfinished.
## 4. Discovery intelligence
Status:
- Partial
Implemented evidence:
- Trending, featured, latest, and rising public feeds exist in `app/Http/Controllers/Web/NovaCardsController.php`
- Dedicated rising service exists in `app/Services/NovaCards/NovaCardRisingService.php`
- Related cards service exists in `app/Services/NovaCards/NovaCardRelatedCardsService.php`
- Public mood, style, palette, editorial, seasonal, creator, collection, challenge, and best-remixes surfaces exist in `app/Http/Controllers/Web/NovaCardsController.php`
- Targeted public-page coverage exists in `tests/Feature/NovaCards/NovaCardPublicPagesTest.php`
Still missing or clearly incomplete:
- The full discovery matrix from the spec is not present; there is no dedicated template family feed, quote-type feed, or broader creator-diversity surfacing layer.
- Discovery balance still looks primarily route-by-route rather than a unified discovery engine with stronger editorial/algorithmic blending.
- No richer creator diversity or new-creator exposure tuning surface was found beyond the rising service and editorial featuring.
Verdict:
- Discovery is already broad enough to feel like a real product surface, but it is not yet the full discovery-intelligence platform described in v3.
## 5. Challenge engine
Status:
- Partial
Implemented evidence:
- Challenge listing and detail pages exist in `app/Http/Controllers/Web/NovaCardsController.php`
- Challenge admin management exists in `app/Http/Controllers/Settings/NovaCardAdminController.php`
- Studio challenge submission controls exist in `resources/js/Pages/Studio/StudioCardEditor.jsx`
- Challenge landing content appears on editorial surfaces via `app/Http/Controllers/Web/NovaCardsController.php`
Still missing or clearly incomplete:
- No recurring challenge series system or scheduled pipeline was found.
- No challenge archive/history navigation system was found.
- No challenge-specific template suggestion rail beyond generic editor options was found.
Verdict:
- Challenge support is solid and operational, but it does not yet match the spec's more central repeatable challenge engine.
## 6. AI-assisted creation
Status:
- Partial
Implemented evidence:
- AI assist service exists in `app/Services/NovaCards/NovaCardAiAssistService.php`
- The Studio AI panel exists in `resources/js/Pages/Studio/StudioCardEditor.jsx`
- Suggestions include tags, mood, layouts, backgrounds, font pairing, and readability fixes in `app/Services/NovaCards/NovaCardAiAssistService.php`
- Suggestions are creator-controlled and optional in the Studio UI
Still missing or clearly incomplete:
- The service is explicitly rule-based/fallback-first, not a deeper AI composition layer.
- No explicit story-conversion or wallpaper-conversion AI actions were found.
- No stronger metadata/title/description assist actions were found.
Verdict:
- AI assist is real and useful, but still much smaller than the spec's longer-term assistive workflow.
## 7. Asset and template ecosystem
Status:
- Partial
Implemented evidence:
- Official asset packs and template packs are configured in `config/nova_cards.php`
- Asset-pack and template admin surfaces exist in `app/Http/Controllers/Settings/NovaCardAdminController.php`
- Advanced editor controls expose frame, color grade, quote-mark, and text-panel systems in `resources/js/Pages/Studio/StudioCardEditor.jsx`
- Creator presets exist and are exposed in Studio through `resources/js/Pages/Studio/StudioCardEditor.jsx`
Still missing or clearly incomplete:
- No explicit template favorites system was found.
- No access-rule-aware premium gating or premium-ready pack entitlement system was found.
- No richer seasonal/official pack surfacing beyond config/admin management was found.
Verdict:
- The pack/template ecosystem exists, but it is still closer to a solid internal/content foundation than the full ecosystem described in the spec.
## 8. Export and distribution
Status:
- Partial
Implemented evidence:
- Export request model/table support exists in `database/migrations/2026_03_27_010000_add_nova_cards_v3_tables.php` and `app/Models/NovaCardExport.php`
- Export request creation and polling are implemented in `app/Services/NovaCards/NovaCardExportService.php` and `app/Http/Controllers/Api/NovaCards/NovaCardExportController.php`
- Queued export generation exists in `app/Jobs/NovaCards/GenerateNovaCardExportJob.php`
- Preview, hires, square, story, wallpaper, and OG exports are supported in `app/Services/NovaCards/NovaCardExportService.php`
- Export controls are exposed in Studio in `resources/js/Pages/Studio/StudioCardEditor.jsx`
- Watermark preference is normalized into project data in `app/Services/NovaCards/NovaCardProjectNormalizer.php`
Still missing or clearly incomplete:
- No actual watermark policy UI or export-policy workflow was found; only a normalized preference field exists.
- No export history management surface was found in Studio.
- No richer saved export-preset system per user or per preset was found.
Verdict:
- Export infrastructure is strong, but the broader distribution/product layer around it remains incomplete.
## 9. Trust, moderation, and rights
Status:
- Partial
Implemented evidence:
- Card moderation fields and staff moderation surfaces exist in `app/Http/Controllers/Settings/NovaCardAdminController.php` and `resources/js/Pages/Collection/NovaCardsAdminIndex.jsx`
- Reporting queue integration exists in the Nova Cards admin surface
- Rights flags such as `allow_remix`, `allow_background_reuse`, and `allow_export` are exposed in Studio and policy/service code
- Public reporting hooks and moderation-aware visibility exist across card/challenge/comment flows
Still missing or clearly incomplete:
- No duplicate or near-duplicate Nova Cards detection service was found.
- No remix-loop abuse controls were found.
- No branch-freeze or targeted remix-branch intervention tooling was found.
- No stronger low-quality-content throttling specific to Nova Cards was found beyond general rate limits and moderation baselines.
Verdict:
- Moderation and rights are credible at the foundation level, but the stronger anti-abuse tooling described in v3 is still missing.
## 10. Migration compatibility and ops tooling
Status:
- Partial
Implemented evidence:
- Legacy normalization is handled in `app/Services/NovaCards/NovaCardProjectNormalizer.php`
- v3 schema additions are present in `database/migrations/2026_03_27_010000_add_nova_cards_v3_tables.php`
- Compatibility behavior is covered by the Nova Cards v3 feature suite
Still missing or clearly incomplete:
- No explicit schema backfill command was found.
- No targeted rerender command/job for migrated cards was found.
- No admin-safe migration utility surface with dry-run/reporting was found.
Verdict:
- Compatibility is implemented. Operational migration tooling is not.
## Overall conclusion
Current repo state versus the v3 spec:
- The v3 foundation is implemented.
- Several public and creator-facing roadmap items that used to be missing are now present, including featured works, featured collections, and featured creators.
- The biggest remaining gaps are no longer basic public discovery or staff creator featuring.
- The largest remaining gaps are advanced studio depth, deeper creator portfolio identity, stronger anti-abuse tooling, and migration/rerender operations.
If prioritizing by product leverage from the current codebase, the clean next targets are:
1. Creator portfolio depth and creator challenge/remix history.
2. Anti-abuse moderation hardening for duplicate and remix-loop control.
3. Migration/backfill/rerender tooling.

View File

@@ -0,0 +1,245 @@
# Nova Cards v3 Priority Roadmap
Roadmap date: 2026-03-28
Companion document:
- `docs/nova-cards-v3-audit-checklist.md`
Purpose:
- Convert the v3 audit into an execution order
- Focus first on features that compound value on top of the existing Nova Cards v3 foundation
- Avoid spending time on low-leverage polish before the public creator/discovery loop is stronger
Assumptions:
- Current foundation is stable: schema versioning, Studio, presets, AI assist, exports, rising, related cards, public browsing, remix lineage, collections, challenges, and moderation/reporting are already working
- Prioritization favors retention, discovery, and creator identity ahead of deeper niche editor polish
Status legend:
- `P0` Next build target
- `P1` High-value follow-up
- `P2` Important but can wait
- `P3` Long-tail / later platform work
## Prioritization principles
1. Build on shipped behavior, not on spec completeness alone.
2. Prefer features that increase creation, publishing, and rediscovery loops.
3. Prefer public-facing discoverability and creator identity before deep editor complexity.
4. Keep schema-safe, testable increments.
5. Defer expensive operational tooling until the product surface justifies it.
## P0: Public Creator Identity And Discovery Expansion
Why first:
- The editor already has enough capability to create cards.
- The biggest missing product loop is stronger public identity and richer discovery after publishing.
- These features make every existing card and creator more valuable without requiring a full editor rewrite.
Scope:
- Add richer creator card pages beyond a flat list
- Add public metadata surfaces for style family, top tags, and top categories
- Add creator “featured works” support
- Add dedicated public feeds for style family and mood
- Add a “best remixes” or expanded remix-discovery surface
Suggested deliverables:
- Creator profile enhancements on the Nova Cards creator page:
- featured cards rail
- creator stats summary
- top styles / tags / categories summary
- cards grouped or filterable by style family
- New public routes/pages:
- `/cards/styles/{style}`
- `/cards/moods/{mood}` or a tag-backed mood feed if mood remains AI/tag derived
- `/cards/remix-highlights` or equivalent best-remixes feed
- Presenter/controller additions for creator-facing payloads and public discovery filters
- Feature tests for all new public routes and canonical behavior
Why this is P0 instead of more Studio work:
- It improves the creator growth loop immediately
- It helps discovery quality with existing content
- It avoids prematurely overbuilding advanced editor controls before public demand is better supported
## P1: Advanced Studio Usability Pass
Why second:
- The Studio is already functional and valuable
- The highest-value missing editor work is usability, not unrestricted complexity
- This pass should improve serious creator workflows without turning Nova Cards into a full design app
Scope:
- Reorder text blocks
- Compare current draft against a selected snapshot at a useful summary level
- Add clearer block visibility controls and editing affordances
- Introduce a true quick mode versus advanced mode split in the Studio UI
Suggested deliverables:
- Text block reorder controls using simple move up/down actions first
- Version compare summary UI:
- changed title/quote/source
- changed layout/background/style sections
- changed tags/publish settings
- Quick mode:
- format
- background/template
- main text
- preset/style
- preview/publish
- Advanced mode:
- current full control surface
- Tests for restore and compare API behavior where needed, plus front-end interaction coverage if available in the repo
Explicitly not in this phase:
- freeform drag canvas
- arbitrary layer transforms
- unbounded design-tool behavior
## P1: Editorial And Themed Discovery Surfaces
Why this is also P1:
- Once creator identity is stronger, editorial discovery becomes more valuable
- The spec calls for featured/editorial/seasonal surfaces, but these are not necessary before the base creator/discovery loop is improved
Scope:
- Add editorial landing support for Nova Cards
- Add seasonal or themed Nova Card hubs
- Add admin-facing hooks for featuring creators/cards/collections/challenges more intentionally
Suggested deliverables:
- `cards/editorial` landing page
- `cards/seasonal` landing page
- Staff-configurable featured creator/card slots or score-driven sections
- Reusable presenter format for editorial rails:
- featured creators
- challenge highlights
- collection picks
- best remixes
## P2: AI Assist And Export Expansion
Why later:
- The current AI assist and export layers already provide useful value
- They do not block core creation or public discovery
- Expanding them before creator/discovery surfaces would be lower leverage
Scope:
- Add higher-level assist actions
- Add export presets and clearer output workflows
Suggested deliverables:
- AI assist actions:
- suggest story format conversion
- suggest wallpaper crop/layout
- suggest palette/style family
- suggest stronger title/description metadata
- Export enhancements:
- save default export preference per creator preset or per user
- explicit watermark policy options if needed by product policy
- better export status/history presentation in Studio
## P2: Moderation And Abuse Hardening
Why later:
- The current moderation/reporting baseline is already present
- This work matters, but it becomes more urgent as creator/discovery scale increases
Scope:
- stronger duplicate/near-duplicate detection hooks
- remix abuse controls
- moderation intervention for problematic remix branches
Suggested deliverables:
- duplicate-card heuristic service hook on publish
- remix-rate guardrails for suspicious loops
- moderation action to freeze remixing on flagged cards or branches
- additional reporting context on lineage-heavy cards
## P3: Migration Ops And Long-Term Platform Tooling
Why last:
- These are important platform investments, but they are less visible to users right now
- The existing normalization path keeps older content functioning
Scope:
- schema backfill commands/jobs
- rerender tools for migrated cards
- operational utilities for long-term format changes
Suggested deliverables:
- artisan command to backfill `schema_version`
- job/command to rerender a targeted subset of cards
- admin-safe batch tooling with dry-run mode
- audit/reporting output for migration health
## Recommended execution order
1. Creator portfolio depth beyond featured works and featured collections
2. Stronger editorial packaging on top of the existing editorial and seasonal pages
3. AI assist expansion
4. Moderation hardening
5. Migration/backfill/rerender tooling
## Suggested implementation slices
### Slice A: Creator page upgrade
- Add featured cards rail
- Add creator stats summary
- Add style/tag/category summary
- Add tests for creator page payload and rendering
Status:
- Partially implemented
### Slice B: Discovery page upgrade
- Add style-family route and controller action
- Add mood route and controller action or tag-backed mood filter
- Add best-remixes feed
- Add tests for public feeds and filters
Status:
- Materially implemented for current public discovery breadth
### Slice C: Studio usability
- Add quick mode toggle
- Add text block reorder controls
- Add version compare summary
- Add front-end coverage if present in the repo workflow
Status:
- Implemented
### Slice D: Editorial/public packaging
- Add seasonal/editorial landing controllers and views
- Add admin config or featured slots
- Add regression coverage for public rendering
Status:
- Public editorial and seasonal landings are implemented, and staff-facing creator featuring controls now exist; the remaining gap is broader editorial packaging depth
## Do not prioritize yet
- Freeform drag canvas architecture
- Arbitrary layer transforms and rotation system
- Premium monetization logic
- Deep animation tooling
- Heavy AI dependence that weakens deterministic/testable behavior
## Recommended next implementation target
If work starts immediately, the best next build target is:
`P1: Editorial controls and creator curation depth`
Reason:
- The public discovery breadth and Studio usability gaps have already been addressed enough for the next increment.
- The highest remaining leverage is better curation: featured works on creator pages, featured creators/cards/collections/challenges, and stronger staff control over public surfacing.
- This closes the gap between existing public landing pages and the fuller editorial ecosystem described by the spec.
Update:
- `P0 Slice A: Creator page upgrade` is now partially implemented through creator summary stats, top category/tag metadata, and creator highlight cards on the public creator page.
- `P0 Slice B` is now partially implemented through public style-family and palette-family discovery pages.
- Public best-remix discovery is also now implemented.
- Mood discovery is now implemented through durable config-backed tag mappings.
- Editorial and seasonal landing pages are now also implemented.
- `P1 Slice C: Studio usability` is now implemented through quick versus advanced mode, text block reordering, version compare summaries, and the supporting payload/test coverage.
- The next strongest gap is no longer public discovery breadth or the Studio usability pass; it is stronger editorial controls and creator-facing curation depth.

View File

@@ -10,7 +10,10 @@ Skinbase Nova messaging now uses Laravel Reverb, Laravel Broadcasting, Laravel E
- Read markers are stored on conversation participants and expanded into `message_reads` for durable receipts.
- The conversation list response now includes `summary.unread_total` for global badge consumers.
- Reconnect recovery uses `GET /api/messages/{conversation_id}/delta?after_message_id=...`.
- Delta recovery also returns the latest conversation summary and aggregate unread total so the inbox sidebar can heal after a missed `conversation.updated` broadcast.
- Presence heartbeats use `POST /api/messages/presence/heartbeat` and are intended only to support offline fallback notification logic plus server-side presence awareness.
- Message sends are idempotent per sender and conversation when the client retries with the same `client_temp_id`.
- The database also enforces sender-scoped `client_temp_id` uniqueness so retry races cannot persist duplicate rows.
## Local setup
@@ -42,3 +45,4 @@ Skinbase Nova messaging now uses Laravel Reverb, Laravel Broadcasting, Laravel E
- The conversation view loads once via HTTP.
- Live message, read, typing, and conversation summary updates arrive over websocket channels.
- When the socket reconnects, the client requests deltas from the explicit `delta` endpoint and merges them idempotently by message id, UUID, and client temp id.
- HTTP send retries also reuse the original stored message when `client_temp_id` matches, preventing duplicate broadcasts during reconnect races.

View File

@@ -0,0 +1,216 @@
# Recommendation AI Production Readiness
This runbook covers the production prerequisites for the Skinbase recommendation AI stack:
- vision analysis via `VISION_GATEWAY_URL` or CLIP/YOLO endpoints
- embedding generation
- vector upsert/search via the vector gateway
- hybrid discovery feed v2/v3
- upload-triggered AI processing
## 1. Required runtime services
You need these services available before enabling the stack:
- Laravel queue workers
- a configured public files/CDN base so artwork derivatives resolve to public URLs
- a vision gateway for `/analyze/all`, or CLIP and YOLO services individually
- a vector gateway exposing `/vectors/upsert` and `/vectors/search`
- a queue backend suitable for async jobs, preferably Redis in production
## 2. Required environment variables
### Core queue and upload
```dotenv
QUEUE_CONNECTION=redis
UPLOAD_QUEUE_DERIVATIVES=true
VISION_QUEUE=vision
RECOMMENDATIONS_QUEUE=recommendations
DISCOVERY_QUEUE=discovery
```
If you do not want dedicated queues, leave the queue names unset or set them to `default`.
### Vision analysis
```dotenv
VISION_ENABLED=true
VISION_IMAGE_VARIANT=md
VISION_GATEWAY_URL=https://vision.example.com
VISION_GATEWAY_TIMEOUT=10
VISION_GATEWAY_CONNECT_TIMEOUT=3
CLIP_BASE_URL=https://clip.example.com
CLIP_ANALYZE_ENDPOINT=/analyze
CLIP_EMBED_ENDPOINT=/embed
YOLO_ENABLED=true
YOLO_BASE_URL=https://yolo.example.com
YOLO_ANALYZE_ENDPOINT=/analyze
YOLO_PHOTOGRAPHY_ONLY=true
```
Notes:
- `VISION_GATEWAY_URL` is the preferred unified path because the app can ingest CLIP tags, BLIP caption, and YOLO objects from `/analyze/all`
- CLIP embedding generation still uses the CLIP embed endpoint configured in `config/recommendations.php`
### Vector search and indexing
```dotenv
VISION_VECTOR_GATEWAY_ENABLED=true
VISION_VECTOR_GATEWAY_URL=https://vector.example.com
VISION_VECTOR_GATEWAY_API_KEY=replace-me
VISION_VECTOR_GATEWAY_COLLECTION=images
VISION_VECTOR_GATEWAY_UPSERT_ENDPOINT=/vectors/upsert
VISION_VECTOR_GATEWAY_SEARCH_ENDPOINT=/vectors/search
VISION_VECTOR_GATEWAY_DELETE_ENDPOINT=/vectors/delete
```
### Discovery and rollout
```dotenv
DISCOVERY_V2_ENABLED=true
DISCOVERY_V2_ALGO_VERSION=clip-cosine-v2-adaptive
DISCOVERY_V2_ROLLOUT_PERCENTAGE=100
DISCOVERY_V3_ENABLED=true
DISCOVERY_V3_CACHE_TTL_MINUTES=5
DISCOVERY_V3_VECTOR_SIMILARITY_WEIGHT=0.8
DISCOVERY_V3_VECTOR_BASE_SCORE=0.75
DISCOVERY_V3_MAX_SEED_ARTWORKS=3
DISCOVERY_V3_VECTOR_CANDIDATE_POOL=60
```
### Embeddings
```dotenv
RECOMMENDATIONS_EMBEDDING_ENABLED=true
RECOMMENDATIONS_EMBEDDING_MODEL=clip
RECOMMENDATIONS_EMBEDDING_MODEL_VERSION=v1
RECOMMENDATIONS_ALGO_VERSION=clip-cosine-v1
RECOMMENDATIONS_MIN_DIM=64
RECOMMENDATIONS_MAX_DIM=4096
```
## 3. Queue worker coverage
The AI stack dispatches jobs onto these queue families:
- `vision` via `AutoTagArtworkJob`
- `recommendations` via embedding generation, vector backfill, and similarity jobs
- `discovery` via feed cache regeneration
- `default` if dedicated queue env vars are not set
The example worker configs in `deploy/` now listen on:
```text
forum-security,forum-moderation,vision,recommendations,discovery,mail,default
```
If you run separate workers per queue, ensure all configured queue names are consumed somewhere.
## 4. Upload pipeline behavior
Upload finish dispatches these async jobs after derivatives exist:
- `AutoTagArtworkJob`
- `GenerateArtworkEmbeddingJob`
If `UPLOAD_QUEUE_DERIVATIVES=true`, derivative generation is also queued before those jobs can run. That means a broken worker setup can block the entire AI post-processing chain even if uploads themselves succeed.
## 5. Database and schema expectations
Confirm the database includes the current AI/discovery schema:
- artwork AI metadata columns on `artworks`
- `last_vector_indexed_at` on `artworks`
- artwork embeddings table
- discovery cache and event tables used by feed generation
Recommended checks:
```bash
php artisan migrate --force
php artisan schema:audit-migrations
```
## 6. Deployment checklist
Run these after deploy:
```bash
php artisan config:cache
php artisan route:cache
php artisan queue:restart
php artisan optimize
```
If you changed frontend assets, also ensure the Vite manifest exists before smoke-testing browser flows.
## 7. Smoke tests
Recommended application-level checks:
```bash
php artisan artworks:vectors-index --limit=1
php artisan artworks:vectors-search {artwork_id} --limit=5
vendor/bin/pest tests/Feature/Vision/GenerateArtworkEmbeddingJobTest.php
vendor/bin/pest tests/Feature/Vision/AiArtworkSearchApiTest.php
vendor/bin/pest tests/Feature/Discovery/FeedEndpointV2Test.php
```
Recommended HTTP checks:
- `GET /api/art/{id}/similar-ai`
- `POST /api/search/image`
- `GET /api/v1/feed?algo_version=clip-cosine-v2-adaptive&limit=12`
## 8. Failure modes to watch
### Uploads succeed but AI fields stay empty
Likely causes:
- workers are not running
- workers do not consume `vision` or `recommendations`
- `VISION_ENABLED=false`
- derivative URLs are not publicly reachable by the vision services
### Similar AI endpoints return 503
Likely causes:
- `VISION_VECTOR_GATEWAY_ENABLED=false`
- missing `VISION_VECTOR_GATEWAY_URL`
- missing `VISION_VECTOR_GATEWAY_API_KEY`
### Feed works but has no vector influence
Likely causes:
- `DISCOVERY_V3_ENABLED=false`
- vector gateway search unavailable
- no recent user seed artworks
- artworks have local embeddings but were never upserted
### Vector repair/backfill stalls
Likely causes:
- `RECOMMENDATIONS_QUEUE` is set but workers do not listen on it
- queue backend is unhealthy
## 9. Operational recommendation
For first rollout, keep the queue names explicit but simple:
```dotenv
VISION_QUEUE=default
RECOMMENDATIONS_QUEUE=default
DISCOVERY_QUEUE=default
```
Once the stack is stable, split them into dedicated workers only if queue volume justifies it.