@polymorphism-tech/morph-spec 9.7.0 → 10.0.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 +11 -11
- package/README.md +4 -4
- package/bin/morph-spec.js +41 -44
- package/claude-plugin.json +1 -1
- package/docs/CHEATSHEET.md +1 -1
- package/docs/QUICKSTART.md +1 -1
- package/framework/CLAUDE.md +24 -30
- package/framework/MORPH.md +47 -123
- package/framework/agents.json +6 -374
- package/framework/commands/morph-apply.md +1 -1
- package/framework/commands/morph-archive.md +4 -3
- package/framework/commands/morph-hotfix.md +8 -30
- package/framework/commands/morph-infra.md +2 -2
- package/framework/commands/morph-media.md +10 -9
- package/framework/commands/morph-review.md +15 -0
- package/framework/commands/morph-status.md +1 -1
- package/framework/docs/CLI.md +100 -102
- package/framework/evals/review-checklist.md +46 -54
- package/framework/hooks/README.md +4 -4
- package/framework/hooks/claude-code/__pycache__/statusline.cpython-313.pyc +0 -0
- package/framework/hooks/claude-code/core/README.md +1 -1
- package/framework/hooks/claude-code/core/denylist.json +4 -4
- package/framework/hooks/claude-code/core/gate-guard.js +9 -0
- package/framework/hooks/claude-code/core/masked-exit.js +49 -0
- package/framework/hooks/claude-code/core/state-sync.js +4 -1
- package/framework/hooks/claude-code/core/telemetry-log.js +1 -2
- package/framework/hooks/claude-code/core/test-budget.js +10 -70
- package/framework/hooks/claude-code/core/validate-completion.js +11 -24
- package/framework/hooks/claude-code/core/worktree-context.js +5 -22
- package/framework/hooks/claude-code/core/worktree-create.js +6 -45
- package/framework/hooks/claude-code/core/worktree-env-inject.js +2 -10
- package/framework/hooks/shared/e2e-check.js +0 -0
- package/framework/hooks/shared/gate-event.js +2 -2
- package/framework/hooks/shared/graph-refresh.js +20 -3
- package/framework/hooks/shared/heavy-command.js +32 -1
- package/framework/hooks/shared/heavy-config.js +1 -1
- package/framework/hooks/shared/heavy-slots.js +41 -4
- package/framework/hooks/shared/next-step.js +63 -24
- package/framework/hooks/shared/phase-utils.js +6 -9
- package/framework/hooks/shared/report-progress.js +86 -0
- package/framework/hooks/shared/state-reader.js +3 -2
- package/framework/hooks/statusline.js +332 -0
- package/framework/phases.json +32 -10
- package/framework/rules/ai-agents-standards.md +9 -1
- package/framework/rules/csharp-standards.md +4 -0
- package/framework/rules/ef-standards.md +20 -0
- package/framework/rules/frontend-standards.md +1 -1
- package/framework/rules/implement-report.md +25 -0
- package/framework/rules/infrastructure-standards.md +2 -0
- package/framework/rules/nextjs-standards.md +7 -0
- package/framework/rules/plan-grammar.md +53 -0
- package/framework/rules/ui-design.md +27 -0
- package/framework/schemas/config.schema.json +12 -19
- package/framework/schemas/feature.schema.json +7 -1
- package/framework/skills/core/create-umbraco-lp/SKILL.md +1 -1
- package/framework/skills/core/create-umbraco-lp/references/umbraco-lp-patterns.md +1 -1
- package/framework/skills/core/migrate-lp-to-umbraco/SKILL.md +2 -2
- package/framework/skills/core/morph-apply/SKILL.md +38 -166
- package/framework/skills/core/morph-apply/references/debugging.md +8 -0
- package/framework/skills/core/morph-apply/references/hotfix.md +42 -0
- package/framework/skills/core/morph-apply/references/machine.md +29 -0
- package/framework/skills/core/{morph-media/SKILL.md → morph-apply/references/media.md} +11 -74
- package/framework/skills/core/morph-apply/references/review.md +65 -0
- package/framework/skills/core/morph-plan/SKILL.md +42 -108
- package/framework/skills/core/morph-plan/references/critique.md +40 -0
- package/framework/skills/core/morph-plan/references/interview.md +25 -0
- package/framework/skills/core/morph-uiux/SKILL.md +47 -64
- package/framework/skills/core/morph-uiux/surfaces.json +32 -0
- package/framework/standards/STANDARDS.json +32 -5
- package/framework/standards/STANDARDS.meta.json +5 -1
- package/framework/standards/ai-agents/agent-session.md +2 -3
- package/framework/standards/ai-agents/context-providers.md +2 -2
- package/framework/standards/ai-agents/durable-workflows-hitl.md +2 -2
- package/framework/standards/ai-agents/providers/model-registry.md +2 -2
- package/framework/standards/ai-agents/rag-custom-pgvector.md +6 -6
- package/framework/standards/ai-agents/setup.md +1 -1
- package/framework/standards/ai-agents/tool-adapters.md +2 -2
- package/framework/standards/architecture/stack-baseline.md +47 -0
- package/framework/standards/backend/integrations/neon-auth/neon-auth.md +2 -4
- package/framework/standards/frontend/design-system/ai-image-generation.md +51 -12
- package/framework/standards/frontend/design-system/ai-video-generation.md +50 -4
- package/framework/standards/frontend/design-system/art-direction.md +2 -2
- package/framework/standards/frontend/scroll-driven/frame-scrub.md +12 -2
- package/framework/standards/frontend/scroll-driven/scroll-components.md +76 -4
- 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/REGISTRY.json +1 -2
- package/framework/templates/code/dotnet/abstractions/api-endpoint.cs +7 -7
- 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/sql/ai-agents/pgvector-embeddings-migration.sql.template +91 -91
- package/framework/templates/context/ARCHITECTURE.md +1 -1
- package/framework/templates/docs/plan.md +12 -12
- package/framework/templates/docs/ui-mockups.md +17 -105
- package/framework/templates/frontend/nextjs/client-component.tsx.hbs +26 -26
- package/framework/templates/frontend/nextjs/tsconfig.json.hbs +26 -26
- 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/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/state.template.json +17 -17
- package/framework/templates/ui/design-system.css +226 -226
- package/package.json +1 -1
- package/src/commands/e2e/e2e.js +88 -23
- package/src/commands/graph/diff.js +74 -0
- package/src/commands/graph/status.js +1 -1
- package/src/commands/observability/cost.js +2 -4
- package/src/commands/observability/telemetry.js +1 -1
- package/src/commands/project/doctor.js +23 -39
- package/src/commands/project/fleet.js +5 -6
- package/src/commands/project/init.js +63 -36
- package/src/commands/project/stack-scan.js +3 -42
- package/src/commands/project/stack-set.js +26 -0
- package/src/commands/project/status.js +12 -13
- package/src/commands/project/update.js +39 -3
- package/src/commands/project/worktree.js +27 -16
- package/src/commands/state/advance.js +17 -17
- package/src/commands/state/approve.js +0 -6
- package/src/commands/state/archive.js +27 -1
- package/src/commands/state/auto-approval.js +1 -1
- package/src/commands/state/create.js +0 -5
- package/src/commands/state/finish.js +43 -1
- package/src/commands/state/gate-check.js +37 -30
- package/src/commands/state/gate-decision.js +3 -2
- package/src/commands/state/next.js +1 -0
- package/src/commands/state/recap.js +67 -0
- package/src/commands/state/report-check.js +39 -146
- package/src/commands/validation/plan-check.js +16 -11
- package/src/commands/validation/validate-feature.js +3 -3
- package/src/commands/validation/verify.js +6 -6
- package/src/core/paths/output-schema.js +3 -3
- package/src/core/state/state-manager.js +2 -4
- package/src/dashboard/app/components/CommandPalette.jsx +2 -5
- package/src/dashboard/app/components/GatePauses.jsx +116 -0
- package/src/dashboard/app/components/SessionMap.jsx +77 -0
- package/src/dashboard/app/main.jsx +13 -13
- package/src/dashboard/app/pages/Activity.jsx +4 -0
- package/src/dashboard/app/pages/AgentMap.jsx +1 -2
- package/src/dashboard/app/pages/FeatureDetail.jsx +129 -186
- package/src/dashboard/app/pages/Features.jsx +7 -7
- package/src/dashboard/app/pages/PhasePipeline.jsx +1 -1
- package/src/dashboard/app/pages/Portfolio.jsx +40 -5
- package/src/dashboard/scanner/activity-scanner.js +29 -0
- package/src/dashboard/scanner/agents-scanner.js +11 -14
- package/src/dashboard/scanner/features-scanner.js +45 -24
- package/src/dashboard/scanner/project-api.js +11 -2
- package/src/dashboard/scanner/skills-scanner.js +11 -1
- package/src/dashboard/vite.config.js +24 -24
- package/src/lib/e2e/applicability.js +3 -1
- package/src/lib/git/tree-state.js +1 -16
- package/src/lib/graph/diff-tree.js +127 -0
- package/src/lib/graph/graphify-runtime.js +12 -5
- package/src/lib/heavy/gate.js +22 -1
- package/src/lib/installers/memory-installer.js +2 -2
- package/src/lib/installers/rules-installer.js +57 -0
- package/src/lib/installers/stack-assets.js +17 -0
- package/src/lib/installers/stack-sync.js +219 -0
- package/src/lib/plan/checks.js +55 -110
- package/src/lib/plan/critique.js +28 -0
- package/src/lib/plan/media.js +42 -0
- package/src/lib/plan/plan-html.js +125 -0
- package/src/lib/plan/plan-parser.js +34 -45
- package/src/lib/recap/piper.js +36 -0
- package/src/lib/recap/recap.js +232 -0
- package/src/lib/review-reports.js +33 -7
- package/src/lib/risk-detector.js +90 -11
- package/src/lib/specs/screen-checklist.js +33 -48
- package/src/lib/stack/dotnet-build-ignores.js +8 -9
- package/src/lib/tasks/test-nodes.js +24 -6
- package/src/lib/tasks/test-runner.js +40 -1
- package/src/lib/telemetry/metrics.js +27 -29
- package/src/lib/validators/reuse/reuse-validator.js +1 -9
- package/src/lib/validators/verify-runner.js +50 -19
- package/src/lib/worktree/fleet-scanner.js +7 -20
- package/src/lib/worktree/worktree-audit.js +0 -37
- package/src/scripts/setup-infra.js +15 -50
- package/src/utils/agents-installer.js +27 -201
- package/src/utils/hooks-installer.js +11 -95
- package/framework/hooks/claude-code/core/warn-bash-source-write.js +0 -23
- package/framework/hooks/claude-code/statusline.py +0 -699
- package/framework/hooks/claude-code/statusline.sh +0 -11
- package/framework/hooks/shared/agent-reap.js +0 -74
- package/framework/hooks/shared/slice-progress.js +0 -110
- package/framework/skills/core/morph-hotfix/SKILL.md +0 -133
- package/framework/skills/core/morph-machine/SKILL.md +0 -46
- package/framework/skills/core/morph-review/SKILL.md +0 -129
- package/framework/skills/core/morph-standards/SKILL.md +0 -52
- package/framework/standards/PROVENANCE.json +0 -119
- package/src/commands/project/worktree-reap.js +0 -34
- package/src/commands/state/handoff.js +0 -65
- package/src/commands/validation/mutate.js +0 -263
- package/src/commands/validation/scout-check.js +0 -28
- package/src/lib/generators/handoff-generator.js +0 -172
- package/src/lib/mutation/adapters.js +0 -79
- package/src/lib/mutation/commands.js +0 -61
- package/src/lib/mutation/dotnet-introspection.js +0 -281
- package/src/lib/mutation/manifest.js +0 -144
- package/src/lib/mutation/plan.js +0 -44
- package/src/lib/mutation/report.js +0 -68
- package/src/lib/mutation/runner.js +0 -301
- package/src/lib/mutation/schemata.js +0 -60
- package/src/lib/mutation/snapshot.js +0 -65
- package/src/lib/mutation/subset.js +0 -109
- package/src/lib/mutation/trx.js +0 -50
- package/src/lib/scout/scout-check.js +0 -293
- package/src/lib/validators/traceability-check.js +0 -103
- package/src/lib/worktree/agent-reaper.js +0 -247
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# Gate 3 — verificador ∥ revisor (∥ segurança)
|
|
2
|
+
|
|
3
|
+
Pergunta: **cada cenário do plano funciona de verdade, sem quebrar o que já funcionava?** Três agentes em contexto fresco, cada um com o seu arquivo em `4-review/`. Você não escreve relatório de review (exceção: hotfix, `references/hotfix.md`).
|
|
4
|
+
|
|
5
|
+
Por que fresco: o que você sabe da implementação é o ponto cego que eles existem para não herdar. Por isso cada um recebe **só** o que o papel precisa — nada do histórico desta conversa, nenhum relatório anterior.
|
|
6
|
+
|
|
7
|
+
## 1. Relatórios já íntegros?
|
|
8
|
+
|
|
9
|
+
`morph-spec report-check {feature} --json` (também ao retomar). `reviews.<papel>`: `complete` → não despache esse papel de novo; `partial` ou ausente → despache no passo 3.
|
|
10
|
+
|
|
11
|
+
## 2. Prova da suíte — uma rodada
|
|
12
|
+
|
|
13
|
+
Commite e rode `morph-spec verify {feature} --ci --json` em `run_in_background` (sem CI, roda local e diz por quê). Sem `--filter`, sempre: verde filtrado é verde sobre código não testado. `reason: "stamp-reused"` = nada andou desde o último verde: vale. Saída `CI rodando` → despache (passo 3) sem esperar o fim; `verify local` → espere, a máquina é uma só.
|
|
14
|
+
|
|
15
|
+
Nó `e2e` `pass` → `morph-spec e2e status {feature} --json` → `baseUrl` vai ao verificador. `fail` → correção (CI: `gh run view <id> --log-failed`). `skip` → o `gate-check` decide se dispensa (`classifyE2eSkip`, em `risk-detector.js`: docker indisponível pausa sozinho, sem `gate-decision` à mão).
|
|
16
|
+
|
|
17
|
+
## 3. Dispatch — os três na mesma resposta
|
|
18
|
+
|
|
19
|
+
`morph-spec report-check {feature} --before-eval --json` tira a foto da árvore e diz `reviewModels.verifier.model` (opus com prompt/modelo ou mídia) e `reviewModels.security.required`. Anote `base` (merge-base com a default) e `sha` (`git rev-parse HEAD`). O revisor abre pela árvore do que mudou (`morph-spec graph diff --base {base} --json`, que ele mesmo roda). Blast radius para o revisor: por símbolo público do diff, `morph-spec graph affected <símbolo> --prod --json`; sem grafo (`no-graph`/`not-found`/`ambiguous`), diga isso a ele — ele cai para `git grep`.
|
|
20
|
+
|
|
21
|
+
Despache **sem nome** no dispatch (com nome, o `agent_type` que o hook `test-budget` lê vira o nome e o guard não reconhece o papel). `chore`: só o revisor (∥ segurança).
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
Agent (subagent_type: "morph-verifier", model: {reviewModels.verifier.model}):
|
|
25
|
+
feature; o conteúdo de 2-plan/checks.json; baseUrl (ou "stack fora do ar: <motivo>");
|
|
26
|
+
reset entre fluxos: `morph-spec e2e reset {feature}`; 1-design/mockups.md se existir;
|
|
27
|
+
grave .morph/features/{feature}/4-review/verifier.md
|
|
28
|
+
Agent (subagent_type: "morph-reviewer"):
|
|
29
|
+
feature, base, sha, blast radius (ou a ausência);
|
|
30
|
+
grave .morph/features/{feature}/4-review/reviewer.md
|
|
31
|
+
Agent (subagent_type: "morph-security"): ← só com security.required
|
|
32
|
+
feature, base, sha, reviewModels.security.reasons;
|
|
33
|
+
grave .morph/features/{feature}/4-review/security.md
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
O verificador **não** recebe plano, diff, `report.md` nem evidências: ele prova o comportamento executando, não lendo a sua versão dele. O contrato fixo de cada papel (formato, `**Reviewed-SHA:**`, read-only) está no corpo da persona e em `.morph/framework/evals/review-checklist.md`.
|
|
37
|
+
|
|
38
|
+
## 4. Ao voltar
|
|
39
|
+
|
|
40
|
+
Não rode build nem teste enquanto um agente está `running`. Com todos de volta, `morph-spec report-check {feature} --json`: `tree.sinceBeforeEval.changed` vazio = árvore como antes. Arquivo listado = alguém mexeu: desfaça pelo diff, **nunca `git checkout --`** (apaga o que não foi commitado).
|
|
41
|
+
|
|
42
|
+
`partial` = o agente bateu no teto de turnos: despache o mesmo papel de novo dizendo o que já está no relatório (append-only).
|
|
43
|
+
|
|
44
|
+
## 5. Bloqueadores
|
|
45
|
+
|
|
46
|
+
O avaliador também erra: **reproduza cada bloqueador antes de editar**. Não se reproduz → é nota sua no `report.md`, e o próximo dispatch de confirmação recebe a contra-evidência. Confirmado → corrija, commite, `verify {feature}` local, foto `--before-eval` nova.
|
|
47
|
+
|
|
48
|
+
Confirmação = **dispatch novo** de cada papel exigido, com o `sha` novo e o escopo da rodada: quem abriu bloqueadores confirma só esses (verificador: "confirme só C2, C5"); os outros julgam só o delta `{sha anterior}..{sha novo}`. `security.required` virou `true` agora → despache a segurança. Ninguém reavalia a feature inteira. O relatório é append-only e vale o último `**Verdict:**`; o `approve` recusa quando o código andou depois de qualquer `**Reviewed-SHA:**`.
|
|
49
|
+
|
|
50
|
+
## 6. Gate 3
|
|
51
|
+
|
|
52
|
+
`morph-spec gate-check {feature} review [--json]` lê os relatórios, a cobertura dos `Cn` e os demais sinais. Forçar passagem apesar da pausa: `morph-spec gate-decision {feature} review --pause false --reason "…"`.
|
|
53
|
+
|
|
54
|
+
Pausa com `resolver: "session"` não é pergunta: faça o que a `reason` diz e rode o `gate-check` de novo. Verify vermelho ou velho → corrija e `verify {feature}`; e2e pulado a pedido → `verify {feature}` sem `--skip-e2e`; bloqueador ou `Cn` não provado → §5; relatório ausente ou sem seção → dispatch. Vira `human` sozinho depois de `FIX_ATTEMPTS` verify vermelhos seguidos ou rodadas de review: a disputa é do usuário.
|
|
55
|
+
|
|
56
|
+
`resolver === "human"` → `AskUserQuestion`, header "Gate 3":
|
|
57
|
+
|
|
58
|
+
```
|
|
59
|
+
question: "Gate 3 — Review de {feature} aprovado?{ reason ? ' Sinal: ' + reason : '' }"
|
|
60
|
+
options: "aprovado, fechar feature" | "preciso ajustar" | "rollback"
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Bloqueador `irreversivel` ou degrau (`rung`, `rung-undeclared`): a pergunta cita o trecho e o que fica depois do revert. "aprovado" é a aceitação do usuário e fecha pelo `approve` com o nome dele, com o bloqueador aberto; "preciso ajustar" → tire o efeito irreversível do diff e despache o revisor para confirmar.
|
|
64
|
+
|
|
65
|
+
`pause === false` → uma linha (vereditos, cenários provados) e `morph-spec approve {feature} review --mode auto`. Fechar: `SKILL.md` §6.
|
|
@@ -1,147 +1,81 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: morph-plan
|
|
3
|
-
description: Leva
|
|
3
|
+
description: Leva um pedido ao plano aprovado — roteia o tipo de trabalho, varre o ambiente, entrevista pela árvore de decisões, escreve 2-plan/plan.md com os cenários que definem "pronto", extrai checks.json com plan-check e apresenta o gate do plano.
|
|
4
4
|
version: core
|
|
5
5
|
when_to_use: Use quando uma feature, bug ou chore começar ("/morph-plan {feature}", "vamos planejar X"), ou ao retomar uma feature cujo gate plan ainda não foi aprovado
|
|
6
6
|
user-invocable: true
|
|
7
|
-
cliVersion: "
|
|
7
|
+
cliVersion: "10.0.0"
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# morph-plan
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
Saída: `.morph/features/{feature}/2-plan/plan.md` (fonte única da feature) e `2-plan/checks.json`, gravado só por `morph-spec plan-check`. O usuário só toca a entrevista e o gate; o resto você resolve. Nada de código nesta fase. O `create` escreve o esqueleto de `plan.md` no nascimento: só é retomada com `2-plan/checks.json` no disco ou com o `plan.md` já sem os `<…>` do esqueleto — aí vá ao §5 (corrigir) ou ao §7 (gate).
|
|
12
|
+
Saída: `2-plan/plan.md` (fonte única) e `2-plan/checks.json` (só o `plan-check` grava). Nada de código nesta fase. Retomada: com `checks.json` no disco, ou o `plan.md` já sem os `<…>` do esqueleto, vá ao §5 (corrigir) ou ao §6 (gate).
|
|
15
13
|
|
|
16
14
|
## 1. Roteamento
|
|
17
15
|
|
|
18
|
-
Sem nome
|
|
19
|
-
|
|
20
|
-
```
|
|
21
|
-
morph-spec create {feature} --request "<pedido do usuário>"
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
Tipo óbvio pelo pedido: `--type <tipo> --description "<o quê/porquê>"`. O `--request` semeia a descrição; sem ele nem `--description`, o `create` recusa. **Exit 2** (empate ou nenhum sinal): você é o roteador — escolha entre os `candidates` e re-rode com `--type <tipo> --request "<pedido>"`. `AskUserQuestion` só quando o pedido é genuinamente indeterminado.
|
|
16
|
+
Sem nome, pergunte (`AskUserQuestion`, header "Feature"). Feature nova: `morph-spec create {feature} --request "<pedido>"` (tipo óbvio: `--type <t> --description "<o quê/porquê>"`). Exit 2 = você escolhe entre os `candidates` e re-roda com `--type`.
|
|
25
17
|
|
|
26
18
|
| Tipo | Caminho |
|
|
27
19
|
|---|---|
|
|
28
|
-
| `hotfix` | `Skill(morph-
|
|
29
|
-
| `chore` |
|
|
30
|
-
| `bug` | fluxo inteiro
|
|
31
|
-
| `feature` | fluxo inteiro
|
|
20
|
+
| `hotfix` | `Skill(morph-apply)` › `references/hotfix.md`; encerre esta skill |
|
|
21
|
+
| `chore` | plano curto (§7), `plan-check`, `Skill(morph-apply)` direto |
|
|
22
|
+
| `bug` | fluxo inteiro, bug-lean (§7) |
|
|
23
|
+
| `feature` | fluxo inteiro |
|
|
24
|
+
|
|
25
|
+
**Stack primeiro, completa.** `config.json` sem `project.stack` (ou `unknown`): antes de qualquer outra pergunta, `AskUserQuestion` header "Stack" com a recomendada sempre a **stack completa do Morph**, `dotnet+nextjs --with neon` (`morph-spec standards --show architecture-stack-baseline#a-stack`), mesmo que o pedido pareça caber em menos; recorte (`dotnet`, `nextjs`) ou outra tecnologia só como escolha explícita do usuário. Escolhida: `morph-spec stack-set <stack> --with <integrações>`, que grava o `config.json` e instala tudo o que a stack carrega (rules, commands, skills). Fora da stack do Morph: ADR `**Alcance:** projeto` em `## Decisões`.
|
|
32
26
|
|
|
33
27
|
## 2. Varredura — antes de qualquer pergunta
|
|
34
28
|
|
|
35
29
|
Fato não se pergunta: as decisões são do usuário, os fatos são seus.
|
|
36
30
|
|
|
37
|
-
1. `morph-spec stack-scan {feature}`
|
|
38
|
-
2.
|
|
39
|
-
3. **
|
|
40
|
-
4.
|
|
31
|
+
1. `morph-spec stack-scan {feature}` — desvio Bloqueante/Alto contra `project.stack` vira nó da árvore.
|
|
32
|
+
2. `.morph/config/config.json`, `.morph/context/` (o `README.md` inventaria componentes e endpoints), features ativas e o índice `.morph/specs/adrs/` (decisão vigente; `.morph/archive/` é história).
|
|
33
|
+
3. **O código que a feature toca**: `morph-spec graph affected|explain <símbolo>` (stale numa worktree → `graph refresh`; sem grafo, `grep -rn`). Você vai implementar o que planejar: o que ler agora fica na sua janela.
|
|
34
|
+
4. Pedido que contradiz ADR ou contexto: uma linha de aviso (fonte, o que diz, o que muda); pedido explícito sobre o ponto → vale o mais novo. Só o conflito ambíguo entra na árvore. Todos vão para `### Conflitos com o acervo`.
|
|
35
|
+
5. Design system (`.morph/context/design-system.md`) divergente do código ou de mocks recentes → nó da árvore e sinal `designSystemDivergence`.
|
|
41
36
|
|
|
42
37
|
## 3. Árvore de decisões e modo
|
|
43
38
|
|
|
44
|
-
Entra na árvore só o que
|
|
45
|
-
|
|
46
|
-
**Pergunta de abertura** (só `feature` e `bug`; `chore` e `hotfix` não passam por aqui): uma `AskUserQuestion`, header "Descoberta", com a árvore resumida e o modo recomendado em primeiro lugar com `(Recomendado)` no label. Muitas decisões, ou decisões acopladas → entrevista; árvore rasa → automático.
|
|
47
|
-
|
|
48
|
-
- **Entrevista:** **uma pergunta por chamada** de `AskUserQuestion` — lote desorienta e impede que uma resposta pode ramos. Cada pergunta traz a resposta recomendada como primeira opção, `(Recomendado)`. Mostre a árvore quando ela mudar de forma. Termina quando a árvore zera; o usuário pode encerrar antes, e o que ficou aberto vira `## Fora de escopo`. O gate do plano pausa sempre neste modo (§7).
|
|
49
|
-
- **Automático:** até 4 perguntas, **só sobre nós abertos** da árvore — nunca uma lista fixa. Árvore vazia → nenhuma pergunta.
|
|
50
|
-
|
|
51
|
-
**Headless** (`AskUserQuestion` indisponível ou negada, como sob `claude -p`): nunca decida você os nós abertos. Escreva-os em texto, numerados, cada um com a resposta recomendada; rode `morph-spec gate-decision {feature} plan --pause true --reason "entrevista headless"` e **encerre o turno**. Retome quando o usuário responder.
|
|
52
|
-
|
|
53
|
-
## 4. Território
|
|
54
|
-
|
|
55
|
-
Feature grande ou brownfield: despache `subagent_type: "morph-scout"` (não registrado: `general-purpose` com o campo `persona` do `scout` de `.morph/framework/agents.json`) para os arquivos que a feature toca e o blast radius dos símbolos centrais. Grave em `2-plan/scout-map.md` e audite:
|
|
39
|
+
Entra na árvore só o que muda escopo, comportamento ou arquitetura e a varredura não respondeu, ordenado pelo que poda. Nó de baixo risco com resposta óbvia não vira pergunta: vira item de `## Padrões assumidos`. Publique a árvore antes de perguntar. Abertura (`feature`/`bug`): uma `AskUserQuestion`, header "Descoberta", modo recomendado primeiro — **entrevista** (uma pergunta por chamada até a árvore zerar; as respostas aprovam o plano) ou **automático** (até 4 perguntas, só nós abertos). Detalhe e headless: `references/interview.md`.
|
|
56
40
|
|
|
57
|
-
|
|
58
|
-
morph-spec scout-check .morph/features/{feature}/2-plan/scout-map.md --json
|
|
59
|
-
```
|
|
41
|
+
## 4. Reuso
|
|
60
42
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
**Reuso — o que já existe.** Para cada conceito central (entidade, DTO, componente, hook, helper, dublê de teste): `morph-spec graph explain <nome> --json` e `morph-spec graph affected <nome> --uses-only --json`. Antes, `morph-spec graph status --json`; stale numa worktree → `morph-spec graph refresh`. `--uses-only` importa: o grep conta herança como uso — no ProspectPRO apontou 23 arquivos onde 20 eram interfaces filhas herdando o contrato e só 2 usavam de verdade. **Sem grafo** (`no-graph`, `not-found` num grafo stale), caia para `grep -rn "<nome>"` e registre que a contagem veio do grep, que superestima consumidores. A ausência de grafo nunca bloqueia.
|
|
43
|
+
Por conceito central (entidade, DTO, componente, hook, helper): `morph-spec graph explain <nome> --json` e `graph affected <nome> --uses-only --json` (`--uses-only`: o grep conta herança como uso). Sem grafo, `grep -rn` e anote que a contagem veio do grep. O veredito vai na tabela `## Reuso`.
|
|
64
44
|
|
|
65
45
|
## 5. plan.md
|
|
66
46
|
|
|
67
|
-
O `create`
|
|
68
|
-
|
|
69
|
-
**Cenários** (`## Cenários`): `- **Cn** — Dado …, quando …, então …`, com `prova:` (`teste` | `e2e` | `eval` | `manual` | `leitura`) **na linha seguinte, sem linha em branco** — linha vazia encerra o cenário.
|
|
70
|
-
- **Teste é por risco, não por código novo.** `prova: teste` exige `risco:` (`regra` | `dinheiro` | `contrato` | `concorrência` | `dado` | `regressão`) na linha abaixo: ramo de regra de negócio, valor, contrato externo, corrida, integridade de dado ou o bug real. Sem risco (CRUD, DTO, mapping, wiring, constante, texto, layout) a prova é `leitura` — o verificador fecha citando `arquivo:linha` — ou `e2e` quando o fluxo é o que importa. O `plan-check` recusa `teste` sem `risco:`.
|
|
71
|
-
- **Observável**: que asserção (ou que linha de código) prova? Sem resposta, reescreva ou descarte.
|
|
72
|
-
- **Artefato não é comportamento.** Cenário que cita `grep`, "contém a string", "o binário", "nenhum arquivo", "arquivo/pasta/diretório em" ou glob `**/` descreve o repositório. Tente o efeito em runtime; se o artefato É o entregável, justifique em `> Por que artefato:` logo abaixo (nunca na mesma linha, nunca `> [!note]`).
|
|
73
|
-
- **Saída de LLM** (o que o modelo responde) prova-se por `eval` de runtime, nunca pelo texto do prompt: evidência em `3-implement/evidencias/{Cn}.md`, path listado em `arquivos:` da fatia; com nó `runner: "evals"` (standard `ai-agents-evals-with-cache`) o cenário mora no dataset. No máximo 1 teste de estrutura da fonte do prompt.
|
|
74
|
-
- **"O comando de teste da raiz roda de ponta a ponta"** prova-se pelo `verify {feature}` (o nó `e2e` e o nó de teste `e2e: true` já percorrem a cadeia): nomeie essa rodada como a prova, nunca uma execução avulsa. Precisando mesmo rodar fora dele, numa linha só (o Bash não guarda o env entre chamadas): `eval "$(morph-spec env {feature} --with-secrets)" && morph-spec heavy run -- <comando>` — o `COMPOSE_PROJECT_NAME` da feature é o que o `finish` derruba com os volumes. `prova: manual` registra passo e resultado em `3-implement/evidencias/{Cn}.md`.
|
|
75
|
-
- **Orçamento de teste**: um teste por cenário de risco — o cenário é a unidade, nunca a pós-condição nem o componente; variantes são linhas de tabela (`[Theory]`/`it.each`); acima disso, o porquê na linha do cenário. Nenhum teste que só fixa texto, prompt ou constante, nenhum de DTO/mapping, e o mesmo comportamento numa camada só (handler **ou** endpoint). Teste além do orçamento é escopo para o revisor. O `verify` avisa quando o teste passa da produção.
|
|
76
|
-
|
|
77
|
-
```markdown
|
|
78
|
-
## Cenários
|
|
79
|
-
- **C1** — Dado um tenant com `criterion_overrides`, quando ele é publicado, então a publicação é recusada nomeando a chave.
|
|
80
|
-
prova: teste
|
|
81
|
-
risco: contrato
|
|
82
|
-
- **C2** — Nenhum arquivo em `tenants/**` contém a chave `criterion_overrides`.
|
|
83
|
-
prova: leitura
|
|
84
|
-
> Por que artefato: a chave saiu do contrato; nenhum leitor de runtime a consulta.
|
|
85
|
-
|
|
86
|
-
## Fatias
|
|
87
|
-
### F1 — Recusar a chave na publicação
|
|
88
|
-
- persona: dotnet-senior
|
|
89
|
-
- standards: backend-dotnet-vsa-handler-patterns, backend-dotnet-testing, architecture-code-comments
|
|
90
|
-
- arquivos: src/Tenants/Publish.cs, tests/Tenants/PublishTests.cs
|
|
91
|
-
- cobre: C1, C2
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
**Decisões** (`## Decisões`): uma `### ADR-001 — título` por decisão não trivial (alternativa descartada, motivo, quem decidiu), com `**Alcance:** feature` ou `projeto` — `projeto` quando vale além desta feature. Em projeto greenfield, a decisão que fixa stack, layout, infraestrutura ou test runner é `projeto`: a próxima feature a herda, e só o índice de ADRs a mostra. `### Conflitos com o acervo` existe sempre; "nenhum" vale. Proibição além das de `MORPH.md` § "Stack baked-in" é ADR.
|
|
95
|
-
|
|
96
|
-
**Arquitetura**: componentes, fluxo de dados, edge cases **técnicos** e integrações; não repita os cenários.
|
|
97
|
-
|
|
98
|
-
**Reuso**: tabela `| conceito | veredito | alvo | why |`, veredito `REUSAR` | `ESTENDER` | `CRIAR`. **`CRIAR` exige `why`** — a consulta que respondeu "não existe" (`graph explain X → not-found; grep -rn X → 0`). Abstração nova (interface, base, factory, camada) soma ao `why` o segundo uso ou a próxima adição que ela barateia; sem isso é excesso (`architecture-engineering-lens#excess`). Conceito de duas features vai para um módulo comum, nunca import cruzado entre slices. O validador `reuse` do `verify` cobra: símbolo novo homônimo de um existente reprova na mesma feature e avisa entre features; `CRIAR` declarado rebaixa a aviso. Conceito sem fatia que o escreva: falta fatia ou o conceito não é desta feature — resolva antes do gate.
|
|
99
|
-
|
|
100
|
-
**Fatias** (`### Fn — título`): a unidade de entrega e de relatório (`3-implement/reports/Fn.md`).
|
|
101
|
-
- `persona:` obrigatório — o id sem `morph-`, cujo `domains` cobre a fatia (uma leitura de `agents.json`). Fatia que cria ou altera UI é `ui-designer`, mesmo sem o ramo de design; com `superfície:`, os standards são os daquela chave de `surfaces`.
|
|
102
|
-
- `standards:` — `morph-spec standards --find "<domínio>"` por domínio (o digest decide): os da persona mais o que a fatia exige, sempre `architecture-code-comments`, `architecture-engineering-lens` e o de teste do stack; agente MAF soma `--category ai-agents`.
|
|
103
|
-
- `arquivos:` — os paths planejados, testes incluídos, **no máximo 8**: acima disso o sub-agente bate no teto de turnos.
|
|
104
|
-
- `depende:` opcional; `cobre:` lista os Cn — todo cenário é coberto por alguma fatia. Fatias sem `depende:` comum e sem arquivo em comum rodam em paralelo; o `plan-check` imprime as ondas.
|
|
105
|
-
- Cenário que se observa por um artefato de outra fatia (rota, endpoint, componente que ela cria) faz da fatia que o cobre um `depende:` daquela — senão as duas caem na mesma onda e o teste do cenário não tem por onde provar. O `plan-check` não vê de quem é a rota: a regra é sua.
|
|
106
|
-
|
|
107
|
-
**Contrato de implementação**: o que quem implementa precisa e o código não diz.
|
|
108
|
-
- **Verificação de runtime:** o stack sobe por `morph-spec e2e up {feature}` (compose do projeto; sem compose, isso é uma fatia); os fluxos que o verificador navega, nos verbos dos cenários; base URL `process.env.PLAYWRIGHT_BASE_URL ?? \`http://localhost:${process.env.PORT ?? 3000}\``, compose com `"${PORT:-3000}:3000"` e sem `container_name` (standard `infrastructure/docker/local-compose-isolation`). App cujo build é caro dentro do Docker sobe como processo do host por `e2e.hostServices` (compose só com as dependências; campos em `morph-spec e2e --help`). App com login: `e2e.auth` em `config.json` (`mode: seed|storageState|bypass|none`, `seedCommand`, `storageStatePath`, `envFile`), credenciais num `.env.e2e` gitignored — **`mode` é obrigatório sempre que houver `seedCommand`**, sem ele o seed fica inerte. Biblioteca pura: registre a dispensa e o porquê.
|
|
109
|
-
- **Baseline é um COMANDO, nunca um número.** O plano congela e é lido por dias: um número cravado está errado na primeira fatia, e quem confia nele "conserta" o que não quebrou. Registre como medir (`npm test`, `dotnet test`); o `expectedCount` sai de `morph-spec verify {feature} --record-baseline`, nunca digitado. Sem `project.stack`/`project.tests` no `config.json`, a `morph-apply` os declara a partir destes comandos antes do primeiro verify.
|
|
110
|
-
- **Pré-requisito é um PREDICADO, nunca um SHA literal:** "`git merge-base --is-ancestor origin/main HEAD` sai 0" — o SHA muda no primeiro squash.
|
|
111
|
-
|
|
112
|
-
Plano bom cabe em duas páginas; crescendo além, corte escopo. Feche com `morph-spec plan-check {feature}` até zero erro. Ele também recusa veredito de reuso fora do enum, id `C`/`F`/`ADR` duplicado, `## Errata` fora do fim, `## Cenários` vazio e fatia sem `persona:`; avisa chave de fatia desconhecida, superfície fora da `ui-designer`, ADR sem **Alcance**, fatia sem `cobre:` e mais de 12 fatias.
|
|
47
|
+
O `create` escreveu o esqueleto; a gramática completa chega pela rule `plan-grammar` quando você abre o `plan.md`; o resto em `morph-spec plan-check --help`. O que importa:
|
|
113
48
|
|
|
114
|
-
|
|
49
|
+
- **`## Cenários` é a definição de pronto.** Cada `Cn` é um comportamento observável que o verificador do Gate 3 vai **executar** contra a app — escreva-o como um fluxo de usuário ou uma regra que dá para disparar. `prova:` `teste` (com `risco:`) | `e2e` | `eval` | `manual` | `leitura`. Sem risco, `leitura`.
|
|
50
|
+
- **`degrau:`** quando o `Cn` não se desfaz com revert: `migrar` (toda migration, aditiva ou não: drop, rename, backfill, coluna nova) ou `irreversível` (apaga dado que alguém lê, quebra contrato externo). Sem a linha, `refazer`. Esses dois degraus pausam o gate do plano para o usuário, e o Gate 3 pausa em migration sem degrau, em arquivo de contrato (`openapi`, `.proto`) sem `irreversível`, e no bloqueador `irreversivel` do revisor.
|
|
51
|
+
- **`## Padrões assumidos`**: todo valor de baixo risco que você decidiu sem perguntar, numerado `1.`…`N.`, com o valor. É o que tira a pergunta trivial da entrevista: o usuário veta por número. Auth, credencial, permissão, pagamento e apagar dado nunca entram: são pergunta.
|
|
52
|
+
- **`## Estados`** (opcional): algo muda de estado (pedido, aprovação) → `- origem → destino: gatilho`, uma por linha; o `plan-check` desenha a máquina no `2-plan/plan.html`.
|
|
53
|
+
- **`## Reuso`**: `REUSAR` | `ESTENDER` | `CRIAR`; `CRIAR` exige `why` (a consulta que respondeu "não existe").
|
|
54
|
+
- **`## Decisões`**: ADR por decisão não trivial, `**Alcance:** feature|projeto`; `### Conflitos com o acervo` sempre.
|
|
55
|
+
- **`## Arquitetura`**: onde entra, o que conversa com o quê, edge cases técnicos. Gera imagem ou vídeo por IA → cite aqui o standard (`ai-agents-modalities-image-gen`, `ai-agents-media-video`, `ai-agents-media-pipeline`): é a citação que arma as provas de mídia do Gate 3, e o `plan-check` recusa o plano que fala em mídia gerada sem ela (falso positivo: a linha `Mídia gerada: não`).
|
|
115
56
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
```
|
|
121
|
-
morph-spec gate-check {feature} plan [--json]
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
Divergência de design system ou violação de standard que o disco não vê entram por `--signals '{"designSystemDivergence":true,"standardsViolations":["<id>"]}'` (as únicas chaves aceitas). **Modo entrevista** pausa sempre, e `shouldPauseGate` não conhece isso — registre direto: `morph-spec gate-decision {feature} plan --pause true --reason "modo entrevista — entendimento compartilhado" --signals '{"discoveryMode":"interview"}'`. Outro risco que nenhuma chave representa: `gate-decision` também. Nunca edite `feature.json` à mão.
|
|
57
|
+
**Contrato de implementação**: o que quem implementa precisa e o código não diz.
|
|
58
|
+
- **Verificação de runtime:** o stack sobe por `morph-spec e2e up {feature}`: app sem dependência (dados no `localStorage`, só APIs externas) sobe só por `e2e.hostServices` (build + start + health, sem compose); com dependência (banco, fila) o compose do projeto sobe ela, e criá-lo entra no plano; os fluxos que o verificador navega, nos verbos dos cenários; base URL `process.env.PLAYWRIGHT_BASE_URL ?? \`http://localhost:${process.env.PORT ?? 3000}\``, compose com `"${PORT:-3000}:3000"` e sem `container_name` (standard `infrastructure/docker/local-compose-isolation`). App de build caro no Docker também sobe como processo do host por `e2e.hostServices`, ao lado do compose das dependências. Login: `e2e.auth` (`mode: seed|storageState|bypass|none`, `seedCommand`, credenciais num `.env.e2e` gitignored) — **`mode` é obrigatório sempre que houver `seedCommand`**, sem ele o seed fica inerte. Estado limpo entre fluxos: o `e2e reset` recria os volumes de dados do stack da feature (`morph-{f}_*`); volume com `name:` fixo é compartilhado com o stack de desenvolvimento, e aí o reset recusa até existir `e2e.resetCommand`. Biblioteca pura: registre a dispensa e o porquê.
|
|
59
|
+
- **Baseline é um COMANDO, nunca um número** (`npm test`, `dotnet test`): número cravado está errado na primeira mudança. `expectedCount` (só `node-test`/`evals`) sai de `morph-spec verify {feature} --record-baseline`, nunca digitado. Sem `project.stack`/`project.tests` no `config.json`, a `morph-apply` os declara a partir destes comandos.
|
|
60
|
+
- **Pré-requisito é um PREDICADO, nunca um SHA literal:** "`git merge-base --is-ancestor origin/main HEAD` sai 0".
|
|
125
61
|
|
|
126
|
-
|
|
62
|
+
Plano bom cabe em duas páginas. `morph-spec plan-check {feature}` até zero erro.
|
|
127
63
|
|
|
128
|
-
|
|
129
|
-
question: "Gate do plano — Plano de {feature} aprovado?{ reason ? ' Sinal: ' + reason : '' }"
|
|
130
|
-
options: "aprovado, prosseguir" | "preciso ajustar" | "cancelar feature"
|
|
131
|
-
```
|
|
64
|
+
## 6. Ramo de design e gate
|
|
132
65
|
|
|
133
|
-
|
|
66
|
+
Cria ou altera UI → `morph-spec advance {feature} --design` (sempre por ele, nunca criando `1-design/` à mão: o `--design` semeia o `mockups.md`) e `Skill(morph-uiux)` depois do gate; senão `advance {feature}` leva a implement. Decidido uma vez, aqui.
|
|
134
67
|
|
|
135
|
-
|
|
68
|
+
Antes do gate, em `feature` e `bug`: a crítica em contexto fresco de `references/critique.md` (o `gate-check` cobra o `2-plan/critica.md` do plano atual).
|
|
136
69
|
|
|
137
|
-
|
|
70
|
+
`morph-spec gate-check {feature} plan [--json]`. Entrevista que zerou a árvore já é a aprovação do usuário: não repause, salvo a pausa de `signal: "rung"`, que vence e pergunta nomeando cada `Cn` e o seu degrau. Encerrada antes, com nós em `## Fora de escopo`: `morph-spec gate-decision {feature} plan --pause true --reason "entrevista encerrada com nós abertos" --signals '{"discoveryMode":"interview"}'`, e a pergunta do gate lista esses nós.
|
|
138
71
|
|
|
139
|
-
|
|
72
|
+
- `resolver === "session"` (`plan-check` com erro, crítica ausente ou de outra versão) → corrija o plano ou despache a crítica, e rode `plan-check` e `gate-check` de novo, sem perguntar.
|
|
73
|
+
- `resolver === "human"` → abra `2-plan/plan.html` no navegador do usuário (`start`/`open`/`xdg-open`; o `plan-check` o gera), o entendimento (problema, fora de escopo, cenários, riscos) e `AskUserQuestion`, header "Gate plano": `"Gate do plano — Plano de {feature} aprovado?"` com `"aprovado, prosseguir" | "preciso ajustar" | "cancelar feature"`; a pergunta lista `## Padrões assumidos` para veto por número; só a decisão sensível que você tomou sozinho vira pergunta antes, na forma de `references/interview.md` (`## Forma da pergunta`). Headless: `morph-spec approve {feature} plan --approver <quem>`.
|
|
74
|
+
- `pause === false` → uma linha e `morph-spec advance {feature}` (ou `--design`).
|
|
140
75
|
|
|
141
|
-
|
|
142
|
-
- **`chore`:** nasce com o gate `plan` carimbado por política. Escreva o plan.md curto numa única escrita (o gate já aprovado congela o arquivo depois de criado): `## Problema`, um ou dois cenários, `## Decisões` só com `### Conflitos com o acervo`, uma fatia. `plan-check` e `Skill(morph-apply)`.
|
|
143
|
-
- **`hotfix`:** é da `morph-hotfix`.
|
|
76
|
+
Aprovado: "Plano aprovado. Rode `/morph-apply {feature}`.", seguido de `## Padrões assumidos` numerado e "veta N antes do /morph-apply". Veto → `## Errata` com "Padrão N vetado: <valor novo>"; a implementação segue a errata. Não comece a implementar (exceção: `chore`). Rodou `stack-set` nesta sessão: "…numa sessão nova", porque as rules de domínio só carregam no início de uma sessão.
|
|
144
77
|
|
|
145
|
-
##
|
|
78
|
+
## 7. Deltas por tipo
|
|
146
79
|
|
|
147
|
-
|
|
80
|
+
- **bug:** árvore de repro e diagnóstico; `## Problema` com repro e causa provável; um `Cn` é o sintoma ausente com `prova: teste` e `risco: regressão`.
|
|
81
|
+
- **chore:** nasce com o gate carimbado — `plan.md` numa única escrita (o arquivo congela ao nascer): `## Problema`, um ou dois cenários, `### Conflitos com o acervo`.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Crítica do plano em contexto fresco
|
|
2
|
+
|
|
3
|
+
Depois do `plan-check` verde e antes do `gate-check {feature} plan`, em `feature` e `bug` (chore e hotfix pulam). Quem planejou não enxerga a premissa que ele mesmo assumiu: um leitor que nunca viu a conversa enxerga. Gaste esse agente antes de gastar a atenção do usuário.
|
|
4
|
+
|
|
5
|
+
## Dispatch
|
|
6
|
+
|
|
7
|
+
`Agent`, `subagent_type: "Plan"` (nativo, sem Edit/Write), em contexto fresco. O prompt leva só:
|
|
8
|
+
|
|
9
|
+
- o caminho do `2-plan/plan.md` e o `planHash` de `2-plan/checks.json`;
|
|
10
|
+
- a missão e o formato abaixo, literais.
|
|
11
|
+
|
|
12
|
+
Nunca a conversa, as respostas da entrevista nem o seu resumo do plano: o crítico lê o plano como o verificador vai ler.
|
|
13
|
+
|
|
14
|
+
> Leia `{plano}` e o código do repositório. Procure só o que um `grep` ou uma leitura confirma, com `arquivo:linha`:
|
|
15
|
+
> `premissa` (o plano afirma algo do código que o código desmente: arquivo, símbolo, contagem, flag);
|
|
16
|
+
> `contradicao` (duas partes do plano se negam);
|
|
17
|
+
> `decisao` (o plano escolhe um valor ou um caminho sem dizer, e o usuário pode querer outro);
|
|
18
|
+
> `cenario` (um `Cn` que nenhuma asserção ou passo no navegador consegue provar).
|
|
19
|
+
> Estilo, nome e "eu faria diferente" não entram. Sem achado, escreva "Nenhum achado.".
|
|
20
|
+
> Grave, pelo Bash, só `{feature}/2-plan/critica.md`, nesta forma, e não toque em mais nada:
|
|
21
|
+
>
|
|
22
|
+
> ```markdown
|
|
23
|
+
> # Crítica — {feature}
|
|
24
|
+
>
|
|
25
|
+
> **Plan-Hash:** {planHash}
|
|
26
|
+
>
|
|
27
|
+
> | id | tipo | onde no plano | evidência |
|
|
28
|
+
> |----|------|---------------|-----------|
|
|
29
|
+
> | K1 | premissa | F1 lista 4 arquivos | `grep -rl X tests/` → 57 arquivos |
|
|
30
|
+
> ```
|
|
31
|
+
|
|
32
|
+
Leia o `critica.md`, não a mensagem final do agente.
|
|
33
|
+
|
|
34
|
+
## O que fazer com cada achado
|
|
35
|
+
|
|
36
|
+
- `premissa`, `contradicao`, `cenario` → corrija o plano você mesmo.
|
|
37
|
+
- `decisao` de baixo risco → novo item de `## Padrões assumidos`.
|
|
38
|
+
- `decisao` sensível (auth, credencial, permissão, pagamento, apagar dado) → pergunta ao usuário na forma de `references/interview.md` (`## Forma da pergunta`).
|
|
39
|
+
|
|
40
|
+
Mudou o plano: `plan-check` de novo e acrescente ao fim do `critica.md` `**Aplicado-em:** <planHash novo do checks.json>`. A crítica vale para o plano que leu e para o plano onde foi aplicada; uma mudança depois disso pede outro `**Aplicado-em:**`, nunca outra crítica.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Entrevista e modos de descoberta
|
|
2
|
+
|
|
3
|
+
## Árvore
|
|
4
|
+
|
|
5
|
+
Só entra o que (a) muda escopo, comportamento ou arquitetura e (b) a varredura não respondeu. Ordene pelo que **poda**: "síncrono ou assíncrono?" antes de "qual política de retry". Publique a árvore ao usuário antes de perguntar, e de novo quando ela mudar de forma.
|
|
6
|
+
|
|
7
|
+
## Pergunta de abertura (só feature e bug)
|
|
8
|
+
|
|
9
|
+
Uma `AskUserQuestion`, header "Descoberta", com a árvore resumida e o modo recomendado primeiro (`(Recomendado)` no label). Muitas decisões ou decisões acopladas → entrevista; árvore rasa → automático.
|
|
10
|
+
|
|
11
|
+
- **Entrevista:** uma pergunta por chamada — lote impede que uma resposta pode os ramos seguintes. Cada pergunta traz a resposta recomendada primeiro. Termina quando a árvore zera; o usuário pode encerrar antes, e o que ficou aberto vira `## Fora de escopo`. Árvore zerada: as respostas aprovam o plano e o gate não repausa. Encerrada antes: o gate pausa e mostra o que foi cortado.
|
|
12
|
+
- **Automático:** até 4 perguntas, só sobre nós abertos. Árvore vazia → nenhuma pergunta.
|
|
13
|
+
|
|
14
|
+
## Forma da pergunta
|
|
15
|
+
|
|
16
|
+
Vale para a entrevista, o automático e o gate do plano.
|
|
17
|
+
|
|
18
|
+
- **Negócio, não código:** a pergunta fala de pessoas, telas e números do usuário ("quem vira dono do card?"), nunca de arquivo ou função. `Cn`, ADR e fatia ficam no `plan.md`.
|
|
19
|
+
- **Efeito à vista:** opção que muda algo visível ou um dado leva `preview` (ASCII, até ~12 linhas) com o efeito num exemplo concreto: nomes, contagem antes → depois, o card duplicado marcado `✖`. Opção sem efeito visível dispensa.
|
|
20
|
+
- **Recomendada primeiro**, com `(Recomendado)` no label; a description diz o custo da alternativa em uma frase.
|
|
21
|
+
- Comentário do usuário chega pelas notas da opção: leia-as antes de seguir.
|
|
22
|
+
|
|
23
|
+
## Headless
|
|
24
|
+
|
|
25
|
+
`AskUserQuestion` indisponível ou negada (`claude -p`): nunca decida você os nós abertos. Escreva-os em texto, numerados, cada um com a resposta recomendada; `morph-spec gate-decision {feature} plan --pause true --reason "entrevista headless"` e encerre o turno. Retome quando o usuário responder.
|
|
@@ -1,103 +1,86 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: morph-uiux
|
|
3
|
-
description: Conduz a fase
|
|
3
|
+
description: Conduz a fase de UI/UX de uma feature com plano aprovado — renderiza 2-3 opções navegáveis por tela, abre no navegador para o usuário escolher, refina a escolhida em protótipo com prints 1280/390, preenche o checklist de tela e apresenta o Gate uiux.
|
|
4
4
|
version: core
|
|
5
|
-
when_to_use: Use quando o ramo de design for tomado (morph-spec advance {feature} --design,
|
|
5
|
+
when_to_use: Use quando o ramo de design for tomado (morph-spec advance {feature} --design), antes de /morph-apply
|
|
6
6
|
user-invocable: true
|
|
7
|
-
cliVersion: "
|
|
7
|
+
cliVersion: "10.0.0"
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# morph-uiux
|
|
11
11
|
|
|
12
|
-
Entra depois do gate do plano, quando a
|
|
12
|
+
Entra depois do gate do plano, quando a feature cria ou altera UI. Sai com `1-design/` aprovado; próximo passo `/morph-apply {feature}`. Você desenha nesta sessão — o que decidir aqui é o que vai implementar depois.
|
|
13
|
+
|
|
14
|
+
A régua de sistema e de estética chega sozinha: a rule `ui-design` carrega quando você abre um arquivo de `1-design/` ou de UI. Carregue `frontend-design:frontend-design` se a sessão a tiver.
|
|
13
15
|
|
|
14
16
|
## 1. Insumos
|
|
15
17
|
|
|
16
|
-
- `2-plan/plan.md` — problema
|
|
17
|
-
- `.morph/context/design-system.md` — o design system
|
|
18
|
-
-
|
|
19
|
-
- `
|
|
18
|
+
- `2-plan/plan.md` — problema e cenários de tela, referidos pelo id (`C3`). Esta fase **nunca** edita `plan.md` nem `checks.json`.
|
|
19
|
+
- `.morph/context/design-system.md` — o design system vivo; toda decisão de token ou componente parte dele e dos tokens reais do CSS do projeto.
|
|
20
|
+
- `config.json` → `project.stack` decide a tecnologia (`nextjs` → Tailwind + shadcn + Motion). Nunca suponha Next.js.
|
|
21
|
+
- A superfície de cada tela (`marketing-site` | `admin-app` | `brand-moment`, em `surfaces.json`) diz quais standards abrir.
|
|
20
22
|
|
|
21
|
-
## 2.
|
|
23
|
+
## 2. Opções — o usuário escolhe vendo, não lendo
|
|
22
24
|
|
|
23
|
-
-
|
|
24
|
-
- Reusa token e componente existentes antes de criar; token novo precisa de justificativa. Sistemas, não telas isoladas.
|
|
25
|
-
- Tarefa principal da tela em até 3 interações, uma ação primária por tela, voltar/cancelar sempre à vista. Erro diz o que fazer a seguir; conteúdo gerado por IA aparece marcado como tal.
|
|
26
|
-
- **Toda tela sai com o checklist de tela preenchido.** O `advance --design` já escreveu `1-design/mockups.md` a partir do template do pacote, a fonte única dos dez itens (tabela `### Checklist de tela` dentro de cada `## Tela:`). "Não se aplica" vale se escrito; `…`, vazio ou "a definir" reprovam. Design sem tela nova ou alterada (só componente ou estilo): apague o `1-design/mockups.md` semeado. É o checklist que faz a lista de 2 000 linhas paginar: o verificador do Gate 3 cobra cada item decidido em `## Checklist de tela`. Tela de dados segue os standards de `admin-app` (lista/tabela, formulário, feedback, estrutura de página); login, onboarding, primeira tela, estado vazio de destaque e sucesso são `brand-moment`.
|
|
27
|
-
- **Conformidade não basta: a régua estética vale junto.** Direção escrita antes de componente (`1-design/direcao.md`: conceito, metáfora, o que torna a tela memorável, o que ela não pode parecer; 2 ou 3 direções para tela nova ou momento de marca), celular desenhado e não derivado, movimento com versão estática digna. A régua é o standard `frontend-design-system-art-direction`.
|
|
28
|
-
- **Toda tela nova ou alterada tem protótipo renderizado e conferido por print.** `1-design/prototipos/{tela}.html` autossuficiente, com os tokens reais do projeto (lidos do CSS de tokens), desktop e celular lado a lado, controles animado/estático/pausar; prints `{tela}-1280.png` e `{tela}-390.png` ao lado, saídos do laço de autocrítica. A `## Tela:` aponta o protótipo na linha `**Protótipo:**`.
|
|
25
|
+
Para cada tela nova ou alterada, `1-design/opcoes/{tela}.html`: **uma página com 2 ou 3 direções distintas**, alternáveis por abas, cada uma com:
|
|
29
26
|
|
|
30
|
-
|
|
27
|
+
- o conceito em uma frase e o que a torna memorável, no topo da aba;
|
|
28
|
+
- desktop (1280) e celular (390) lado a lado em moldura de aparelho, com conteúdo realista (nunca lorem ipsum nem métrica inventada);
|
|
29
|
+
- controles animado/estático; `prefers-reduced-motion` respeitado;
|
|
30
|
+
- os tokens reais do projeto; uma direção pode propor tokens novos, marcados como tal.
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
Direções genuinamente diferentes (layout, hierarquia, densidade, tom), não três variações de cor. Sirva a pasta por HTTP (`npx http-server 1-design -p <porta>` em background), **abra no navegador do usuário** (`start` no Windows, `open` no macOS, `xdg-open` no Linux) e pergunte:
|
|
33
33
|
|
|
34
34
|
```
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
Design system: `.morph/context/design-system.md` (tokens e componentes a reusar).
|
|
38
|
-
|
|
39
|
-
Nesta ordem, só o aplicável ao escopo:
|
|
40
|
-
1. `1-design/direcao.md` — antes de qualquer componente: conceito em uma frase, metáfora visual,
|
|
41
|
-
o que torna a tela memorável, o que ela NÃO pode parecer. Tela nova ou momento de marca:
|
|
42
|
-
2 ou 3 direções distintas, uma recomendada com o porquê (standard `frontend-design-system-art-direction`).
|
|
43
|
-
2. `1-design/design-system.md` (obrigatório: sem ele o `advance` recusa) — tokens (cor, tipografia, espaço, motion) que a feature usa ou acrescenta, lidos do CSS de tokens real do projeto; token novo também reescreve `.morph/context/design-system.md` (§4).
|
|
44
|
-
3. `1-design/prototipos/{tela}.html` por tela nova ou alterada — autossuficiente, tokens reais,
|
|
45
|
-
desktop e celular (folha inferior, zona do polegar, 44px) lado a lado em moldura de aparelho,
|
|
46
|
-
controles animado/estático/pausar e `prefers-reduced-motion`. Laço de autocrítica: sirva a pasta
|
|
47
|
-
por HTTP local (o Playwright MCP recusa `file:`), print em 1280 e em 390 (`{tela}-1280.png`,
|
|
48
|
-
`{tela}-390.png` ao lado do HTML), avalie (hierarquia, contraste, ritmo, celular, "parece template?"),
|
|
49
|
-
corrija e repita até passar.
|
|
50
|
-
4. `mockups.md` — um `## Tela: <nome>` por tela nova ou alterada, com a fatia que a entrega, a linha
|
|
51
|
-
`**Protótipo:** 1-design/prototipos/{tela}.html` e a tabela `### Checklist de tela` que o
|
|
52
|
-
`advance --design` já escreveu em `1-design/mockups.md`, cada item decidido.
|
|
53
|
-
5. `components.md` — componentes novos e reusados, com props e estados.
|
|
54
|
-
6. `flows.md` — navegação entre as telas.
|
|
55
|
-
|
|
56
|
-
Relatório por artefato em `1-design/reports/[artefato]-report.md`: o que foi feito (2-3 frases),
|
|
57
|
-
o artefato, as decisões de design e por quê, o que ficou aberto; o do protótipo lista as rodadas
|
|
58
|
-
do laço e o que cada uma corrigiu. É o retorno; a mensagem final é cortesia.
|
|
59
|
-
Bash só para consulta (`morph-spec standards --find`, `npx`, screenshot, `git log/diff`) e para o
|
|
60
|
-
servidor estático do protótipo (`npx http-server <pasta> -p <porta>` em background; ao fim, encerre
|
|
61
|
-
esse processo pelo id do background ou pelo PID dono da porta, nunca por nome de executável):
|
|
62
|
-
sem build, teste, `verify`, `approve` ou `advance`.
|
|
63
|
-
Não toque `feature.json`, `state.json`, `plan.md` nem `checks.json`.
|
|
35
|
+
AskUserQuestion — header "Direção", question: "Qual direção para {tela}?"
|
|
36
|
+
options: uma por direção (nome curto + o conceito) — a sua recomendação primeiro, com "(Recomendado)"
|
|
64
37
|
```
|
|
65
38
|
|
|
66
|
-
|
|
39
|
+
"Outra" com comentário → ajuste a página e pergunte de novo. Componente ou estilo sem tela nova: pule para o §3 com uma opção só.
|
|
67
40
|
|
|
68
|
-
##
|
|
41
|
+
## 3. Protótipo da escolhida
|
|
69
42
|
|
|
70
|
-
|
|
43
|
+
`1-design/prototipos/{tela}.html` refina a direção escolhida até o nível de entrega: todos os estados (vazio, carregando, erro, sucesso), foco visível, alvos de 44px no celular. **Seletor de estado** no topo do protótipo: um botão por estado com `data-estado="vazio|carregando|erro"`, e o mesmo estado abre por `?estado=<nome>` na URL — o usuário vê cada estado num clique, sem ler. **Laço de autocrítica:** print em 1280 e em 390 pelo Playwright MCP (ele recusa `file:` — use a URL HTTP), salvos como `{tela}-1280.png` e `{tela}-390.png` ao lado do HTML, mais `{tela}-{estado}-390.png` de cada estado que o checklist diz que se aplica (vazio e carregando pelo item "Estados", erro pelo item "Erro"; "não se aplica" dispensa) — o gate uiux confere o `data-estado` e os prints; avalie (hierarquia, contraste AA, ritmo, celular, "parece template?"), corrija, repita até passar. Ao terminar, encerre o servidor pelo id do background ou pelo PID da porta, nunca por nome de executável.
|
|
71
44
|
|
|
72
|
-
##
|
|
45
|
+
## 4. mockups.md
|
|
73
46
|
|
|
74
|
-
|
|
47
|
+
O `advance --design` já escreveu `1-design/mockups.md` a partir do template — a tabela do checklist mora lá, não copie. Por tela, um `## Tela: <nome>` com:
|
|
75
48
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
49
|
+
- `**Protótipo:** 1-design/prototipos/{tela}.html` e `**Direção escolhida:**` (qual opção e por quê, numa frase);
|
|
50
|
+
- o `### Checklist de tela` com cada item decidido (`não se aplica` vale se escrito; vazio ou "a definir" reprova);
|
|
51
|
+
- `### Componentes` (novos e reusados, com props e estados) e `### Fluxo` (de onde vem, para onde vai).
|
|
52
|
+
|
|
53
|
+
Sem tela nova ou alterada: apague o `mockups.md` semeado.
|
|
54
|
+
|
|
55
|
+
## 5. Design system vivo
|
|
56
|
+
|
|
57
|
+
Token ou componente novo aprovado: **reescreva o corpo** de `.morph/context/design-system.md` (o valor novo substitui o antigo na própria seção); o changelog guarda só data e motivo.
|
|
79
58
|
|
|
80
|
-
|
|
59
|
+
## 6. Destino de toda capacidade nova
|
|
81
60
|
|
|
82
|
-
|
|
61
|
+
Uma tela que pede algo que o plano não tem (endpoint, campo, permissão) **nunca fica sem destino**. Antes do gate, varra o que você escreveu:
|
|
83
62
|
|
|
84
63
|
```
|
|
85
|
-
|
|
64
|
+
grep -riE "capacidade nova|precisa de backend|dimensionar junto" .morph/features/{feature}/1-design/
|
|
86
65
|
```
|
|
87
66
|
|
|
88
|
-
|
|
67
|
+
Cada ocorrência vai para o `Cn` do plano que já a cobre, para uma exclusão registrada no `mockups.md`, ou — escopo novo — `morph-spec unapprove {feature} plan`, ajuste, `plan-check` e o gate de novo.
|
|
68
|
+
|
|
69
|
+
## 7. Gate uiux
|
|
70
|
+
|
|
71
|
+
`morph-spec gate-check {feature} uiux [--json]` cobra por código: tela sem checklist completo, sem `**Protótipo:**`, sem o HTML ou sem os dois prints pausa nomeando o que falta. Complete antes de pedir aprovação.
|
|
89
72
|
|
|
90
|
-
|
|
73
|
+
Apresente aberto, não descrito: abra cada protótipo no navegador e cite a direção de cada tela em uma frase. Divergência de design system vista aqui: `--signals '{"designSystemDivergence":true}'`.
|
|
91
74
|
|
|
92
|
-
|
|
75
|
+
Pausa com `resolver: "session"` não é pergunta: faça o que a `reason` diz e rode o `gate-check` de novo. Checklist ou protótipo incompleto → complete-o. Sem como completar (sem navegador para os prints): `morph-spec gate-decision {feature} uiux --pause true --reason "<o que falta>"`, pausa manual, que é do usuário.
|
|
76
|
+
|
|
77
|
+
`resolver === "human"` → `AskUserQuestion`, header "Gate uiux":
|
|
93
78
|
|
|
94
79
|
```
|
|
95
80
|
question: "Gate uiux — Design de {feature} aprovado?{ reason ? ' Sinal: ' + reason : '' }"
|
|
96
81
|
options: "aprovado, prosseguir" | "preciso ajustar" | "cancelar feature"
|
|
97
82
|
```
|
|
98
83
|
|
|
99
|
-
O hook `state-sync`
|
|
100
|
-
|
|
101
|
-
**`pause === false`**: resumo (tokens novos, N telas, componentes novos/reusados, fluxos) e `morph-spec advance {feature}`.
|
|
84
|
+
O hook `state-sync` grava a aprovação pela feature nomeada. Headless: `morph-spec advance {feature} --approver <quem>` — sem `--approver`, um terminal não interativo grava `approvedBy: "auto"` num gate que um humano devia assinar. `pause === false` → uma linha e `morph-spec advance {feature}`.
|
|
102
85
|
|
|
103
|
-
Aprovado
|
|
86
|
+
Aprovado, `1-design/` trava: retrabalho passa pelo gate de novo. Diga que `/morph-apply {feature}` está pronto.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"marketing-site": {
|
|
3
|
+
"when": "site de marketing: landing page, institucional, campanha — narrativa, conversão, movimento e SEO",
|
|
4
|
+
"standards": [
|
|
5
|
+
"frontend-design-system-ai-image-generation",
|
|
6
|
+
"frontend-design-system-ai-video-generation",
|
|
7
|
+
"frontend-scroll-driven-frame-scrub",
|
|
8
|
+
"frontend-scroll-driven-smooth-scroll",
|
|
9
|
+
"frontend-scroll-driven-scroll-components",
|
|
10
|
+
"frontend-seo-meta-schema-audit",
|
|
11
|
+
"frontend-gsap-core",
|
|
12
|
+
"frontend-gsap-scrolltrigger",
|
|
13
|
+
"frontend-gsap-plugins"
|
|
14
|
+
]
|
|
15
|
+
},
|
|
16
|
+
"admin-app": {
|
|
17
|
+
"when": "app de dados: painel administrativo, CRUD, back office, dashboard — lista, tabela, formulário e densidade",
|
|
18
|
+
"standards": [
|
|
19
|
+
"frontend-admin-app-data-table",
|
|
20
|
+
"frontend-admin-app-forms",
|
|
21
|
+
"frontend-admin-app-feedback",
|
|
22
|
+
"frontend-admin-app-page-structure"
|
|
23
|
+
]
|
|
24
|
+
},
|
|
25
|
+
"brand-moment": {
|
|
26
|
+
"when": "momento de marca dentro do produto: login e auth, onboarding, primeira tela, estado vazio de destaque, sucesso, vitrine — direção, cena e movimento",
|
|
27
|
+
"standards": [
|
|
28
|
+
"frontend-gsap-core",
|
|
29
|
+
"frontend-gsap-scrolltrigger"
|
|
30
|
+
]
|
|
31
|
+
}
|
|
32
|
+
}
|