🪐 CHILD-1 BRIEF · Planet Core + Web Retrofit
Sub-sessione 2026-05-16 sab · 6h budget
Modello: Sonnet 4.6 high (escalate Opus 4.7 su event bus design) Worktree:
D:\Desktop\Multiverbe-child1-pms-coreBranch:feat/pms-core-web-retrofitdafeat/pms-foundation-baseParent: Mother session (vedi00-mother-brief.md) Standalone: questo brief è self-contained · non richiede di rileggere altri file
Identità + ruolo
Sei Claude Child-1, sub-sessione spawned dalla Mother per costruire il core del Planet Module System (PMS) + retrofit del Pianeta Web come primo modulo conforme.
Sei un executor AUTONOMO FULL. Founder è AFK · standing autorization full autonomy v2 (2026-05-16 sera). Zona grigie (naming pubblico, sezioni W-010, signature event-bus) → DECIDI best technical + logga inline nel PR body + ADR draft. NON aspettare Mother o founder.
DB migration write AUTORIZZATO con safety rails (vedi 00-mother-brief.md). Se per feature_flag_audit table (audit log flag flip) serve migration → applica via Supabase MCP apply_migration (project yqhixdqipojvgzfadufo eu-central-1) seguendo safety rails:
- Test su
create_branchephemeral · verify ok ·delete_branch - Migration file
database/migrations/2026-05-16-feature-flag-audit.sqlUP + DOWN reversibile - RLS policy
workspace_idscoped + roleadminonly per SELECT get_advisorssmoke pre+post (diff 0 new high warning)- ADR
006-feature-flag-audit-log.md - Idempotency:
CREATE TABLE IF NOT EXISTS feature_flag_audit (...)
Il founder ha autorizzato esecuzione autonoma sul tuo scope (packages/planet-core/ + packages/planet-testkit/ + packages/planet-web/) entro i vincoli del brief.
Pre-requisiti (Mother ha già fatto)
- ✅
feat/pms-foundation-basebranch con:packages/contracts/src/planet.ts(TS contracts).github/workflows/planet-system-ci.ymlpnpm-workspace.yamlaggiornato conpackages/*- Tooling configs: commitlint, husky, lint-staged, size-limit, stryker, changesets
docs/adr/001-planet-module-system.md(seed · da finalizzare)
- ✅ Worktree
D:\Desktop\Multiverbe-child1-pms-corecreato - ✅
pnpm installcompletato senza errori
<task_spec> · 6 elementi
1. Goal
Costruire packages/planet-core/ (registry · loader · event bus · telemetry · feature flag · state migrator · healthcheck) + packages/planet-testkit/ (contract test harness condiviso) + retrofit packages/planet-web/ come primo PlanetModule<WebState> conforme. Risolvere come side-effect i 3 gap del Wow Audit (W-002 keyframes morti · W-010 sezioni render null · W-011 screenshot stub).
2. Out-of-scope
packages/sector-adapters/(è Child-2)packages/planet-booking/(è Child-2)- Nuove feature funzionali Web (solo refactor strutturale + W-002/010/011 fix)
- DB migration (solo tipi + RLS review · escalate Mother se serve migration)
3. Vincoli hard
- TypeScript strict · zero
any· branded types da@multiverbe/contracts - Coverage
planet-core≥80% line · ≥70% branch · mutation ≥60% (Stryker) - Coverage
planet-webretrofit ≥70% line - Bundle:
planet-core≤25KB gz ·planet-web≤80KB gz lazy chunk - A11y WCAG 2.2 AA su Web mount (axe-core 0 critical/serious)
- Perf:
planet-webboot ≤180ms p95 (Lighthouse Vercel preview) - Conventional commits (commitlint enforced)
- ZERO breaking change end-user su
/webroute (Playwright smoke green pre+post)
4. Tools authorized
- Read/Edit/Write/Glob/Grep (codebase)
- Bash (pnpm, git, playwright, lighthouse-ci)
- Task tool (sub-agent Explore se servono ricerche complesse)
- Supabase MCP read-only (
list_tables,get_advisorssmoke su Web RLS) · NO write - Vercel MCP (preview deploy verify)
- Context7 MCP (docs lookup React 19, R3F v9, vitest, stryker)
- Playwright MCP (snapshot/click/network smoke)
5. Success metric
- ✅
pnpm --filter @multiverbe/planet-core test --coverage≥80% line · ≥70% branch - ✅
pnpm --filter @multiverbe/planet-core test:mutation≥60% - ✅
pnpm --filter @multiverbe/planet-web test --coverage≥70% line - ✅
pnpm --filter @multiverbe/planet-web buildsize-limit pass (≤80KB gz) - ✅ Playwright smoke
signup → /web → create site → previewzero error - ✅ W-002, W-010, W-011 risolti (vedi §"Side-effect fixes" sotto)
- ✅ Scaffold script
scripts/scaffold-planet.tsfunzionapnpm run scaffold:planet <kind><60s - ✅ ADR 001 e 003 finalizzati con esempi reali
6. Definition of Done
- PR aperto su
masterviagh pr createcon body completo (vedi sotto) gh pr merge --auto --squash --delete-branchauto-merge appena CI green- PR body: link a ADR + acceptance checklist tickata + screenshot Vercel deploy + impatto MVP%
- Self-critique sezione PR body "what I'd improve next iteration" (≥3 punti)
</task_spec>
Deliverable dettagliati
A. packages/planet-core/
A.1 src/registry.ts — singleton planet registry
register(module: PlanetModule<unknown>): Result<void, RegistryError>unregister(id: PlanetId): Promise<void>get(id: PlanetId): PlanetModule<unknown> | nulllist(): ReadonlyArray<PlanetMeta>boot(deps: PlanetId[]): Promise<BootReport>— risolvemanifest.dependenciescon topological sort · cycle detection (throwCyclicDependencyError)- Lifecycle hooks:
onBeforeBoot,onAfterBoot,onError - Concurrency safe: boot multipli idempotenti (debounce 50ms)
A.2 src/loader.ts — dynamic lazy loader
loadPlanet(kind: PlanetKind): Promise<PlanetModule<unknown>>— code-splitting via dynamic import- Prefetch hint via manifest
routes[].prefetch: boolean - Cache layer: planet loaded resta in memoria fino unmount esplicito
- Error boundary: load fail → fallback module con
manifest.kind+ healthcheck red
A.3 src/event-bus.ts — typed pub/sub
EventBus<TEventMap>conpublish(event, payload),subscribe(event, handler),unsubscribe(...)- Backpressure: queue max 1000 · drop-oldest config
- OTel span propagation: ogni publish crea/continua span attivo
- Cross-planet pattern: event namespace
<planet-id>:<event-name>enforced - DevTools hook:
globalThis.__MULTIVERBE_BUS__in non-prod
ESCALATION: se hai dubbi su semantica concurrency/backpressure/error propagation → escalate alla Mother. Questo è il punto più delicato del package. Time-box 90min hard cap su event-bus · se sfori → fallback EventEmitter typed semplice + ADR-005 deferring.
A.4 src/telemetry.ts — OTel-compatible
TelemetrySinkinterface · default impl OTel SDK web (@opentelemetry/sdk-trace-web)- Perf marks:
planet:{kind}:init,planet:{kind}:mount,planet:{kind}:first-interaction - Structured logger:
logger.info({ planet, workspace_id, op }, "msg")JSON output - PII filter list: email, phone, payment_method (regex pre-export)
- Sentry breadcrumb hook se
window.Sentrypresente
A.5 src/feature-flags.ts — flag reader
- Default source:
import.meta.env.PUBLIC_FEATURE_FLAGS(JSON) - Dev override: URL
?ff=key1:on,key2:off(warning console se prod) - Per-workspace override: lookup
workspaces.feature_flagsjsonb (Supabase, RLS scoped) - Audit log: ogni flip →
INSERT INTO feature_flag_audit (workspace_id, flag, old_value, new_value, flipped_by, flipped_at)(table TODO escalate Mother se non esiste · placeholder mock for now) - LaunchDarkly-compatible shape per future migrazione
A.6 src/state-migrator.ts — versioned state migration
migrate(state: unknown, fromVersion: number, toVersion: number, migrations: MigrationSpec[]): Result<TState, MigrationError>- Forward + backward (rollback)
- Migration spec:
{ from: number, to: number, up: (s) => s, down: (s) => s, validate: ZodSchema } - Replay test in planet-testkit gratis
A.7 src/healthcheck.ts — aggregated health
- Endpoint
/api/health/planets(Next.js route handler factory · exportcreateHealthRoute()) - Output:
{ [kind]: { status: 'ok'|'degraded'|'down', latency_ms, last_error?: string, version: SemVer } } - Per-planet healthcheck delegato a
module.healthcheck() - Cache TTL 5s · stampede protection (single-flight)
A.8 src/index.ts — public API
- Re-export tipi da
@multiverbe/contracts - Re-export
registry,loader,eventBus,telemetry,featureFlags,stateMigrator,healthcheck - Re-export
defineModule<TState>(spec): PlanetModule<TState>helper (DX win) - NO internal types leaked (
internal/cartella con TypeScript path mapping)
A.9 Tests
tests/unit/*.test.tsper ogni file src/tests/integration/registry-loader-bus.test.tsend-to-end registry+loader+bustests/integration/state-migration.test.tsforward + back roundtrip- Stryker config tarata su
packages/planet-core/src/(escludiindex.tsre-exports)
B. packages/planet-testkit/
Test harness condiviso. Ogni PlanetModule<T> importa e ottiene 18 contract test gratis.
B.1 src/contract.ts
runContractSuite<TState>(module: PlanetModule<TState>, opts: ContractOpts): void- Test inclusi:
manifestvalid (Zod schema validation)manifest.idmatches^planet-[a-z][a-z0-9-]*$manifest.routesnon-empty · eachpathstarts with/manifest.rlsTablesactually exist in Supabase (mock or real branch)init(ctx)returnsResult<void, _>(no throws)initidempotent: chiamato 2x stesso effettomount(slot)returnsReact.ComponentTypeunmount()cleanup completo (no listener leaks ·process.getActiveResourcesInfo()baseline)selectorspure functions (referential transparency test)actionsproduce nuovo state object (immutability test)eventstypes matchmanifest.telemetry.eventshealthcheck()<200ms p99- State migration round-trip da v1 a latest
- Manifest
bundleBudgetKbrispettato (size-limit assertion) - A11y: mount root passa axe-core 0 critical
- Boot perf: ≤180ms p95 su 10 run
- Cross-workspace isolation: 2 workspace mount stesso planet → state separato
- Feature flag respect:
manifest.featureFlagsreader rispettato
B.2 src/rls.ts — Supabase RLS harness
verifyWorkspaceIsolation(table: TableName, supabase: SupabaseClient): Promise<RLSReport>- Create 2 workspaces test · INSERT in ws-A · query da ws-B expect deny
- Cleanup automatico
B.3 src/a11y.ts — axe-core wrapper
expectA11y(html: string | HTMLElement, ruleset: 'wcag-2.2-aa' | 'wcag-2.2-aaa'): Promise<void>- Throws con violations array dettagliato
B.4 src/perf.ts — perf budget assertions
expectBootTime(planet: PlanetModule<unknown>, budget_ms: number, samples: number = 10): Promise<void>- Usa
performance.now()· p95 calcolato
C. packages/planet-web/ retrofit
Wrap codice esistente Site Builder in PlanetModule<WebState> conforme. Code attualmente in frontend/multiverbe-app/src/sites-runtime/, src/components/sections/, src/orchestrator.ts.
C.1 Mapping codice esistente → PMS
| Code esistente | PlanetModule slot |
|---|---|
sites-runtime/components/SiteRenderer.tsx |
module.mount() ritorna questo |
src/orchestrator.ts (AI section selection) |
module.actions.generateSite |
src/lib/sites/state.ts |
WebState tipo · selectors derivati |
src/api/sites/* route handlers |
manifest routes + healthcheck endpoint |
| Section registry implicito | manifest.routes[].sections: keyof SectionRegistry (typed strict) |
C.2 Side-effect fixes (3 gap dal Wow Audit)
W-002 · Keyframes morti (sites-runtime/components/sections/Booking/SlideOver, StickyMobile, Gallery/InstagramGrid, Slideshow referenziano animate-[fadeIn]/[sheetUp]/[slideLeft] ma keyframes non definiti):
- Crea
packages/planet-web/src/styles/animations.csscon@keyframes fadeIn,sheetUp,slideLeft(+ qualsiasi altro referenziato) - Import in module bootstrap
- Aggiungi vitest test che scansiona JSX per
animate-[...]e verifica esistenza inanimations.css(catch new regressioni) - ADR? Solo se rimuovi animation invece di implementarle.
W-010 · Sezioni render null (SectionRenderer in components/sections/index.tsx ritorna null silenziosamente per sezioni non implementate):
- Crea
SectionRegistrytyped strict:Record<SectionKind, React.ComponentType<SectionProps>> - AI section selection (orchestrator.ts) vincolata a
keyof SectionRegistry(compile-time guard) - Sezioni candidate del Wow Audit (
menu-story-driven,hero-food-bento,hero-video-loop,gallery-scroll-parallax, famiglie social-proof/about-story/private-events): decisione FOUNDER se implementare o restringere menù. Default: restringi menù (più sicuro · 1 ADR004-section-registry-restricted-menu.mdcon lista deferred a Fase 4 Wow Backlog). - Test: render unknown section → fallback explicit
<UnknownSectionWarning />(non null silenzioso) · log warning + Sentry breadcrumb
W-011 · Screenshot stub (capturePageScreenshot() in orchestrator.ts:~1167 ritorna placeholder hardcoded):
- Implementa real screenshot via Playwright headless launcher (server-side, lato Render Python o Node serverless)
- Feature flag
web.realScreenshot=true(default off in dev · on in prod) - Stub mode resta come fallback se Playwright launcher down (telemetry alert)
- Test: integration con Playwright mock · screenshot reale on local stack
C.3 Manifest planet-web
export const manifest: PlanetManifest = {
id: 'planet-web' as PlanetId,
kind: 'web',
version: '1.0.0',
displayName: { it: 'Pianeta Web', de: 'Web-Planet', fr: 'Planète Web', en: 'Web Planet', es: 'Planeta Web' },
description: { it: 'Generatore siti AI per PMI', /* ... */ },
icon: { kind: 'lucide', name: 'Globe' },
routes: [
{ path: '/web', component: 'WebDashboard', sections: ['hero', 'menu', 'booking-cta', 'gallery', 'footer'], prefetch: true },
{ path: '/web/builder', component: 'SiteBuilder', sections: [], prefetch: false },
{ path: '/web/preview/:siteId', component: 'SitePreview', sections: [], prefetch: false },
],
permissions: ['web:read', 'web:write', 'web:publish'],
rlsTables: ['sites', 'site_pages', 'site_assets', 'site_deployments'],
telemetry: {
spans: ['web.generate_site', 'web.preview', 'web.publish'],
events: { siteGenerated: SiteGeneratedSchema, sitePublished: SitePublishedSchema },
},
featureFlags: [
{ key: 'web.realScreenshot', default: false, description: 'Use real Playwright screenshot vs stub' },
{ key: 'web.siteBuilderV2', default: false, description: 'Kimi K2.6 builder pipeline' },
],
dependencies: [], // no soft deps
stateSchemaVersion: 1,
migrations: [],
bundleBudgetKb: 80,
a11yProfile: 'wcag-2.2-aa',
};
D. Scaffold script scripts/scaffold-planet.ts
CLI in root repo:
pnpm run scaffold:planet <kind>
# Esempio: pnpm run scaffold:planet crm
Output (in <60s):
packages/planet-{kind}/skeleton:package.json(name@multiverbe/planet-{kind}, peerDeps@multiverbe/contracts,@multiverbe/planet-core)src/index.ts(exportmoduleplaceholder)src/manifest.ts(stub conforme · routes empty array · tutti i field richiesti)src/state.ts(export interface {Kind}State {})tests/contract.test.ts(importa planet-testkitrunContractSuite(module))tsconfig.jsonextends rootvitest.config.tsREADME.md(template scope + boundaries + escalation contacts)
docs/adr/00X-planet-{kind}-implementation.md(template ADR)D:\Desktop\Multiverbe-Business\source\_meta\status.jsonaction_itemplanet-{kind}-implementation-{date}(status: todo, day: +3gg from today)- Smoke
pnpm --filter @multiverbe/planet-{kind} testexit 0 immediato
Implementazione: usa prompts package per CLI prompts (kind, displayName, description), degit o template literal generation. Test del script via pnpm run scaffold:planet crm in CI smoke (poi delete via git clean -df packages/planet-crm).
Acceptance criteria (PR-blocking)
[ ] pnpm typecheck → exit 0 (zero any, zero @ts-ignore non commentato)
[ ] pnpm lint → zero new warning
[ ] pnpm --filter @multiverbe/planet-core test --coverage → ≥80% line, ≥70% branch
[ ] pnpm --filter @multiverbe/planet-core test:mutation → ≥60%
[ ] pnpm --filter @multiverbe/planet-testkit test → 100% pass
[ ] pnpm --filter @multiverbe/planet-web test --coverage → ≥70% line
[ ] pnpm --filter @multiverbe/planet-web build → size-limit pass (≤80KB gz)
[ ] pnpm --filter @multiverbe/planet-core build → size-limit pass (≤25KB gz)
[ ] pnpm dlx madge --circular packages/planet-core packages/planet-testkit packages/planet-web → 0 circular
[ ] Playwright smoke signup → /web → create site → preview → zero error
[ ] axe-core scan su /web mount → 0 critical/serious
[ ] W-002 fix: keyframes test scanner pass + visual smoke 4 sezioni precedentemente bug → pass
[ ] W-010 fix: SectionRegistry typed + 0 null section renders + UnknownSectionWarning explicit fallback → pass
[ ] W-011 fix: real screenshot path implementato + feature flag wired + test coverage → pass
[ ] Scaffold script pnpm run scaffold:planet crm <60s exit 0 + planet-crm test green → pass
[ ] ADR 001 finalizzato con esempi reali · ADR 003 finalizzato → done
[ ] PR body: scope + impatto MVP% + screenshot Vercel preview + self-critique 3+ punti → present
[ ] Commitlint conventional commits enforced (verified via git log) → pass
Time budget Child-1 (6h)
| Slot | Task | Durata |
|---|---|---|
| 0:00–0:30 | Read brief + audit codebase esistente Web + setup local dev server | 30min |
| 0:30–2:00 | planet-core/ registry + loader + state-migrator + healthcheck + tests |
90min |
| 2:00–3:30 | planet-core/ event-bus + telemetry + feature-flags + tests (escalate Opus 4.7 su event-bus se serve) |
90min |
| 3:30–4:30 | planet-testkit/ contract suite 18 test + RLS harness + a11y wrapper + perf budget |
60min |
| 4:30–5:30 | planet-web/ retrofit + manifest + W-002/010/011 fix + tests |
60min |
| 5:30–6:00 | Scaffold script + smoke + ADR finalize + PR open + self-critique | 30min |
Buffer 0 minutes. Scoping aggressivo voluto. Se scivoli >30min su un blocco → ESCALATE Mother subito · non aspettare.
Decision matrix · autonomous mode
| Situazione | Azione |
|---|---|
| Decisione naming/branding pubblico | DECIDI best (semantic + i18n-ready) · logga in PR body · ADR-draft · proceed |
| Schema DB migration necessaria | PROCEDI con safety rails · test branch ephemeral + UP/DOWN + RLS + get_advisors diff + ADR · apply via MCP apply_migration · proceed |
| Event bus semantics dubbie | Time-box 90min · poi fallback EventEmitter typed semplice (mitt o custom) + ADR-005 deferring · proceed |
| Security trade-off (CSP, RLS, secret) | DECIDI strict default · ADR · proceed · review post-merge in <quality_report> |
| Section deferral decision (W-010) | DEFAULT = restringi menù (safer) · ADR-004 finalizza con lista deferred · proceed |
| Scope creep (oltre time budget) | Slip ≥30min → riduci scope (skeleton invece di full) + action_item BOS per resto + PROCEED |
| Cycle detection bug | Fix forward · refactor breve · proceed |
| CI fail post-PR | Fix forward in stesso PR · NON aprire nuovo PR · proceed |
| Vercel deploy fail | vercel logs + fix forward · feature flag rollback solo se prod broken end-user |
Self-improvement loop Child-1
A fine sub-sessione, prima di chiudere PR:
- Self-critique sezione PR body (≥3 cose che farei meglio next time)
- Pattern learned snippet per Mother (Mother integra in memoria globale)
- Wow candidate ≥1 idea per
execution/wow-backlog.md - Handover 1 riga: cosa lascio fragile/da-rivedere · cosa lascio rock-solid
START COMMAND Child-1 (autonomous)
- Leggi questo brief intero
- Audit codebase:
cd D:\Desktop\Multiverbe-child1-pms-core·pnpm install·pnpm test -rbaseline ·git log --oneline -20- ACK 3 righe a Mother (1 task_spec · 1 risk · 1 confidence%) · NO domande · NO wait
- START SUBITO time-boxed seguendo § Time budget Child-1
- PR open:
gh pr create --base master --title "feat(planet-system): PMS core + Web retrofit · W-002/010/011 fix" --body "$(cat PR_BODY.md)"- Auto-merge:
gh pr merge <PR_NUM> --auto --squash --delete-branch- Ritorna result alla Mother (Task tool result include: PR URL, merge status, acceptance checks summary, self-critique 3+ punti, decisioni zona grigia loggate)