@polymorphism-tech/morph-spec 8.46.0 → 8.47.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.
Files changed (140) hide show
  1. package/CLAUDE.md +5 -5
  2. package/README.md +2 -2
  3. package/bin/morph-spec.js +1 -4
  4. package/bin/validate.js +4 -25
  5. package/claude-plugin.json +1 -1
  6. package/docs/CHEATSHEET.md +2 -2
  7. package/docs/QUICKSTART.md +1 -1
  8. package/framework/CLAUDE.md +1 -1
  9. package/framework/MORPH.md +8 -8
  10. package/framework/commands/create-umbraco-lp.md +2 -0
  11. package/framework/commands/migrate-lp-to-umbraco.md +2 -0
  12. package/framework/commands/morph-archive.md +1 -1
  13. package/framework/commands/morph-hotfix.md +1 -1
  14. package/framework/commands/morph-infra.md +17 -203
  15. package/framework/commands/morph-media.md +3 -0
  16. package/framework/commands/morph-preflight.md +5 -28
  17. package/framework/commands/morph-proposal.md +2 -2
  18. package/framework/commands/morph-troubleshoot.md +2 -14
  19. package/framework/docs/CLI.md +3 -3
  20. package/framework/hooks/claude-code/core/state-sync.js +13 -1
  21. package/framework/hooks/shared/e2e-check.js +3 -4
  22. package/framework/hooks/shared/state-writer.js +1 -0
  23. package/framework/rules/ai-agents-standards.md +18 -16
  24. package/framework/rules/asaas-standards.md +3 -1
  25. package/framework/rules/csharp-standards.md +10 -8
  26. package/framework/rules/data-standards.md +5 -5
  27. package/framework/rules/dotnet-templates.md +1 -1
  28. package/framework/rules/frontend-standards.md +4 -2
  29. package/framework/rules/gsap-standards.md +10 -5
  30. package/framework/rules/hangfire-standards.md +3 -1
  31. package/framework/rules/infrastructure-standards.md +4 -2
  32. package/framework/rules/morph-workflow.md +2 -2
  33. package/framework/rules/neon-auth-standards.md +3 -1
  34. package/framework/rules/neon-standards.md +6 -4
  35. package/framework/rules/nextjs-standards.md +13 -11
  36. package/framework/rules/nextjs-templates.md +1 -1
  37. package/framework/rules/resend-standards.md +3 -1
  38. package/framework/schemas/feature.schema.json +1 -3
  39. package/framework/skills/README.md +1 -1
  40. package/framework/skills/core/create-umbraco-lp/SKILL.md +3 -3
  41. package/framework/skills/core/migrate-lp-to-umbraco/SKILL.md +3 -3
  42. package/framework/skills/core/morph-apply/SKILL.md +3 -3
  43. package/framework/skills/core/morph-brainstorming/SKILL.md +3 -3
  44. package/framework/skills/core/morph-hotfix/SKILL.md +4 -4
  45. package/framework/skills/core/morph-implement/SKILL.md +3 -3
  46. package/framework/skills/core/morph-machine/SKILL.md +3 -3
  47. package/framework/skills/core/morph-media/SKILL.md +3 -3
  48. package/framework/skills/core/morph-plan/SKILL.md +3 -3
  49. package/framework/skills/core/morph-proposal/SKILL.md +3 -3
  50. package/framework/skills/core/morph-review/SKILL.md +3 -3
  51. package/framework/skills/core/morph-stack-scan/SKILL.md +3 -3
  52. package/framework/skills/core/morph-standards/SKILL.md +6 -6
  53. package/framework/skills/core/morph-uiux/SKILL.md +3 -3
  54. package/framework/standards/STANDARDS.json +59 -56
  55. package/framework/standards/ai-agents/evals-with-cache.md +1 -1
  56. package/framework/standards/ai-agents/llm-runtime-defaults.md +1 -1
  57. package/framework/standards/ai-agents/modalities-speech-to-text.md +36 -26
  58. package/framework/standards/ai-agents/prompt-sources.md +6 -4
  59. package/framework/standards/ai-agents/providers/model-registry.md +1 -1
  60. package/framework/standards/ai-agents/rag-custom-pgvector.md +67 -39
  61. package/framework/standards/ai-agents/setup.md +1 -1
  62. package/framework/standards/ai-agents/structured-output.md +1 -1
  63. package/framework/standards/ai-agents/sweet-spot.md +1 -1
  64. package/framework/standards/architecture/code-comments.md +2 -2
  65. package/framework/standards/architecture/vertical-slice/vertical-slice.md +18 -9
  66. package/framework/standards/backend/api/validation.md +135 -47
  67. package/framework/standards/backend/database/postgresql/database.md +11 -7
  68. package/framework/standards/backend/database/vector-search-rag.md +207 -324
  69. package/framework/standards/backend/dotnet/fluent-validation-vsa.md +14 -8
  70. package/framework/standards/backend/dotnet/result-pattern.md +40 -6
  71. package/framework/standards/backend/dotnet/scalar-ui.md +13 -7
  72. package/framework/standards/backend/dotnet/scrutor.md +1 -1
  73. package/framework/standards/backend/dotnet/testing.md +1 -1
  74. package/framework/standards/backend/dotnet/vsa-handler-patterns.md +7 -7
  75. package/framework/standards/backend/integrations/asaas/asaas-api.md +309 -165
  76. package/framework/standards/backend/integrations/hangfire/hangfire-jobs.md +134 -154
  77. package/framework/standards/data/nosql/cache/redis.md +120 -44
  78. package/framework/standards/data/nosql/cosmos-db.md +114 -71
  79. package/framework/standards/frontend/design-system/animations.md +1 -1
  80. package/framework/standards/frontend/design-system/naming.md +1 -1
  81. package/framework/standards/frontend/nextjs/motion-patterns.md +45 -29
  82. package/framework/standards/frontend/nextjs/naming-conventions.md +1 -1
  83. package/framework/standards/infrastructure/docker/coolify-deploy.md +8 -6
  84. package/framework/standards/infrastructure/neon/neon-pgvector.md +120 -75
  85. package/framework/standards/infrastructure/neon/neon-setup.md +53 -31
  86. package/framework/templates/code/dotnet/contracts/contracts-vsa.cs +2 -2
  87. package/framework/templates/code/dotnet/extensions/database-extensions.cs +1 -1
  88. package/framework/templates/code/dotnet/extensions/result-extensions.cs +27 -0
  89. package/framework/templates/code/dotnet/feature/endpoint.cs.hbs +2 -2
  90. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/MediaDisclosureTests.cs +1 -1
  91. package/framework/templates/infrastructure/docker/coolify.template.json +3 -3
  92. package/framework/templates/infrastructure/github/README.md +2 -1
  93. package/framework/templates/infrastructure/github/workflows/deploy-coolify.yml.hbs +2 -1
  94. package/package.json +1 -1
  95. package/src/commands/observability/telemetry.js +3 -5
  96. package/src/commands/project/init.js +2 -1
  97. package/src/commands/project/update.js +16 -18
  98. package/src/commands/state/approve.js +17 -0
  99. package/src/commands/state/gate-check.js +4 -14
  100. package/src/commands/validation/verify.js +3 -12
  101. package/src/core/paths/output-schema.js +1 -1
  102. package/src/dashboard/app/App.jsx +0 -2
  103. package/src/dashboard/app/components/CommandPalette.jsx +2 -3
  104. package/src/dashboard/app/components/EntityLink.jsx +0 -1
  105. package/src/dashboard/app/components/Markdown.jsx +1 -1
  106. package/src/dashboard/app/components/Sidebar.jsx +1 -2
  107. package/src/dashboard/app/pages/RulesMap.jsx +3 -3
  108. package/src/dashboard/app/pages/SkillsLibrary.jsx +3 -3
  109. package/src/dashboard/scanner/activity-scanner.js +1 -1
  110. package/src/dashboard/scanner/docs-scanner.js +5 -23
  111. package/src/dashboard/scanner/features-scanner.js +1 -1
  112. package/src/dashboard/scanner/index.js +0 -2
  113. package/src/dashboard/scanner/rules-scanner.js +15 -10
  114. package/src/dashboard/scanner/skills-scanner.js +2 -3
  115. package/src/lib/evaluator-report.js +13 -0
  116. package/src/lib/risk-detector.js +8 -0
  117. package/src/lib/stack/stack-profile.js +1 -1
  118. package/src/lib/validators/reuse/reuse-validator.js +2 -3
  119. package/src/lib/validators/reuse/symbol-scanner.js +2 -4
  120. package/src/lib/validators/validation-runner.js +8 -88
  121. package/src/lib/validators/verify-runner.js +22 -72
  122. package/src/scripts/setup-infra.js +33 -22
  123. package/src/utils/agents-installer.js +20 -8
  124. package/src/utils/file-copier.js +7 -5
  125. package/framework/commands/commit.md +0 -166
  126. package/framework/rubrics/backend.json +0 -41
  127. package/framework/rubrics/default.json +0 -36
  128. package/framework/rubrics/frontend.json +0 -36
  129. package/framework/templates/project/validate.js +0 -97
  130. package/src/dashboard/app/pages/Rubrics.jsx +0 -97
  131. package/src/dashboard/scanner/rubrics-scanner.js +0 -12
  132. package/src/lib/validators/architecture/architecture-validator.js +0 -270
  133. package/src/lib/validators/architecture/index.js +0 -7
  134. package/src/lib/validators/css/css-validator.js +0 -340
  135. package/src/lib/validators/css/index.js +0 -7
  136. package/src/lib/validators/design-system/design-system-validator.js +0 -237
  137. package/src/lib/validators/design-system/index.js +0 -7
  138. package/src/lib/validators/score-aggregator.js +0 -244
  139. package/src/lib/validators/ui/index.js +0 -7
  140. package/src/lib/validators/ui/ui-contrast-validator.js +0 -422
package/CLAUDE.md CHANGED
@@ -48,7 +48,7 @@ No build step — pure ESM JavaScript, runs directly via Node.js 18+.
48
48
  - `templates/` — Handlebars template registry and renderer
49
49
  - `workflows/` — Workflow type detector
50
50
  - **`src/lib/`** — Libraries and subsystems:
51
- - `validators/` — Data-driven validators (architecture, css, design-system, nextjs)
51
+ - `validators/` — Validators run by the `verify` validators node (code-budget, contracts, nextjs, packages, reuse)
52
52
  - `generators/` — Code generation (recap, context, handoff)
53
53
  - `stack-filter.js` — Stack-aware asset filtering via YAML frontmatter `stacks:` tags
54
54
  - `installers/` — Agents, skills, hooks installers
@@ -117,7 +117,7 @@ When modifying framework components, verify the full scope of related files.
117
117
  | When you modify... | Also verify... |
118
118
  |----------------------------------|-------------------------------------------------------------------------------------------|
119
119
  | `framework/agents.json` | agents-installer.js (test/utils/agents-installer.test.js), doctor.js (REQUIRED_AGENTS). **`maxTurns` (ADR-004):** UMA régua de validade, `maxTurnsError` em `agents-installer.js`, com QUATRO leitores — `installAgents` (recusa antes de escrever), `checkAgentsDrift` (`invalid`), `validateAgentsJson` do `doctor` (error) e o Check 6 do `validate-framework.js` (`test/framework/validate-framework-agents.test.js`); uma segunda noção de "valor válido" faz o mesmo arquivo passar num e ser recusado no outro. Sem o campo, o frontmatter sai byte a byte igual ao de antes (canário COMPAT). O corpo gerado anuncia o teto ao sub-agent, e a cláusula 5 dos templates de dispatch depende disso. O drift lê o registry MCP do PACOTE (`mcpRegistryDir`): a cópia instalada não tem `mcp/`, e ler dela dava toda persona com `mcp` como stale numa instalação limpa. O marcador `PARCIAL` (1ª linha) que a cláusula 5 e o corpo da persona mandam gravar é lido por `report-check.js` (`PARTIAL_MARKER` → `report-incomplete`, ação `resume`): mudar a grafia num lado só devolve o parcial lido como `ok`. **`effort`:** mesma régua única em quatro leitores (`effortError`); ausente, o frontmatter não ganha linha e o sub-agent herda o effort da sessão (COMPAT intacto). Implementadores e `scout` `medium`, `evaluator` sem o campo — o Gate 3 não é barateado. **`surfaces` (ADR-005):** mesma régua única em quatro leitores (`surfacesError`), e `personaStandardIds` é a leitura única de "todo standard da persona" para o Check 1, o drift e os scanners do dashboard (`agents-scanner.js`, `standards-scanner.js`) — iterar só `standards` deixa id de superfície sem validar e a aresta do grafo sumida. Sem o campo, o `.md` sai byte a byte o de antes: `test/fixtures/agents/ui-designer-5.3.0.{json,md}` é a persona do 5.3.0 e o render do installer de main, comparados com `strictEqual` — nunca regere a fixture para fazer o teste passar. A chave da superfície é a que o checklist de tela do `morph-uiux` escreve em `Superfície` e que o `morph-plan` §5a usa para somar a lista em `tasks[].standards` |
120
- | `framework/standards/**` | STANDARDS.json entry exists (o **digest** e o que `standards --find` devolve — corrigir a prosa e esquecer o digest e o caso mais comum), agents reference standard, .md file exists. **Bloco de codigo `csharp` num standard e afirmacao verificavel:** extraia com `node scripts/extract-doc-csharp.mjs <std.md> "## Secao" out.cs` e compile numa sonda com o pin + `TreatWarningsAsErrors` (sem ele `MEAI001` vira aviso e o build fica verde sobre codigo que o consumidor nao compila). Medido: um exemplo carimbado sem compilar tinha 3 erros independentes |
120
+ | `framework/standards/**` | STANDARDS.json entry exists (o **digest** e o que `standards --find` devolve — corrigir a prosa e esquecer o digest e o caso mais comum), e o bullet do standard na rule `framework/rules/*-standards.md` que o roteia (resumo inline; `@`-import em rule resolve relativo ao arquivo da rule e, quando resolve, carrega em TODA sessão ignorando `paths:` — medido; canário `test/framework/rules-no-imports.test.js`), agents reference standard, .md file exists. **Bloco de codigo `csharp` num standard e afirmacao verificavel:** extraia com `node scripts/extract-doc-csharp.mjs <std.md> "## Secao" out.cs` e compile numa sonda com o pin + `TreatWarningsAsErrors` (sem ele `MEAI001` vira aviso e o build fica verde sobre codigo que o consumidor nao compila). Medido: um exemplo carimbado sem compilar tinha 3 erros independentes |
121
121
  | `isImplementer` (Check 6 de `scripts/validate-framework.js`) | toda persona com Write/Edit no escopo efetivo de tools tem de alcançar, pelos `standards`, as âncoras `comment-policy` e `test-budget` do STANDARDS.json (`IMPLEMENTER_ANCHORS`). Renomear a chave da âncora no registry derruba o `validate`, e persona implementadora nova sem os dois standards também. Installer e `doctor` não cobram isso de propósito: um `agents.json` instalado antigo continua valendo |
122
122
  | `scripts/generate-standards-registry.js` | `framework/standards/STANDARDS.json` (REGENERE, nunca patch textual — tres features escrevem no mesmo arquivo), `src/lib/standards/verified-against.js` (`parseVerifiedAgainst`/`deriveProvedBy`: `verifiedAgainst` e `provedBy` sao DERIVADOS a cada run e NAO entram em `PRESERVE_FIELDS`), `test/framework/standards-registry.test.js`. **Renomear um standard e uma PARADA, nao um exit 0**: path sumido + path novo faz o gerador recusar nomeando os dois conjuntos e prescrevendo a edicao do campo `path` da entrada antiga — ele nao adivinha o par. `MORPH_STANDARDS_BASE` e o unico seam de teste do script e nada em producao o define |
123
123
  | `framework/hooks/claude-code/**` | hooks-installer.js MORPH_HOOKS array, hook follows fail-open pattern. O `timeout` de cada entrada é em SEGUNDOS, a unidade que o Claude Code lê — em milissegundos ele passa do default de 600 e prende a sessão por horas (canário em `test/hooks/hooks-installer.test.js`); binding `async: true` não tem timeout aplicado |
@@ -162,8 +162,8 @@ When modifying framework components, verify the full scope of related files.
162
162
  | `framework/hooks/shared/graph-freshness.js` (a regra única de "grafo em dia") | os três lados que perguntam: `graph-refresh.js` (decide se roda e se o disparo solta processo), `graph-loader.js` `getFreshness` (`graph status\|explain\|affected` e o `doctor`) e `graph build\|refresh` (gravam a rodada em `<git-common-dir>/morph-spec/graph-refresh-state.json`). O registro da rodada existe porque o `graphify update` 0.9.50 não recarimba `built_at_commit` quando a topologia não muda: sem ele, o grafo parecia velho para sempre e cada disparo rodava o graphify de novo (~80 s no MORPH_GHLBrain). As regras do `.graphifyignore` entram por CONTEÚDO (hash sem comentário, BOM e CRLF), nunca pelo relógio, e `ignoreTextOf` é a ÚNICA leitura de "as regras desta árvore": numa worktree sem arquivo próprio, as da raiz — as mesmas que o `graph refresh` põe ali durante a rodada (`prepareIgnore` em `build.js`). O arquivo temporário leva `TEMP_IGNORE_MARKER` na 1ª linha; nas duas triagens de sujeira (`finish` e `worktree remove`) `withoutLeftoverIgnore` o tira da conta ANTES das recusas e `dropLeftoverIgnore` o apaga só DEPOIS delas — apagar antes é mutação atrás de uma precondição. Mudar a grafia do marcador num lado só devolve o `worktree-dirty` de uma rodada morta no meio. Mora em `hooks/shared` porque hook não importa `src/` |
163
163
  | `framework/hooks/shared/graph-refresh.js` (o refresh em background) | os dois disparos (`graph-refresh-kick`, depois de Bash/PowerShell com `git`/`gh`/`morph-spec`, e o SessionStart de `worktree-context.js`), `graph build\|refresh` (o MESMO lock por repositório) e `worktree.js` (`seedGraphFromRoot`: a worktree nasce com o grafo da raiz e o registro dela — em dia no HEAD só se a raiz estava). **Só a raiz**: o worker destacado nasce com `cwd` no git common dir e nunca recebe o caminho de uma worktree — no win32 um diretório em uso não se apaga, e o `finish` de uma worktree com refresh correndo falhava no meio. A worktree anda por `morph-spec graph refresh`, em primeiro plano. `runGraphify` roda o graphify com `cwd` no git common dir, nunca na árvore (ele lê o alvo, o ignore e o git pelo argumento — medido no 0.9.50). O disparo lê o HEAD pelo disco (`readPrimaryHead`, `git-paths.js`) e não solta processo quando o grafo não pede refresh: ele roda a cada comando git do agente. O step 18b de `setup-infra.js` não instala o hook git do graphify: ele não roda em worktree, não tem `post-merge` e carimba como em dia um grafo sem os arquivos do merge |
164
164
  | `framework/hooks/shared/git-exclude.js` | ÚNICO escritor dos blocos do morph-spec no `info/exclude` do COMMON dir — o `.git/worktrees/<id>/info/exclude` o git não lê para worktree vinculada. Leitores que passam o seu marcador: `worktree.js`, `handoff-generator.js` e `graph-refresh.js`. Resolve o common dir pelo disco, sem subprocesso: um `git` gerado por um processo destacado abria janela de console no win32 |
165
- | `src/lib/validators/reuse/**` | `validation-runner.js` (case + push universal), `framework/rubrics/*.json` (o id `reuse` mapeado numa categoria, senão o achado não pesa no score), `test/fixtures/graph/prospectpro-reuse.graph.json` (recorte do grafo real — regerar com `build-reuse-fixture.mjs`, nunca editar à mão) |
166
- | `src/lib/validators/code-budget/**` | `validation-runner.js` (case + push universal fora do `light`), `framework/rubrics/*.json` (o id `code-budget` em `code_quality` nas TRÊS, senão o aviso não pesa), `framework/docs/CLI.md` (o que conta como teste e os limites 1,5×/40 linhas) e `test/integration/code-budget-verify.test.js`. Lê `addedLinesAgainst` (`default-branch.js`), `isTestFile` (`symbol-scanner.js`, a mesma régua de teste do `reuse`), `isProjectSource`/`isGenerated` (`hooks/shared/source-files.js`) e `commentLines`/`citesProcess` (`hooks/shared/comment-scanner.js`, sobre `stripComments` com `js`). Sempre `warning`. Não conseguir medir é skip `unavailable` com razão, e o `validation-runner` não põe validador pulado em `results`: pulado não conta como verde |
165
+ | `src/lib/validators/reuse/**` | `validation-runner.js` (case + push universal), `test/fixtures/graph/prospectpro-reuse.graph.json` (recorte do grafo real — regerar com `build-reuse-fixture.mjs`, nunca editar à mão) |
166
+ | `src/lib/validators/code-budget/**` | `validation-runner.js` (case + push universal fora do `light`), `framework/docs/CLI.md` (o que conta como teste e os limites 1,5×/40 linhas) e `test/integration/code-budget-verify.test.js`. Lê `addedLinesAgainst` (`default-branch.js`), `isTestFile` (`symbol-scanner.js`, a mesma régua de teste do `reuse`), `isProjectSource`/`isGenerated` (`hooks/shared/source-files.js`) e `commentLines`/`citesProcess` (`hooks/shared/comment-scanner.js`, sobre `stripComments` com `js`). Sempre `warning`. Não conseguir medir é skip `unavailable` com razão, e o `validation-runner` não põe validador pulado em `results`: pulado não conta como verde |
167
167
  | `framework/hooks/shared/comment-rules.js` / `comment-scanner.js` / `source-files.js` (o hook `comment-guard`) | Os dois leitores do MESMO comentário: o hook `comment-guard` (PostToolUse `Write\|Edit`, bloqueia na hora da edição) e o `code-budget` (avisa no `verify`). Moram em `hooks/shared` porque hook não importa `src/`; o `src/` importa daqui, nunca uma cópia. O hook julga só o comentário ADICIONADO (`tool_response.originalFile`, medido: `null` no Write que cria) e só FORMA — processo, banner/`#region`, bloco > 3 linhas, doc-comment fora de pacote publicado —, nunca "repete o código". É o ÚLTIMO elo da chain `Write\|Edit` (um block encerra a chain; canário em `test/hooks/hooks-installer.test.js`). Marcador que template precisa manter (`READS STANDARD(S):`, `VERIFY:`) entra em `ALLOWED`; o canário de template em `test/hooks/comment-rules.test.js` reprova template que dispararia o hook no scaffold |
168
168
  | o ciclo de reuso (`tasks[].reuse`) | `framework/schemas/tasks.schema.json` + `tasks-json-parser.js` (campo `reuse`, com `why` no CRIAR — o parser só checa tipo, para não travar a escrita de status de plano antigo), `morph-plan` §1c/§5b, template de dispatch de `morph-implement`/`morph-apply`, personas de `agents.json`, o validador `reuse` (`src/lib/validators/reuse/`) e `test/framework/graph-fallback.test.js` |
169
169
  | `framework/mcp/registry.json` | mcp-installer.js, claude-config-detector.js, agents-installer.js (personas' `mcp` field), `scripts/validate-framework.js` Check 8, `test/framework/mcp-registry.test.js` |
@@ -180,7 +180,7 @@ When modifying framework components, verify the full scope of related files.
180
180
  | `src/lib/tasks/test-nodes.js` | os DOIS leitores de `validateTestNodes` — `verify-runner.js` (fail-closed: nó inválido avermelha o gate) e `doctor.js` (`doctor --full`, camada 3 do contrato do spec §2.2: WARN, e **pula sem imprimir nada** sem `config.json` ou sem `project.tests`, senão quebra `test/commands/doctor.test.js:46`). Uma segunda noção de "nó válido" faz o mesmo config passar num lugar e falhar no outro. `morphConfigPath` deriva de `CONFIG_FILE_NAME` (`core/state/state-manager.js`), a mesma constante de `readMorphConfig` — o JSDoc promete "one spelling" e agora é literal. O campo `groups` (#87): `TASK_GROUPS` é o MESMO enum do `group` de `tasks.schema.json` e de `config.schema.json` (canário em `test/lib/tasks/test-nodes.test.js`), `RUNNER_DEFAULT_GROUPS` dá o default por runner e `effectiveGroups` é o que `test-scope.js` lê — `null` é nó sem grupo, nunca palpite. `discoverFrontendPackages` (a união do fallback de `resolveTestNodes` e o WARN do `doctor --full`) varre as pastas de `PACKAGE_LOCATIONS`, de `src/lib/detectors/index.js` — uma segunda lista de pastas é como dois detectores começam a discordar |
181
181
  | `src/lib/worktree/docker-audit.js` | `worktree-audit.js` (`auditWorktrees` concatena os achados e é quem PASSA as features conhecidas — um segundo scan aqui discordaria sobre o que é órfão), `doctor.js` (a classificação `info`/`warn` = não-falha em `doctorWorktreesCommand`; e `samePathCase`, a regra de caixa de path que o WARN de frontend do `doctor --full` e o `spelled` de `test-scope.js` reusam — uma segunda cópia dela foi removida), `env-allocator.js` (`allocatedFeatures` é read-only de propósito: `allocateEnvBlock` ESCREVE, e uma auditoria que aloca inventa o estado que reporta), `test/lib/worktree/docker-audit.test.js`. Nunca no `doctor --full` (D10): `test/commands/doctor.test.js:46` exige zero `✗` neste repo |
182
182
  | `src/lib/risk-detector.js` | os DOIS lados da mesma decisão de gate: `gate-check.js` (`collectSignals` COLETA do disco; nenhum sinal que descreva um FATO pode entrar em `OVERRIDABLE_SIGNAL_KEYS` — `gate`/`workType`/`e2e*` são o precedente), `src/commands/validation/verify.js` (o stamp `verification` é a ÚNICA coisa que o gate lê: campo novo aqui só vira sinal se o stamp o gravar), `framework/schemas/feature.schema.json` (`verification` é `additionalProperties: false`), `framework/MORPH.md` §5 (tabela de sinais — ela se declara fonte única) e `framework/docs/CLI.md`. Política escrita no coletor cria duas fontes para o mesmo fato — foi assim que `gate-check` e `approve` divergiram uma vez sobre o Gate 3. O veredito do avaliador é lido por UM leitor (`evaluatorReportState`, `src/lib/evaluator-report.js`) e decidido por UMA regra (`verdictPause`): `approve` exige `status: ok`, `gate-check` pausa em `FIX`, bloqueador aberto ou sem tipo. **`verificationScope` é sinal, não auditoria**: a dispensa de e2e (`project`/`scope`) só conta vinda de um stamp de escopo `feature` — um `verify {f} {task}` de task `group: docs` carimba a razão de dispensa e compraria o Gate 3 da feature inteira. **E o escopo de task pausa o ship por si só** (#87): no `review`, `verificationScope` string ≠ `'feature'` pausa ANTES do bloco de e2e, mesmo com todos os nós verdes — o recorte automático faz TODO `verify {f} {task}` rodar menos que a suíte; `null` (stamp legado) não pausa por esta regra. O par mora em `verify.js`: `--filter` de escopo de feature não persiste o stamp (`reason: 'filtered'`), nem `--skip-tests`/`--skip-build` (`'skip-tests'`/`'skip-build'`, #113 — nó pulado não reprova o rollup e nenhuma regra do gate lê `tests`/`build` pulados; a lista é `PARTIAL_RUN_FLAGS`) |
183
- | `src/lib/installers/effects.js` | os NOVE pontos de emissão que atravessam o caminho de `update`: `update.js` (clean, payloads, spawn de `generate-refs.js`, `gitIndex`), `skills-installer.js`, `agents-installer.js`, `setup-infra.js` (`installRulesForStack`, `updateClaudeMdAgentsBlock`), `hooks-installer.js` (`installClaudeHooks`, `installGlobalStatusline`), `file-copier.js` (`updateGitignore`, `ensureGitattributes`), `claude-md-injector.js`, `version-checker.js` (`saveProjectMorphVersion`) e `templates-reconcile.js`. **O caminho real também emite** — o resumo de uma execução real sai de `list()`, e é por isso que um ponto de emissão esquecido some das DUAS saídas ao mesmo tempo. Canários: `test/lib/installers/effects.test.js` (igualdade dry × real do MESMO roteiro) e `test/commands/update-dry-run.test.js` — que tem DOIS canários e precisa dos dois: **igualdade** prova que os dois lados percorrem o mesmo caminho, **diferencial** (mudar `--templates` muda a previsão) prova que o caminho lê a flag. Só igualdade aprova uma previsão e uma execução que ignoram a MESMA flag — foi medido nesta feature, por mutação. Um laço de limpeza de órfão novo tem de nascer calado em `fx.dryRun` (D6): o clean o subsome. E a lista de `frameworkDirsToClean` é pinada **à mão** no teste (`DIRETORIOS_APAGADOS_POR_INTEIRO`, dez caminhos, `deepEqual` ordenado): derivar a expectativa chamando a própria função deixou a suíte inteira cega — medido, dava para remover 2 das 10 entradas sem matar nenhum dos 207 arquivos de teste |
183
+ | `src/lib/installers/effects.js` | os NOVE pontos de emissão que atravessam o caminho de `update`: `update.js` (clean, payloads, spawn de `generate-refs.js`, `gitIndex`), `skills-installer.js`, `agents-installer.js`, `setup-infra.js` (`installRulesForStack`, `installCommandsForStack`, `updateClaudeMdAgentsBlock`), `hooks-installer.js` (`installClaudeHooks`, `installGlobalStatusline`), `file-copier.js` (`updateGitignore`, `ensureGitattributes`), `claude-md-injector.js`, `version-checker.js` (`saveProjectMorphVersion`) e `templates-reconcile.js`. **O caminho real também emite** — o resumo de uma execução real sai de `list()`, e é por isso que um ponto de emissão esquecido some das DUAS saídas ao mesmo tempo. Canários: `test/lib/installers/effects.test.js` (igualdade dry × real do MESMO roteiro) e `test/commands/update-dry-run.test.js` — que tem DOIS canários e precisa dos dois: **igualdade** prova que os dois lados percorrem o mesmo caminho, **diferencial** (mudar `--templates` muda a previsão) prova que o caminho lê a flag. Só igualdade aprova uma previsão e uma execução que ignoram a MESMA flag — foi medido nesta feature, por mutação. Um laço de limpeza de órfão novo tem de nascer calado em `fx.dryRun` (D6): o clean o subsome. E a lista de `frameworkDirsToClean` é pinada **à mão** no teste (`DIRETORIOS_APAGADOS_POR_INTEIRO`, dez caminhos, `deepEqual` ordenado): derivar a expectativa chamando a própria função deixou a suíte inteira cega — medido, dava para remover 2 das 10 entradas sem matar nenhum dos 207 arquivos de teste |
184
184
  | `src/lib/ai/**` (`doctor --ai`) | `src/commands/project/doctor.js` (`doctorAiCommand` + a guarda de uso indevido), `bin/morph-spec.js` (`--ai`), `framework/docs/CLI.md`. **`--ai` NUNCA entra no `doctor --full` nem no default** — o renderer do `--full` manda tudo que não é `ok`/`warn` para `✗` e `test/commands/doctor.test.js` exige zero `✗` neste repositório. **Nada alcançável por `--ai` pode escrever**: `test/commands/doctor-ai.test.js` varre o grafo de imports E o corpo de `doctorAiCommand` (com os imports dinâmicos fixados nos dois permitidos), reprovando `writeFileSync`/`spawn`/`fs-extra` em CÓDIGO — comentários apagados antes, porque os módulos EXPLICAM por escrito que não fazem isso e medir a menção seria medir uma cópia do objeto. `null` é DESCONHECIDO e vira `skip` **com razão obrigatória**; `[]` é "perguntei e não achei" e vira `ok` |
185
185
  | `src/lib/ai/registry-audit.js` | o leitor de PRODUÇÃO do mesmo documento: `framework/templates/dotnet/ai-kit/src/Morph.AiKit/Providers/ModelRegistry.cs` (`CommentHandling = Skip`, `AllowTrailingCommas`, `AllowedAliasProperties` com `pricing`/`pricingWaiver`) e o exemplar `model-registry.v2.json` que o framework manda COPIAR. A auditoria tem de enxergar a **mesma forma** que o leitor de produção enxerga: com `JSON.parse` estrito, duas das cinco checagens saíam `skip` sobre o exemplar canônico — e `skip` não muda exit code, então o silêncio era total. A tolerância a JSONC vive em `framework/hooks/shared/comment-stripper.js`, ÚNICA (o `code-audit.js` usa o mesmo varredor, e o `code-budget` também, o único com a opção `js` — template e regex literal de TS/JS; sem ela o varredor é o de antes) — e a paridade é nos DOIS sentidos: `jsoncToJson` **lança** no comentário de bloco não fechado, porque o `JsonCommentHandling.Skip` do .NET lança, e ser mais frouxo que o kit é aprovar documento que a app recusa carregar. Ao mascarar strings, **as aspas delimitadoras ficam**: apagá-las junto faz um elemento-string virar espaço puro e o detector de vírgula sobrando comer um SEPARADOR real (`{"tags":["a","b"]}` saía inválido). Canário obrigatório: array terminado em **string**, com e sem vírgula sobrando — uma suíte só com arrays de número passa dos dois lados dessa inversão. A **REGRA DURA** do exemplar — *todo alias declara `pricing` OU `pricingWaiver`, nunca os dois, nunca nenhum* — é do alias, não de um mapa no topo: ler só o mapa dava 6 falsos positivos sobre um documento correto. O canário **copia o exemplar do disco**, nunca uma paráfrase dele |
186
186
  | `src/lib/worktree/dirs.js` | ÚNICA fonte do nome do container (`worktrees/`, sem ponto — Jest esconde diretório com ponto e reporta 0 testes sem erro). `worktree.js` re-exporta; `graphifyignore.js`, `file-copier.js`, `architecture-scanner.js`, `test-runner.js`, `worktree-audit.js`, os scanners do dashboard (`features-scanner.js`, `project-api.js`), `tasks/linux-runner.js` (exclusões do `tar` do `--linux`) importam. `test/lib/worktree/dirs.test.js` cobra cada leitor |
package/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  > Spec-driven development framework for multi-stack projects. Turns feature requests into implementation-ready code through structured, AI-orchestrated phases.
4
4
 
5
5
  **Package:** `@polymorphism-tech/morph-spec`
6
- **Version:** 8.46.0
6
+ **Version:** 8.47.0
7
7
  **Requires:** Node.js 22+, Claude Code
8
8
 
9
9
  ---
@@ -379,4 +379,4 @@ Code generated by morph-spec (contracts, templates, implementation output) belon
379
379
 
380
380
  ---
381
381
 
382
- *morph-spec v8.46.0 by [Polymorphism Tech](https://polymorphism.tech)*
382
+ *morph-spec v8.47.0 by [Polymorphism Tech](https://polymorphism.tech)*
package/bin/morph-spec.js CHANGED
@@ -366,17 +366,15 @@ graphCommand
366
366
  // ─── Validation ───────────────────────────────────────────────────────────
367
367
  program
368
368
  .command('validate [validator]')
369
- .description('Run project validations (all | packages | architecture | contrast)')
369
+ .description('Run project validations (all | packages | next-components | spec-tasks)')
370
370
  .option('-v, --verbose', 'Show detailed output')
371
371
  .option('--auto-fix, --fix', 'Auto-fix issues where possible')
372
372
  .option('--no-fail', 'Don\'t exit with error code')
373
- .option('--wcag-aaa', 'Use WCAG AAA standard (stricter)')
374
373
  .action((validator, options) => {
375
374
  const args = validator ? [validator] : ['all'];
376
375
  if (options.verbose) args.push('--verbose');
377
376
  if (options.autoFix) args.push('--auto-fix');
378
377
  if (options.noFail) args.push('--no-fail');
379
- if (options.wcagAaa) args.push('--wcag-aaa');
380
378
  validateCommand(args);
381
379
  });
382
380
 
@@ -393,7 +391,6 @@ program
393
391
  .command('verify <feature> [task]')
394
392
  .description('Run the deterministic verification chain (build + tests + validators + e2e) — code before the LLM judge')
395
393
  .option('--json', 'Output as JSON')
396
- .option('--rubric <id>', 'Force a rubric (default: by task group → config → default)')
397
394
  .option('--timeout <ms>', 'Timeout in ms for the build AND tests nodes (build default 120000; tests default 120000 per test project, or project.testTimeoutMs)', (v) => parseInt(v, 10))
398
395
  .option('--filter <ids>', 'Run only the test nodes whose id matches (comma-separated; exact or substring). Unmatched nodes are reported as skip; matching nothing is a usage error (exit 2)')
399
396
  .option('--linux', 'Run the test nodes inside a Linux container, on a COPY of the tree (the host tree is mounted read-only and copied in — a bind mount is case-insensitive and cannot reproduce case defects). No Docker = usage error, never a skip')
package/bin/validate.js CHANGED
@@ -5,7 +5,7 @@
5
5
  *
6
6
  * Runs validators for the current project stack (detected from .morph/config/config.json).
7
7
  *
8
- * .NET/Blazor stacks: packages, architecture, contrast, spec-tasks
8
+ * .NET stacks: packages, spec-tasks
9
9
  * Next.js stack: next-components, spec-tasks
10
10
  * Other stacks: spec-tasks
11
11
  *
@@ -23,7 +23,7 @@ import { getStackProfile } from '../src/lib/stack/stack-profile.js';
23
23
 
24
24
  /**
25
25
  * Build the VALIDATORS registry for the current stack.
26
- * .NET stacks → packages, architecture, contrast, spec-tasks
26
+ * .NET stacks → packages, spec-tasks
27
27
  * nextjs stack → next-components, spec-tasks
28
28
  * other stacks → spec-tasks only
29
29
  */
@@ -35,24 +35,12 @@ async function buildValidators(stack) {
35
35
 
36
36
  if (isDotnet) {
37
37
  const { validatePackages } = await import('../src/lib/validators/packages/package-validator.js');
38
- const { validateArchitecture } = await import('../src/lib/validators/architecture/architecture-validator.js');
39
- const { validateContrast } = await import('../src/lib/validators/ui/ui-contrast-validator.js');
40
38
 
41
39
  validators.packages = {
42
40
  name: 'Package Compatibility',
43
41
  description: 'Validates NuGet package versions against .NET compatibility matrix',
44
42
  run: validatePackages
45
43
  };
46
- validators.architecture = {
47
- name: 'Architecture Patterns',
48
- description: 'Detects DI anti-patterns, middleware issues, and configuration problems in .NET',
49
- run: validateArchitecture
50
- };
51
- validators.contrast = {
52
- name: 'UI Contrast (WCAG)',
53
- description: 'Validates color contrast ratios for accessibility',
54
- run: validateContrast
55
- };
56
44
  }
57
45
 
58
46
  if (isNextjs) {
@@ -273,8 +261,7 @@ async function runValidator(VALIDATORS, name, options) {
273
261
  try {
274
262
  const result = await validator.run('.', {
275
263
  verbose: true, // Always verbose for single validator
276
- autoFix: options.autoFix,
277
- wcagLevel: options.wcagLevel
264
+ autoFix: options.autoFix
278
265
  });
279
266
 
280
267
  if (result.status === 'ok') {
@@ -302,8 +289,7 @@ function parseOptions(args) {
302
289
  const options = {
303
290
  verbose: false,
304
291
  autoFix: false,
305
- noFail: false,
306
- wcagLevel: 'AA'
292
+ noFail: false
307
293
  };
308
294
 
309
295
  for (const arg of args) {
@@ -313,8 +299,6 @@ function parseOptions(args) {
313
299
  options.autoFix = true;
314
300
  } else if (arg === '--no-fail') {
315
301
  options.noFail = true;
316
- } else if (arg === '--wcag-aaa') {
317
- options.wcagLevel = 'AAA';
318
302
  }
319
303
  }
320
304
 
@@ -334,20 +318,15 @@ ${chalk.bold('USAGE')}
334
318
  ${chalk.bold('VALIDATORS')}
335
319
  all Run all validators (default)
336
320
  packages Validate NuGet package compatibility (.NET 10)
337
- architecture Validate architecture patterns (DI, lifecycle)
338
- contrast Validate UI contrast ratios (WCAG 2.1)
339
321
 
340
322
  ${chalk.bold('OPTIONS')}
341
323
  --verbose, -v Show detailed output
342
324
  --auto-fix, --fix Auto-fix issues where possible
343
325
  --no-fail Don't exit with error code
344
- --wcag-aaa Use WCAG AAA standard (stricter)
345
326
 
346
327
  ${chalk.bold('EXAMPLES')}
347
328
  morph-spec validate # Run all validators
348
329
  morph-spec validate packages --fix # Validate packages and auto-fix
349
- morph-spec validate architecture -v # Verbose architecture validation
350
- morph-spec validate contrast --wcag-aaa # Stricter contrast validation
351
330
  morph-spec validate all # Run all validators
352
331
 
353
332
  ${chalk.bold('EXIT CODES')}
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "morph-spec",
3
- "version": "8.46.0",
3
+ "version": "8.47.0",
4
4
  "displayName": "MORPH-SPEC Framework",
5
5
  "description": "Spec-driven development with 38 agents and 8-phase workflow for .NET/Blazor/Next.js/Azure",
6
6
  "publisher": "polymorphism-tech",
@@ -94,7 +94,7 @@ Never hand-edit `gateDecisions`/`approvalGates` in `feature.json` — always go
94
94
  ## CLI — validation
95
95
 
96
96
  ```bash
97
- morph-spec validate [architecture|packages|contrast] [--wcag-aaa]
97
+ morph-spec validate [packages|next-components|spec-tasks]
98
98
  morph-spec validate-feature {feature} [--phase {phase}] [--json] # alias: vf
99
99
  morph-spec verify {feature} [task] [--json] [--skip-tests] [--skip-build] # deterministic build+test+validator chain, before the LLM judge
100
100
  ```
@@ -185,4 +185,4 @@ Never edited directly — go through CLI commands or `morph-spec update` instead
185
185
 
186
186
  ---
187
187
 
188
- *morph-spec v8.46.0 by Polymorphism Tech*
188
+ *morph-spec v8.47.0 by Polymorphism Tech*
@@ -249,4 +249,4 @@ morph-spec doctor
249
249
 
250
250
  ---
251
251
 
252
- *morph-spec v8.46.0 by Polymorphism Tech*
252
+ *morph-spec v8.47.0 by Polymorphism Tech*
@@ -32,7 +32,7 @@ Se não houver feature ativa, pergunte ao usuário qual feature trabalhar.
32
32
  - Fechar cada task só com `verify {f} {T}` verde e cada `doneCriteria` com a evidência que o prova; vermelho ou critério sem prova dispara o loop de correção autônomo, sem escalar ao humano entre tarefas. No Gate 3, o veredito (`SHIP`/`FIX`) vem do **avaliador independente** despachado pela `morph-review` — nunca de quem implementou.
33
33
  - Em `hotfix`, o Gate 3 pausa **sempre** para um humano, mesmo em `trust: auto` — `approve ... review --mode auto` é recusado; aprove com `--approver`.
34
34
  - Confirmar antes de `finish`/`archive`/`delete` se o SessionStart avisar que outra sessão tem claim vivo na mesma feature.
35
- - **Contrato do relatório final** em todo dispatch de sub-agent: (1) grava o relatório em arquivo canônico ANTES de encerrar — `.morph/features/{f}/3-implement/reports/{taskId}.md` (avaliador: `4-review/evaluator-report.md`) — com o quê / **Arquivos:** / **Critérios:** (cada doneCriteria com evidência) / problemas; é o retorno autoritativo, nunca chamar `SendMessage`; (2) não tocar `tasks.json`/`feature.json`/`state.json` nem o board de sessão; (3) testes pelo orçamento, só o próprio filtro uma vez, sem red→green (a prova é o `verify` do orquestrador); (8) nunca mutar produção. Racional completo: `MORPH.md` §6. Templates: `morph-implement` §4, `morph-apply` §3b. **O orquestrador lê o arquivo ao retomar controle** — nunca confia só na mensagem de retorno da tool.
35
+ - **Ao retomar o controle depois de um dispatch, o orquestrador lê o arquivo de relatório, não a mensagem final** — a mensagem pode não chegar ou vir resumida. As cláusulas do prompt vivem só nos templates (`morph-implement` §4, `morph-apply` §3b).
36
36
 
37
37
  ## Slash commands
38
38
 
@@ -21,7 +21,7 @@ Entre gates, você opera com autonomia total. O dev valida. Você executa.
21
21
  | Task implementada (código escrito) | `morph-spec verify <feature> <task>` e cada `doneCriteria` com a evidência que o prova |
22
22
  | Verify verde e critérios atendidos | Task `done`, próxima tarefa, sem anúncio |
23
23
  | Verify vermelho ou critério sem evidência | Loop de correção autônomo com o feedback, até 3 tentativas, sem pausa humana |
24
- | 3 tentativas sem fechar | Escalar ao usuário (aceitar/continuar/pular) — único ponto de pausa do loop |
24
+ | 3 tentativas sem fechar | `AskUserQuestion` (aceitar/continuar/pular) — único ponto de pausa do loop; nunca uma 4ª tentativa por conta própria nem re-dispatch: sem informação nova, repete o erro |
25
25
  | `verify` exit 3 (fila pesada cheia) | A fila já esperou: no máximo uma chamada nova, depois avise — nunca laço de espera |
26
26
 
27
27
  **Regra de ouro:** dúvida que não bloqueia → resolver e registrar; dúvida que bloqueia → uma pergunta, máximo. Vale **entre gates** (plan/implement/review) — **não** vale na abertura da feature: a fase proposal pode rodar em **modo entrevista** (escolhido na pergunta de abertura, `morph-brainstorming` Parte 2), onde perguntar até fechar o entendimento é o comportamento desejado.
@@ -64,7 +64,7 @@ O morph-spec opera com três papéis que você assume conforme o contexto:
64
64
 
65
65
  **Orchestrator** — ativo na abertura de uma feature e nas transições de fase. Lê o mandato, entende o escopo, propõe o plano de ataque, identifica dependências entre tarefas, garante que gates sejam respeitados antes de avançar. Anti-padrão: não escreve código — se percebe que começou a implementar, pare, você transitou de papel sem intenção.
66
66
 
67
- **Specialist** — ativo durante a implementação. Executa tarefas do tasks.json em ordem, consulta standards antes de cada uma, registra decisões/desvios no decisions.md, mantém o recap.md atualizado ao final de cada tarefa. Anti-padrão: não cria novas tarefas — descoberta de escopo vai para decisions.md com flag "escopo expandido", o Orchestrator avalia se o tasks.json precisa mudar.
67
+ **Specialist** — ativo durante a implementação. Executa tarefas do tasks.json em ordem, consulta standards antes de cada uma, registra decisões/desvios no decisions.md, mantém o recap.md atualizado ao final de cada tarefa. Anti-padrão: não cria novas tarefas — escopo descoberto: adição pequena → `notes` da task; erro de fato do spec → `## Errata` (§3); o escopo mudou → `morph-spec unapprove {f} plan` e re-aprovar, porque o contrato do Gate 2 é congelado.
68
68
 
69
69
  **Evaluator** — ativo no Gate 3, sempre um sub-agent independente com contexto fresco (`morph-evaluator`), nunca quem implementou (enforcement: relatório obrigatório, `--self-assessed`, exceção `hotfix` — **§5**). Segue `.morph/framework/evals/review-checklist.md`: veredito `SHIP`/`FIX` e bloqueador só com evidência (uc, teste, regressão, segurança); o resto é nota. Não roda a suíte (a prova é o verify do orquestrador) e não reescreve código.
70
70
 
@@ -188,11 +188,11 @@ Cada fase produz um trace JSON em `.morph/traces/YYYY-MM-DD-{feature}-{phase}.js
188
188
  **Fluxo de consulta:**
189
189
 
190
190
  1. Antes de iniciar uma tarefa, identifique 1-3 standards relevantes — rode `morph-spec standards --find "<domínio/tecnologia da task>"` (devolve o top 3 como `id · path · digest`) em vez de filtrar `id`/`tags` à mão no JSON.
191
- 2. Leia apenas o arquivo `.md` daquele standard (campo `path`).
191
+ 2. O `digest` (resumo de ~700 chars) costuma bastar; abra o `.md` (campo `path`) só quando não bastar — exemplo completo, seção que o resumo não cobre.
192
192
  3. Aplique durante a implementação. Se precisar de mais contexto, leia mais um standard.
193
193
  4. Registre no recap.md qual standard foi consultado e como foi aplicado.
194
194
 
195
- **Como identificar o standard certo:** filtre por `category` primeiro (ex: "architecture", "contracts", "testing"), depois por `tags` (ex: "dotnet", "nextjs", "blazor"). Dois standards relevantes em conflito → adote o mais específico ao stack do projeto e registre o conflito no decisions.md.
195
+ **Como identificar o standard certo:** filtre por `category` primeiro (ex: "architecture", "backend", "frontend", "ai-agents"), depois por `tags` (ex: "dotnet", "nextjs", "maf"). Dois standards relevantes em conflito → adote o mais específico ao stack do projeto e registre o conflito no decisions.md.
196
196
 
197
197
  O agente responsável por um domínio está em `.morph/framework/agents.json` (fonte única — os subagents `morph-{id}` são gerados dele). O campo `persona` define o ponto de vista e o nível de rigor a adotar ao aplicar os standards daquele domínio trabalhando inline (um agente de arquitetura é mais rígido que um de suporte mensal).
198
198
 
@@ -218,6 +218,7 @@ Gates são pontos de **pausa potencial**. Em `trust: "auto"` (default), auto-pas
218
218
  | `standardsViolations` | array.length > 0 | Plano ou código viola padrões proibidos |
219
219
  | `evaluatorVerdict` | ≠ SHIP, bloqueador, ou ausente | Veredito do `evaluator-report`: `FIX`, bloqueador aberto, bloqueador sem tipo, ou relatório sem `**Verdict:**`. Só no **ship** |
220
220
  | `verificationStatus` | === 'fail' | `verify` vermelho — build, testes, validadores **ou e2e**. Vale em **qualquer** gate |
221
+ | `verificationStatus` | ausente, no `review` | nenhum `verify` carimbado: ship sem prova; `approve` auto aplica a mesma régua |
221
222
  | `verificationStale` | true | Stamp do `verify` com sha != HEAD: o verde é de outro código. Só no **ship** |
222
223
  | `e2eSkipClass` (derivada) | environment/requested/unknown | e2e pulou sem dispensa legítima (só `project`/`scope`). Só no **ship** |
223
224
  | `verificationScope` | !== `feature` (presente) | Stamp do `verify` é de escopo parcial (`task:{id}`) — não cobre a feature inteira. Só no **ship** |
@@ -241,9 +242,9 @@ Modo: `.morph/config/config.json → trust` (`"auto"`, o default, ou `"manual"`)
241
242
 
242
243
  **Comportamento padrão fora de gate:** autonomia total — só pausa nestes três pontos. Ambiguidade de escopo fora do plano: registre em decisions.md, resolva conservadoramente, sinalize na entrega da task.
243
244
 
244
- **A aprovação de gate é unificada nos comandos da CLI — nunca edite o estado à mão.** Em `trust: "auto"` (sem `AskUserQuestion`): `morph-spec approve <feature> <gate> --mode auto`; `morph-spec advance <feature>` aprova o gate corrente **e** cria a pasta da próxima fase (`--design` = ramo opcional de uiux). **O hook state-sync.js** cobre o caminho manual: `AskUserQuestion` respondida com label "aprovado" → registra o gate no `feature.json` autoritativo com `approvedBy: "manual"`. **A feature é identificada pelo nome que a pergunta cita** — grava na árvore dona dela, nunca na "feature ativa" da sessão. Pergunta sem nome numa árvore com mais de uma feature: o hook **recusa gravar** e avisa — aprove por `morph-spec approve`.
245
+ **A aprovação de gate é unificada nos comandos da CLI — nunca edite o estado à mão.** Em `trust: "auto"` (sem `AskUserQuestion`): `morph-spec approve <feature> <gate> --mode auto`; `morph-spec advance <feature>` aprova o gate corrente **e** cria a pasta da próxima fase (`--design` = ramo opcional de uiux). **O hook state-sync.js** cobre o caminho manual: `AskUserQuestion` respondida com frase de aprovação (abaixo) → registra o gate no `feature.json` autoritativo com `approvedBy: "manual"`. **A feature é identificada pelo nome que a pergunta cita** — grava na árvore dona dela, nunca na "feature ativa" da sessão. Pergunta sem nome numa árvore com mais de uma feature: o hook **recusa gravar** e avisa — aprove por `morph-spec approve`.
245
246
 
246
- **Registre quem aprovou (`approvedBy`):** objeto `{ approved, timestamp, approvedBy }`. `"auto"` — política `trust: auto` sem decisão humana. `"manual"` — humano aprovou (via `AskUserQuestion` ou, em headless, texto iniciado em "aprovado"); em `trust: manual` todo gate é `"manual"` — nunca `"auto"` num gate humano.
247
+ **Registre quem aprovou (`approvedBy`):** objeto `{ approved, timestamp, approvedBy }`. `"auto"` — política `trust: auto` sem decisão humana. `"manual"` — humano aprovou — via `AskUserQuestion` ou, em headless, texto; o hook só reconhece resposta que começa com "aprovado" ou contém "pode avançar", "pode implementar" ou "pode prosseguir" (outra frase, ex. "lgtm", não grava: aprove por `morph-spec approve`); em `trust: manual` todo gate é `"manual"` — nunca `"auto"` num gate humano.
247
248
 
248
249
  **O hook gate-guard.js** confere, sem bloquear, se a ação num gate (pausar vs auto-aprovar) bateu com a decisão persistida. **Default:** `gate-check <feature> <gate> [--signals <json>] [--json]` decide via `shouldPauseGate`; `--signals` sobrescreve só o que o disco não expõe (`designSystemDivergence`, `standardsViolations`). **Escape manual** (sinal que `shouldPauseGate` não representa): `gate-decision <feature> <gate> --pause <bool> [--reason <txt>] [--signals <json>]`. Ambos gravam `gateDecisions[gate] = { pause, reason, signals, trust, decidedAt }` server-side (`.morph/framework/schemas/feature.schema.json`). **Nunca edite `gateDecisions` à mão** — colide com state-sync. Divergência → o guard avisa no contexto.
249
250
 
@@ -257,7 +258,6 @@ A thread principal é o **Orchestrator**. Trabalho pesado ou fora do domínio co
257
258
 
258
259
  - **Domínio diferente do contexto corrente** (ver `agents.json → domains`) — ex: backend agora, próxima task é frontend/UI/dados. Gatilho mais importante: cada domínio tem sua persona e standards, e o sub-agent escopado os carrega sem inchar seu contexto.
259
260
  - **Esforço L ou XL** (> 5 minutos).
260
- - Mais de 3 tentativas de correção falharam no mesmo problema.
261
261
  - Análise de arquivo com mais de 500 linhas.
262
262
  - Tarefa repetitiva com mais de 3 instâncias do mesmo padrão.
263
263
  - Risco de "contaminar" o contexto principal com detalhes de baixo nível irrelevantes.
@@ -314,7 +314,7 @@ aceito em silêncio. Segunda ausência sem trabalho entregue é falha real: esca
314
314
  - **Critérios:** cada `doneCriteria`, atendido (com o teste ou `arquivo:linha`) ou não (por quê)
315
315
  - Problemas encontrados e como foram resolvidos
316
316
 
317
- **Contrato do relatório final:** as oito cláusulas que todo prompt de dispatch inclui vivem nos DOIS templates — `morph-implement` §4 e `morph-apply` §3b — e não são repetidas aqui: duas cópias da mesma regra divergem, e quem manda é a que o sub-agent recebe. **4-8** (escopo, sobrevivência, processos, retorno, mutação) são idênticas **palavra por palavra**, e um canário as compara; **1-3** (relatório, estado, teste) dizem o mesmo na redação de cada template.
317
+ **Contrato do relatório final:** as oito cláusulas que todo prompt de dispatch de implementador inclui vivem nos DOIS templates — `morph-implement` §4 e `morph-apply` §3b — e não são repetidas aqui: duas cópias da mesma regra divergem, e quem manda é a que o sub-agent recebe. **4-8** (escopo, sobrevivência, processos, retorno, mutação) são idênticas **palavra por palavra**, e um canário as compara; **1-3** (relatório, estado, teste) dizem o mesmo na redação de cada template.
318
318
 
319
319
  **Teto de turnos:** `maxTurns` por persona no `agents.json` (sem o campo, 20; implementadores 120), anunciado ao sub-agent no corpo da persona. O corte é cego: a cláusula 5 manda `wip` por marco e, a ~70% do teto, relatório `PARCIAL` sem critério dado como atendido (`report-incomplete`): retome o agente, não carimbe DEGRADADO.
320
320
 
@@ -2,6 +2,8 @@
2
2
  description: Cria uma nova landing page ponta-a-ponta a partir do template MORPH Umbraco genérico: coleta decisões, scaffolda com new-lp, sobe e valida, customiza branding e módulos.
3
3
  argument-hint: [nome-do-projeto]
4
4
  allowed-tools: Read, Write, Edit, Bash, Glob, Grep, AskUserQuestion, Skill
5
+ stacks:
6
+ - umbraco
5
7
  ---
6
8
 
7
9
  # /create-umbraco-lp — Nova LP Umbraco
@@ -2,6 +2,8 @@
2
2
  description: Migra uma LP existente (React/Vite, Next.js estático ou HTML) para o template Umbraco-headless MORPH entregando a LP EXATAMENTE igual à origem (mesmo CSS, imagens, fontes e comportamento) + Umbraco — obtenção automática do template, lift-and-rewire verbatim de cada seção para módulo editável, conexão do formulário ao backend de leads e gate de paridade determinístico. Repo-agnóstica.
3
3
  argument-hint: <projeto>
4
4
  allowed-tools: Read, Write, Edit, Bash, Glob, Grep, Agent, AskUserQuestion, Skill
5
+ stacks:
6
+ - umbraco
5
7
  ---
6
8
 
7
9
  # /migrate-lp-to-umbraco — Migração de LP para Umbraco Headless
@@ -1,5 +1,5 @@
1
1
  ---
2
- description: Archive a completed MORPH-SPEC feature after Gate 3 approval
2
+ description: Archive a feature WITHOUT integrating — reserved for legacy features (no morph/{f} branch) and cleanup; the normal close is morph-spec finish
3
3
  argument-hint: <feature-name>
4
4
  allowed-tools: Read, Bash
5
5
  ---
@@ -22,7 +22,7 @@ Resolve uma queda ou bug crítico de produção com prioridade máxima em veloci
22
22
  4. **Fix cirúrgico:** implementa a mudança mínima que resolve o sintoma — sem refatoração, sem hardening fora de escopo.
23
23
  5. **Test loop:** `morph-spec verify {feature-name} {task} --json` focado no blast radius até verde; evidência real capturada no `recap.md`.
24
24
  6. **Gate 3 sempre humano:** `morph-spec gate-check {feature-name} review` (força a pausa via `workType: hotfix`, lido do disco) → `4-review/review-report.md` → `AskUserQuestion` sempre. **Nunca** `morph-spec approve {feature-name} review --mode auto` — o CLI recusa essa combinação num hotfix.
25
- 7. **Pós-gate:** `morph-spec verify {feature-name}` (suíte completa da feature) e sinaliza commit/archive — não arquiva automaticamente.
25
+ 7. **Pós-gate:** `morph-spec verify {feature-name}` (suíte completa da feature), depois `morph-spec finish {feature-name} --pr|--merge` — o encerramento único (arquiva, integra, desmonta). O usuário decide o modo, porque `finish` toca a default ou o remoto; `--pr` **não integra** (`awaiting: "merge"`), então o incidente só está resolvido depois do merge.
26
26
 
27
27
  ## Anti-padrões
28
28
 
@@ -1,215 +1,29 @@
1
1
  ---
2
- description: Manage Azure infrastructure with Bicep templates — provision, update, and monitor cloud resources
3
- argument-hint: [up|down|plan|status]
4
- allowed-tools: Read, Write, Edit, Bash, Glob, AskUserQuestion
2
+ description: Infra do projeto — Docker Compose local e deploy no Coolify (API via SSH), com política de custo
3
+ argument-hint: [compose|deploy|status]
4
+ allowed-tools: Read, Write, Edit, Bash, Glob, Grep, AskUserQuestion, Agent
5
5
  ---
6
6
 
7
- # /morph-infra - Infrastructure Management
7
+ # /morph-infra — Infraestrutura
8
8
 
9
- Manage Azure infrastructure using Bicep templates.
9
+ Antes de agir, leia os standards: `morph-spec standards --find infra` (deploy no Coolify e isolamento do compose local). Trabalho de infra vai para a persona `morph-infra-engineer` quando ela está instalada; sem ela, siga os standards direto.
10
10
 
11
- ## Usage
11
+ ## Local — Docker Compose
12
12
 
13
- ```
14
- /morph-infra [action] [options]
15
- ```
13
+ Cada worktree sobe o próprio stack: portas do bloco do worktree (`${VAR:-default}`), nunca `container_name`, healthcheck em todo serviço. Subir e provar: `morph-spec e2e up {feature}` e o nó e2e do `morph-spec verify {feature}`.
16
14
 
17
- ### Actions
15
+ ## Deploy — Coolify
18
16
 
19
- | Action | Description |
20
- |--------|-------------|
21
- | `init` | Initialize IaC structure in the project |
22
- | `validate` | Validate Bicep templates |
23
- | `plan` | Show what-if of changes |
24
- | `deploy` | Execute resource deployment |
25
- | `destroy` | Remove all resources |
17
+ Não existe MCP nem CLI do Coolify: o acesso é por SSH ao servidor (alias configurado pelo usuário) e `curl` na API em `localhost`, com o token lido do lado do servidor e nunca impresso. Variáveis de ambiente ficam no Coolify, nunca no Dockerfile. Repositório e PRs pelo `gh`.
26
18
 
27
- ---
28
-
29
- ## Workflow
30
-
31
- ### 1. INIT - Initialize IaC
32
-
33
- When the user requests `/morph-infra init`:
34
-
35
- 1. Create the `infra/` structure in the project:
36
- ```
37
- infra/
38
- ├── main.bicep
39
- ├── parameters.dev.json
40
- ├── parameters.prod.json
41
- └── modules/
42
- ├── container-app.bicep
43
- ├── container-app-env.bicep
44
- ├── sql-database.bicep
45
- ├── storage.bicep
46
- ├── key-vault.bicep
47
- └── app-insights.bicep
48
- ```
49
-
50
- 2. Copy templates from `.morph/framework/templates/infrastructure/...`
51
-
52
- 3. Replace placeholders:
53
- - `{{APP_NAME}}` → project name
54
- - `{{SUBSCRIPTION_ID}}` → request from user
55
- - `{{RESOURCE_GROUP}}` → suggest default `rg-{app}-{env}`
56
-
57
- 4. Document the created structure in `decisions.md`
58
-
59
- ---
60
-
61
- ### 2. VALIDATE - Validate Templates
62
-
63
- When the user requests `/morph-infra validate`:
64
-
65
- 1. Run Bicep validation:
66
- ```bash
67
- az bicep build --file infra/main.bicep
68
- ```
69
-
70
- 2. Check required parameters
71
-
72
- 3. Report errors or success
73
-
74
- ---
75
-
76
- ### 3. PLAN - Preview Changes
77
-
78
- When the user requests `/morph-infra plan [env]`:
79
-
80
- 1. Check if Azure CLI is authenticated:
81
- ```bash
82
- az account show
83
- ```
84
-
85
- 2. Run what-if:
86
- ```bash
87
- az deployment group what-if \
88
- --resource-group rg-{app}-{env} \
89
- --template-file infra/main.bicep \
90
- --parameters @infra/parameters.{env}.json
91
- ```
92
-
93
- 3. Present change summary:
94
- - Resources to create
95
- - Resources to modify
96
- - Resources to delete
97
- - Estimated costs
98
-
99
- 4. **STOP and wait for approval** before deploy
100
-
101
- ---
102
-
103
- ### 4. DEPLOY - Execute Deploy
104
-
105
- When the user requests `/morph-infra deploy [env]`:
106
-
107
- 1. Verify plan was approved
108
-
109
- 2. Create resource group if it doesn't exist:
110
- ```bash
111
- az group create --name rg-{app}-{env} --location brazilsouth
112
- ```
113
-
114
- 3. Execute deploy:
115
- ```bash
116
- az deployment group create \
117
- --resource-group rg-{app}-{env} \
118
- --template-file infra/main.bicep \
119
- --parameters @infra/parameters.{env}.json
120
- ```
19
+ ## Custo
121
20
 
122
- 4. Capture outputs:
123
- - Container App URL
124
- - SQL Connection String
125
- - Key Vault URI
21
+ | Custo mensal | Ação |
22
+ |---|---|
23
+ | grátis | segue |
24
+ | até US$ 10 | confirme com o usuário |
25
+ | acima de US$ 10 | ADR em `decisions.md` antes de criar |
126
26
 
127
- 5. Update documentation with deploy information
128
-
129
- ---
130
-
131
- ### 5. DESTROY - Remove Resources
132
-
133
- When the user requests `/morph-infra destroy [env]`:
134
-
135
- 1. **WARN** that this action is irreversible
136
-
137
- 2. List resources that will be deleted
138
-
139
- 3. **STOP and wait for explicit confirmation** ("yes, delete")
140
-
141
- 4. Execute:
142
- ```bash
143
- az group delete --name rg-{app}-{env} --yes --no-wait
144
- ```
145
-
146
- ---
147
-
148
- ## Security Rules
149
-
150
- ### NEVER:
151
- - Expose secrets in logs
152
- - Commit files with secrets
153
- - Delete production resources without explicit confirmation
154
- - Create resources outside Bicep (zero portal)
155
-
156
- ### ALWAYS:
157
- - Use Key Vault for secrets
158
- - Validate Bicep before deploy
159
- - Run what-if before deploy
160
- - Document estimated costs
161
- - Keep parameters.json separated by environment
162
-
163
- ---
164
-
165
- ## Cost Guardian Integration
166
-
167
- Before any deploy, check with Cost Guardian:
168
-
169
- 1. Estimate monthly resource costs
170
- 2. Verify it's within approved limits:
171
- - Free tier: no approval needed
172
- - Up to $10/month: requires confirmation
173
- - Above $10: requires ADR
174
-
175
- ---
176
-
177
- ## Usage Example
178
-
179
- ```
180
- User: /morph-infra init
181
- Claude: Creating IaC structure...
182
- - infra/main.bicep
183
- - infra/parameters.dev.json
184
- - infra/modules/*.bicep
185
- Done! Run /morph-infra validate to verify.
186
-
187
- User: /morph-infra plan dev
188
- Claude: Analyzing changes for dev environment...
189
-
190
- CREATE:
191
- + Container App Environment
192
- + Container App
193
- + SQL Server (Free)
194
- + Storage Account (LRS)
195
- + Key Vault
196
- + Application Insights
197
-
198
- ESTIMATED COST: ~$0/month (Free tier)
199
-
200
- Approve deploy? (yes/no)
201
-
202
- User: yes
203
- Claude: Executing deploy...
204
- ✓ Resource Group created
205
- ✓ Deploy completed in 3m 45s
206
-
207
- OUTPUTS:
208
- - URL: https://myapp-dev.azurecontainerapps.io
209
- - SQL: tcp:myapp-dev-sql.database.windows.net
210
- - Key Vault: https://myapp-dev-kv.vault.azure.net
211
- ```
212
-
213
- ---
27
+ Nunca apague recurso de produção sem confirmação explícita.
214
28
 
215
- *MORPH-SPEC by Polymorphism Tech*
29
+ **Input:** $ARGUMENTS
@@ -2,6 +2,9 @@
2
2
  description: Conduz a autoria de mídia gerada por IA — escolher o modelo pelo trabalho, montar o prompt como spec versionada, encadear a partir de um herói aprovado, subir a escada de custo e conduzir o gate humano de escolha entre N candidatas.
3
3
  argument-hint: [o que gerar]
4
4
  allowed-tools: Read, Write, Edit, Bash, Glob, Grep, AskUserQuestion, Skill
5
+ stacks:
6
+ - dotnet
7
+ - nextjs
5
8
  ---
6
9
 
7
10
  # /morph-media — Autoria de mídia gerada