@polymorphism-tech/morph-spec 8.43.0 → 8.45.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 (203) hide show
  1. package/CLAUDE.md +16 -13
  2. package/README.md +10 -10
  3. package/bin/morph-spec.js +10 -13
  4. package/bin/validate.js +379 -379
  5. package/claude-plugin.json +1 -1
  6. package/docs/CHEATSHEET.md +2 -4
  7. package/docs/QUICKSTART.md +6 -6
  8. package/framework/CLAUDE.md +6 -8
  9. package/framework/MORPH.md +39 -45
  10. package/framework/agents.json +8 -9
  11. package/framework/commands/morph-apply.md +1 -3
  12. package/framework/commands/morph-hotfix.md +1 -1
  13. package/framework/commands/morph-proposal.md +2 -2
  14. package/framework/docs/CLI.md +22 -17
  15. package/framework/evals/review-checklist.md +90 -0
  16. package/framework/evals/trace-schema.md +2 -12
  17. package/framework/hooks/README.md +2 -3
  18. package/framework/hooks/claude-code/core/heavy-gate.js +1 -1
  19. package/framework/hooks/claude-code/core/protect-spec-files.js +2 -2
  20. package/framework/hooks/claude-code/core/telemetry-log.js +2 -2
  21. package/framework/hooks/claude-code/core/trace-autogen.js +1 -22
  22. package/framework/hooks/claude-code/core/validate-completion.js +3 -56
  23. package/framework/hooks/claude-code/core/worktree-env-inject.js +1 -4
  24. package/framework/hooks/claude-code/statusline.sh +11 -11
  25. package/framework/hooks/git/commit-msg/conventional-commits.sh +33 -33
  26. package/framework/hooks/git/pre-commit/agents.sh +25 -25
  27. package/framework/hooks/git/pre-commit/orchestrator.sh +64 -64
  28. package/framework/hooks/git/pre-commit/specs.sh +50 -50
  29. package/framework/hooks/git/pre-push/run-tests.sh +44 -44
  30. package/framework/hooks/shared/build-check.js +1 -1
  31. package/framework/hooks/shared/comment-scanner.js +1 -1
  32. package/framework/hooks/shared/phase-utils.js +0 -5
  33. package/framework/hooks/shared/stdin-reader.js +26 -26
  34. package/framework/phases.json +4 -6
  35. package/framework/rubrics/backend.json +1 -1
  36. package/framework/rubrics/default.json +1 -1
  37. package/framework/rubrics/frontend.json +1 -1
  38. package/framework/rules/ai-agents-standards.md +1 -0
  39. package/framework/rules/morph-workflow.md +6 -6
  40. package/framework/schemas/feature.schema.json +2 -28
  41. package/framework/schemas/tasks.schema.json +6 -2
  42. package/framework/skills/README.md +1 -2
  43. package/framework/skills/core/create-umbraco-lp/SKILL.md +1 -1
  44. package/framework/skills/core/migrate-lp-to-umbraco/SKILL.md +1 -1
  45. package/framework/skills/core/morph-apply/SKILL.md +145 -246
  46. package/framework/skills/core/morph-brainstorming/SKILL.md +1 -1
  47. package/framework/skills/core/morph-hotfix/SKILL.md +5 -3
  48. package/framework/skills/core/morph-implement/SKILL.md +101 -201
  49. package/framework/skills/core/morph-machine/SKILL.md +3 -3
  50. package/framework/skills/core/morph-media/SKILL.md +1 -1
  51. package/framework/skills/core/morph-plan/SKILL.md +171 -287
  52. package/framework/skills/core/morph-proposal/SKILL.md +4 -5
  53. package/framework/skills/core/morph-review/SKILL.md +109 -430
  54. package/framework/skills/core/morph-stack-scan/SKILL.md +1 -1
  55. package/framework/skills/core/morph-standards/SKILL.md +2 -2
  56. package/framework/skills/core/morph-uiux/SKILL.md +2 -3
  57. package/framework/standards/STANDARDS.json +54 -10
  58. package/framework/standards/ai-agents/agent-archetypes.md +1 -1
  59. package/framework/standards/ai-agents/agent-session.md +1 -1
  60. package/framework/standards/ai-agents/agent-spec.md +1 -1
  61. package/framework/standards/ai-agents/batching.md +1 -1
  62. package/framework/standards/ai-agents/context-providers.md +1 -1
  63. package/framework/standards/ai-agents/conversational-agent-with-phases.md +1 -1
  64. package/framework/standards/ai-agents/cost-and-budget.md +1 -1
  65. package/framework/standards/ai-agents/durable-workflows-hitl.md +1 -1
  66. package/framework/standards/ai-agents/guardrails.md +1 -1
  67. package/framework/standards/ai-agents/llm-runtime-defaults.md +1 -1
  68. package/framework/standards/ai-agents/mcp-server.md +1 -1
  69. package/framework/standards/ai-agents/mcp-tools.md +1 -1
  70. package/framework/standards/ai-agents/media-pipeline.md +1 -1
  71. package/framework/standards/ai-agents/media-video.md +1 -1
  72. package/framework/standards/ai-agents/middleware-patterns.md +1 -1
  73. package/framework/standards/ai-agents/modalities-image-gen.md +1 -1
  74. package/framework/standards/ai-agents/modalities-speech-to-text.md +1 -1
  75. package/framework/standards/ai-agents/modalities-text-to-speech.md +1 -1
  76. package/framework/standards/ai-agents/modalities-vision.md +1 -1
  77. package/framework/standards/ai-agents/multi-agent-patterns.md +1 -1
  78. package/framework/standards/ai-agents/observability-patterns.md +3 -3
  79. package/framework/standards/ai-agents/production.md +2 -2
  80. package/framework/standards/ai-agents/prompt-sources.md +1 -1
  81. package/framework/standards/ai-agents/providers/model-registry.md +1 -1
  82. package/framework/standards/ai-agents/rag-custom-pgvector.md +1 -1
  83. package/framework/standards/ai-agents/service-tier-flex.md +1 -1
  84. package/framework/standards/ai-agents/setup.md +1 -1
  85. package/framework/standards/ai-agents/structured-output.md +1 -1
  86. package/framework/standards/ai-agents/sweet-spot.md +1 -1
  87. package/framework/standards/ai-agents/testing-ai.md +1 -1
  88. package/framework/standards/ai-agents/tool-adapters.md +226 -0
  89. package/framework/standards/ai-agents/vector-data-extensions.md +1 -1
  90. package/framework/standards/ai-agents/workflows.md +1 -1
  91. package/framework/standards/infrastructure/docker/local-compose-isolation.md +11 -1
  92. package/framework/templates/CLAUDE.md.core.template +1 -1
  93. package/framework/templates/IDE-SNIPPETS.md +262 -262
  94. package/framework/templates/README.md +1 -1
  95. package/framework/templates/REGISTRY.json +0 -81
  96. package/framework/templates/code/dotnet/abstractions/api-endpoint.cs +7 -7
  97. package/framework/templates/code/dotnet/feature/endpoint.cs.hbs +21 -21
  98. package/framework/templates/code/dotnet/feature/request.cs.hbs +4 -4
  99. package/framework/templates/code/dotnet/feature/response.cs.hbs +4 -4
  100. package/framework/templates/code/sql/ai-agents/pgvector-embeddings-migration.sql.template +91 -91
  101. package/framework/templates/docs/spec.md +19 -205
  102. package/framework/templates/docs/ui-components.md +52 -52
  103. package/framework/templates/docs/ui-design-system.md +76 -76
  104. package/framework/templates/docs/ui-flows.md +167 -167
  105. package/framework/templates/frontend/nextjs/client-component.tsx.hbs +26 -26
  106. package/framework/templates/frontend/nextjs/feature-form.tsx.hbs +56 -56
  107. package/framework/templates/frontend/nextjs/tsconfig.json.hbs +26 -26
  108. package/framework/templates/infrastructure/docker/Dockerfile.template +58 -58
  109. package/framework/templates/infrastructure/docker/dockerfile-api.dockerfile +38 -38
  110. package/framework/templates/infrastructure/docker/dockerfile-web.dockerfile +48 -48
  111. package/framework/templates/infrastructure/github/README.md +56 -56
  112. package/framework/templates/infrastructure/github/actions/docker-build-push/action.yml.hbs +45 -45
  113. package/framework/templates/infrastructure/github/actions/health-check/action.yml.hbs +27 -27
  114. package/framework/templates/infrastructure/github/workflows/docker-build-push.yml.hbs +59 -59
  115. package/framework/templates/infrastructure/github/workflows/dotnet-build.yml.hbs +39 -39
  116. package/framework/templates/meta-prompts/fusion/fusion-agent.md +76 -76
  117. package/framework/templates/meta-prompts/fusion/fusion-aggregator.md +100 -100
  118. package/framework/templates/meta-prompts/validators/pre-commit-validator.md +95 -95
  119. package/framework/templates/state.template.json +17 -17
  120. package/framework/templates/ui/design-system.css +226 -226
  121. package/package.json +2 -2
  122. package/src/commands/e2e/e2e.js +1 -1
  123. package/src/commands/project/heavy.js +1 -1
  124. package/src/commands/project/status.js +3 -3
  125. package/src/commands/project/worktree.js +34 -16
  126. package/src/commands/state/approve.js +9 -50
  127. package/src/commands/state/finish.js +4 -0
  128. package/src/commands/state/gate-check.js +18 -107
  129. package/src/commands/state/gate-decision.js +1 -1
  130. package/src/commands/state/report-check.js +42 -17
  131. package/src/commands/validation/mutate.js +1 -1
  132. package/src/commands/validation/scout-check.js +28 -0
  133. package/src/commands/validation/validate-feature.js +5 -32
  134. package/src/commands/validation/verify.js +16 -25
  135. package/src/core/paths/output-schema.js +0 -2
  136. package/src/core/state/state-manager.js +1 -2
  137. package/src/core/templates/template-renderer.js +477 -477
  138. package/src/dashboard/app/lib/format.js +5 -0
  139. package/src/dashboard/app/main.jsx +13 -13
  140. package/src/dashboard/app/pages/FeatureDetail.jsx +16 -22
  141. package/src/dashboard/app/pages/Features.jsx +7 -7
  142. package/src/dashboard/app/pages/PhasePipeline.jsx +1 -1
  143. package/src/dashboard/app/pages/Rubrics.jsx +7 -11
  144. package/src/dashboard/scanner/docs-scanner.js +1 -2
  145. package/src/dashboard/scanner/features-scanner.js +3 -4
  146. package/src/dashboard/scanner/rubrics-scanner.js +12 -12
  147. package/src/dashboard/vite.config.js +24 -24
  148. package/src/lib/agents/output-collector.js +0 -1
  149. package/src/lib/detectors/design-system-detector.js +188 -188
  150. package/src/lib/e2e/compose-env.js +5 -2
  151. package/src/lib/evaluator-report.js +52 -334
  152. package/src/lib/generators/design-system-generator.js +508 -508
  153. package/src/lib/generators/handoff-generator.js +4 -5
  154. package/src/lib/git/evidence-staleness.js +39 -0
  155. package/src/lib/installers/memory-installer.js +2 -2
  156. package/src/lib/mutation/manifest.js +8 -2
  157. package/src/lib/mutation/report.js +5 -3
  158. package/src/lib/mutation/runner.js +9 -7
  159. package/src/lib/risk-detector.js +63 -125
  160. package/src/lib/scout/scout-check.js +293 -0
  161. package/src/lib/tasks/eval-node.js +4 -34
  162. package/src/lib/tasks/task-classifier.js +30 -30
  163. package/src/lib/tasks/task-parser.js +209 -209
  164. package/src/lib/tasks/tasks-json-parser.js +7 -5
  165. package/src/lib/tasks/test-nodes.js +1 -1
  166. package/src/lib/tasks/test-runner.js +1 -1
  167. package/src/lib/validators/contracts/contract-compliance-validator.js +4 -42
  168. package/src/lib/validators/css/css-validator.js +340 -340
  169. package/src/lib/validators/reuse/reuse-validator.js +6 -8
  170. package/src/lib/validators/verify-runner.js +1 -1
  171. package/src/lib/worktree/env-allocator.js +35 -5
  172. package/src/scripts/setup-infra.js +1 -1
  173. package/src/utils/agent-id-mapper.js +11 -11
  174. package/src/utils/agents-installer.js +5 -9
  175. package/src/utils/claude-settings-manager.js +300 -300
  176. package/src/utils/hooks-installer.js +3 -10
  177. package/src/utils/skills-installer.js +1 -1
  178. package/framework/evals/proof-rubrics/README.md +0 -76
  179. package/framework/evals/proof-rubrics/eval-de-modelo.md +0 -80
  180. package/framework/evals/proof-rubrics/fiacao.md +0 -54
  181. package/framework/evals/proof-rubrics/guard-cego.md +0 -52
  182. package/framework/evals/proof-rubrics/media-claims.md +0 -109
  183. package/framework/evals/proof-rubrics/mutation-proof.md +0 -107
  184. package/framework/evals/proof-rubrics/observabilidade-genai.md +0 -119
  185. package/framework/evals/proof-rubrics/verde-nao-e-coberto.md +0 -48
  186. package/framework/evals/rubrics/README.md +0 -45
  187. package/framework/evals/rubrics/architecture.md +0 -103
  188. package/framework/evals/rubrics/code-quality.md +0 -98
  189. package/framework/evals/rubrics/condensed.md +0 -57
  190. package/framework/evals/rubrics/contracts.md +0 -67
  191. package/framework/evals/rubrics/test-coverage.md +0 -99
  192. package/framework/evals/scenarios/dotnet-crud.yaml +0 -42
  193. package/framework/evals/scenarios/nextjs-auth.yaml +0 -38
  194. package/framework/evals/suites/standard.yaml +0 -5
  195. package/framework/hooks/claude-code/core/post-edit-typecheck.js +0 -127
  196. package/framework/skills/core/morph-eval/SKILL.md +0 -64
  197. package/framework/templates/.idea/morph-templates.xml +0 -92
  198. package/framework/templates/.vscode/morph-templates.code-snippets +0 -186
  199. package/framework/templates/docs/clarifications.md +0 -253
  200. package/framework/templates/docs/onboarding.md +0 -122
  201. package/framework/templates/docs/schema-analysis.md +0 -119
  202. package/framework/templates/docs/user-stories.md +0 -34
  203. package/src/commands/state/score.js +0 -147
@@ -3,8 +3,8 @@
3
3
  *
4
4
  * A terceira camada do ciclo de reuso, no molde do `design-system-validator`:
5
5
  *
6
- * PROSA (morph-plan §1c, personas) ──► ARTEFATO (2-plan/reuse-map.md,
7
- * `reuse` em tasks.json) ──► COBRANÇA (este arquivo)
6
+ * PROSA (morph-plan, personas) ──► ARTEFATO (`reuse` em tasks.json)
7
+ * ──► COBRANÇA (este arquivo)
8
8
  *
9
9
  * Prosa sozinha não segura — `morph-brainstorming/SKILL.md:39` já manda olhar
10
10
  * o que existe, e o ProspectPRO redefiniu `SimpleBuilding` em cinco arquivos da
@@ -21,8 +21,8 @@
21
21
  * 3. Mesma feature = achado (`error`); feature diferente = aviso
22
22
  * (`warning`), porque VSA prescreve DTO homônimo entre slices.
23
23
  * 4. Veredito `CRIAR` declarado no plano (tasks.json `reuse`) rebaixa o
24
- * achado a aviso: a decisão foi tomada no Gate 2, com justificativa no
25
- * reuse-map. O validador cobra a decisão AUSENTE, não a decisão tomada.
24
+ * achado a aviso: a decisão foi tomada no Gate 2, com justificativa em
25
+ * `why`. O validador cobra a decisão AUSENTE, não a decisão tomada.
26
26
  *
27
27
  * Sem grafo o validador não roda (ADR-002: ausência de grafo nunca bloqueia).
28
28
  *
@@ -155,7 +155,7 @@ export function findDuplicateSymbols(declarations, existing, opts = {}) {
155
155
  ? `Reuse ou estenda o tipo existente em vez de redeclarar. Confirme com ` +
156
156
  `\`morph-spec graph explain ${decls[0].name}\` (sem grafo: ` +
157
157
  `\`grep -rn "${decls[0].name}"\`) e, se a criação for mesmo necessária, ` +
158
- `registre o veredito CRIAR com justificativa no reuse-map da feature.`
158
+ 'registre o veredito CRIAR com a justificativa em "why" no tasks[].reuse da task.'
159
159
  : `VSA tolera DTO homônimo entre slices — confirme que são conceitos ` +
160
160
  `diferentes e não a mesma coisa escrita duas vezes.`,
161
161
  });
@@ -170,9 +170,7 @@ export function findDuplicateSymbols(declarations, existing, opts = {}) {
170
170
  /**
171
171
  * Vereditos de reuso carimbados no plano: `tasks[].reuse[]`.
172
172
  *
173
- * Ler do `tasks.json` — e não do `reuse-map.md` — é deliberado: o veredito é
174
- * um dado estruturado, e o markdown existe para o humano ler no Gate 2. Duas
175
- * leituras do mesmo fato, cada uma na forma certa para o seu consumidor.
173
+ * O veredito mora só no `tasks.json`: dado estruturado, lido aqui e no Gate 2.
176
174
  *
177
175
  * @param {string} projectPath
178
176
  * @param {string} featureName
@@ -4,7 +4,7 @@
4
4
  * v8 adds a DETERMINISTIC verification node that runs BEFORE the LLM judge
5
5
  * in the per-task loop: build + tests + validators (code, free) first; the
6
6
  * LLM judge is only invoked once verify passes. This is a BINARY gate
7
- * (pass/fail per node), NOT a second "bar 9" — the bar 9 remains morph-eval's.
7
+ * (pass/fail per node).
8
8
  *
9
9
  * The `e2e` node closes the last gap in that chain: build proves the code
10
10
  * COMPILES, tests prove units behave, validators read structure — none of
@@ -168,10 +168,10 @@ export const PORT_OFFSETS = Object.freeze({ web: 0, api: 1, postgres: 2, redis:
168
168
  * not in the root's. Every value is a string (env-safe); key order is stable.
169
169
  *
170
170
  * @param {{ base: number, range: [number, number] }} block
171
- * @param {{ stack?: string, feature?: string }} [opts]
171
+ * @param {{ stack?: string, feature?: string, aliases?: Record<string, string> }} [opts] - aliases: resolvePortAliases()
172
172
  * @returns {Record<string,string>}
173
173
  */
174
- export function portLayout(block, { stack = '', feature = '' } = {}) {
174
+ export function portLayout(block, { stack = '', feature = '', aliases = {} } = {}) {
175
175
  const env = {};
176
176
  if (feature) env.COMPOSE_PROJECT_NAME = composeProjectName(feature);
177
177
  env.MORPH_PORT_BASE = String(block.base);
@@ -183,9 +183,39 @@ export function portLayout(block, { stack = '', feature = '' } = {}) {
183
183
  if (/\bdotnet\b/i.test(String(stack))) {
184
184
  env.ASPNETCORE_URLS = `http://localhost:${block.base + PORT_OFFSETS.api}`;
185
185
  }
186
+ for (const [alias, port] of Object.entries(aliases)) env[alias] = String(block.base + PORT_OFFSETS[port]);
186
187
  return env;
187
188
  }
188
189
 
190
+ const ENV_NAME = /^[A-Za-z_][A-Za-z0-9_]*$/;
191
+ const RESERVED_ENV_NAMES = new Set([
192
+ ...Object.keys(portLayout({ base: 0, range: [0, 0] }, { stack: 'dotnet', feature: 'x' })),
193
+ 'PLAYWRIGHT_BASE_URL',
194
+ 'MORPH_FEATURE',
195
+ ]);
196
+
197
+ // e2e.portEnvNames: extra env names for the same four ports, so a compose file reading
198
+ // ${PG_PORT} is fed by the block, not by its own default. An entry that cannot be
199
+ // honoured is dropped and named in `problems`.
200
+ export function resolvePortAliases(config) {
201
+ const declared = config?.e2e?.portEnvNames;
202
+ const aliases = {};
203
+ const problems = [];
204
+ if (declared === undefined || declared === null) return { aliases, problems };
205
+ if (typeof declared !== 'object' || Array.isArray(declared)) {
206
+ return { aliases, problems: [`e2e.portEnvNames deve ser um objeto { ${Object.keys(PORT_OFFSETS).join('|')}: "NOME" }`] };
207
+ }
208
+ for (const [port, name] of Object.entries(declared)) {
209
+ const at = `e2e.portEnvNames.${port}`;
210
+ if (!Object.hasOwn(PORT_OFFSETS, port)) problems.push(`${at}: porta desconhecida (use ${Object.keys(PORT_OFFSETS).join('|')})`);
211
+ else if (typeof name !== 'string' || !ENV_NAME.test(name)) problems.push(`${at}: ${JSON.stringify(name)} não é um nome de variável de ambiente válido`);
212
+ else if (RESERVED_ENV_NAMES.has(name)) problems.push(`${at}: "${name}" já é uma variável do layout`);
213
+ else if (Object.hasOwn(aliases, name)) problems.push(`${at}: "${name}" já é o alias de ${aliases[name]}`);
214
+ else aliases[name] = port;
215
+ }
216
+ return { aliases, problems };
217
+ }
218
+
189
219
  /**
190
220
  * Render the `.morph/worktree.env` contents for a block: a header, the
191
221
  * feature, and exactly the `portLayout()` pairs — nothing else, so the file
@@ -199,15 +229,15 @@ export function portLayout(block, { stack = '', feature = '' } = {}) {
199
229
  * @param {string} feature - the env-registry key: `<feature>` or `task/<name>`
200
230
  * @param {{ base: number, range: [number, number] }} block
201
231
  * @param {string} [stack] - config.json `project.stack` (e.g. "nextjs+dotnet")
202
- * @param {{ morphFeature?: string|null }} [opts]
232
+ * @param {{ morphFeature?: string|null, aliases?: Record<string, string> }} [opts]
203
233
  * @returns {string}
204
234
  */
205
- export function buildEnvFileContent(feature, block, stack = '', { morphFeature = null } = {}) {
235
+ export function buildEnvFileContent(feature, block, stack = '', { morphFeature = null, aliases = {} } = {}) {
206
236
  const lines = [
207
237
  `# Managed by morph-spec — ambiente dedicado desta worktree (feature: ${feature}).`,
208
238
  '# Derivado, git-invisível, regenerado por `worktree setup|link`; nunca editar nem commitar.',
209
239
  `MORPH_FEATURE=${morphFeature || feature}`,
210
- ...Object.entries(portLayout(block, { stack, feature })).map(([k, v]) => `${k}=${v}`),
240
+ ...Object.entries(portLayout(block, { stack, feature, aliases })).map(([k, v]) => `${k}=${v}`),
211
241
  ];
212
242
  return `${lines.join('\n')}\n`;
213
243
  }
@@ -346,7 +346,7 @@ export async function setupInfra(targetPath, {
346
346
 
347
347
  // --- 7c. Copy framework/evals → .morph/framework/evals ---
348
348
  // Rubricas .md (bandas 0-10) + trace-schema.md — referenciadas por
349
- // morph-eval/morph-review/agents.json via .morph/framework/evals/.
349
+ // morph-review/agents.json via .morph/framework/evals/.
350
350
  log('Step 7c: Copying evals (rubrics .md + trace schema)...');
351
351
  const evalsSrc = join(FRAMEWORK_DIR, 'evals');
352
352
  const evalsDest = join(frameworkDestDir, 'evals');
@@ -1,11 +1,11 @@
1
- /**
2
- * Map an agents.json ID to the Claude Code subagent_type.
3
- *
4
- * @param {string} id - Agent ID from agents.json (e.g., "nextjs-expert")
5
- * @param {number} [tier] - Agent tier (1-4). Defaults to non-validator.
6
- * @returns {string} subagent_type matching .claude/agents/ filename stem
7
- */
8
- export function agentIdToSubagentType(id, tier) {
9
- const prefix = tier === 4 ? 'morph-validator-' : 'morph-';
10
- return `${prefix}${id}`;
11
- }
1
+ /**
2
+ * Map an agents.json ID to the Claude Code subagent_type.
3
+ *
4
+ * @param {string} id - Agent ID from agents.json (e.g., "nextjs-expert")
5
+ * @param {number} [tier] - Agent tier (1-4). Defaults to non-validator.
6
+ * @returns {string} subagent_type matching .claude/agents/ filename stem
7
+ */
8
+ export function agentIdToSubagentType(id, tier) {
9
+ const prefix = tier === 4 ? 'morph-validator-' : 'morph-';
10
+ return `${prefix}${id}`;
11
+ }
@@ -433,7 +433,7 @@ function buildFrontmatter(agent, description, knownMcpIds, maxTurns) {
433
433
  `description: ${description}`,
434
434
  // model is dimensioned per stage/criticality in agents.json (v5.2.0):
435
435
  // evaluator (quality multiplier) → opus, domain implementers → sonnet,
436
- // scout (read-only, cheap) → haiku. Falls back to `inherit` only for
436
+ // scout → sonnet (measured: same cost as haiku, fewer rejected maps). Falls back to `inherit` only for
437
437
  // personas that omit the field.
438
438
  `model: ${agent.model ?? 'inherit'}`,
439
439
  `tools: ${buildToolsLine(agent, knownMcpIds)}`,
@@ -490,14 +490,10 @@ function buildBody(agent, maxTurns) {
490
490
  lines.push(
491
491
  '## How you operate',
492
492
  '',
493
- 'You are a domain persona dispatched per task. Read the spec/mandate/tasks/standards passed to you, do the work, and return a concise summary plus an auto-score 0-10. Refer to MORPH.md section 6 for the dispatch contract.',
493
+ 'You are a domain persona dispatched per task. Read the spec/tasks/standards passed to you, do the work, and report each doneCriteria with its evidence. Refer to MORPH.md section 6 for the dispatch contract.',
494
494
  '',
495
- // Generic on purpose: this body reaches every dispatch (implement, apply,
496
- // uiux, hotfix, review). The scout has no canonical file and no Write; the
497
- // evaluator's file is evaluator-report.md. `PARCIAL` on line 1 is what
498
- // report-check reads (verdict report-incomplete, action resume); "no
499
- // score" keeps an evaluator partial from carrying a Composite-Score the
500
- // gate would read as final.
495
+ // `PARCIAL` on line 1 is what report-check reads; "no verdict" keeps an
496
+ // evaluator partial from carrying a Verdict the gate would read as final.
501
497
  '## Turn budget',
502
498
  '',
503
499
  // Pasted into EVERY dispatch of every persona — kept to the minimum that
@@ -506,7 +502,7 @@ function buildBody(agent, maxTurns) {
506
502
  `You have ${maxTurns} turns (\`maxTurns\`); at the ceiling you are cut off mid-work, without warning. ` +
507
503
  'One response is one turn, however many parallel tool calls it makes. ' +
508
504
  `By turn ${checkpointTurn(maxTurns)}, if your dispatch names a report file, save a partial there — ` +
509
- '`PARCIAL` on line 1, done, remaining, files, no score (final report only) — then continue or stop, your call; the final report replaces it.',
505
+ '`PARCIAL` on line 1, done, remaining, files, no verdict (final report only) — then continue or stop, your call; the final report replaces it.',
510
506
  );
511
507
 
512
508
  // The dispatch template is paraphrased by the orchestrator in the field; this