@polymorphism-tech/morph-spec 8.47.0 → 9.1.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 +51 -43
- package/README.md +39 -38
- package/bin/morph-spec.js +41 -113
- package/bin/validate.js +1 -147
- package/claude-plugin.json +1 -1
- package/docs/CHEATSHEET.md +1 -1
- package/docs/QUICKSTART.md +1 -1
- package/framework/CLAUDE.md +41 -101
- package/framework/MORPH.md +95 -252
- package/framework/agents.json +86 -21
- package/framework/commands/morph-apply.md +5 -28
- package/framework/commands/morph-archive.md +1 -1
- package/framework/commands/morph-hotfix.md +8 -8
- package/framework/commands/morph-infra.md +1 -1
- package/framework/commands/morph-preflight.md +2 -3
- package/framework/commands/morph-status.md +4 -4
- package/framework/docs/CLI.md +574 -286
- package/framework/evals/review-checklist.md +82 -41
- package/framework/hooks/README.md +10 -11
- package/framework/hooks/claude-code/core/block-destructive-worktree-removal.js +6 -49
- package/framework/hooks/claude-code/core/block-raw-worktree-add.js +2 -35
- package/framework/hooks/claude-code/core/chain.js +4 -65
- package/framework/hooks/claude-code/core/comment-guard.js +3 -17
- package/framework/hooks/claude-code/core/denylist.json +33 -3
- package/framework/hooks/claude-code/core/enforce-phase-writes.js +15 -63
- package/framework/hooks/claude-code/core/gate-guard.js +9 -78
- package/framework/hooks/claude-code/core/graph-refresh-kick.js +3 -24
- package/framework/hooks/claude-code/core/heavy-gate.js +3 -21
- package/framework/hooks/claude-code/core/heavy-release.js +2 -13
- package/framework/hooks/claude-code/core/loop-detect.js +2 -31
- package/framework/hooks/claude-code/core/pre-bash-denylist.js +36 -2
- package/framework/hooks/claude-code/core/protect-spec-files.js +25 -297
- package/framework/hooks/claude-code/core/state-sync.js +15 -85
- package/framework/hooks/claude-code/core/telemetry-log.js +15 -96
- package/framework/hooks/claude-code/core/validate-completion.js +37 -147
- package/framework/hooks/claude-code/core/warn-bash-source-write.js +23 -0
- package/framework/hooks/claude-code/core/worktree-context.js +15 -114
- package/framework/hooks/claude-code/core/worktree-create.js +6 -70
- package/framework/hooks/claude-code/core/worktree-env-inject.js +5 -56
- package/framework/hooks/claude-code/core/worktree-remove.js +5 -31
- package/framework/hooks/claude-code/statusline.py +55 -41
- package/framework/hooks/package.json +3 -0
- package/framework/hooks/shared/activity-logger.js +9 -89
- package/framework/hooks/shared/agent-reap.js +2 -17
- package/framework/hooks/shared/build-check.js +11 -76
- package/framework/hooks/shared/claim-registry.js +9 -119
- package/framework/hooks/shared/command-tokens.js +168 -44
- package/framework/hooks/shared/comment-rules.js +5 -20
- package/framework/hooks/shared/comment-scanner.js +11 -43
- package/framework/hooks/shared/comment-stripper.js +11 -85
- package/framework/hooks/shared/e2e-check.js +0 -0
- package/framework/hooks/shared/errata.js +59 -0
- package/framework/hooks/shared/feature-locator.js +11 -95
- package/framework/hooks/shared/frontend-locations.js +4 -0
- package/framework/hooks/shared/gate-question.js +12 -0
- package/framework/hooks/shared/git-exclude.js +3 -20
- package/framework/hooks/shared/git-paths.js +8 -104
- package/framework/hooks/shared/graph-freshness.js +22 -166
- package/framework/hooks/shared/graph-refresh.js +21 -149
- package/framework/hooks/shared/heavy-command.js +4 -12
- package/framework/hooks/shared/hook-response.js +8 -83
- package/framework/hooks/shared/morph-cli.js +8 -52
- package/framework/hooks/shared/payload-utils.js +10 -132
- package/framework/hooks/shared/phase-utils.js +14 -72
- package/framework/hooks/shared/redact-secrets.js +4 -15
- package/framework/hooks/shared/reparse-scan.js +6 -66
- package/framework/hooks/shared/slice-progress.js +99 -0
- package/framework/hooks/shared/source-files.js +4 -17
- package/framework/hooks/shared/spawn-command.js +23 -0
- package/framework/hooks/shared/state-reader.js +51 -247
- package/framework/hooks/shared/state-writer.js +9 -54
- package/framework/hooks/shared/stdin-reader.js +1 -11
- package/framework/hooks/shared/telemetry-logger.js +7 -67
- package/framework/hooks/shared/transcript-usage.js +7 -29
- package/framework/hooks/shared/worktree-root.js +7 -29
- package/framework/mcp/registry.json +3 -4
- package/framework/phases.json +23 -39
- package/framework/rules/csharp-standards.md +1 -1
- package/framework/rules/frontend-standards.md +1 -0
- package/framework/rules/hangfire-standards.md +1 -1
- package/framework/rules/neon-standards.md +1 -1
- package/framework/schemas/config.schema.json +14 -9
- package/framework/schemas/feature.schema.json +15 -50
- package/framework/skills/README.md +3 -4
- package/framework/skills/core/create-umbraco-lp/SKILL.md +1 -1
- package/framework/skills/core/migrate-lp-to-umbraco/SKILL.md +1 -1
- package/framework/skills/core/morph-apply/SKILL.md +149 -222
- package/framework/skills/core/morph-hotfix/SKILL.md +33 -42
- package/framework/skills/core/morph-machine/SKILL.md +2 -2
- package/framework/skills/core/morph-media/SKILL.md +1 -1
- package/framework/skills/core/morph-plan/SKILL.md +137 -299
- package/framework/skills/core/morph-review/SKILL.md +111 -136
- package/framework/skills/core/morph-standards/SKILL.md +27 -39
- package/framework/skills/core/morph-uiux/SKILL.md +94 -152
- package/framework/standards/STANDARDS.json +109 -1219
- package/framework/standards/STANDARDS.meta.json +1319 -0
- package/framework/standards/ai-agents/agent-archetypes.md +2 -2
- package/framework/standards/ai-agents/agent-session.md +1 -1
- package/framework/standards/ai-agents/conversational-agent-with-phases.md +4 -4
- package/framework/standards/ai-agents/durable-workflows-hitl.md +3 -3
- package/framework/standards/ai-agents/evals-with-cache.md +1 -2
- package/framework/standards/ai-agents/guardrails.md +1 -1
- package/framework/standards/ai-agents/multi-agent-patterns.md +2 -2
- package/framework/standards/ai-agents/observability-patterns.md +1 -1
- package/framework/standards/ai-agents/production.md +1 -1
- package/framework/standards/ai-agents/prompt-sources.md +2 -2
- package/framework/standards/ai-agents/providers/model-registry.md +1 -1
- package/framework/standards/ai-agents/rag-custom-pgvector.md +2 -2
- package/framework/standards/ai-agents/setup.md +3 -3
- package/framework/standards/ai-agents/sweet-spot.md +2 -2
- package/framework/standards/ai-agents/tool-adapters.md +0 -2
- package/framework/standards/ai-agents/vector-data-extensions.md +4 -4
- package/framework/standards/ai-agents/workflows.md +1 -1
- package/framework/standards/architecture/code-comments.md +7 -7
- package/framework/standards/architecture/vertical-slice/vertical-slice.md +1 -1
- package/framework/standards/backend/api/validation.md +1 -1
- package/framework/standards/backend/dotnet/vsa-handler-patterns.md +5 -5
- package/framework/standards/backend/integrations/hangfire/hangfire-jobs.md +1 -1
- package/framework/standards/backend/integrations/neon-auth/neon-auth.md +2 -2
- package/framework/standards/data/nosql/cache/redis.md +1 -1
- package/framework/standards/data/nosql/cosmos-db.md +3 -3
- package/framework/standards/frontend/admin-app/forms.md +1 -1
- package/framework/standards/frontend/design-system/art-direction.md +88 -0
- package/framework/standards/frontend/design-system/premium-finish.md +77 -2
- package/framework/standards/infrastructure/neon/neon-pgvector.md +5 -5
- package/framework/standards/integration/mcp/mcp-tools.md +7 -7
- package/framework/templates/CLAUDE.md.core.template +3 -3
- package/framework/templates/README.md +2 -3
- package/framework/templates/REGISTRY.json +15 -179
- package/framework/templates/docs/plan.md +72 -0
- package/framework/templates/docs/ui-mockups.md +4 -0
- package/framework/templates/dotnet/ai-kit/README.md +1 -9
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Morph.AiKit.Tests.csproj +0 -10
- package/framework/templates/meta-prompts/squad-leaders/backend-squad.md +1 -1
- package/framework/templates/meta-prompts/squad-leaders/frontend-squad.md +1 -1
- package/framework/templates/meta-prompts/squad-leaders/squad-leader.md +1 -1
- package/framework/templates/meta-prompts/validators/pre-commit-validator.md +3 -4
- package/package.json +1 -1
- package/src/commands/context/context-refresh.js +0 -16
- package/src/commands/dashboard/dashboard.js +2 -8
- package/src/commands/e2e/e2e.js +18 -105
- package/src/commands/graph/affected.js +0 -14
- package/src/commands/graph/build.js +11 -50
- package/src/commands/graph/explain.js +0 -16
- package/src/commands/graph/status.js +1 -12
- package/src/commands/mcp/mcp-setup.js +4 -62
- package/src/commands/observability/cost.js +17 -111
- package/src/commands/observability/telemetry.js +1 -14
- package/src/commands/project/branch.js +4 -45
- package/src/commands/project/claim.js +4 -48
- package/src/commands/project/doctor-procs.js +1 -1
- package/src/commands/project/doctor.js +53 -307
- package/src/commands/project/env.js +1 -27
- package/src/commands/project/fleet.js +6 -35
- package/src/commands/project/heavy.js +3 -3
- package/src/commands/project/init.js +8 -68
- package/src/commands/project/install-plugin-cmd.js +0 -1
- package/src/commands/project/setup-infra-cmd.js +2 -1
- package/src/commands/project/stack-scan.js +58 -0
- package/src/commands/project/standards.js +65 -72
- package/src/commands/project/status.js +28 -121
- package/src/commands/project/update.js +31 -223
- package/src/commands/project/worktree.js +109 -883
- package/src/commands/scaffold/scaffold.js +0 -25
- package/src/commands/state/advance.js +65 -120
- package/src/commands/state/approve.js +87 -229
- package/src/commands/state/archive.js +23 -139
- package/src/commands/state/auto-approval.js +65 -0
- package/src/commands/state/create.js +49 -109
- package/src/commands/state/delete.js +11 -63
- package/src/commands/state/finish.js +105 -494
- package/src/commands/state/gate-check.js +74 -183
- package/src/commands/state/gate-decision.js +8 -42
- package/src/commands/state/handoff.js +4 -31
- package/src/commands/state/list.js +21 -91
- package/src/commands/state/report-check.js +134 -338
- package/src/commands/state/retype.js +12 -28
- package/src/commands/validation/index.js +0 -3
- package/src/commands/validation/mutate.js +79 -19
- package/src/commands/validation/plan-check.js +81 -0
- package/src/commands/validation/validate-feature.js +52 -216
- package/src/commands/validation/verify.js +45 -160
- package/src/core/paths/output-schema.js +9 -155
- package/src/core/state/feature-identity.js +1 -25
- package/src/core/state/gate-order.js +2 -30
- package/src/core/state/lifecycle-audit.js +8 -100
- package/src/core/state/state-manager.js +32 -395
- package/src/core/templates/template-registry.js +2 -97
- package/src/core/templates/template-renderer.js +13 -93
- package/src/core/templates/template-seed.js +21 -0
- package/src/core/work-types.js +10 -45
- package/src/dashboard/app/App.jsx +1 -8
- package/src/dashboard/app/components/ActivityFeed.jsx +2 -8
- package/src/dashboard/app/components/CommandPalette.jsx +4 -11
- package/src/dashboard/app/components/DetailPanel.jsx +1 -5
- package/src/dashboard/app/components/EntityLink.jsx +0 -12
- package/src/dashboard/app/components/ErrorBoundary.jsx +1 -8
- package/src/dashboard/app/components/KnowledgeMarkdown.jsx +0 -11
- package/src/dashboard/app/components/Markdown.jsx +0 -9
- package/src/dashboard/app/components/PhaseRail.jsx +0 -11
- package/src/dashboard/app/components/SearchFilter.jsx +0 -4
- package/src/dashboard/app/components/Sidebar.jsx +0 -5
- package/src/dashboard/app/hooks/useMorphQuery.js +1 -11
- package/src/dashboard/app/hooks/usePref.js +1 -5
- package/src/dashboard/app/lib/format.js +0 -2
- package/src/dashboard/app/lib/phases.js +3 -9
- package/src/dashboard/app/lib/project.js +0 -12
- package/src/dashboard/app/pages/Activity.jsx +1 -1
- package/src/dashboard/app/pages/AgentMap.jsx +1 -8
- package/src/dashboard/app/pages/FeatureDetail.jsx +139 -133
- package/src/dashboard/app/pages/Features.jsx +9 -16
- package/src/dashboard/app/pages/Guide.jsx +2 -3
- package/src/dashboard/app/pages/HookInspector.jsx +2 -23
- package/src/dashboard/app/pages/PhasePipeline.jsx +3 -7
- package/src/dashboard/app/pages/Portfolio.jsx +0 -1
- package/src/dashboard/app/pages/RulesMap.jsx +1 -16
- package/src/dashboard/app/pages/SkillsLibrary.jsx +1 -16
- package/src/dashboard/app/pages/Standards.jsx +2 -17
- package/src/dashboard/scanner/activity-scanner.js +14 -83
- package/src/dashboard/scanner/agents-scanner.js +1 -23
- package/src/dashboard/scanner/docs-scanner.js +1 -7
- package/src/dashboard/scanner/feature-status.js +2 -5
- package/src/dashboard/scanner/features-scanner.js +92 -113
- package/src/dashboard/scanner/hooks-scanner.js +5 -28
- package/src/dashboard/scanner/index.js +0 -4
- package/src/dashboard/scanner/portfolio.js +5 -29
- package/src/dashboard/scanner/project-api.js +8 -54
- package/src/dashboard/scanner/rules-scanner.js +1 -2
- package/src/dashboard/scanner/skills-scanner.js +2 -12
- package/src/dashboard/scanner/standards-scanner.js +4 -7
- package/src/dashboard/vite-plugin-morph-data.js +5 -19
- package/src/lib/ai/ai-checks.js +7 -52
- package/src/lib/ai/ai-project-scan.js +14 -108
- package/src/lib/ai/code-audit.js +7 -63
- package/src/lib/ai/pin-drift.js +8 -51
- package/src/lib/ai/registry-audit.js +11 -90
- package/src/lib/ci/ci-verify.js +14 -13
- package/src/lib/ci/github-ci.js +9 -37
- package/src/lib/ci/workflow-scaffold.js +2 -10
- package/src/lib/detectors/claude-config-detector.js +13 -74
- package/src/lib/detectors/index.js +8 -59
- package/src/lib/e2e/compose-env.js +5 -66
- package/src/lib/e2e/stack-teardown.js +6 -40
- package/src/lib/generators/architecture-scanner.js +18 -156
- package/src/lib/generators/handoff-generator.js +37 -112
- package/src/lib/generators/scaffold-generator.js +5 -101
- package/src/lib/generators/settings-generator.js +11 -122
- package/src/lib/git/branch-classifier.js +11 -84
- package/src/lib/git/default-branch.js +14 -169
- package/src/lib/git/evidence-staleness.js +2 -1
- package/src/lib/git/gh.js +2 -17
- package/src/lib/git/pending-prs.js +6 -37
- package/src/lib/git/pr-files.js +3 -28
- package/src/lib/git/pr-index.js +3 -34
- package/src/lib/git/tree-fingerprint.js +17 -17
- package/src/lib/git/tree-state.js +6 -33
- package/src/lib/graph/god-nodes.js +2 -22
- package/src/lib/graph/graph-health.js +3 -24
- package/src/lib/graph/graph-loader.js +5 -56
- package/src/lib/graph/graphify-runtime.js +7 -37
- package/src/lib/graph/graphifyignore.js +8 -74
- package/src/lib/graph/sanitize.js +16 -136
- package/src/lib/heavy/cleanup.js +2 -6
- package/src/lib/installers/effects.js +8 -93
- package/src/lib/installers/mcp-installer.js +9 -169
- package/src/lib/installers/memory-installer.js +8 -33
- package/src/lib/installers/templates-reconcile.js +5 -60
- package/src/lib/mutation/commands.js +3 -2
- package/src/lib/mutation/dotnet-introspection.js +281 -0
- package/src/lib/mutation/plan.js +14 -6
- package/src/lib/mutation/runner.js +1 -1
- package/src/lib/mutation/subset.js +47 -13
- package/src/lib/plan/artifact-vocabulary.js +40 -0
- package/src/lib/plan/checks.js +208 -0
- package/src/lib/plan/plan-parser.js +204 -0
- package/src/lib/plan/plan-template.js +18 -0
- package/src/lib/projects/registry.js +7 -44
- package/src/lib/review-reports.js +204 -0
- package/src/lib/risk-detector.js +131 -274
- package/src/lib/specs/adr-index.js +38 -85
- package/src/lib/specs/design-seed.js +18 -0
- package/src/lib/specs/frontmatter.js +31 -0
- package/src/lib/specs/gfm-table.js +11 -0
- package/src/lib/specs/revocations.js +31 -102
- package/src/lib/specs/screen-checklist.js +56 -132
- package/src/lib/stack/dotnet-build-ignores.js +43 -0
- package/src/lib/stack/stack-profile.js +1 -28
- package/src/lib/stack/stack-scan.js +260 -0
- package/src/lib/stack-filter.js +4 -27
- package/src/lib/standards/registry.js +37 -0
- package/src/lib/standards/sections.js +47 -0
- package/src/lib/standards/verified-against.js +19 -191
- package/src/lib/tasks/eval-node.js +23 -179
- package/src/lib/tasks/linux-runner.js +18 -142
- package/src/lib/tasks/test-nodes.js +43 -313
- package/src/lib/tasks/test-runner.js +107 -447
- package/src/lib/telemetry/metrics.js +13 -103
- package/src/lib/telemetry/telemetry-reader.js +13 -238
- package/src/lib/telemetry/verify-event.js +4 -34
- package/src/lib/validators/code-budget/code-budget-validator.js +4 -44
- package/src/lib/validators/code-budget/index.js +0 -7
- package/src/lib/validators/contracts/contract-compliance-validator.js +4 -26
- package/src/lib/validators/contracts/index.js +0 -6
- package/src/lib/validators/nextjs/index.js +0 -5
- package/src/lib/validators/nextjs/next-component-validator.js +4 -81
- package/src/lib/validators/packages/index.js +0 -6
- package/src/lib/validators/packages/package-validator.js +6 -56
- package/src/lib/validators/reuse/index.js +0 -8
- package/src/lib/validators/reuse/reuse-validator.js +24 -137
- package/src/lib/validators/reuse/symbol-scanner.js +6 -62
- package/src/lib/validators/traceability-check.js +54 -156
- package/src/lib/validators/validation-runner.js +20 -125
- package/src/lib/validators/verify-runner.js +152 -575
- package/src/lib/work-type-detector.js +5 -67
- package/src/lib/worktree/docker-audit.js +17 -137
- package/src/lib/worktree/env-allocator.js +10 -98
- package/src/lib/worktree/feature-truth.js +12 -115
- package/src/lib/worktree/finish-backup.js +32 -242
- package/src/lib/worktree/fleet-scanner.js +31 -126
- package/src/lib/worktree/ignored-triage.js +15 -91
- package/src/lib/worktree/vscode-settings.js +2 -3
- package/src/lib/worktree/worktree-audit.js +21 -213
- package/src/lib/worktree/worktree-include.js +3 -5
- package/src/scripts/global-install.js +3 -9
- package/src/scripts/install-plugin.js +1 -13
- package/src/scripts/setup-infra.js +17 -138
- package/src/utils/agents-installer.js +92 -272
- package/src/utils/banner.js +4 -25
- package/src/utils/claude-md-injector.js +1 -37
- package/src/utils/claude-settings-manager.js +1 -87
- package/src/utils/file-copier.js +32 -90
- package/src/utils/hooks-installer.js +26 -296
- package/src/utils/skills-installer.js +4 -102
- package/src/utils/version-checker.js +4 -83
- package/framework/commands/morph-proposal.md +0 -57
- package/framework/evals/trace-schema.md +0 -67
- package/framework/hooks/claude-code/core/tasks-json-guard.js +0 -83
- package/framework/hooks/claude-code/core/trace-autogen.js +0 -277
- package/framework/hooks/git/pre-commit/specs.sh +0 -50
- package/framework/hooks/shared/tasks-validator.js +0 -111
- package/framework/rules/morph-task-tracking.md +0 -54
- package/framework/rules/morph-workflow.md +0 -244
- package/framework/schemas/tasks.schema.json +0 -79
- package/framework/skills/core/morph-brainstorming/SKILL.md +0 -161
- package/framework/skills/core/morph-implement/SKILL.md +0 -194
- package/framework/skills/core/morph-proposal/SKILL.md +0 -152
- package/framework/skills/core/morph-stack-scan/SKILL.md +0 -145
- package/framework/templates/docs/proposal.md +0 -192
- package/framework/templates/docs/spec.md +0 -57
- package/framework/templates/docs/ui-components.md +0 -52
- package/framework/templates/docs/ui-design-system.md +0 -76
- package/framework/templates/docs/ui-flows.md +0 -167
- package/framework/templates/examples/spec-examples.md +0 -91
- package/framework/templates/feature/decisions.md +0 -124
- package/framework/templates/feature/recap.md +0 -145
- package/framework/templates/tasks.template.json +0 -17
- package/src/commands/state/usecase.js +0 -143
- package/src/commands/tasks/dag.js +0 -181
- package/src/commands/utils/index.js +0 -3
- package/src/lib/agents/output-collector.js +0 -76
- package/src/lib/detectors/design-system-detector.js +0 -188
- package/src/lib/evaluator-report.js +0 -104
- package/src/lib/generators/design-system-generator.js +0 -508
- package/src/lib/specs/acervo-format.js +0 -70
- package/src/lib/specs/acervo-lifecycle.js +0 -264
- package/src/lib/specs/done-criteria-check.js +0 -200
- package/src/lib/specs/usecase-check.js +0 -301
- package/src/lib/specs/usecase-promoter.js +0 -301
- package/src/lib/specs/usecase-registry.js +0 -237
- package/src/lib/tasks/dispatch-planner.js +0 -319
- package/src/lib/tasks/dotnet-test-introspection.js +0 -632
- package/src/lib/tasks/mermaid-renderer.js +0 -132
- package/src/lib/tasks/task-classifier.js +0 -30
- package/src/lib/tasks/task-parser.js +0 -209
- package/src/lib/tasks/tasks-json-parser.js +0 -296
- package/src/lib/tasks/test-scope.js +0 -597
- package/src/utils/agent-id-mapper.js +0 -11
|
@@ -128,13 +128,13 @@ não escolhe o histórico; escolher "chat com histórico" não escolhe as fases.
|
|
|
128
128
|
| Agente de batch no caminho síncrono de uma requisição | Latência de LLM no p99 do endpoint, sem retry e sem visibilidade | Job assíncrono |
|
|
129
129
|
| Imagem descrita numa chamada e tipada noutra | Duas chamadas pagas, e o erro de descrição deixa de ser rastreável | Uma chamada multimodal com `RunAsync<T>` |
|
|
130
130
|
| Projeção papel → `ChatMessage` em dois arquivos | Os dois divergem, e o bug aparece como "o agente esqueceu" | Uma projeção, pura e testável |
|
|
131
|
-
| Escolher o arquétipo na implementação | A forma muda o desenho das tasks; escolhida depois, ela vira refactor | Escolha na fase de plano, e registre em `
|
|
131
|
+
| Escolher o arquétipo na implementação | A forma muda o desenho das tasks; escolhida depois, ela vira refactor | Escolha na fase de plano, e registre em `plan.md` (`## Decisões`) |
|
|
132
132
|
|
|
133
133
|
---
|
|
134
134
|
|
|
135
135
|
## Checklist (verifiable in review)
|
|
136
136
|
|
|
137
|
-
- [ ] O arquétipo escolhido está **nomeado** no `
|
|
137
|
+
- [ ] O arquétipo escolhido está **nomeado** no `plan.md` (`## Decisões`) da feature, com a pergunta de
|
|
138
138
|
`## Como escolher` que o decidiu
|
|
139
139
|
- [ ] Nenhum agente novo por fase de conversa — a fase é dado do turno
|
|
140
140
|
- [ ] Agente one-shot recebe prompt e alias como parâmetro, e não guarda estado entre invocações
|
|
@@ -228,7 +228,7 @@ O histórico cresce a cada turno. Quando estoura o context window do modelo, as
|
|
|
228
228
|
|
|
229
229
|
## Checklist (verifiable in review)
|
|
230
230
|
|
|
231
|
-
- [ ] A escolha da fonte de histórico foi feita pela tabela de critério — e está escrita em `
|
|
231
|
+
- [ ] A escolha da fonte de histórico foi feita pela tabela de critério — e está escrita em `plan.md` (`## Decisões`) quando não foi a conversa própria
|
|
232
232
|
- [ ] O provider de histórico é registrado como **uma** instância compartilhada
|
|
233
233
|
- [ ] Nenhum campo de instância do provider guarda estado de conversa; o que é por sessão está em `ProviderSessionState<TState>` e declarado em `StateKeys`
|
|
234
234
|
- [ ] Existe teste com **duas sessões concorrentes** sobre o mesmo provider
|
|
@@ -170,7 +170,7 @@ comprar a única coisa que o aninhamento oferece — deixar o modelo decidir.
|
|
|
170
170
|
contabilidade por agente); o teto de tool calls do externo não governa o interno; o timeout do turno
|
|
171
171
|
passa a cobrir duas chamadas de LLM em série; e o span do interno pendura-se sob `execute_tool`, onde
|
|
172
172
|
nenhum painel de agente procura. Quando a decisão **é** do modelo, esses quatro custos continuam
|
|
173
|
-
valendo — a diferença é que aí eles foram escolhidos, e o `
|
|
173
|
+
valendo — a diferença é que aí eles foram escolhidos, e o `plan.md` (`## Decisões`) diz por quê.
|
|
174
174
|
|
|
175
175
|
Os dois lados de campo, e é raro ter os dois:
|
|
176
176
|
|
|
@@ -198,7 +198,7 @@ A composição legítima — quando ela é mesmo necessária — é assunto de
|
|
|
198
198
|
| Teto tratado como opção de chamada | Vai ao provider, onde não significa nada | É opção do pipeline, nível de agente |
|
|
199
199
|
| `RequireAny` adotado sem medir `recovered` | Troca uma recuperação medida por uma falha nova | Aplique o critério de saída antes |
|
|
200
200
|
| Etapa FIXA do turno aninhada numa tool call | Paga custo, teto, timeout e span quebrados sem comprar nada — ninguém precisava decidir | Sequência, no código |
|
|
201
|
-
| Agent-as-Tool adotado sem registrar a decisão, ou além de 2 níveis | Os quatro custos viram surpresa, e o 3º nível é sinal de que devia ser sequência | Decisão no `
|
|
201
|
+
| Agent-as-Tool adotado sem registrar a decisão, ou além de 2 níveis | Os quatro custos viram surpresa, e o 3º nível é sinal de que devia ser sequência | Decisão no `plan.md` (`## Decisões`), teto ≤ 2 níveis (`ai-agents-multi-agent-patterns`) |
|
|
202
202
|
|
|
203
203
|
---
|
|
204
204
|
|
|
@@ -212,8 +212,8 @@ A composição legítima — quando ela é mesmo necessária — é assunto de
|
|
|
212
212
|
- [ ] Há teto de tool calls por turno, com tool isenta, e bater o teto é observável
|
|
213
213
|
- [ ] O teto está no nível de agente, não nas opções de chamada
|
|
214
214
|
- [ ] Se `RequireAny` foi adotado: a taxa de `recovered` e o custo da segunda chamada estão no
|
|
215
|
-
`
|
|
216
|
-
- [ ] Nenhuma etapa **fixa** do turno é invocada de dentro de uma tool call. Onde há aninhamento, quem decide é o **modelo**, está registrado no `
|
|
215
|
+
`plan.md` (`## Decisões`). Se não foi: o critério de saída está escrito
|
|
216
|
+
- [ ] Nenhuma etapa **fixa** do turno é invocada de dentro de uma tool call. Onde há aninhamento, quem decide é o **modelo**, está registrado no `plan.md` (`## Decisões`), e respeita o teto de ≤ 2 níveis de `ai-agents-multi-agent-patterns`
|
|
217
217
|
|
|
218
218
|
---
|
|
219
219
|
|
|
@@ -226,7 +226,7 @@ public sealed class PostgresCheckpointStore(NpgsqlDataSource dataSource) : IChec
|
|
|
226
226
|
|
|
227
227
|
`Microsoft.Agents.AI.DurableTask` (prerelease) adds durability backed by the **Azure Durable Task Scheduler**, including cost-efficient multi-day HITL waits with zero compute cost while paused. Even its "bring-your-own-compute / self-hosted" mode still requires a Durable Task Scheduler backend (`Microsoft.DurableTask.*.AzureManaged` packages) — self-hosted means your own worker process, not an Azure-free backend.
|
|
228
228
|
|
|
229
|
-
This framework deploys to VPS/Coolify by default and does not adopt Azure as a default dependency (see `ai-agents-setup` §3.4 on Azure OpenAI). For that reason, `Microsoft.Agents.AI.DurableTask` is **not adopted as default** here. The `CheckpointManager` + custom `ICheckpointStore` pattern above covers the same durability need without an Azure dependency. Only reach for the Durable Task extension when a specific client already runs on Azure and needs multi-day/serverless HITL waits — record that decision in `
|
|
229
|
+
This framework deploys to VPS/Coolify by default and does not adopt Azure as a default dependency (see `ai-agents-setup` §3.4 on Azure OpenAI). For that reason, `Microsoft.Agents.AI.DurableTask` is **not adopted as default** here. The `CheckpointManager` + custom `ICheckpointStore` pattern above covers the same durability need without an Azure dependency. Only reach for the Durable Task extension when a specific client already runs on Azure and needs multi-day/serverless HITL waits — record that decision in `plan.md` (`## Decisões`).
|
|
230
230
|
|
|
231
231
|
---
|
|
232
232
|
|
|
@@ -248,12 +248,12 @@ This framework deploys to VPS/Coolify by default and does not adopt Azure as a d
|
|
|
248
248
|
|
|
249
249
|
## Checklist (verifiable in review)
|
|
250
250
|
|
|
251
|
-
- [ ] `ai-agents-workflows`' HITL or long-running criterion is documented in `
|
|
251
|
+
- [ ] `ai-agents-workflows`' HITL or long-running criterion is documented in `plan.md` (`## Decisões`) before this standard is applied.
|
|
252
252
|
- [ ] Every HITL wait point uses `RequestPort` + handles `RequestInfoEvent`.
|
|
253
253
|
- [ ] A `CheckpointManager` is wired whenever the workflow can pause across a process restart — `CreateInMemory()` is acceptable only for tests/demos.
|
|
254
254
|
- [ ] If a custom `ICheckpointStore` was implemented, it persists to infrastructure already owned by the project (e.g., Neon Postgres), not a new ad hoc store.
|
|
255
255
|
- [ ] Executors with instance state implement `OnCheckpointingAsync` and `OnCheckpointRestoredAsync`.
|
|
256
|
-
- [ ] `Microsoft.Agents.AI.DurableTask` is present only if the project already runs on Azure and the choice is recorded in `
|
|
256
|
+
- [ ] `Microsoft.Agents.AI.DurableTask` is present only if the project already runs on Azure and the choice is recorded in `plan.md` (`## Decisões`) — ciente de que, desde a 1.17, o pacote vive em repositório separado e ficou para trás do framework.
|
|
257
257
|
- [ ] Toda tool com efeito irreversível está embrulhada em `ApprovalRequiredAIFunction` **ou** tem um guard determinístico documentado — e a escolha entre os dois está escrita.
|
|
258
258
|
- [ ] A resposta de aprovação é enviada na **mesma** `AgentSession`, num laço que checa pendências depois de cada run.
|
|
259
259
|
- [ ] Nenhum `Workflow` foi criado apenas para pausar uma tool de um agente único.
|
|
@@ -228,8 +228,7 @@ Declare-o como um nó a mais em `project.tests[]` — não como uma estrutura pa
|
|
|
228
228
|
|
|
229
229
|
| Quando | O que acontece |
|
|
230
230
|
|---|---|
|
|
231
|
-
| `verify {feature}
|
|
232
|
-
| `verify {feature}` (escopo de feature) | **roda**, offline, contra a cache commitada |
|
|
231
|
+
| `verify {feature}` | **roda**, offline, contra a cache commitada |
|
|
233
232
|
| miss de cache sem credencial | **reprova** nomeando o cenário, o caminho, o comando de regravação e o arquivo de credencial |
|
|
234
233
|
| `--refresh-cache` | regrava a árvore contra o provider real. **Nunca implícito**: é uma chamada paga |
|
|
235
234
|
|
|
@@ -189,7 +189,7 @@ primeira pergunta a fazer quando um guard "nunca reprova nada".
|
|
|
189
189
|
## Checklist (verifiable in review)
|
|
190
190
|
|
|
191
191
|
- [ ] Toda regra com consequência real existe como condição em código, não apenas no prompt
|
|
192
|
-
- [ ] O choke-point escolhido está nomeado no `
|
|
192
|
+
- [ ] O choke-point escolhido está nomeado no `plan.md` (`## Decisões`), com o que ele pega
|
|
193
193
|
- [ ] O middleware de tool devolve **vocabulário fechado** de desfecho
|
|
194
194
|
- [ ] Argumento obrigatório ausente é barrado **sem** executar a tool, lendo o schema da própria função
|
|
195
195
|
- [ ] Nenhum identificador com efeito vem do modelo — todos vêm da closure do turno
|
|
@@ -178,13 +178,13 @@ Tenho múltiplos agents — qual padrão usar?
|
|
|
178
178
|
| Handoff sem `turnLimit` nem condição de término | Dois agentes devolvem a conversa um ao outro indefinidamente | `.WithAutonomousMode(turnLimit:)` ou `.WithTerminationCondition(...)` |
|
|
179
179
|
| `Id` de agente gerado a cada boot num workflow de handoff | O destino do handoff deixa de existir entre reinícios | `Id` estável, vindo de configuração |
|
|
180
180
|
| Group chat com 5+ agentes | O gerente gasta os turnos escolhendo quem fala | ≤ 3 agentes; acima disso, repense a decomposição |
|
|
181
|
-
| Agents com responsabilidades sobrepostas | Nenhum dos dois sabe quando agir; o LLM fica confuso | Fronteiras claras de responsabilidade; documente em `
|
|
181
|
+
| Agents com responsabilidades sobrepostas | Nenhum dos dois sabe quando agir; o LLM fica confuso | Fronteiras claras de responsabilidade; documente em `plan.md` (`## Decisões`). |
|
|
182
182
|
|
|
183
183
|
---
|
|
184
184
|
|
|
185
185
|
## Checklist (verifiable in review)
|
|
186
186
|
|
|
187
|
-
- [ ] Foi verificado em `
|
|
187
|
+
- [ ] Foi verificado em `plan.md` (`## Decisões`) que single agent não resolve?
|
|
188
188
|
- [ ] O padrão escolhido é o mais simples que atende ao requisito? (Tool < Sequential imperativo < Workflow)
|
|
189
189
|
- [ ] `agent.AsAIFunction()` usado para composição local (não `AIFunctionFactory.Create` desnecessariamente)?
|
|
190
190
|
- [ ] Agents usando alias do Model Registry — nenhum model string hardcoded?
|
|
@@ -313,7 +313,7 @@ Workflow para diagnosticar um incidente relatado ("o agente X respondeu errado/l
|
|
|
313
313
|
2. **Suba do trace raiz para os spans filhos.** O span raiz mostra a duração total; os filhos (`Function Calling`, `IChatClient`) mostram onde o tempo/erro realmente está. Não assuma — meça. Um "agente lento" é quase sempre UM tool call específico (chamada de API externa, query sem índice), não o LLM.
|
|
314
314
|
3. **Correlacione com métricas antes de teorizar.** Confira a tabela "What to Monitor" abaixo pelo período do incidente — um pico de `tool call failure rate` ou `token usage` aponta a causa mais rápido que ler traces individuais um a um.
|
|
315
315
|
4. **Reproduza com Debug ligado, nunca em produção.** Se a causa não estiver clara nos atributos estruturados, habilite `Debug` (com dados sensíveis, se necessário) num ambiente de staging com o mesmo input — nunca habilite log de prompt/response completo em produção para investigar.
|
|
316
|
-
5. **Documente a causa raiz em `
|
|
316
|
+
5. **Documente a causa raiz em `plan.md` (`## Decisões`)** se a investigação levar a uma mudança de arquitetura (novo middleware de retry, novo timeout, novo cache) — não só no commit message.
|
|
317
317
|
|
|
318
318
|
### What to Monitor
|
|
319
319
|
|
|
@@ -202,7 +202,7 @@ Na **1.18** (2026-08-18) essa superfície foi renomeada. Nomes atuais, medidos p
|
|
|
202
202
|
|
|
203
203
|
**Duas advertências que valem mais que os nomes:**
|
|
204
204
|
|
|
205
|
-
1. **O pacote é prerelease.** `Microsoft.Agents.AI.Hosting` não tem versão estável (apurado 2026-09-08). Isolamento multi-tenant por esse caminho é adoção de preview — registre em `
|
|
205
|
+
1. **O pacote é prerelease.** `Microsoft.Agents.AI.Hosting` não tem versão estável (apurado 2026-09-08). Isolamento multi-tenant por esse caminho é adoção de preview — registre em `plan.md` (`## Decisões`).
|
|
206
206
|
2. **A chave vem da credencial, nunca do payload.** Uma chave derivada de algo que o cliente envia é uma chave que o cliente escolhe. `UseClaimsBasedAgentIsolation()` existe exatamente para não deixar essa decisão passar pelo corpo do request.
|
|
207
207
|
|
|
208
208
|
### Invocação concorrente de tools é opt-in desde 1.18
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
> **Keywords:** prompt sources, prompts in db, agent prompts, prompt versioning, prompt hot-reload, editable instructions, prompt management, prompt por tenant, spec publicado, reconciliação de prompt
|
|
6
6
|
> **Read by Claude in:** implement (quando as instruções de um agente precisam viver fora do código) e troubleshoot (quando a versão que rodou não é a que se esperava)
|
|
7
7
|
|
|
8
|
-
**Verified against:** Microsoft.Agents.AI 1.20.0 + Microsoft.Extensions.AI 10.9.0 (ai-pin 2026-09-08). **Verificação documental**, sem cláusula `provado por` — o ai-kit não traz loader de prompt, e os dois mecanismos descritos aqui são destilados de três produtos em produção. As **quatro** superfícies de API que este standard cita foram medidas por reflexão, e vivem em **três assemblies diferentes** — o carimbo diz onde remedir, então o nome importa: `IChatClient.AsAIAgent(instructions:, name:)` é `Microsoft.Extensions.AI.ChatClientExtensions`, em **`Microsoft.Agents.AI` 1.20.0** (medida em 2026-09-08); `AIAgent.RunAsync` (as oito sobrecargas) e `AIAgent.CreateSessionAsync` são de `Microsoft.Agents.AI.AIAgent`, na assembly **`Microsoft.Agents.AI.Abstractions` 1.20.0** — **remedidas** em 2026-09-09, porque a leitura de 2026-09-08 estava errada no *quê*, e a de 2026-09-09 estava errada no *onde* (as duas retificações estão no callout abaixo); e `builder.AddAIAgent` (§Keyed singleton) é `Microsoft.Agents.AI.Hosting.HostApplicationBuilderAgentExtensions` — cinco sobrecargas, na assembly **`Microsoft.Agents.AI.Hosting` 1.20.0.0**, que vem do pacote **`Microsoft.Agents.AI.Hosting` `1.20.0-preview.260831.1`**: ele é **prerelease** e está **FORA do `ai-pin.json`** (apurado em `scripts/api-probe/companions.json`, 2026-09-08) — quem adotar esta seção registra a dependência prerelease em `
|
|
8
|
+
**Verified against:** Microsoft.Agents.AI 1.20.0 + Microsoft.Extensions.AI 10.9.0 (ai-pin 2026-09-08). **Verificação documental**, sem cláusula `provado por` — o ai-kit não traz loader de prompt, e os dois mecanismos descritos aqui são destilados de três produtos em produção. As **quatro** superfícies de API que este standard cita foram medidas por reflexão, e vivem em **três assemblies diferentes** — o carimbo diz onde remedir, então o nome importa: `IChatClient.AsAIAgent(instructions:, name:)` é `Microsoft.Extensions.AI.ChatClientExtensions`, em **`Microsoft.Agents.AI` 1.20.0** (medida em 2026-09-08); `AIAgent.RunAsync` (as oito sobrecargas) e `AIAgent.CreateSessionAsync` são de `Microsoft.Agents.AI.AIAgent`, na assembly **`Microsoft.Agents.AI.Abstractions` 1.20.0** — **remedidas** em 2026-09-09, porque a leitura de 2026-09-08 estava errada no *quê*, e a de 2026-09-09 estava errada no *onde* (as duas retificações estão no callout abaixo); e `builder.AddAIAgent` (§Keyed singleton) é `Microsoft.Agents.AI.Hosting.HostApplicationBuilderAgentExtensions` — cinco sobrecargas, na assembly **`Microsoft.Agents.AI.Hosting` 1.20.0.0**, que vem do pacote **`Microsoft.Agents.AI.Hosting` `1.20.0-preview.260831.1`**: ele é **prerelease** e está **FORA do `ai-pin.json`** (apurado em `scripts/api-probe/companions.json`, 2026-09-08) — quem adotar esta seção registra a dependência prerelease em `plan.md` (`## Decisões`), como manda `ai-agents-production`. **Duas ressalvas de escopo**, porque um carimbo que não as diz promete mais do que mediu: `Microsoft.Agents.AI.Abstractions` e `Microsoft.Extensions.AI.Abstractions` são nomes de **assembly** (elas viajam dentro dos pacotes `Microsoft.Agents.AI` e `Microsoft.Extensions.AI`), não ids de pacote; e `IMemoryCache`/`DbContext`, usados no padrão de cache e na §Keyed singleton, são superfícies de ASP.NET Core e EF Core — **fora do pin, não medidas aqui, verificação documental**. Last-verified: 2026-09-08.
|
|
9
9
|
|
|
10
10
|
---
|
|
11
11
|
|
|
@@ -356,7 +356,7 @@ rastreabilidade (hash em span, prompt cru só em harness) está em `ai-agents-ob
|
|
|
356
356
|
- [ ] `GetActivePromptAsync` throws `InvalidOperationException` (not returns null) when no active prompt found
|
|
357
357
|
- [ ] Versionamento pattern followed: INSERT + flip, never UPDATE content
|
|
358
358
|
- [ ] At least one seed row per `agent_key` in migrations or seed script
|
|
359
|
-
- [ ] A fonte escolhida (banco versionado × composição por tenant) está nomeada no `
|
|
359
|
+
- [ ] A fonte escolhida (banco versionado × composição por tenant) está nomeada no `plan.md` (`## Decisões`),
|
|
360
360
|
com a pergunta "o texto varia por cliente?" respondida
|
|
361
361
|
- [ ] No caminho composto: a moldura e o YAML estão versionados no repo, e o blob publicado **não** é
|
|
362
362
|
editado à mão
|
|
@@ -185,7 +185,7 @@ Going through `Microsoft.Extensions.AI` (`IChatClient`) or the MAF (`AIAgent`) k
|
|
|
185
185
|
| **Anthropic Claude** | `anthropic` | Confirm current SDK on NuGet before use | ignora o campo | Adapt provider client to `IChatClient` |
|
|
186
186
|
| **Azure OpenAI** (opt-in, not default) | `azure-openai` | `Azure.AI.OpenAI` + `Azure.Identity` — confirm exact versions on NuGet before use | segue o OpenAI | Add only when a client requires data residency |
|
|
187
187
|
|
|
188
|
-
> **Restore trap, measured 2026-09-08:** `Microsoft.Extensions.AI.OpenAI` 10.9.0 declares `OpenAI (>= 2.12.0 && < 2.13.0)`. Pairing it with the pinned `OpenAI` 2.13.0 emits **NU1608** on restore. Either pin `OpenAI` to 2.12.x alongside the bridge, or accept the warning knowingly and write the decision in `
|
|
188
|
+
> **Restore trap, measured 2026-09-08:** `Microsoft.Extensions.AI.OpenAI` 10.9.0 declares `OpenAI (>= 2.12.0 && < 2.13.0)`. Pairing it with the pinned `OpenAI` 2.13.0 emits **NU1608** on restore. Either pin `OpenAI` to 2.12.x alongside the bridge, or accept the warning knowingly and write the decision in `plan.md` (`## Decisões`). Do not discover this in CI.
|
|
189
189
|
|
|
190
190
|
**No floating ranges.** Every `PackageReference` above is an exact version. A floating `2.*` on a weekly-cadence SDK is how ProspectPRO bought a `MissingMethodException` on the Responses API **after paying for the call** (`docs/specs/elevacao-9/brutos/scan-prospectpro.md:55`).
|
|
191
191
|
|
|
@@ -179,7 +179,7 @@ Registered on the agent with `tools: [AIFunctionFactory.Create(tool.SearchAsync)
|
|
|
179
179
|
|
|
180
180
|
The `tenant_id` filter is **never a tool parameter** (that would allow the LLM to cross tenant boundaries). It is injected via a constructor dependency — e.g., a scoped `ITenantContext` or a `Guid currentTenantId` resolved from the authenticated request. See §Multi-tenant below.
|
|
181
181
|
|
|
182
|
-
Note on raw Npgsql vs EF Core: the EF Core LINQ form above is the default (`ApplicationDbContext` in the slice, no raw SQL). A raw `NpgsqlDataSource` query is acceptable only with a `
|
|
182
|
+
Note on raw Npgsql vs EF Core: the EF Core LINQ form above is the default (`ApplicationDbContext` in the slice, no raw SQL). A raw `NpgsqlDataSource` query is acceptable only with a `plan.md` (`## Decisões`) justification (e.g. a project with no EF Core model for this table). The legacy `VectorSearchTool.cs.template` still uses raw SQL and `EmbeddingService`; prefer the block above.
|
|
183
183
|
|
|
184
184
|
---
|
|
185
185
|
|
|
@@ -319,7 +319,7 @@ ALTER TABLE kb_embeddings ENABLE ROW LEVEL SECURITY;
|
|
|
319
319
|
- [ ] `VectorSearchTool` registered on the agent via `AIFunctionFactory.Create(tool.SearchAsync)`.
|
|
320
320
|
- [ ] No `Microsoft.SemanticKernel` references in the project.
|
|
321
321
|
- [ ] Vector dimensions consistent between embedding model and `vector(N)` column definition.
|
|
322
|
-
- [ ] RLS enabled on `kb_embeddings` (or equivalent app-level guard documented in `
|
|
322
|
+
- [ ] RLS enabled on `kb_embeddings` (or equivalent app-level guard documented in `plan.md` (`## Decisões`)).
|
|
323
323
|
- [ ] Ingestion follows §*Ingestão delta por lookup-key*: a pure `Plan(...)` produces `Added`/`Updated`/`Removed`/`Unchanged`, and `Unchanged` is never re-embedded.
|
|
324
324
|
- [ ] No `DELETE`-everything-then-reinsert: `Removed` is applied **after** `Added`/`Updated`, in the same transaction — there is no window where the search returns empty.
|
|
325
325
|
- [ ] `Updated` is an **upsert** on a deterministic id, never delete+insert.
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
> **Scope:** stacks=["dotnet"]
|
|
4
4
|
> **Layer:** 0 (lista da persona `maf-expert`; resumo injetado pela rule `ai-agents-standards` em `**/Agents/**`, `**/agents/**`, `**/*Agent*.cs`; texto completo sob demanda via `morph-spec standards --find`)
|
|
5
5
|
> **Keywords:** maf setup, microsoft agents ai, chatclient, ai agent, agent framework, agent dotnet, AsAIAgent, responses api, chat completions, store false
|
|
6
|
-
> **Read by Claude in:** plan (pra citar pacote
|
|
6
|
+
> **Read by Claude in:** plan (pra citar pacote no plan.md) + implement (pra escrever .csproj e Program.cs)
|
|
7
7
|
|
|
8
8
|
**Verified against:** Microsoft.Agents.AI 1.20.0 + Microsoft.Extensions.AI 10.9.0 + OpenAI 2.13.0 (ai-pin 2026-09-08); provado por `templates/dotnet/ai-kit/src/Morph.AiKit/Agents/AgentFactory.cs` (pipeline e escolha de protocolo). A superfície do SDK `OpenAI` e das pontes `Microsoft.Agents.AI.OpenAI` / `Microsoft.Extensions.AI.OpenAI` foi **medida por reflexão sobre as assemblies do pin** em 2026-09-08 — o ai-kit **não exercita** o cliente concreto da OpenAI — referencia o pacote no `.csproj`, mas não há `using OpenAI` em `src/` (medido 2026-09-08); ver a tabela "Dois níveis de garantia" no README do kit. Last-verified: 2026-09-08.
|
|
9
9
|
|
|
@@ -62,7 +62,7 @@ Está adicionando um agente AI a um projeto .NET?
|
|
|
62
62
|
<!-- Azure OpenAI (somente se data residency exigir) — confira Azure.AI.OpenAI + Azure.Identity no NuGet -->
|
|
63
63
|
```
|
|
64
64
|
|
|
65
|
-
> **Armadilha de restore, medida em 2026-09-08:** `Microsoft.Extensions.AI.OpenAI` 10.9.0 declara a dependência `OpenAI (>= 2.12.0 && < 2.13.0)`. Com o `OpenAI` **2.13.0** do pin, o `dotnet restore` emite **NU1608** (*"Versão detectada do pacote fora da restrição de dependência"*). Duas saídas honestas: fixar `OpenAI` em 2.12.x ao lado da ponte, **ou** aceitar o aviso conscientemente e registrar a decisão em `
|
|
65
|
+
> **Armadilha de restore, medida em 2026-09-08:** `Microsoft.Extensions.AI.OpenAI` 10.9.0 declara a dependência `OpenAI (>= 2.12.0 && < 2.13.0)`. Com o `OpenAI` **2.13.0** do pin, o `dotnet restore` emite **NU1608** (*"Versão detectada do pacote fora da restrição de dependência"*). Duas saídas honestas: fixar `OpenAI` em 2.12.x ao lado da ponte, **ou** aceitar o aviso conscientemente e registrar a decisão em `plan.md` (`## Decisões`). Não descubra isso no CI.
|
|
66
66
|
|
|
67
67
|
> **De onde vem cada extensão** (medido por reflexão sobre as assemblies do pin, 2026-09-08):
|
|
68
68
|
> | Extensão | Assembly que a publica | Namespace do `using` |
|
|
@@ -155,7 +155,7 @@ Fontes, ambas lidas em 2026-09-08:
|
|
|
155
155
|
|
|
156
156
|
A Responses API **armazena por padrão**. OpenAI, mesmo guia, verbatim: *"Responses are stored by default. Chat completions are stored by default for new accounts. To disable storage when using either API, set `store: false`."* Respostas retidas ficam 30 dias no provedor.
|
|
157
157
|
|
|
158
|
-
Projetos desta casa mantêm o histórico **próprio** (ver `ai-agents-agent-session`), então não se quer uma segunda cópia da conversa no provedor. **Regra: `store: false` explícito.** Quem quiser o oposto registra o porquê em `
|
|
158
|
+
Projetos desta casa mantêm o histórico **próprio** (ver `ai-agents-agent-session`), então não se quer uma segunda cópia da conversa no provedor. **Regra: `store: false` explícito.** Quem quiser o oposto registra o porquê em `plan.md` (`## Decisões`).
|
|
159
159
|
|
|
160
160
|
O MAF tem um atalho de primeira classe para isso — medido na assembly `Microsoft.Agents.AI.OpenAI` 1.20.0:
|
|
161
161
|
|
|
@@ -105,11 +105,11 @@ You may need to step outside the sweet spot when:
|
|
|
105
105
|
|
|
106
106
|
## Checklist (verifiable in review)
|
|
107
107
|
|
|
108
|
-
- [ ] Was each agent designed as single-agent BEFORE reaching for multi-agent? (Check `
|
|
108
|
+
- [ ] Was each agent designed as single-agent BEFORE reaching for multi-agent? (Check `plan.md` (`## Decisões`).)
|
|
109
109
|
- [ ] If a Workflow is used, is fan-in/out or HITL checkpointing genuinely present? Or could `foreach + LINQ` replace it?
|
|
110
110
|
- [ ] Are the 4 features (Chat, Structured Output, Tools, RAG Custom) all present where applicable?
|
|
111
111
|
- [ ] Are hosted agent services avoided?
|
|
112
|
-
- [ ] Nenhum agente carrega mais de ~12 tools sem uma decisão escrita em `
|
|
112
|
+
- [ ] Nenhum agente carrega mais de ~12 tools sem uma decisão escrita em `plan.md` (`## Decisões`) sobre a poda
|
|
113
113
|
|
|
114
114
|
---
|
|
115
115
|
|
|
@@ -210,8 +210,6 @@ MORPH_GHLBrain, `src/Morph.GHLBrain/Features/Conversation/Operator/`:
|
|
|
210
210
|
| `set_lead_fields` | `Tools/SetLeadFieldsTool.cs` | `Ops/DossieOps.cs` | `CamposDesfecho` |
|
|
211
211
|
| `route_lead` | `Tools/RouteLeadTool.cs` | `Ops/TriagemOps.cs` | `TriagemDesfecho` |
|
|
212
212
|
|
|
213
|
-
As decisões estão em `.morph/features/tools-finas/2-plan/decisions.md` (ADR-1 e ADR-2) daquele repositório.
|
|
214
|
-
|
|
215
213
|
## Regras
|
|
216
214
|
|
|
217
215
|
- **ALWAYS** a regra de uma tool vai numa `sealed class XOps(...)` com construtor primário e `AddScoped` explícito
|
|
@@ -86,7 +86,7 @@ Preview packages are subject to breaking API changes before GA (see the rename `
|
|
|
86
86
|
|-----------|-----|
|
|
87
87
|
| Default production RAG on Neon/Postgres (this framework's default stack), **already implemented and tested** | **`ai-agents-rag-custom-pgvector`** — framework-owned raw SQL, zero external connector, already the checklisted default. **Não se migra o que funciona** (item D4 da elevação-9) |
|
|
88
88
|
| **Projeto novo** onde a escolha do store ainda não foi cravada, e trocá-lo depois deve custar pouco | `Microsoft.Extensions.VectorData.Abstractions` 10.9.0 + `CommunityToolkit.VectorData.PgVector` 1.0.1 — hoje **ambos estáveis**, o que remove o argumento "é preview" que existia em julho/2026 |
|
|
89
|
-
| Project needs genuine portability across >1 vector backend (a client contract requires swapping Postgres for Qdrant or Azure AI Search later) | `Microsoft.Extensions.VectorData` + o conector correspondente — document the choice in `
|
|
89
|
+
| Project needs genuine portability across >1 vector backend (a client contract requires swapping Postgres for Qdrant or Azure AI Search later) | `Microsoft.Extensions.VectorData` + o conector correspondente — document the choice in `plan.md` (`## Decisões`) |
|
|
90
90
|
| Prototyping, tests, or demos where an in-memory store is enough | `CommunityToolkit.VectorData.InMemory` 1.0.1 |
|
|
91
91
|
| Ingestão em pipeline (reader → chunker → writer) hoje | Só com `Microsoft.Extensions.DataIngestion`, que **continua preview**: registre a aceitação e um lembrete de revisitar no GA |
|
|
92
92
|
|
|
@@ -175,10 +175,10 @@ This maps conceptually onto the existing custom pattern: `IngestionDocumentReade
|
|
|
175
175
|
|
|
176
176
|
- [ ] If `Microsoft.SemanticKernel.Connectors.*` appears in a `.csproj`, it is used only for `VectorStoreCollection`/`VectorStore` types — no `Kernel`, `KernelFunction`, or `ChatHistory` usage anywhere in the project.
|
|
177
177
|
- [ ] No plain `Microsoft.SemanticKernel` (core) package reference.
|
|
178
|
-
- [ ] If VectorData was chosen over custom pgvector, the reason is recorded in `
|
|
178
|
+
- [ ] If VectorData was chosen over custom pgvector, the reason is recorded in `plan.md` (`## Decisões`) per the decision matrix.
|
|
179
179
|
- [ ] No new `Microsoft.SemanticKernel.Connectors.*` reference — new work uses `CommunityToolkit.VectorData.*`.
|
|
180
|
-
- [ ] If a preview package (`Microsoft.Extensions.DataIngestion`, or any `*-preview` connector) was adopted, `
|
|
181
|
-
- [ ] Every VectorData/ingestion `PackageReference` carries an exact version — these packages are **not** in `framework/ai-pin.json`, so the project's own `
|
|
180
|
+
- [ ] If a preview package (`Microsoft.Extensions.DataIngestion`, or any `*-preview` connector) was adopted, `plan.md` (`## Decisões`) records the preview-acceptance and a revisit-at-GA note.
|
|
181
|
+
- [ ] Every VectorData/ingestion `PackageReference` carries an exact version — these packages are **not** in `framework/ai-pin.json`, so the project's own `plan.md` (`## Decisões`) (or a comment) states when the version was checked.
|
|
182
182
|
- [ ] Embedding model/dimensions consistent between the `VectorStoreVector(N)` attribute and the chosen embedding model.
|
|
183
183
|
|
|
184
184
|
---
|
|
@@ -186,7 +186,7 @@ Sempre use `await using` no `StreamingRun` / `Run` — é `IAsyncDisposable`.
|
|
|
186
186
|
## Checklist (verifiable in review)
|
|
187
187
|
|
|
188
188
|
- [ ] Foi verificado que um `foreach` ou single agent não resolve o problema?
|
|
189
|
-
- [ ] O critério de fan-in/out genuíno ou HITL está documentado em `
|
|
189
|
+
- [ ] O critério de fan-in/out genuíno ou HITL está documentado em `plan.md` (`## Decisões`)?
|
|
190
190
|
- [ ] `Microsoft.Agents.AI` 1.0.* presente no `.csproj` (sem pacotes preview separados)?
|
|
191
191
|
- [ ] Agents referenciando alias do Model Registry (não model strings hardcoded)?
|
|
192
192
|
- [ ] `await using` no `StreamingRun` / `Run`?
|
|
@@ -41,10 +41,10 @@ Só o **porquê que o código não mostra**:
|
|
|
41
41
|
|
|
42
42
|
## O que não merece
|
|
43
43
|
|
|
44
|
-
- **História de processo.**
|
|
45
|
-
implementar a
|
|
46
|
-
data e autor e não envelhece dentro do arquivo. Em teste, o elo com
|
|
47
|
-
do teste (`
|
|
44
|
+
- **História de processo.** Fatia, cenário, ADR, Gate, avaliador, `plan.md`, mockup, "confirmado ao
|
|
45
|
+
implementar a F2", "o Gate 3 pediu". Isso vai na mensagem de commit e no `plan.md`, onde tem
|
|
46
|
+
data e autor e não envelhece dentro do arquivo. Em teste, o elo com o cenário vai no **nome**
|
|
47
|
+
do teste (`C5_estado_do_lead_espelha_o_crm`, `DisplayName`), nunca em `// C5`.
|
|
48
48
|
- **Repetição do código.** `// incrementa o contador` sobre `count++`, `// valida o request` sobre
|
|
49
49
|
`validator.Validate(request)`. Nome bom substitui comentário.
|
|
50
50
|
- **Doc-comment que repete a assinatura.** `/// <summary>Obtém o pedido.</summary>` sobre
|
|
@@ -62,7 +62,7 @@ Só o **porquê que o código não mostra**:
|
|
|
62
62
|
## Tamanho
|
|
63
63
|
|
|
64
64
|
Uma linha é o normal; teto de ~3. Acima disso o comentário justifica o volume (algoritmo não
|
|
65
|
-
óbvio, armadilha de terceiro com a reprodução). Bloco longo narrando decisões é `
|
|
65
|
+
óbvio, armadilha de terceiro com a reprodução). Bloco longo narrando decisões é `plan.md` (`## Decisões`) com
|
|
66
66
|
outro nome. Em volume, código de aplicação fica perto de zero: mais de uma linha de comentário a
|
|
67
67
|
cada dez de código é sinal de que os nomes não estão fazendo o trabalho. Arquivo vizinho muito
|
|
68
68
|
comentado não é modelo: código novo segue este padrão, não a densidade do legado.
|
|
@@ -70,12 +70,12 @@ comentado não é modelo: código novo segue este padrão, não a densidade do l
|
|
|
70
70
|
## Exemplo
|
|
71
71
|
|
|
72
72
|
```ts
|
|
73
|
-
// Ruim: rotula, conta a
|
|
73
|
+
// Ruim: rotula, conta a fatia, repete o código e afirma comportamento que nenhum teste cobra.
|
|
74
74
|
/**
|
|
75
75
|
* Salva o documento.
|
|
76
76
|
* @param doc o documento
|
|
77
77
|
*/
|
|
78
|
-
//
|
|
78
|
+
// F2 + C3: mutação obrigatória do relatório, item c. Faz upsert e nunca duplica.
|
|
79
79
|
async function save(doc: Doc) {
|
|
80
80
|
await upsert({ key: doc.sourceId, hash: sha256(doc.body) });
|
|
81
81
|
}
|
|
@@ -333,7 +333,7 @@ var page = await _db.Books
|
|
|
333
333
|
(ex.: `SELECT ... FOR UPDATE`, retry de `DbUpdateConcurrencyException`) ou SQL específico
|
|
334
334
|
que o LINQ não expressa, escreva um store hand-written e purpose-built (ex.: `OutboxStore`,
|
|
335
335
|
`LeaseStore`) com métodos nomeados pela intenção — e registre a justificativa em
|
|
336
|
-
`
|
|
336
|
+
`plan.md` (`## Decisões`). Nunca um genérico por entidade.
|
|
337
337
|
|
|
338
338
|
Veja `backend/dotnet/vsa-handler-patterns.md` → "Data Access: DbContext in the Slice".
|
|
339
339
|
|
|
@@ -173,7 +173,7 @@ The state check (`>= Completed`) and the business rule (`RequiresPayment && !IsP
|
|
|
173
173
|
- [ ] Failures come back as `ValidationError` → 400 ProblemDetails with `errors[]`, never an exception?
|
|
174
174
|
- [ ] Existence / uniqueness / state checks in the handler, returning typed `Error`s?
|
|
175
175
|
- [ ] State checks validate INVALID states, with the error range at 100+?
|
|
176
|
-
- [ ] All flows documented in
|
|
176
|
+
- [ ] All flows documented in plan.md (## Decisões) and tested?
|
|
177
177
|
|
|
178
178
|
---
|
|
179
179
|
|
|
@@ -225,13 +225,13 @@ public sealed class SearchBooksHandler(
|
|
|
225
225
|
When a slice needs concurrency control (`SELECT ... FOR UPDATE`, lease/outbox semantics,
|
|
226
226
|
`DbUpdateConcurrencyException` retry loops) or SQL that LINQ cannot express, write a
|
|
227
227
|
**hand-written, purpose-built store** with intention-named methods (e.g. `OutboxStore.ClaimBatchAsync`,
|
|
228
|
-
`LeaseStore.TryAcquireAsync`) — and document the justification in `
|
|
228
|
+
`LeaseStore.TryAcquireAsync`) — and document the justification in `plan.md` (`## Decisões`).
|
|
229
229
|
Never a generic-per-entity abstraction.
|
|
230
230
|
|
|
231
231
|
**Rule of thumb:** everything → `ApplicationDbContext` in the slice. Concurrency or
|
|
232
|
-
specific SQL → dedicated hand-written store + `
|
|
232
|
+
specific SQL → dedicated hand-written store + `plan.md` (`## Decisões`) entry. Never reach for raw SQL
|
|
233
233
|
(`FromSqlRaw`) unless a query genuinely cannot be expressed in LINQ — and document that
|
|
234
|
-
in `
|
|
234
|
+
in `plan.md` (`## Decisões`).
|
|
235
235
|
|
|
236
236
|
---
|
|
237
237
|
|
|
@@ -307,8 +307,8 @@ builder.Services.AddExceptionHandler<CustomExceptionHandler>()
|
|
|
307
307
|
| Share handlers across features | Each feature has its own handler, even if similar |
|
|
308
308
|
| Use constructor + field for DI | Use primary constructors: `class Handler(IDep dep)` |
|
|
309
309
|
| Group by technical concern (Controllers/, Services/) | Group by feature: `Features/BookFeature/CreateBook/` |
|
|
310
|
-
| Route data access through any indirection layer | Inject `DbContext` and write LINQ in the slice; dedicated store only with `
|
|
311
|
-
| Use raw SQL (`FromSqlRaw` / `ExecuteQuery(string)`) by default | Use LINQ; raw SQL only with a `
|
|
310
|
+
| Route data access through any indirection layer | Inject `DbContext` and write LINQ in the slice; dedicated store only with `plan.md` (`## Decisões`) justification |
|
|
311
|
+
| Use raw SQL (`FromSqlRaw` / `ExecuteQuery(string)`) by default | Use LINQ; raw SQL only with a `plan.md` (`## Decisões`) justification |
|
|
312
312
|
|
|
313
313
|
---
|
|
314
314
|
|
|
@@ -15,7 +15,7 @@ Background job processing for .NET 10 VSA applications with Hangfire on Neon Pos
|
|
|
15
15
|
|
|
16
16
|
## When to use Hangfire
|
|
17
17
|
|
|
18
|
-
Hangfire is in the stack **only with a real reason**: work that must survive a process restart, run on a schedule, or be retried later (daily reindex, delayed reminders, retrying a flaky third party). Work that fits in the request (send one email after a signup, index one uploaded document) runs in the slice handler. Record the reason in `
|
|
18
|
+
Hangfire is in the stack **only with a real reason**: work that must survive a process restart, run on a schedule, or be retried later (daily reindex, delayed reminders, retrying a flaky third party). Work that fits in the request (send one email after a signup, index one uploaded document) runs in the slice handler. Record the reason in `plan.md` (`## Decisões`).
|
|
19
19
|
|
|
20
20
|
Hangfire provides fire-and-forget, delayed and recurring (cron) jobs, continuations, a dashboard and automatic retries.
|
|
21
21
|
|
|
@@ -64,7 +64,7 @@ place to audit.
|
|
|
64
64
|
**The exception process:** a feature that genuinely needs the frontend to reach Neon directly for
|
|
65
65
|
business data (for example, via the Neon MCP `provision_neon_data_api` tool) is an exception, not a
|
|
66
66
|
default — treat it exactly like vertical-slice.md's "Stores dedicados (exceção justificada)" clause:
|
|
67
|
-
document the justification in the feature's `
|
|
67
|
+
document the justification in the feature's `plan.md` (`## Decisões`) before writing the code. A tool being
|
|
68
68
|
available is not, by itself, justification.
|
|
69
69
|
|
|
70
70
|
See [Row-Level Security Integration](#row-level-security-integration) for how to constrain a
|
|
@@ -727,7 +727,7 @@ Each Neon branch gets its own isolated auth data. This means:
|
|
|
727
727
|
fetch and cache the JWKS yourself and verify EdDSA signatures manually (BouncyCastle)
|
|
728
728
|
11. **Route business data through the .NET backend by default** — the frontend's only inherent
|
|
729
729
|
reason to talk to Neon directly is its own auth/session SDK; a direct Data API call needs a
|
|
730
|
-
`
|
|
730
|
+
`plan.md` (`## Decisões`) ADR (see [Data Access Boundary](#data-access-boundary--backend-first-by-default))
|
|
731
731
|
|
|
732
732
|
---
|
|
733
733
|
|
|
@@ -179,4 +179,4 @@ The minute comes from `TimeProvider` (testable with `FakeTimeProvider`), never `
|
|
|
179
179
|
- Never omit TTL -- unbounded keys fill memory
|
|
180
180
|
- Never wrap the cache in a `XService`/repository class -- cache-aside is three lines in the handler
|
|
181
181
|
- Never return `null` for "not found" -- the handler returns `Result` with `NotFound`
|
|
182
|
-
- Never swallow `RedisConnectionException` in an empty `catch`: a cache outage must be visible (health check + logs). Falling back to the database while Redis is down is a product decision: record it in `
|
|
182
|
+
- Never swallow `RedisConnectionException` in an empty `catch`: a cache outage must be visible (health check + logs). Falling back to the database while Redis is down is a product decision: record it in `plan.md` (`## Decisões`) and implement it once, at the cache boundary, not per call site
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
> **Scope:** data-nosql
|
|
4
4
|
> **Layer:** 3 (opcional — nenhuma rule nem persona o carrega; só sob demanda via `morph-spec standards --find`, depois de a decisão existir)
|
|
5
5
|
> **Keywords:** cosmos-db, nosql, document-database, event-store, partition-key, azure-cosmos
|
|
6
|
-
> **Load When:** `
|
|
6
|
+
> **Load When:** `plan.md` (`## Decisões`) already records the choice of Cosmos DB over Neon for a specific store
|
|
7
7
|
|
|
8
8
|
**Verified against:** .NET 10 (SDK 10.0.400-preview) + Microsoft.Azure.Cosmos 3.63.2 + Newtonsoft.Json 13.0.4 — every `csharp` block below compiles with `TreatWarningsAsErrors` against the `Result`/`Error` types of `backend-dotnet-result-pattern`. Last-verified: 2026-10-03.
|
|
9
9
|
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
|
|
12
12
|
## Overview
|
|
13
13
|
|
|
14
|
-
**Cosmos DB is not part of the stack.** The default store is Neon (Postgres) through EF Core, with the `ApplicationDbContext` used directly in the slice. Reach for Cosmos only when a requirement Postgres cannot meet is written down in `
|
|
14
|
+
**Cosmos DB is not part of the stack.** The default store is Neon (Postgres) through EF Core, with the `ApplicationDbContext` used directly in the slice. Reach for Cosmos only when a requirement Postgres cannot meet is written down in `plan.md` (`## Decisões`) (the "why not Neon" included). Everything below applies the stack conventions to that exception: the client is injected straight into the slice handler, ids are `Guid.CreateVersion7()`, expected failures are `Result` values, and classes are `sealed`.
|
|
15
15
|
|
|
16
16
|
## When It Can Be Justified
|
|
17
17
|
|
|
@@ -155,7 +155,7 @@ using var feed = container.GetItemQueryIterator<OrderEvent>(
|
|
|
155
155
|
|
|
156
156
|
| Do NOT | Do Instead |
|
|
157
157
|
|--------|------------|
|
|
158
|
-
| Pick Cosmos without a `
|
|
158
|
+
| Pick Cosmos without a `plan.md` (`## Decisões`) entry | Neon (Postgres) via EF Core is the default store |
|
|
159
159
|
| Wrap `Container` in a generic `CosmosRepository<T>` | Inject the keyed `Container` into the slice handler |
|
|
160
160
|
| `try/catch (CosmosException)` for 404/409 | Stream APIs + `StatusCode` → `Result` |
|
|
161
161
|
| `Guid.NewGuid()` for document ids | `Guid.CreateVersion7()` |
|
|
@@ -16,7 +16,7 @@ An admin app has **one** form pattern. It is the base pattern of `nextjs/forms.m
|
|
|
16
16
|
- **The Zod schema is shared.** The same schema types the form, validates it, and parses the API response (`admin-app/data-table.md` parses the list query with Zod too). One source of truth per entity.
|
|
17
17
|
- **react-hook-form keeps inputs uncontrolled** — a 30-field form does not re-render on every keystroke, which is what `useState` per field does.
|
|
18
18
|
- **shadcn's current form docs are written around it** (`Field`, `FieldLabel`, `FieldError` + `Controller`).
|
|
19
|
-
- **Coexisting styles are the defect this rule exists for.** Measured in a real admin app: three form styles side by side (react-hook-form in some screens, hand-rolled `useState` in others) — three validation behaviours for one product, and a redesign that changed none of them. A screen that needs something the pattern cannot do registers the exception in `
|
|
19
|
+
- **Coexisting styles are the defect this rule exists for.** Measured in a real admin app: three form styles side by side (react-hook-form in some screens, hand-rolled `useState` in others) — three validation behaviours for one product, and a redesign that changed none of them. A screen that needs something the pattern cannot do registers the exception in `plan.md` (`## Decisões`); it does not start a fourth style.
|
|
20
20
|
|
|
21
21
|
## Core Rules
|
|
22
22
|
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# Art Direction — Decide What the Screen Is Before Drawing It
|
|
2
|
+
|
|
3
|
+
> **Scope:** frontend-design-system
|
|
4
|
+
> **Layer:** 3
|
|
5
|
+
> **Keywords:** art direction, concept, visual metaphor, design direction, template look, generic ui, memorable, mobile-first, brand moment
|
|
6
|
+
> **Load When:** ui-designer active, before any component of a new or changed screen
|
|
7
|
+
|
|
8
|
+
**Verified against:** the `login-ciclo-do-produto` design round (2026-10-06): a correct, plain design was rejected; a second round with a written direction, an HTML prototype and a screenshot self-review was approved on first sight. Last-verified: 2026-10-06.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
A design that follows the tokens, has every state and passes WCAG can still be forgettable. What made the difference in practice was not talent but order: a direction written before any component, a real prototype, and a critical look at the rendered result. This standard is the first of the three.
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Section 1: Write the Direction First
|
|
17
|
+
|
|
18
|
+
Before the first component, answer four questions in `1-design/direcao.md`:
|
|
19
|
+
|
|
20
|
+
1. **Concept in one sentence.** What the screen says, not what it contains. *"The login tells the product cycle in scenes while you sign in."*
|
|
21
|
+
2. **Visual metaphor.** The image that organizes the layout. *Stories; a control room; a ticket being stamped; a garden that grows.*
|
|
22
|
+
3. **What makes it memorable.** The one thing someone would describe to a colleague. If nothing, the direction is not done.
|
|
23
|
+
4. **What it must NOT look like.** Name the generic version you are avoiding (Section 4).
|
|
24
|
+
|
|
25
|
+
Only then pick components. A component chosen before the direction is chosen by habit.
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Section 2: Explore Two or Three Directions
|
|
30
|
+
|
|
31
|
+
For a new screen or a brand moment (login, onboarding, first screen, empty state, success, showcase), write two or three directions that are **distinct**, not three color variations of one layout. For each: concept, metaphor, the mobile idea, the motion idea, and the risk. Recommend one and say why, in terms of the product and the user, not taste.
|
|
32
|
+
|
|
33
|
+
A changed screen inside an established system may need only one direction, written the same way, with what changes and why.
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Section 3: Good and Bad Directions
|
|
38
|
+
|
|
39
|
+
| Bad direction | Why it fails | Good direction |
|
|
40
|
+
|---|---|---|
|
|
41
|
+
| "Clean, modern login with the logo and a form." | Describes every login. Nothing to remember. | "The panel tells the product cycle in three scenes, stories-style; the form is a sheet the thumb reaches." |
|
|
42
|
+
| "Dashboard with cards for each metric." | Content, not concept. Layout by habit. | "A control room: one hero number the operator acts on, the rest as quiet instruments around it." |
|
|
43
|
+
| "Empty state with an icon and a button." | The default of every kit. | "The empty list is the first page of a notebook: an illustrated first entry shows what a good one looks like." |
|
|
44
|
+
| "Mobile: same layout, stacked." | Mobile derived, not designed. | "Mobile is an app: bottom sheet, thumb-zone actions, the scene compressed to a strip above." |
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Section 4: Template Tells to Avoid
|
|
49
|
+
|
|
50
|
+
Each one is fine in isolation; together they read as "generated". If the screen has three or more, raise it.
|
|
51
|
+
|
|
52
|
+
- Raw shadcn look: default radius, default gray border, no brand in any surface.
|
|
53
|
+
- A white card centered on a gray background, logo on top, form inside.
|
|
54
|
+
- A generic icon list (three features, three Lucide icons, three lines of copy).
|
|
55
|
+
- Stack-default or AI-tell fonts with no tracking or scale decision (see `premium-finish` Section 1).
|
|
56
|
+
- Flat solid backgrounds with no light, layer or texture.
|
|
57
|
+
- Mobile as the desktop stacked: centered card, tiny targets, actions out of thumb reach.
|
|
58
|
+
- Motion as decoration: everything fades in, nothing tells a sequence.
|
|
59
|
+
- Made-up numbers on illustrative cards (`R$ 12.430`, `98% satisfaction`).
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## Section 5: Mobile Is Designed, Not Derived
|
|
64
|
+
|
|
65
|
+
Draw the phone at 390 px as its own composition: bottom sheet for the primary task, actions in the thumb zone, targets of at least 44 px, the brand scene compressed rather than removed. Then check the desktop is not the phone blown up either.
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## Section 6: Motion With Intent
|
|
70
|
+
|
|
71
|
+
Motion should tell something (a sequence, a cause, a state change). Pick the lightest tool that delivers it: CSS transition and `@keyframes`, then CSS scroll-driven animation, then Framer Motion, then GSAP with ScrollTrigger and timelines. Budget: 60 fps, only `transform` and `opacity`, no layout thrash, lazy below the fold. `prefers-reduced-motion` gets a composed static version, designed as carefully as the animated one.
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## Section 7: Prototype and Self-Review
|
|
76
|
+
|
|
77
|
+
The direction is proved in a rendered prototype, not in prose: `1-design/prototipos/{screen}.html`, self-contained, using the project's REAL tokens read from its token CSS (the design-system doc can be stale), desktop and phone side by side in a device frame, with animated / static / pause controls. Serve it over local HTTP, screenshot at 1280 and 390, judge against this standard and the system bar (hierarchy, contrast, rhythm, mobile, "does it look like a template?"), fix, repeat. The final screenshots sit next to the HTML.
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## Checklist
|
|
82
|
+
|
|
83
|
+
- [ ] `direcao.md` answers concept, metaphor, memorable, must-not-look-like
|
|
84
|
+
- [ ] Two or three distinct directions for a new screen or brand moment, one recommended with a reason
|
|
85
|
+
- [ ] Fewer than three template tells on the final screen
|
|
86
|
+
- [ ] Mobile composed at 390 px on its own terms
|
|
87
|
+
- [ ] Motion tells something, with a composed reduced-motion version
|
|
88
|
+
- [ ] Prototype rendered, screenshotted at 1280 and 390, and revised until it passes
|