@polymorphism-tech/morph-spec 8.28.0 → 8.31.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLAUDE.md +6 -1
- package/README.md +13 -2
- package/bin/morph-spec.js +48 -0
- package/bin/validate.js +379 -379
- package/claude-plugin.json +1 -1
- package/docs/CHEATSHEET.md +1 -1
- package/docs/QUICKSTART.md +1 -1
- package/framework/CLAUDE.md +2 -0
- package/framework/MORPH.md +2 -1
- package/framework/agents.json +20 -9
- package/framework/commands/create-umbraco-lp.md +1 -1
- package/framework/commands/morph-status.md +1 -1
- package/framework/docs/CLI.md +18 -0
- package/framework/evals/rubrics/code-quality.md +17 -0
- package/framework/evals/rubrics/condensed.md +3 -1
- package/framework/hooks/claude-code/statusline.sh +11 -11
- package/framework/hooks/git/commit-msg/conventional-commits.sh +33 -33
- package/framework/hooks/git/pre-commit/agents.sh +25 -25
- package/framework/hooks/git/pre-commit/orchestrator.sh +64 -64
- package/framework/hooks/git/pre-commit/specs.sh +50 -50
- package/framework/hooks/git/pre-push/run-tests.sh +44 -44
- package/framework/hooks/shared/phase-utils.js +2 -0
- package/framework/hooks/shared/stdin-reader.js +26 -26
- package/framework/mcp/registry.json +97 -11
- package/framework/rubrics/backend.json +2 -2
- package/framework/rubrics/default.json +2 -2
- package/framework/rubrics/frontend.json +2 -2
- package/framework/schemas/tasks.schema.json +25 -0
- package/framework/skills/core/create-umbraco-lp/SKILL.md +13 -2
- package/framework/skills/core/create-umbraco-lp/references/umbraco-lp-patterns.md +598 -0
- package/framework/skills/core/migrate-lp-to-umbraco/SKILL.md +92 -7
- package/framework/skills/core/morph-apply/SKILL.md +12 -3
- package/framework/skills/core/morph-brainstorming/SKILL.md +1 -1
- package/framework/skills/core/morph-eval/SKILL.md +1 -1
- package/framework/skills/core/morph-hotfix/SKILL.md +1 -1
- package/framework/skills/core/morph-implement/SKILL.md +12 -2
- package/framework/skills/core/morph-plan/SKILL.md +45 -3
- package/framework/skills/core/morph-proposal/SKILL.md +1 -1
- package/framework/skills/core/morph-review/SKILL.md +11 -3
- package/framework/skills/core/morph-stack-scan/SKILL.md +13 -1
- package/framework/skills/core/morph-standards/SKILL.md +1 -1
- package/framework/skills/core/morph-uiux/SKILL.md +1 -1
- package/framework/standards/PROVENANCE.json +41 -0
- package/framework/standards/STANDARDS.json +218 -7
- package/framework/standards/ai-agents/agent-session.md +160 -160
- package/framework/standards/ai-agents/batching.md +193 -193
- package/framework/standards/ai-agents/context-providers.md +188 -188
- package/framework/standards/ai-agents/mcp-server.md +250 -250
- package/framework/standards/ai-agents/mcp-tools.md +197 -197
- package/framework/standards/ai-agents/middleware-patterns.md +207 -207
- package/framework/standards/ai-agents/modalities-image-gen.md +173 -173
- package/framework/standards/ai-agents/modalities-speech-to-text.md +171 -171
- package/framework/standards/ai-agents/modalities-text-to-speech.md +181 -181
- package/framework/standards/ai-agents/modalities-vision.md +201 -201
- package/framework/standards/ai-agents/multi-agent-patterns.md +155 -155
- package/framework/standards/ai-agents/production.md +231 -231
- package/framework/standards/ai-agents/prompts-in-db.md +214 -214
- package/framework/standards/ai-agents/providers/model-registry.md +158 -158
- package/framework/standards/ai-agents/service-tier-flex.md +135 -135
- package/framework/standards/ai-agents/structured-output.md +249 -249
- package/framework/standards/ai-agents/sweet-spot.md +109 -109
- package/framework/standards/frontend/design-system/ai-image-generation.md +43 -0
- package/framework/standards/frontend/design-system/ai-video-generation.md +113 -0
- package/framework/standards/frontend/design-system/premium-finish.md +160 -0
- package/framework/standards/frontend/gsap/gsap-core.md +1 -1
- package/framework/standards/frontend/gsap/gsap-plugins.md +1 -1
- package/framework/standards/frontend/gsap/gsap-scrolltrigger.md +3 -1
- package/framework/standards/frontend/nextjs/motion-patterns.md +3 -1
- package/framework/standards/frontend/scroll-driven/frame-scrub.md +287 -0
- package/framework/standards/frontend/scroll-driven/scroll-components.md +256 -0
- package/framework/standards/frontend/scroll-driven/smooth-scroll.md +148 -0
- package/framework/standards/frontend/seo/meta-schema-audit.md +134 -0
- package/framework/templates/.idea/morph-templates.xml +92 -0
- package/framework/templates/.vscode/morph-templates.code-snippets +186 -0
- package/framework/templates/IDE-SNIPPETS.md +262 -262
- package/framework/templates/code/dotnet/abstractions/api-endpoint.cs +7 -7
- package/framework/templates/code/dotnet/ai-agents/AgentBootstrap.cs.template +39 -39
- package/framework/templates/code/dotnet/ai-agents/EmbeddingService.cs.template +68 -68
- package/framework/templates/code/dotnet/ai-agents/ModelRegistry.cs.template +117 -117
- package/framework/templates/code/dotnet/ai-agents/PromptRepository.cs.template +95 -95
- package/framework/templates/code/dotnet/ai-agents/ResilientToolMiddleware.cs.template +61 -61
- package/framework/templates/code/dotnet/ai-agents/VectorSearchTool.cs.template +107 -107
- package/framework/templates/code/dotnet/ai-agents/model-registry.json.template +58 -58
- package/framework/templates/code/dotnet/contracts/contracts-vsa.cs +281 -281
- package/framework/templates/code/dotnet/database/migration.cs +83 -83
- package/framework/templates/code/dotnet/feature/endpoint.cs.hbs +21 -21
- package/framework/templates/code/dotnet/feature/request.cs.hbs +4 -4
- package/framework/templates/code/dotnet/feature/response.cs.hbs +4 -4
- package/framework/templates/code/dotnet/feature/validator.cs.hbs +15 -15
- package/framework/templates/code/sql/ai-agents/agent-prompts-migration.sql.template +58 -58
- package/framework/templates/code/sql/ai-agents/pgvector-embeddings-migration.sql.template +91 -91
- package/framework/templates/code/typescript/contracts.ts +167 -167
- package/framework/templates/context/ARCHITECTURE.md +20 -0
- package/framework/templates/docs/clarifications.md +253 -253
- package/framework/templates/docs/schema-analysis.md +119 -119
- package/framework/templates/docs/ui-components.md +52 -52
- package/framework/templates/docs/ui-design-system.md +76 -76
- package/framework/templates/docs/ui-flows.md +167 -167
- package/framework/templates/docs/ui-mockups.md +98 -98
- package/framework/templates/feature/decisions.md +122 -122
- package/framework/templates/frontend/nextjs/Dockerfile.nextjs.hbs +43 -43
- package/framework/templates/frontend/nextjs/client-component.tsx.hbs +26 -26
- package/framework/templates/frontend/nextjs/env.mjs.hbs +32 -32
- package/framework/templates/frontend/nextjs/feature-form.tsx.hbs +56 -56
- package/framework/templates/frontend/nextjs/page.tsx.hbs +22 -22
- package/framework/templates/frontend/nextjs/tsconfig.json.hbs +26 -26
- package/framework/templates/frontend/nextjs/use-feature.ts.hbs +54 -54
- package/framework/templates/infrastructure/docker/Dockerfile.template +58 -58
- package/framework/templates/infrastructure/docker/dockerfile-api.dockerfile +38 -38
- package/framework/templates/infrastructure/docker/dockerfile-web.dockerfile +48 -48
- package/framework/templates/infrastructure/github/README.md +56 -56
- package/framework/templates/infrastructure/github/actions/docker-build-push/action.yml.hbs +45 -45
- package/framework/templates/infrastructure/github/actions/health-check/action.yml.hbs +27 -27
- package/framework/templates/infrastructure/github/workflows/docker-build-push.yml.hbs +59 -59
- package/framework/templates/infrastructure/github/workflows/dotnet-build.yml.hbs +39 -39
- package/framework/templates/integrations/asaas-client.cs +387 -387
- package/framework/templates/integrations/asaas-webhook.cs +351 -351
- package/framework/templates/meta-prompts/fusion/fusion-agent.md +76 -76
- package/framework/templates/meta-prompts/fusion/fusion-aggregator.md +100 -100
- package/framework/templates/meta-prompts/validators/pre-commit-validator.md +95 -95
- package/framework/templates/project/validate.js +120 -120
- package/framework/templates/state.template.json +17 -17
- package/framework/templates/ui/design-system.css +226 -226
- package/package.json +1 -1
- package/src/commands/dashboard/dashboard.js +53 -53
- package/src/commands/graph/affected.js +89 -0
- package/src/commands/graph/build.js +94 -0
- package/src/commands/graph/explain.js +96 -0
- package/src/commands/graph/status.js +93 -0
- package/src/commands/index.js +13 -13
- package/src/commands/project/checkpoint.js +209 -209
- package/src/commands/project/doctor.js +11 -0
- package/src/core/paths/output-schema.js +7 -0
- package/src/core/state/phase-state-machine.js +197 -197
- package/src/core/templates/template-renderer.js +477 -477
- package/src/dashboard/app/components/DetailPanel.jsx +11 -11
- package/src/dashboard/app/components/FlowGraph.jsx +17 -17
- package/src/dashboard/app/components/SearchFilter.jsx +22 -22
- package/src/dashboard/app/hooks/useDetailPanel.js +15 -15
- package/src/dashboard/app/main.jsx +13 -13
- package/src/dashboard/app/pages/AgentMap.jsx +370 -370
- package/src/dashboard/app/pages/HookInspector.jsx +418 -418
- package/src/dashboard/app/pages/PhasePipeline.jsx +408 -408
- package/src/dashboard/app/pages/RulesMap.jsx +273 -273
- package/src/dashboard/app/pages/SkillsLibrary.jsx +366 -366
- package/src/dashboard/app/pages/Standards.jsx +332 -332
- package/src/dashboard/app/styles/index.css +47 -47
- package/src/dashboard/index.html +12 -12
- package/src/dashboard/package.json +24 -24
- package/src/dashboard/scanner/phases-scanner.js +15 -15
- package/src/dashboard/scanner/rubrics-scanner.js +12 -12
- package/src/dashboard/scanner/rules-scanner.js +37 -37
- package/src/dashboard/scanner/skills-scanner.js +43 -43
- package/src/dashboard/scanner/squads-scanner.js +13 -13
- package/src/dashboard/vite-plugin-morph-data.js +17 -17
- package/src/dashboard/vite.config.js +24 -24
- package/src/lib/detectors/design-system-detector.js +188 -188
- package/src/lib/detectors/index.js +217 -217
- package/src/lib/generators/architecture-scanner.js +45 -4
- package/src/lib/generators/design-system-generator.js +508 -508
- package/src/lib/generators/settings-generator.js +209 -209
- package/src/lib/graph/god-nodes.js +75 -0
- package/src/lib/graph/graph-health.js +61 -0
- package/src/lib/graph/graph-loader.js +86 -0
- package/src/lib/graph/graphify-runtime.js +100 -0
- package/src/lib/graph/graphifyignore.js +86 -0
- package/src/lib/graph/sanitize.js +280 -0
- package/src/lib/hooks/hook-executor.js +167 -167
- package/src/lib/installers/mcp-installer.js +719 -719
- package/src/lib/tasks/task-classifier.js +30 -30
- package/src/lib/tasks/task-parser.js +209 -209
- package/src/lib/tasks/tasks-json-parser.js +26 -0
- package/src/lib/validators/checkpoint-persistence.js +39 -39
- package/src/lib/validators/css/css-validator.js +340 -340
- package/src/lib/validators/reuse/index.js +10 -0
- package/src/lib/validators/reuse/reuse-validator.js +324 -0
- package/src/lib/validators/reuse/symbol-scanner.js +144 -0
- package/src/lib/validators/shared/emit-validator-dispatch.js +14 -14
- package/src/lib/validators/shared/issue-counter.js +14 -14
- package/src/lib/validators/validation-runner.js +40 -1
- package/src/scripts/setup-infra.js +60 -1
- package/src/utils/agent-id-mapper.js +11 -11
- package/src/utils/claude-settings-manager.js +300 -300
- package/src/utils/file-copier.js +40 -0
- package/src/utils/skills-installer.js +187 -187
|
@@ -4,7 +4,7 @@ description: Migra uma landing page existente (React/Vite, Next.js estático ou
|
|
|
4
4
|
version: core
|
|
5
5
|
when-to-invoke: ao receber instrução "use /migrate-lp-to-umbraco {projeto}" do usuário, ou quando o usuário descrever necessidade de migrar uma LP para Umbraco
|
|
6
6
|
user-invokable: true
|
|
7
|
-
cliVersion: "8.
|
|
7
|
+
cliVersion: "8.31.0"
|
|
8
8
|
stacks:
|
|
9
9
|
- umbraco
|
|
10
10
|
---
|
|
@@ -35,6 +35,7 @@ O processo é reproduzível para qualquer LP (React/Vite, Next.js estático ou H
|
|
|
35
35
|
- **(a) código-fonte local** da LP (React/Vite, Next.js ou HTML) — caminho de **fidelidade máxima**, pois o CSS, o markup e os assets exatos estão disponíveis para o lift verbatim.
|
|
36
36
|
- **(b) apenas a URL** da LP em produção — fallback: scrapear o HTML renderizado, o CSS computado e baixar todos os assets. O mesmo gate de paridade (passo 6) se aplica.
|
|
37
37
|
- **Docker** disponível para boot local (`docker compose`), ou .NET 10 SDK + Node para boot sem container.
|
|
38
|
+
- **Se a origem é scroll-driven** (canvas frame-scrub, pin, parallax, smooth scroll), leia antes os standards `frontend/scroll-driven/frame-scrub.md`, `smooth-scroll.md` e `scroll-components.md`. Eles carregam o conhecimento que o lift precisa preservar; o passo 4e diz onde os assets dessa animação vivem no destino.
|
|
38
39
|
|
|
39
40
|
## Passo 0 — Obter o template (sempre)
|
|
40
41
|
|
|
@@ -192,15 +193,31 @@ O script:
|
|
|
192
193
|
|
|
193
194
|
Nunca commitar `.env`. O cache do passo 0 permanece intacto (read-only) — todo o trabalho acontece nesta cópia.
|
|
194
195
|
|
|
195
|
-
**Smoke-boot antes de qualquer customização** — boot limpo do template para confirmar que o ambiente funciona:
|
|
196
|
+
**Smoke-boot antes de qualquer customização** — boot limpo do template para confirmar que o ambiente funciona. Suba **na ordem**, backend primeiro, e só depois construa o frontend:
|
|
196
197
|
|
|
197
198
|
```bash
|
|
198
|
-
docker compose up
|
|
199
|
+
docker compose up -d backend
|
|
200
|
+
# espere a Delivery API, não o backoffice (ver abaixo)
|
|
201
|
+
until [ "$(curl -s -o /dev/null -w '%{http_code}' \
|
|
202
|
+
'http://localhost:5001/umbraco/delivery/api/v2/content?take=1')" = "200" ]; do sleep 5; done
|
|
203
|
+
docker compose up --build -d frontend
|
|
199
204
|
```
|
|
200
205
|
|
|
201
|
-
Backend sobe em `http://localhost:5001`, frontend em `http://localhost:3000`. Acessar `http://localhost:3000` e confirmar que a página carrega sem erro 500. Isso elimina problemas de ambiente antes de introduzir customizações
|
|
206
|
+
Backend sobe em `http://localhost:5001`, frontend em `http://localhost:3000`. Acessar `http://localhost:3000` e confirmar que a página carrega sem erro 500. Isso elimina problemas de ambiente antes de introduzir customizações; falha precoce economiza horas.
|
|
202
207
|
|
|
203
|
-
**Atenção (gotcha Build do Next.js):** o Dockerfile do frontend executa `next build` na imagem
|
|
208
|
+
**Atenção (gotcha Build do Next.js):** o Dockerfile do frontend executa `next build` na imagem, e nesse momento o Next busca conteúdo via Delivery API para o SSG. Se a API não responder **conteúdo**, o build falha, e a mensagem que chega é só `npm run build ... exit code 1`, sem dizer que o problema é o backend. Por isso `docker compose up --build` sozinho, do zero, não é um comando confiável: ele constrói o frontend junto com o backend.
|
|
209
|
+
|
|
210
|
+
> **O critério de prontidão é a Delivery API responder 200, nunca o backoffice.** Um healthcheck
|
|
211
|
+
> que bate em `/umbraco` fica **healthy** enquanto `/umbraco/delivery/api/v2/content` ainda devolve
|
|
212
|
+
> **500**: o backoffice sobe, o uSync importa, o seed grava, e a API só quebra quando alguém pede o
|
|
213
|
+
> conteúdo. `depends_on: condition: service_healthy` apontando para o healthcheck errado dá uma
|
|
214
|
+
> falsa sensação de ordem resolvida e o build do frontend morre mesmo assim. Aponte o healthcheck
|
|
215
|
+
> do backend para a Delivery API.
|
|
216
|
+
>
|
|
217
|
+
> **E se ela devolver 500, não é questão de esperar mais.** Um 500 persistente na Delivery API com
|
|
218
|
+
> banco recém-seedado é quase sempre **dado seedado no formato errado**, não lentidão de boot.
|
|
219
|
+
> Aumentar timeout não resolve; vá para a seção "Gotchas de campo" e diagnostique pelo log do
|
|
220
|
+
> Umbraco antes de seguir.
|
|
204
221
|
|
|
205
222
|
### 4. Lift verbatim — portar markup, mídia e tema
|
|
206
223
|
|
|
@@ -401,6 +418,33 @@ Registrar o módulo em `frontend/src/components/modules/moduleRegistry.ts`:
|
|
|
401
418
|
nomeSection: () => import('./NomeSection'),
|
|
402
419
|
```
|
|
403
420
|
|
|
421
|
+
#### 4e. Sequências de frames e assets de animação (LP scroll-driven)
|
|
422
|
+
|
|
423
|
+
Se a origem tem hero (ou seção) com **canvas frame-scrub** (o scroll avançando um vídeo quadro a quadro), a animação atravessa a migração intacta, mas só se os assets forem para o balde certo. O modelo abaixo é o que roda em produção; foi decidido uma vez e não deve ser reaberto por engano.
|
|
424
|
+
|
|
425
|
+
**Dois baldes, e a fronteira não é opinião:**
|
|
426
|
+
|
|
427
|
+
| O quê | Onde | Editável no backoffice |
|
|
428
|
+
|---|---|---|
|
|
429
|
+
| Sequência de frames (`hero-frames/`, `oficio-frames/`), fontes, monograma da marca, ícones posicionais | `frontend/public/` | não, é asset estrutural |
|
|
430
|
+
| Poster do scrub, fotos editoriais, logo, imagem de OG | `backend/seed-assets/` → Media Library → MediaPicker3 | sim |
|
|
431
|
+
|
|
432
|
+
**Por que os frames não vão para a Media Library.** Três razões, em ordem de gravidade:
|
|
433
|
+
|
|
434
|
+
1. O processamento on-the-fly do ImageSharp (`?format=webp`) exige URL assinada por HMAC, e no Umbraco 17 o HMAC não é relaxável por configuração. Uma sequência servida de `/media/` perde o webp e não tem como recuperá-lo no frontend headless.
|
|
435
|
+
2. São 145 arquivos por sequência. Como requests assinadas ao backend, é um custo por visitante que não existe servindo de `/public`.
|
|
436
|
+
3. O `SeedContentHandler` só enxerga `backend/seed-assets/` e o banco. Deixando os frames em `frontend/public/`, eles ficam fora do universo do seed: sobrevivem a re-seed, a re-import do uSync e a um `--reset-db` completo, sem nenhum tratamento especial.
|
|
437
|
+
|
|
438
|
+
**O poster é o que fica editável.** É ele que aparece no mobile e sob `prefers-reduced-motion`, então é o único da dupla que o cliente tem motivo para trocar. Frames fixos, poster no MediaPicker.
|
|
439
|
+
|
|
440
|
+
**Cache-bust é obrigatório e manual.** `frontend/public/` não recebe hash de build (o Dockerfile copia o diretório verbatim e o Next só versiona `.next/static`), então reextrair frames mantendo os mesmos nomes serve os bytes antigos de qualquer cache intermediário. O `framePath` carrega um `?v=N` que sobe a cada reextração:
|
|
441
|
+
|
|
442
|
+
```ts
|
|
443
|
+
const framePath = (i: number) => `/hero-frames/frame_${String(i).padStart(3, '0')}.jpg?v=2`
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
**No lift, não trocar a lib de animação.** O template não traz `gsap` nem `lenis`; se a origem usa, adicione ao `frontend/package.json` do destino. Portar o registry de motion e o runtime de scroll como componentes `'use client'`, com o guard de SSR no registro do ScrollTrigger (ele toca `document`) e o runtime montado uma vez na page. Detalhe completo em `frontend/scroll-driven/smooth-scroll.md` e `frontend/scroll-driven/frame-scrub.md` no acervo de standards.
|
|
447
|
+
|
|
404
448
|
### 5. Conectar o formulário ao backend de leads
|
|
405
449
|
|
|
406
450
|
O template usa uma arquitetura de **multi-sink**: o backend seleciona automaticamente a integração correta pelo valor de `leadIntegration` configurado no nó `leadsConfig` do backoffice.
|
|
@@ -446,8 +490,12 @@ Objetivo: **provar** que a LP migrada é idêntica à origem. Com o lift verbati
|
|
|
446
490
|
|
|
447
491
|
#### 6a. Boot + checklist manual (sanidade)
|
|
448
492
|
|
|
493
|
+
Mesma ordem do passo 3: backend primeiro, Delivery API respondendo 200, e só então o frontend.
|
|
494
|
+
|
|
449
495
|
```bash
|
|
450
|
-
docker compose up
|
|
496
|
+
docker compose up -d backend
|
|
497
|
+
until [ "$(curl -s -o /dev/null -w '%{http_code}' 'http://localhost:5001/umbraco/delivery/api/v2/content?take=1')" = "200" ]; do sleep 5; done
|
|
498
|
+
docker compose up --build -d frontend
|
|
451
499
|
```
|
|
452
500
|
|
|
453
501
|
Percorrer a página em `http://localhost:3000` e conferir, lado a lado com a origem: todas as seções na ordem certa, textos/mídias corretos, formulário visível, navegação e footer funcionando. Isso é só uma sanidade rápida antes dos checks automáticos.
|
|
@@ -459,7 +507,27 @@ A skill **scaffolda** o harness de paridade no projeto destino (o template **nã
|
|
|
459
507
|
1. **Estrutura DOM + nomes de classe** por seção — `compare-sections.mjs` extrai o esqueleto de tags+classes de cada `<section>`/`<nav>`/`<footer>` dos dois lados (agrupado por chave semântica/texto âncora) e aponta diferenças. Adaptar o array `KEYS` (`[nome, matchFn]`) aos textos âncora das seções do projeto.
|
|
460
508
|
2. **Estilo computado** em elementos amostrados — para cada seção, comparar `getComputedStyle` de elementos-chave (cor, `font-family`, `font-size`, `font-weight`, paddings/margins, `border-radius`) origem × destino. Divergência = falha.
|
|
461
509
|
3. **Checksum de assets** — o conjunto de `sha256` de todas as imagens/vídeos/fontes servidas pelo destino deve igualar o conjunto capturado da origem no passo 1. Asset reencode/otimizado quebra aqui (proposital).
|
|
462
|
-
4. **Comportamento por interação** — uma asserção Playwright por comportamento capturado no passo 1 (scroll-expand, carrossel, marquee, autoplay de vídeo, hover, máscara/validação de telefone, submit do formulário com `/api/leads` mockado retornando `{"ok":true}`).
|
|
510
|
+
4. **Comportamento por interação** — uma asserção Playwright por comportamento capturado no passo 1 (scroll-expand, **canvas frame-scrub**, carrossel, marquee, autoplay de vídeo, hover, máscara/validação de telefone, submit do formulário com `/api/leads` mockado retornando `{"ok":true}`).
|
|
511
|
+
|
|
512
|
+
> **Scrub e qualquer efeito dirigido por scroll se verificam COM MOVIMENTO.** Um screenshot
|
|
513
|
+
> estático não distingue um scrub vivo de um canvas quebrado: o canvas pode estar 1x1 desenhando
|
|
514
|
+
> um pixel esticado, ou ignorando o scroll por completo, e a foto continua plausível. Dirija o
|
|
515
|
+
> scroll e compare o que foi desenhado em posições diferentes:
|
|
516
|
+
>
|
|
517
|
+
> ```js
|
|
518
|
+
> const lenis = window.__lenis
|
|
519
|
+
> const h = document.querySelector('header.hero-scrub').getBoundingClientRect().height
|
|
520
|
+
> for (const p of [0, .15, .3, .45, .6, .8, 1]) {
|
|
521
|
+
> lenis.scrollTo(Math.round((h - innerHeight) * p), { immediate: true })
|
|
522
|
+
> await new Promise(r => setTimeout(r, 350)) // deixa o scrub:0.4 assentar
|
|
523
|
+
> // capture aqui: screenshot, ou uma assinatura de pixels via ctx.getImageData
|
|
524
|
+
> }
|
|
525
|
+
> ```
|
|
526
|
+
>
|
|
527
|
+
> A espera não é opcional: com `scrub: 0.4` o desenho não salta, e sem ela você fotografa o frame
|
|
528
|
+
> anterior. **Critério de aprovação:** as capturas diferem entre si. Todas iguais significa scrub
|
|
529
|
+
> morto, mesmo que a página pareça correta. Confirmar também que os frames respondem 200 com o
|
|
530
|
+
> `?v=N` em uso e que os beats de texto trocam ao longo do percurso.
|
|
463
531
|
|
|
464
532
|
```bash
|
|
465
533
|
cd frontend
|
|
@@ -487,6 +555,22 @@ A migração é "exata" quando **todos** são verdade:
|
|
|
487
555
|
- `robots.txt`/`sitemap.xml` de produção apontam pro domínio real (não o placeholder `minha-landing-page.com.br` do template) — só acontece se `NEXT_PUBLIC_SITE_URL` foi setada como Build Variable no provedor.
|
|
488
556
|
- Nenhuma chave de API ou token aparece em arquivo versionado.
|
|
489
557
|
|
|
558
|
+
## Gotchas de campo
|
|
559
|
+
|
|
560
|
+
Furos que já custaram build quebrado ou deploy revertido em migração real. Nenhum deles aparece como erro óbvio no caminho feliz.
|
|
561
|
+
|
|
562
|
+
**Property editor guarda JSON, não escalar. Seedar string crua derruba a Delivery API inteira.** `Umbraco.DropDown.Flexible` persiste **array JSON mesmo com `Multiple: false`**. Dentro do JSON de um Block List a tentação é escrever `"ctaAcao": "ancora"` como qualquer outro campo do bloco; o correto é `["ancora"]`. O erro não fica no campo: a exceção sobe pelo `BlockListPropertyValueConverter` e **derruba o documento inteiro** (500 na home), o que mata o `next build` com SSG e chega até você como `npm run build ... exit code 1`. Só aparece com banco novo, então passa despercebido até o primeiro `--reset-db` ou deploy limpo.
|
|
563
|
+
|
|
564
|
+
Regra, diagnóstico pela letra citada no `JsonException` e o procedimento de A/B estão em `references/umbraco-lp-patterns.md` (seção 6) da skill `create-umbraco-lp`, instalada em `.claude/skills/create-umbraco-lp/`. Leia essa seção antes de seedar qualquer dropdown.
|
|
565
|
+
|
|
566
|
+
**MediaPicker3 sempre volta array, mesmo em single-pick.** Na Delivery API, todo campo de mídia chega como array (`poster`, `logo`, `favicon`, `imageSeo`, `modalLogo`), embutido sem `expand`. Acessar `campo.url` direto funciona enquanto o campo está vazio e passa a estourar no instante em que um editor o preenche. Pior: em `generateMetadata` o Next trata a exceção como fatal e derruba o build inteiro, então o sintoma é um deploy que quebra sozinho depois de alguém publicar no backoffice, sem nenhuma mudança de código. Tipar como `UmbracoImage[]` e indexar em `[0]`, sempre com fallback para o asset estático de `/public`.
|
|
567
|
+
|
|
568
|
+
**Label de Block List aninhado usa UFM.** O backoffice do Umbraco 17 (Bellissima) renderiza o label do bloco com Umbraco Flavored Markdown, `{=alias}`, e não com o `{{ alias }}` do backoffice AngularJS antigo. Com a sintaxe velha o header do bloco mostra a chave literal para o editor. É só display do backoffice, não afeta o render da LP, e por isso passa despercebido em toda validação automática.
|
|
569
|
+
|
|
570
|
+
**Reverse proxy e bind do Next.** Atrás de Traefik ou Coolify, o backend precisa de `UseForwardedHeaders` (X-Forwarded-Proto/For), senão o OpenIddict do backoffice não vê HTTPS e o login em `/umbraco` falha com `ID2083: This server only accepts HTTPS requests`. E o runner do frontend precisa de `HOSTNAME=0.0.0.0`: sem isso o `server.js` do Next standalone faz bind no id do container, o healthcheck via `localhost:3000` nunca passa, o container nunca fica healthy e o deploy dá rollback sem erro de aplicação nenhum.
|
|
571
|
+
|
|
572
|
+
**Antes de escrever qualquer um destes, confira se o template já resolveu.** Correções são portadas do projeto de volta para o `MORPH_Umbraco_LP_Template`, então parte desta lista pode já estar no scaffold que o passo 0 baixou. Ensinar de novo uma correção existente cria divergência.
|
|
573
|
+
|
|
490
574
|
## Anti-padrões
|
|
491
575
|
|
|
492
576
|
- Não commitar `.env` nem nenhum arquivo com tokens ou senhas.
|
|
@@ -531,3 +615,4 @@ Repo do template (privado, branch `master`): `polymorphism-tech/MORPH_Umbraco_LP
|
|
|
531
615
|
- `MORPH_Umbraco_LP_Template/frontend/src/app/globals.css` — bloco `@theme` para portar o tema da origem
|
|
532
616
|
- `MORPH_Umbraco_LP_Template/frontend/e2e/home.spec.ts` + `playwright.config.ts` — base de e2e (estender com `parity.spec.ts`)
|
|
533
617
|
- `MORPH_Umbraco_LP_Template/docker-compose.yml` — orquestração backend + frontend com variáveis de ambiente
|
|
618
|
+
- `.claude/skills/create-umbraco-lp/references/umbraco-lp-patterns.md` — padrões e gotchas do template (controller público, multi-sink, leitura server-side, segurança da Delivery API, uSync, **dropdown como JSON array (seção 6)**, seed idempotente, build do Next.js exigindo backend). Instalado junto com a skill irmã; carregue sob demanda.
|
|
@@ -4,7 +4,7 @@ description: Orquestra a execução autônoma de tasks de uma feature morph-spec
|
|
|
4
4
|
version: core
|
|
5
5
|
when-to-invoke: após Gate 2 aprovado, ao receber instrução "use /morph-apply" ou "implementar feature"
|
|
6
6
|
user-invokable: true
|
|
7
|
-
cliVersion: "8.
|
|
7
|
+
cliVersion: "8.31.0"
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# morph-apply
|
|
@@ -143,11 +143,20 @@ while (true):
|
|
|
143
143
|
|
|
144
144
|
```
|
|
145
145
|
dispatch Agent (subagent_type: "morph-{id}") with prompt:
|
|
146
|
-
contexto: spec.md, mandate.md, task description completa, doneCriteria
|
|
146
|
+
contexto: spec.md, mandate.md, task description completa, doneCriteria,
|
|
147
|
+
task.reuse (veredito REUSAR/ESTENDER/CRIAR por conceito) e os paths
|
|
148
|
+
dos alvos de reuso
|
|
147
149
|
standard: <path(s) .md do(s) standard(s) do domínio — leia-o(s) antes de implementar>
|
|
148
150
|
instrução: |
|
|
149
151
|
Leia o(s) standard(s) indicado(s) antes de escrever código.
|
|
150
|
-
Implemente esta task (ou cadeia de tasks do fluxo)
|
|
152
|
+
Implemente esta task (ou cadeia de tasks do fluxo) sem depender do trabalho
|
|
153
|
+
dos outros agentes deste batch: seu ISOLAMENTO é de ESTADO e de ÁRVORE DE
|
|
154
|
+
TRABALHO — nunca de conhecimento do codebase. Antes de criar tipo,
|
|
155
|
+
componente, hook ou serviço NOVO, verifique se já existe: `morph-spec graph
|
|
156
|
+
explain <nome>` e `graph affected <conceito> --uses-only`; sem grafo
|
|
157
|
+
(`no-graph`), caia para `grep -rn "<nome>"` e siga — a ausência de grafo
|
|
158
|
+
nunca bloqueia. Se algo cobre o caso, reuse ou estenda; se criar mesmo
|
|
159
|
+
assim, diga por que em uma linha no relatório.
|
|
151
160
|
Não modifique spec.md, mandate.md.
|
|
152
161
|
|
|
153
162
|
Contrato do relatório final:
|
|
@@ -4,7 +4,7 @@ description: Entende o negócio, os usuários e a arquitetura antes de qualquer
|
|
|
4
4
|
version: core
|
|
5
5
|
when-to-invoke: ao receber um novo request de feature, antes de morph-plan
|
|
6
6
|
user-invokable: true
|
|
7
|
-
cliVersion: "8.
|
|
7
|
+
cliVersion: "8.31.0"
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# morph-brainstorming
|
|
@@ -4,7 +4,7 @@ description: Avalia a qualidade de uma tarefa ou fase com rubricas graduadas 0-1
|
|
|
4
4
|
version: core
|
|
5
5
|
when-to-invoke: ao completar uma tarefa ou ao finalizar uma fase de implementação
|
|
6
6
|
user-invokable: false
|
|
7
|
-
cliVersion: "8.
|
|
7
|
+
cliVersion: "8.31.0"
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# morph-eval
|
|
@@ -4,7 +4,7 @@ description: ADW cirúrgico de hotfix — resolve uma queda/bug crítico de prod
|
|
|
4
4
|
version: core
|
|
5
5
|
when-to-invoke: ao receber "/morph-hotfix {feature}", quando a morph-proposal classifica o pedido como workType hotfix (Passo 0), ou o usuário diz "produção caiu / hotfix / urgente"
|
|
6
6
|
user-invokable: true
|
|
7
|
-
cliVersion: "8.
|
|
7
|
+
cliVersion: "8.31.0"
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# morph-hotfix
|
|
@@ -4,7 +4,7 @@ description: Guia a execução de cada tarefa de implementação com standard e
|
|
|
4
4
|
version: core
|
|
5
5
|
when-to-invoke: ao iniciar cada task de implementação listada em tasks.json
|
|
6
6
|
user-invokable: false
|
|
7
|
-
cliVersion: "8.
|
|
7
|
+
cliVersion: "8.31.0"
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# morph-implement
|
|
@@ -60,9 +60,19 @@ Ao iniciar cada task de `tasks.json` — antes de escrever qualquer código. Nor
|
|
|
60
60
|
|
|
61
61
|
Spec: [description completa do tasks.json]
|
|
62
62
|
Standard: [path do .md do standard identificado no passo 2]
|
|
63
|
-
Arquivos relevantes: [
|
|
63
|
+
Arquivos relevantes: [os `target` de task.reuse + o que o scout/grafo apontou
|
|
64
|
+
— este campo não é decorativo: é por ele que o código já existente chega
|
|
65
|
+
ao sub-agente, que trabalha em contexto fresco e não conhece o projeto]
|
|
66
|
+
Reuso: [task.reuse do tasks.json — `CONCEITO: VEREDITO → alvo`, uma linha por
|
|
67
|
+
conceito; ausente numa task que não introduz conceito]
|
|
64
68
|
Done quando: [doneCriteria do tasks.json]
|
|
65
69
|
|
|
70
|
+
Antes de criar tipo, componente, hook ou serviço NOVO, verifique se já
|
|
71
|
+
existe: `morph-spec graph explain <nome>` e `graph affected <conceito>
|
|
72
|
+
--uses-only`. Sem grafo (`no-graph`), caia para `grep -rn "<nome>"` e siga —
|
|
73
|
+
a ausência de grafo nunca bloqueia. Se algo cobre o caso, reuse ou estenda;
|
|
74
|
+
se criar mesmo assim, diga por que em uma linha no relatório.
|
|
75
|
+
|
|
66
76
|
Contrato do relatório final:
|
|
67
77
|
1. GRAVE `.morph/features/{feature}/3-implement/reports/[ID].md` ANTES de
|
|
68
78
|
encerrar — é o retorno autoritativo, não a sua mensagem final (que é
|
|
@@ -4,7 +4,7 @@ description: Guia a produção dos artefatos de planejamento de uma feature (use
|
|
|
4
4
|
version: core
|
|
5
5
|
when-to-invoke: ao iniciar a fase plan de uma feature, após o Gate 1 (proposal aprovado)
|
|
6
6
|
user-invokable: true
|
|
7
|
-
cliVersion: "8.
|
|
7
|
+
cliVersion: "8.31.0"
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# morph-plan
|
|
@@ -24,6 +24,41 @@ Ao iniciar a fase plan — após o `proposal.md` ser aprovado e antes de qualque
|
|
|
24
24
|
|
|
25
25
|
1. **Garanta que `proposal.md` e `stack-scan.md` estão no seu contexto antes de planejar.** Se não tem o conteúdo atual em contexto (sessão fresca, ou conteúdo possivelmente desatualizado), **use a tool Read para carregá-los** — não confie em cache de turnos anteriores. Na dúvida, Read. `.morph/features/{feature}/0-proposal/proposal.md` (problema, escopo, riscos — o comportamento é destilado aqui no passo 2, não vem pronto do proposal) e `.morph/features/{feature}/0-proposal/stack-scan.md` (contexto técnico detectado: greenfield vs brownfield, stack atual, drift). Em brownfield, o stack-scan informa decisões de spec/mandate — não invente padrões que conflitam com o detectado.
|
|
26
26
|
|
|
27
|
+
1b. **Scout — mapa do território antes de planejar (opcional, mas o default em feature grande ou brownfield).** É o call-site do "scout opcional antes do plan" que a MORPH.md promete. Dispare quando a feature toca área que você não tem em contexto, ou quando o `stack-scan.md` acusou brownfield com desvios.
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
subagent_type: "morph-scout"
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Peça: os arquivos que a feature vai tocar, o blast radius dos símbolos centrais dessa área e o que quebra junto. O scout começa por `morph-spec graph affected|explain` e **cai para grep sozinho quando não há grafo** — nunca trate a ausência de grafo como impedimento para planejar.
|
|
34
|
+
|
|
35
|
+
**Fallback** (se `morph-scout` não estiver registrado nos subagent types deste projeto): `general-purpose` com o campo `persona` do agente `scout` colado no prompt (Read em `.morph/framework/agents.json`), registrando o fallback no `decisions.md`.
|
|
36
|
+
|
|
37
|
+
Pular o scout é aceitável em feature pequena dentro de domínio já carregado — nesse caso **registre a decisão em uma linha no `decisions.md`**.
|
|
38
|
+
|
|
39
|
+
1c. **Mapa de reuso — o que desta feature JÁ EXISTE no codebase.** Antes de destilar os use cases, responda por conceito: *isto já está implementado?* É o passo que falta hoje e cujo efeito é medido — 17 duplicações intra-feature no ProspectPRO, `SimpleBuilding` redefinido em cinco arquivos da MESMA pasta, um deles já sem um campo. Sem este passo, quem implementa não tem como saber, e o framework nunca pergunta.
|
|
40
|
+
|
|
41
|
+
**Insumos, nesta ordem:**
|
|
42
|
+
1. **O grafo** — para cada conceito central (entidade, DTO, componente, hook, serviço, helper) que a feature vai introduzir: `morph-spec graph explain <nome-candidato>` (existe? onde?) e `morph-spec graph affected <conceito> --uses-only` (quem usa de verdade, sem contar quem só implementa).
|
|
43
|
+
2. **O inventário do projeto** — `.morph/context/README.md` (gerado por `morph-spec context refresh`): entidades, endpoints com método e rota, páginas e **componentes com path**. É a granularidade de *conceito* que o grafo, que casa por símbolo, não dá. **Este passo é o consumidor declarado desse arquivo** — se ele não existir, rode `morph-spec context refresh` ou siga sem ele.
|
|
44
|
+
3. **Sem grafo** (`no-graph`, projeto sem Python) — **caia para `grep -rn "<nome-candidato>"` no diretório de código e siga**; a ausência de grafo nunca bloqueia o plano (ADR-002). Registre a queda no `decisions.md`.
|
|
45
|
+
|
|
46
|
+
**Produza `.morph/features/{feature}/2-plan/reuse-map.md`** — artefato, não prosa solta:
|
|
47
|
+
|
|
48
|
+
```markdown
|
|
49
|
+
| Conceito | Já existe? | Onde | Decisão |
|
|
50
|
+
|---|---|---|---|
|
|
51
|
+
| SimpleBuilding | SIM (5×) | features/roulette/types/roulette.types.ts | REUSAR |
|
|
52
|
+
| FilterValues | SIM (ambíguo) | dashboard + leads + store | ESTENDER o de dashboard |
|
|
53
|
+
| RouletteScore | NÃO | — | CRIAR — nenhum tipo cobre pontuação por sorteio |
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
**`CRIAR` exige justificativa em uma linha, na própria célula** — a mesma forma que `morph-uiux` §"Consistência" já impõe para token de design (*"um token novo precisa de justificativa: o existente não cobre o caso"*). Sem a justificativa, o veredito não vale.
|
|
57
|
+
|
|
58
|
+
**Distinga "extrair para shared" de "importar de outra feature".** Reuso não é desculpa para acoplar slices: se o conceito é de duas features, o alvo é um módulo comum, não um import cruzado — a rubrica `architecture` penaliza dependência cross-feature e continua valendo.
|
|
59
|
+
|
|
60
|
+
O veredito viaja para o implementador pelo campo `reuse` de cada task (passo 5). Quem cobra o resultado é o `morph-spec verify`: o validador `reuse` acusa símbolo novo cujo nome já existe no grafo, na mesma linguagem — **intra-feature reprova**, cross-feature avisa, e um `CRIAR` declarado no plano rebaixa o achado a aviso.
|
|
61
|
+
|
|
27
62
|
2. **Destile os use cases — ANTES de escrever `spec.md` e `tasks.json`.**
|
|
28
63
|
|
|
29
64
|
Um arquivo por use case em `.morph/features/{feature}/2-plan/usecases/UC-{nn}-{slug}.md`:
|
|
@@ -87,7 +122,7 @@ Ao iniciar a fase plan — após o `proposal.md` ser aprovado e antes de qualque
|
|
|
87
122
|
4. Produza `mandate.md` em `.morph/features/{feature}/2-plan/`:
|
|
88
123
|
- Stack exata do projeto (leia de `.morph/config/config.json` → `project.stack` ou do CLAUDE.md).
|
|
89
124
|
- Standards obrigatórios: descubra-os com `morph-spec standards --find "<domínio/tecnologia>"` (top 3 `id · path · digest` — o digest decide) por domínio tocado; liste os IDs escolhidos.
|
|
90
|
-
- Patterns proibidos — **copie por extenso no mandate.md** a lista canônica de `MORPH.md` § "Stack baked-in" (`Guid.NewGuid()`→`Guid.CreateVersion7()`, classes não-sealed sem justificativa, exceptions como fluxo de controle, camada de Service/Manager entre handler e dados, repository genérico `IRepository<T>`/`IUnitOfWork`, SQL cru sem justificativa) mais qualquer proibição específica da feature. Copie o texto completo — o mandate.md é lido por implementadores em contexto fresco, sem `MORPH.md` carregado, então um ponteiro sozinho não basta aqui.
|
|
125
|
+
- Patterns proibidos — **copie por extenso no mandate.md** a lista canônica de `MORPH.md` § "Stack baked-in" (`Guid.NewGuid()`→`Guid.CreateVersion7()`, classes não-sealed sem justificativa, exceptions como fluxo de controle, camada de Service/Manager entre handler e dados, repository genérico `IRepository<T>`/`IUnitOfWork`, SQL cru sem justificativa, redeclarar tipo/componente que já existe na mesma feature) mais qualquer proibição específica da feature. Copie o texto completo — o mandate.md é lido por implementadores em contexto fresco, sem `MORPH.md` carregado, então um ponteiro sozinho não basta aqui.
|
|
91
126
|
- Política de acesso a dados (registre no mandate): `ApplicationDbContext` injetado direto no slice — para CRUD e para queries específicas (joins, projeção, paginação). Para concorrência ou SQL específico, store dedicado hand-written com justificativa em `decisions.md`.
|
|
92
127
|
- **Features com agentes de IA (MAF):** se a feature envolve um agente (Microsoft Agent Framework), **use a tool Read** nos standards relevantes de `.morph/framework/standards/ai-agents/*.md` (ex.: `setup`, `agent-session`, `middleware-patterns`, `mcp-server`, `mcp-tools`, `multi-agent-patterns`, `production`) — filtre pelo que a feature exige via `morph-spec standards --find "<tema>" --category ai-agents`. Esses standards carregam as **convenções de projeto** (single-agent por padrão — Workflows só para fan-in/out real; provider, caching, observability, A2A) que uma fonte externa de docs (ex.: context7) não conhece. Padrão de divisão: **superfície da API** pode vir de docs ao vivo/context7 (mais frescas para um SDK em evolução), mas **as convenções vêm dos standards** — registre ambas no mandate. Não pule os `ai-agents/*.md` só porque o STANDARDS.json index lista que eles existem.
|
|
93
128
|
- **Verificação de runtime** — como se PROVA que a feature funciona rodando, não só compilando.
|
|
@@ -146,7 +181,8 @@ Ao iniciar a fase plan — após o `proposal.md` ser aprovado e antes de qualque
|
|
|
146
181
|
"group": "backend",
|
|
147
182
|
"usecase": "UC-07",
|
|
148
183
|
"agent": "dotnet-senior",
|
|
149
|
-
"standards": ["standards/backend/dotnet/vsa-handler-patterns.md"]
|
|
184
|
+
"standards": ["standards/backend/dotnet/vsa-handler-patterns.md"],
|
|
185
|
+
"reuse": [{ "concept": "SimpleBuilding", "verdict": "REUSAR", "target": "features/roulette/types/roulette.types.ts" }]
|
|
150
186
|
}
|
|
151
187
|
]
|
|
152
188
|
}
|
|
@@ -161,12 +197,15 @@ Ao iniciar a fase plan — após o `proposal.md` ser aprovado e antes de qualque
|
|
|
161
197
|
- `outputs` (opcional): array de paths que serão criados/modificados.
|
|
162
198
|
- `usecase` (opcional): o **ID** do use case que a task realiza — `UC-07`, nunca o nome do arquivo. Task puramente técnica (build, config, migração) não tem.
|
|
163
199
|
- `agent` (opcional): o `id` da persona de `agents.json` responsável pelo domínio da task — **sem** o prefixo `morph-` (ex.: `"dotnet-senior"`, não `"morph-dotnet-senior"`). Carimbado no passo 5a abaixo; ausente numa task sem domínio de agente claro (config/docs) ou num plano legado.
|
|
200
|
+
- `reuse` (opcional): os vereditos do `reuse-map.md` (passo 1c) que ESTA task realiza — `[{concept, verdict: REUSAR|ESTENDER|CRIAR, target}]`. Só nas tasks que tocam o conceito; task que não introduz conceito nenhum não tem. **A justificativa do CRIAR fica no `reuse-map.md`, não aqui** — o mesmo fato escrito em dois lugares diverge. É este campo que o `morph-spec verify` lê para saber se a criação de um símbolo homônimo foi decidida no Gate 2 ou aconteceu por descuido.
|
|
164
201
|
- `standards` (opcional): array de paths relativos de `.morph/framework/standards/` (ex.: `["standards/backend/dotnet/vsa-handler-patterns.md"]`) — os standards da persona resolvida em `agent`, mais qualquer standard específico que a task exija.
|
|
165
202
|
|
|
166
203
|
**5a. Carimbe `agent` e `standards` — uma leitura de `agents.json`, N tasks.** Antes de fechar o array `tasks`, **use a tool Read UMA VEZ** em `.morph/framework/agents.json` (não releia por task — é essa releitura repetida por task, hoje feita em `morph-implement`/`morph-apply` a cada dispatch, que este passo existe para eliminar). Para cada task do plano, resolva:
|
|
167
204
|
- `agent`: o `id` da persona (chave do objeto `agents`, sem prefixo `morph-`) cujo `domains` cobre o `group`/domínio da task — o mesmo casamento que `morph-implement` §3 e `morph-apply` §3b fariam manualmente a cada dispatch; aqui você faz uma vez, no plano.
|
|
168
205
|
- `standards`: o array `standards` dessa persona, mais qualquer standard adicional que a task especificamente exija (some, não substitua).
|
|
169
206
|
|
|
207
|
+
**5b. Carimbe `reuse` — do `reuse-map.md` para a task que realiza o conceito.** Para cada linha do mapa produzido no passo 1c, encontre a task que vai escrever aquele conceito e copie o veredito para `reuse` (`concept` + `verdict` + `target`). Um conceito sem task é sinal de plano incompleto — ou o mapa listou o que a feature não vai tocar, ou falta task. Resolva antes do Gate 2.
|
|
208
|
+
|
|
170
209
|
**Task que cria ou altera superfície de UI** (componente, página, estilo, fluxo de navegação) carimba `agent: "ui-designer"` — inclusive numa feature que não tomou o ramo uiux (MORPH.md §2.1): o critério de agente é por domínio da task, não por fase percorrida.
|
|
171
210
|
|
|
172
211
|
Uma task cujo domínio não bate com nenhuma persona registrada (ex.: task pura de config/docs) fica sem `agent` — `morph-implement` cai no fallback de Read de `agents.json` nesse caso.
|
|
@@ -226,6 +265,7 @@ Ao iniciar a fase plan — após o `proposal.md` ser aprovado e antes de qualque
|
|
|
226
265
|
- `.morph/features/{feature}/2-plan/usecases/UC-{nn}-{slug}.md` — um arquivo por use case, com pós-condições testáveis
|
|
227
266
|
- `.morph/features/{feature}/2-plan/spec.md` — especificação técnica completa
|
|
228
267
|
- `.morph/features/{feature}/2-plan/mandate.md` — contrato de implementação
|
|
268
|
+
- `.morph/features/{feature}/2-plan/reuse-map.md` — veredito REUSAR/ESTENDER/CRIAR por conceito, com justificativa de uma linha em cada CRIAR (passo 1c)
|
|
229
269
|
- `.morph/features/{feature}/2-plan/tasks.json` — task list estruturada válida contra schema, com o `doneCriteria` carregando a pós-condição literal e, por task, `agent`/`standards` carimbados a partir de `agents.json` (passo 5a)
|
|
230
270
|
- Gate 2 registrado aprovado em `.morph/features/{feature}/feature.json` (autoritativo)
|
|
231
271
|
|
|
@@ -237,6 +277,8 @@ Ao registrar a aprovação do Gate 2, atualize o frontmatter de cada use case de
|
|
|
237
277
|
- `morph-spec standards --find "<query>"` — para identificar standards relevantes ao mandate (o índice inteiro só como navegação exploratória; ver `morph-standards`)
|
|
238
278
|
- `.morph/framework/agents.json` — personas por domínio; lido UMA VEZ no passo 5a para carimbar `agent`/`standards` por task
|
|
239
279
|
- `.morph/framework/schemas/tasks.schema.json` — schema obrigatório de tasks.json
|
|
280
|
+
- `morph-spec graph explain|affected --uses-only` — "isto já existe?" e "quem usa de verdade" (passo 1c); **sem grafo, o fallback é `grep -rn`**
|
|
281
|
+
- `.morph/context/README.md` — inventário do projeto (entidades, endpoints, componentes com path); insumo declarado do passo 1c, atualizado por `morph-spec context refresh`
|
|
240
282
|
- `.morph/specs/usecases/` — acervo permanente de use cases do projeto (`usecase reserve` já lê antes de numerar; em `bug`, é onde mora o UC a corrigir)
|
|
241
283
|
- `.morph/features/{feature}/0-proposal/proposal.md` — escopo da feature
|
|
242
284
|
- `.morph/features/{feature}/0-proposal/stack-scan.md` — contexto técnico detectado
|
|
@@ -4,7 +4,7 @@ description: Orquestra a fase de proposta+plano de uma feature morph-spec. Encad
|
|
|
4
4
|
version: core
|
|
5
5
|
when-to-invoke: ao receber instrução "use /morph-proposal" do usuário, ou ao iniciar uma nova feature
|
|
6
6
|
user-invokable: true
|
|
7
|
-
cliVersion: "8.
|
|
7
|
+
cliVersion: "8.31.0"
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# morph-proposal
|
|
@@ -4,7 +4,7 @@ description: Conduz a fase de revisão e produz o review-report.md para o Gate 3
|
|
|
4
4
|
version: core
|
|
5
5
|
when-to-invoke: ao iniciar a fase review, após todas as tasks de tasks.json estarem com status `done`
|
|
6
6
|
user-invokable: true
|
|
7
|
-
cliVersion: "8.
|
|
7
|
+
cliVersion: "8.31.0"
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# morph-review
|
|
@@ -72,12 +72,19 @@ e o `recap.md` estar atualizado. Normalmente invocada pela skill orquestradora `
|
|
|
72
72
|
- **Confira também `traceability.warnings`** (advisory, nunca faz `verify` falhar): cada entrada é
|
|
73
73
|
um arquivo citado no `recap.md` sem task dona em `outputs` — repasse ao avaliador como sinal de
|
|
74
74
|
rastreabilidade para a dimensão de qualidade, não como bloqueio automático do gate.
|
|
75
|
+
- **Anexe o `reuse-map.md`** (`.morph/features/{feature}/2-plan/reuse-map.md`), quando existir: é o
|
|
76
|
+
que o plano decidiu por conceito (REUSAR/ESTENDER/CRIAR) e o único insumo que permite ao
|
|
77
|
+
avaliador julgar a dimensão `code-quality` **contra o codebase**, não só contra o diff — símbolo
|
|
78
|
+
recriado não aparece no diff como problema. Junto dele, repasse os achados do validador `reuse`
|
|
79
|
+
do nó `validators` do verify. Sem `reuse-map.md` (plano anterior a este passo), diga isso ao
|
|
80
|
+
avaliador em vez de deixá-lo supor que não havia conceito a reusar.
|
|
75
81
|
- Gere o **diff da implementação** (`git diff` do range da feature, ou a lista de arquivos do recap.md com seus conteúdos atuais).
|
|
82
|
+
- **Blast radius dos símbolos do diff (se houver grafo).** Para cada símbolo público que o diff tocou, rode `morph-spec graph affected <símbolo> --prod --json` e inclua o resultado no contexto do avaliador. É o que permite perguntar *"o que esta mudança pode ter quebrado FORA do diff"* sem que o avaliador leia o repositório inteiro. **Fallback:** `no-graph`, `not-found` ou `ambiguous` — siga sem o blast radius e **registre a ausência na seção de método do review-report**; o gate não depende disso. **Trate o resultado como possivelmente stale:** o rebuild do hook é assíncrono, então logo depois de um commit o grafo ainda é o anterior. E lembre que em frontend ele responde "quem importa", não "quem chama".
|
|
76
83
|
- Despache o subagent registrado `morph-evaluator` (gerado de `agents.json` — a persona do avaliador é o system prompt dele, com Read/Glob/Grep + Bash somente para verificação + Playwright para navegar, sem Write/Edit), com contexto fresco:
|
|
77
84
|
```
|
|
78
85
|
dispatch Agent (subagent_type: "morph-evaluator") with prompt:
|
|
79
|
-
contexto: mandate.md + spec.md + diff da implementação
|
|
80
|
-
+ nó e2e do verify (stack no ar? em qual URL?)
|
|
86
|
+
contexto: mandate.md + spec.md + reuse-map.md + diff da implementação
|
|
87
|
+
+ saída real dos testes + nó e2e do verify (stack no ar? em qual URL?)
|
|
81
88
|
instrução: |
|
|
82
89
|
Você NÃO participou da implementação — avalie o que está no diff,
|
|
83
90
|
contra o mandate. NÃO leia `4-review/evaluator-report.md` neste
|
|
@@ -207,6 +214,7 @@ e o `recap.md` estar atualizado. Normalmente invocada pela skill orquestradora `
|
|
|
207
214
|
|
|
208
215
|
## Referências
|
|
209
216
|
- `morph-spec verify {feature} [task] --json` — cadeia determinística build+testes+validadores+e2e anexada ao prompt do avaliador (passo 4)
|
|
217
|
+
- `.morph/features/{feature}/2-plan/reuse-map.md` — veredito de reuso por conceito; insumo do avaliador para julgar `code-quality` contra o codebase
|
|
210
218
|
- `.morph/framework/MORPH.md` — seção 5 (Gate 3 + regras de pausa), seção 1 (papel Evaluator), Trust Mode
|
|
211
219
|
- `.claude/agents/morph-evaluator.md` — subagent do avaliador (gerado de `.morph/framework/agents.json`), despachado no passo 4
|
|
212
220
|
- `.claude/skills/morph-eval/SKILL.md` — rubricas e bandas que o avaliador aplica
|
|
@@ -4,7 +4,7 @@ description: Varre o codebase existente, detecta stack atual, compara com o stac
|
|
|
4
4
|
version: core
|
|
5
5
|
when-to-invoke: ao iniciar uma feature em projeto brownfield (codebase já existente)
|
|
6
6
|
user-invokable: true
|
|
7
|
-
cliVersion: "8.
|
|
7
|
+
cliVersion: "8.31.0"
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# morph-stack-scan
|
|
@@ -60,6 +60,18 @@ Antes de despachar Explore, verifique se o projeto é greenfield:
|
|
|
60
60
|
|
|
61
61
|
## O que fazer (brownfield)
|
|
62
62
|
|
|
63
|
+
0. **Se houver grafo, ele responde a pergunta do repository genérico melhor que o grep.**
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
morph-spec graph status --json # available:false? pule este passo
|
|
67
|
+
morph-spec graph affected IRepository --uses-only --json
|
|
68
|
+
morph-spec graph explain IRepository --json # o registro no DI aparece aqui
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
A pergunta do passo 1 é *"quantos CONSUMIDORES REAIS"*, e é exatamente aí que o grep erra: no ProspectPRO ele aponta **23 arquivos**, mas 20 são interfaces filhas **herdando** o contrato e só **2** são uso real. Quem lê 23 conclui "está em uso, não é código morto" — e a conclusão certa é a oposta. `--uses-only` exclui `inherits`/`implements`/`extends` e devolve os 2. O `explain` do mesmo símbolo entrega de brinde a outra metade da pergunta: onde ele está registrado no DI.
|
|
72
|
+
|
|
73
|
+
**Fallback:** grafo ausente (`no-graph`), símbolo não encontrado ou ambíguo — siga com o `Explore` e o grep do passo 1, e **registre no `stack-scan.md` que a contagem veio do grep**, que superestima consumidores por não separar herança de uso.
|
|
74
|
+
|
|
63
75
|
1. Despache um `Explore` subagent para varrer o codebase:
|
|
64
76
|
|
|
65
77
|
```
|
|
@@ -4,7 +4,7 @@ description: Localiza um standard específico via busca server-side (morph-spec
|
|
|
4
4
|
version: core
|
|
5
5
|
when-to-invoke: quando precisar consultar um standard específico durante a implementação
|
|
6
6
|
user-invokable: true
|
|
7
|
-
cliVersion: "8.
|
|
7
|
+
cliVersion: "8.31.0"
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# morph-standards
|
|
@@ -4,7 +4,7 @@ description: Conduz a fase opcional de UI/UX — design system, mockups, compone
|
|
|
4
4
|
version: core
|
|
5
5
|
when-to-invoke: ao tomar o ramo uiux (morph-spec advance --design), depois do Gate 1 e antes do morph-plan
|
|
6
6
|
user-invokable: true
|
|
7
|
-
cliVersion: "8.
|
|
7
|
+
cliVersion: "8.31.0"
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# morph-uiux
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "1.0.0",
|
|
3
|
+
"_note": "Standards distilled from an external source. The source is not a dependency at runtime: it lives in another repository and is not needed to use the framework. This file exists so drift is detectable instead of silent. Pin `sourceTree` when distilling, and re-pin deliberately after reviewing what changed. See test/framework/standards-provenance.test.js.",
|
|
4
|
+
"sources": [
|
|
5
|
+
{
|
|
6
|
+
"id": "morph-lp-cinematic",
|
|
7
|
+
"repo": "morph-HUB",
|
|
8
|
+
"path": "skills/morph-lp-cinematic",
|
|
9
|
+
"envVar": "MORPH_HUB",
|
|
10
|
+
"defaultCheckout": "R:/Polymorphism Tech/repos/morph-HUB",
|
|
11
|
+
"sourceTree": "e43114d4b28ff55680a5355cce27d31ffa74f22f",
|
|
12
|
+
"sourceCommit": "465c9b0",
|
|
13
|
+
"distilledOn": "2026-08-21",
|
|
14
|
+
"distilledFrom": [
|
|
15
|
+
"references/build-stack.md",
|
|
16
|
+
"references/component-recipes.md",
|
|
17
|
+
"references/premium-finish.md",
|
|
18
|
+
"references/seo-and-qa.md",
|
|
19
|
+
"references/gemini-image-prompt.md",
|
|
20
|
+
"references/seedance-scrub-prompt.md",
|
|
21
|
+
"references/seedance-loop-prompt.md"
|
|
22
|
+
],
|
|
23
|
+
"notDistilled": [
|
|
24
|
+
"references/gates.md",
|
|
25
|
+
"references/last-mile.md",
|
|
26
|
+
"references/copy-and-messaging.md",
|
|
27
|
+
"references/section-blueprint.md"
|
|
28
|
+
],
|
|
29
|
+
"notDistilledReason": "Deliberate split: a standard carries knowledge, a skill carries process. HITL gates, deploy and copy strategy stay with the skill.",
|
|
30
|
+
"standards": [
|
|
31
|
+
"frontend-scroll-driven-frame-scrub",
|
|
32
|
+
"frontend-scroll-driven-smooth-scroll",
|
|
33
|
+
"frontend-scroll-driven-scroll-components",
|
|
34
|
+
"frontend-design-system-premium-finish",
|
|
35
|
+
"frontend-design-system-ai-image-generation",
|
|
36
|
+
"frontend-design-system-ai-video-generation",
|
|
37
|
+
"frontend-seo-meta-schema-audit"
|
|
38
|
+
]
|
|
39
|
+
}
|
|
40
|
+
]
|
|
41
|
+
}
|