@polymorphism-tech/morph-spec 8.32.0 → 8.34.2
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 +4 -0
- package/README.md +2 -2
- package/bin/morph-spec.js +26 -2
- package/bin/validate.js +379 -379
- package/claude-plugin.json +1 -1
- package/docs/CHEATSHEET.md +1 -1
- package/docs/QUICKSTART.md +1 -1
- package/framework/CLAUDE.md +2 -2
- package/framework/MORPH.md +4 -5
- package/framework/agents.json +1 -0
- package/framework/docs/CLI.md +71 -68
- package/framework/hooks/README.md +11 -1
- package/framework/hooks/claude-code/core/block-destructive-worktree-removal.js +5 -8
- package/framework/hooks/claude-code/core/block-raw-worktree-add.js +79 -0
- package/framework/hooks/claude-code/core/chain.js +27 -7
- package/framework/hooks/claude-code/core/worktree-context.js +83 -14
- package/framework/hooks/claude-code/core/worktree-create.js +206 -0
- package/framework/hooks/claude-code/core/worktree-env-inject.js +87 -0
- package/framework/hooks/claude-code/core/worktree-remove.js +81 -0
- package/framework/hooks/claude-code/statusline.sh +11 -11
- package/framework/hooks/git/commit-msg/conventional-commits.sh +33 -33
- package/framework/hooks/git/pre-commit/agents.sh +25 -25
- package/framework/hooks/git/pre-commit/orchestrator.sh +64 -64
- package/framework/hooks/git/pre-commit/specs.sh +50 -50
- package/framework/hooks/git/pre-push/run-tests.sh +44 -44
- package/framework/hooks/shared/command-tokens.js +23 -0
- package/framework/hooks/shared/e2e-check.js +0 -0
- package/framework/hooks/shared/git-paths.js +25 -0
- package/framework/hooks/shared/hook-response.js +17 -0
- package/framework/hooks/shared/morph-cli.js +134 -0
- package/framework/hooks/shared/stdin-reader.js +26 -26
- package/framework/rules/infrastructure-standards.md +3 -1
- 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 +3 -3
- package/framework/skills/core/morph-brainstorming/SKILL.md +1 -1
- package/framework/skills/core/morph-eval/SKILL.md +1 -1
- package/framework/skills/core/morph-hotfix/SKILL.md +1 -1
- package/framework/skills/core/morph-implement/SKILL.md +3 -1
- package/framework/skills/core/morph-plan/SKILL.md +6 -3
- package/framework/skills/core/morph-proposal/SKILL.md +1 -1
- package/framework/skills/core/morph-review/SKILL.md +1 -1
- package/framework/skills/core/morph-stack-scan/SKILL.md +1 -1
- package/framework/skills/core/morph-standards/SKILL.md +1 -1
- package/framework/skills/core/morph-uiux/SKILL.md +1 -1
- package/framework/standards/STANDARDS.json +30 -0
- package/framework/standards/ai-agents/agent-session.md +160 -160
- package/framework/standards/ai-agents/batching.md +193 -193
- package/framework/standards/ai-agents/context-providers.md +188 -188
- package/framework/standards/ai-agents/mcp-server.md +250 -250
- package/framework/standards/ai-agents/mcp-tools.md +197 -197
- package/framework/standards/ai-agents/middleware-patterns.md +207 -207
- package/framework/standards/ai-agents/modalities-image-gen.md +173 -173
- package/framework/standards/ai-agents/modalities-speech-to-text.md +171 -171
- package/framework/standards/ai-agents/modalities-text-to-speech.md +181 -181
- package/framework/standards/ai-agents/modalities-vision.md +201 -201
- package/framework/standards/ai-agents/multi-agent-patterns.md +155 -155
- package/framework/standards/ai-agents/production.md +231 -231
- package/framework/standards/ai-agents/prompts-in-db.md +214 -214
- package/framework/standards/ai-agents/providers/model-registry.md +158 -158
- package/framework/standards/ai-agents/service-tier-flex.md +135 -135
- package/framework/standards/ai-agents/structured-output.md +249 -249
- package/framework/standards/ai-agents/sweet-spot.md +109 -109
- package/framework/standards/infrastructure/docker/local-compose-isolation.md +88 -0
- package/framework/templates/IDE-SNIPPETS.md +262 -262
- package/framework/templates/REGISTRY.json +1 -1
- package/framework/templates/code/dotnet/abstractions/api-endpoint.cs +7 -7
- package/framework/templates/code/dotnet/ai-agents/AgentBootstrap.cs.template +39 -39
- package/framework/templates/code/dotnet/ai-agents/EmbeddingService.cs.template +68 -68
- package/framework/templates/code/dotnet/ai-agents/ModelRegistry.cs.template +117 -117
- package/framework/templates/code/dotnet/ai-agents/PromptRepository.cs.template +95 -95
- package/framework/templates/code/dotnet/ai-agents/ResilientToolMiddleware.cs.template +61 -61
- package/framework/templates/code/dotnet/ai-agents/VectorSearchTool.cs.template +107 -107
- package/framework/templates/code/dotnet/ai-agents/model-registry.json.template +58 -58
- package/framework/templates/code/dotnet/contracts/contracts-vsa.cs +281 -281
- package/framework/templates/code/dotnet/database/migration.cs +83 -83
- package/framework/templates/code/dotnet/feature/endpoint.cs.hbs +21 -21
- package/framework/templates/code/dotnet/feature/request.cs.hbs +4 -4
- package/framework/templates/code/dotnet/feature/response.cs.hbs +4 -4
- package/framework/templates/code/dotnet/feature/validator.cs.hbs +15 -15
- package/framework/templates/code/sql/ai-agents/agent-prompts-migration.sql.template +58 -58
- package/framework/templates/code/sql/ai-agents/pgvector-embeddings-migration.sql.template +91 -91
- package/framework/templates/code/typescript/contracts.ts +167 -167
- package/framework/templates/docs/clarifications.md +253 -253
- package/framework/templates/docs/schema-analysis.md +119 -119
- package/framework/templates/docs/ui-components.md +52 -52
- package/framework/templates/docs/ui-design-system.md +76 -76
- package/framework/templates/docs/ui-flows.md +167 -167
- package/framework/templates/docs/ui-mockups.md +98 -98
- package/framework/templates/feature/decisions.md +122 -122
- package/framework/templates/frontend/nextjs/Dockerfile.nextjs.hbs +43 -43
- package/framework/templates/frontend/nextjs/client-component.tsx.hbs +26 -26
- package/framework/templates/frontend/nextjs/env.mjs.hbs +32 -32
- package/framework/templates/frontend/nextjs/feature-form.tsx.hbs +56 -56
- package/framework/templates/frontend/nextjs/page.tsx.hbs +22 -22
- package/framework/templates/frontend/nextjs/tsconfig.json.hbs +26 -26
- package/framework/templates/frontend/nextjs/use-feature.ts.hbs +54 -54
- package/framework/templates/infrastructure/docker/Dockerfile.template +58 -58
- package/framework/templates/infrastructure/docker/docker-compose.template.yml +24 -14
- package/framework/templates/infrastructure/docker/dockerfile-api.dockerfile +38 -38
- package/framework/templates/infrastructure/docker/dockerfile-web.dockerfile +48 -48
- package/framework/templates/infrastructure/github/README.md +56 -56
- package/framework/templates/infrastructure/github/actions/docker-build-push/action.yml.hbs +45 -45
- package/framework/templates/infrastructure/github/actions/health-check/action.yml.hbs +27 -27
- package/framework/templates/infrastructure/github/workflows/docker-build-push.yml.hbs +59 -59
- package/framework/templates/infrastructure/github/workflows/dotnet-build.yml.hbs +39 -39
- package/framework/templates/integrations/asaas-client.cs +387 -387
- package/framework/templates/integrations/asaas-webhook.cs +351 -351
- package/framework/templates/meta-prompts/fusion/fusion-agent.md +76 -76
- package/framework/templates/meta-prompts/fusion/fusion-aggregator.md +100 -100
- package/framework/templates/meta-prompts/validators/pre-commit-validator.md +95 -95
- package/framework/templates/project/validate.js +120 -120
- package/framework/templates/state.template.json +17 -17
- package/framework/templates/ui/design-system.css +226 -226
- package/package.json +1 -1
- package/src/commands/dashboard/dashboard.js +53 -53
- package/src/commands/e2e/e2e.js +77 -39
- package/src/commands/index.js +13 -13
- package/src/commands/project/checkpoint.js +209 -209
- package/src/commands/project/doctor.js +8 -6
- package/src/commands/project/env.js +95 -0
- package/src/commands/project/worktree.js +266 -52
- package/src/commands/state/delete.js +8 -0
- package/src/commands/state/finish.js +29 -34
- package/src/core/state/phase-state-machine.js +197 -197
- package/src/core/templates/template-renderer.js +477 -477
- package/src/dashboard/app/components/DetailPanel.jsx +11 -11
- package/src/dashboard/app/components/FlowGraph.jsx +17 -17
- package/src/dashboard/app/components/SearchFilter.jsx +22 -22
- package/src/dashboard/app/hooks/useDetailPanel.js +15 -15
- package/src/dashboard/app/main.jsx +13 -13
- package/src/dashboard/app/pages/AgentMap.jsx +370 -370
- package/src/dashboard/app/pages/HookInspector.jsx +430 -418
- package/src/dashboard/app/pages/PhasePipeline.jsx +408 -408
- package/src/dashboard/app/pages/RulesMap.jsx +273 -273
- package/src/dashboard/app/pages/SkillsLibrary.jsx +366 -366
- package/src/dashboard/app/pages/Standards.jsx +332 -332
- package/src/dashboard/app/styles/index.css +47 -47
- package/src/dashboard/index.html +12 -12
- package/src/dashboard/package.json +24 -24
- package/src/dashboard/scanner/hooks-scanner.js +5 -1
- package/src/dashboard/scanner/phases-scanner.js +15 -15
- package/src/dashboard/scanner/rubrics-scanner.js +12 -12
- package/src/dashboard/scanner/rules-scanner.js +37 -37
- package/src/dashboard/scanner/skills-scanner.js +43 -43
- package/src/dashboard/scanner/squads-scanner.js +13 -13
- package/src/dashboard/vite-plugin-morph-data.js +17 -17
- package/src/dashboard/vite.config.js +24 -24
- package/src/lib/detectors/design-system-detector.js +188 -188
- package/src/lib/detectors/index.js +217 -217
- package/src/lib/e2e/compose-env.js +6 -11
- package/src/lib/e2e/stack-teardown.js +115 -0
- package/src/lib/generators/architecture-scanner.js +2 -1
- package/src/lib/generators/design-system-generator.js +508 -508
- package/src/lib/generators/settings-generator.js +209 -209
- package/src/lib/graph/graphifyignore.js +2 -1
- package/src/lib/hooks/hook-executor.js +167 -167
- package/src/lib/installers/mcp-installer.js +719 -719
- package/src/lib/tasks/task-classifier.js +30 -30
- package/src/lib/tasks/task-parser.js +209 -209
- package/src/lib/tasks/test-runner.js +218 -39
- package/src/lib/validators/checkpoint-persistence.js +39 -39
- package/src/lib/validators/css/css-validator.js +340 -340
- package/src/lib/validators/shared/emit-validator-dispatch.js +14 -14
- package/src/lib/validators/shared/issue-counter.js +14 -14
- package/src/lib/validators/verify-runner.js +37 -4
- package/src/lib/worktree/dirs.js +32 -0
- package/src/lib/worktree/env-allocator.js +45 -11
- package/src/lib/worktree/worktree-audit.js +40 -2
- package/src/utils/agent-id-mapper.js +11 -11
- package/src/utils/claude-settings-manager.js +300 -300
- package/src/utils/file-copier.js +18 -13
- package/src/utils/hooks-installer.js +46 -3
- package/src/utils/skills-installer.js +187 -187
- package/framework/templates/.idea/morph-templates.xml +0 -92
- package/framework/templates/.vscode/morph-templates.code-snippets +0 -186
|
@@ -4,7 +4,7 @@ description: Entende o negócio, os usuários e a arquitetura antes de qualquer
|
|
|
4
4
|
version: core
|
|
5
5
|
when-to-invoke: ao receber um novo request de feature, antes de morph-plan
|
|
6
6
|
user-invokable: true
|
|
7
|
-
cliVersion: "8.
|
|
7
|
+
cliVersion: "8.34.2"
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# morph-brainstorming
|
|
@@ -4,7 +4,7 @@ description: Avalia a qualidade de uma tarefa ou fase com rubricas graduadas 0-1
|
|
|
4
4
|
version: core
|
|
5
5
|
when-to-invoke: ao completar uma tarefa ou ao finalizar uma fase de implementação
|
|
6
6
|
user-invokable: false
|
|
7
|
-
cliVersion: "8.
|
|
7
|
+
cliVersion: "8.34.2"
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# morph-eval
|
|
@@ -4,7 +4,7 @@ description: ADW cirúrgico de hotfix — resolve uma queda/bug crítico de prod
|
|
|
4
4
|
version: core
|
|
5
5
|
when-to-invoke: ao receber "/morph-hotfix {feature}", quando a morph-proposal classifica o pedido como workType hotfix (Passo 0), ou o usuário diz "produção caiu / hotfix / urgente"
|
|
6
6
|
user-invokable: true
|
|
7
|
-
cliVersion: "8.
|
|
7
|
+
cliVersion: "8.34.2"
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# morph-hotfix
|
|
@@ -4,7 +4,7 @@ description: Guia a execução de cada tarefa de implementação com standard e
|
|
|
4
4
|
version: core
|
|
5
5
|
when-to-invoke: ao iniciar cada task de implementação listada em tasks.json
|
|
6
6
|
user-invokable: false
|
|
7
|
-
cliVersion: "8.
|
|
7
|
+
cliVersion: "8.34.2"
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# morph-implement
|
|
@@ -84,6 +84,8 @@ Ao iniciar cada task de `tasks.json` — antes de escrever qualquer código. Nor
|
|
|
84
84
|
(`morph-spec verify`) é do orquestrador, pós-batch. Em batch COM
|
|
85
85
|
`isolation: "worktree"`, rode build/test no seu worktree, commite na
|
|
86
86
|
branch do worktree como último ato antes do relatório — nunca faça merge.
|
|
87
|
+
Worktree não commitado NÃO é removido pelo hook e vira pendência do
|
|
88
|
+
`doctor`; o commit é o que torna o seu trabalho integrável.
|
|
87
89
|
|
|
88
90
|
Seu relatório (no arquivo, e na mensagem final quando ela chega) deve conter
|
|
89
91
|
APENAS: (1) o que foi feito em 2-3 frases, (2) arquivos modificados,
|
|
@@ -4,7 +4,7 @@ description: Guia a produção dos artefatos de planejamento de uma feature (use
|
|
|
4
4
|
version: core
|
|
5
5
|
when-to-invoke: ao iniciar a fase plan de uma feature, após o Gate 1 (proposal aprovado)
|
|
6
6
|
user-invokable: true
|
|
7
|
-
cliVersion: "8.
|
|
7
|
+
cliVersion: "8.34.2"
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# morph-plan
|
|
@@ -138,8 +138,11 @@ Ao iniciar a fase plan — após o `proposal.md` ser aprovado e antes de qualque
|
|
|
138
138
|
- **Base URL vinda do ambiente:** o harness dá a cada feature um bloco de portas próprio (para
|
|
139
139
|
duas worktrees não brigarem pela porta 3000), então o `playwright.config.ts` **não pode**
|
|
140
140
|
cravar a URL — leia `process.env.PLAYWRIGHT_BASE_URL ?? \`http://localhost:${process.env.PORT ?? 3000}\``
|
|
141
|
-
e faça o compose publicar `"${PORT:-3000}:3000"
|
|
142
|
-
|
|
141
|
+
e faça o compose publicar `"${PORT:-3000}:3000"` e `"${POSTGRES_PORT:-5432}:5432"`, sem
|
|
142
|
+
`container_name` (o projeto compose já namespaceia; nome explícito colide entre worktrees —
|
|
143
|
+
standard `infrastructure/docker/local-compose-isolation`). Config cravada = suíte batendo em
|
|
144
|
+
porta vazia e `ECONNREFUSED` com cara de app quebrada; compose cravado **reprova o nó e2e**
|
|
145
|
+
dentro de um worktree. Se estiver cravado, **isso é uma task**.
|
|
143
146
|
- **Setup de autenticação**, se a aplicação tem login: `e2e.auth` em `config.json`
|
|
144
147
|
(`mode: seed|storageState|bypass|none`, `seedCommand`, `storageStatePath`, `envFile`), com as
|
|
145
148
|
credenciais num `.env.e2e` **gitignored** — nunca no config commitado. **Se a app tem login e
|
|
@@ -4,7 +4,7 @@ description: Orquestra a fase de proposta+plano de uma feature morph-spec. Encad
|
|
|
4
4
|
version: core
|
|
5
5
|
when-to-invoke: ao receber instrução "use /morph-proposal" do usuário, ou ao iniciar uma nova feature
|
|
6
6
|
user-invokable: true
|
|
7
|
-
cliVersion: "8.
|
|
7
|
+
cliVersion: "8.34.2"
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# morph-proposal
|
|
@@ -4,7 +4,7 @@ description: Conduz a fase de revisão e produz o review-report.md para o Gate 3
|
|
|
4
4
|
version: core
|
|
5
5
|
when-to-invoke: ao iniciar a fase review, após todas as tasks de tasks.json estarem com status `done`
|
|
6
6
|
user-invokable: true
|
|
7
|
-
cliVersion: "8.
|
|
7
|
+
cliVersion: "8.34.2"
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# morph-review
|
|
@@ -4,7 +4,7 @@ description: Varre o codebase existente, detecta stack atual, compara com o stac
|
|
|
4
4
|
version: core
|
|
5
5
|
when-to-invoke: ao iniciar uma feature em projeto brownfield (codebase já existente)
|
|
6
6
|
user-invokable: true
|
|
7
|
-
cliVersion: "8.
|
|
7
|
+
cliVersion: "8.34.2"
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# morph-stack-scan
|
|
@@ -4,7 +4,7 @@ description: Localiza um standard específico via busca server-side (morph-spec
|
|
|
4
4
|
version: core
|
|
5
5
|
when-to-invoke: quando precisar consultar um standard específico durante a implementação
|
|
6
6
|
user-invokable: true
|
|
7
|
-
cliVersion: "8.
|
|
7
|
+
cliVersion: "8.34.2"
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# morph-standards
|
|
@@ -4,7 +4,7 @@ description: Conduz a fase opcional de UI/UX — design system, mockups, compone
|
|
|
4
4
|
version: core
|
|
5
5
|
when-to-invoke: ao tomar o ramo uiux (morph-spec advance --design), depois do Gate 1 e antes do morph-plan
|
|
6
6
|
user-invokable: true
|
|
7
|
-
cliVersion: "8.
|
|
7
|
+
cliVersion: "8.34.2"
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# morph-uiux
|
|
@@ -2018,6 +2018,36 @@
|
|
|
2018
2018
|
"prompt-skeleton": "#section-5-prompt-skeleton"
|
|
2019
2019
|
},
|
|
2020
2020
|
"digest": "The decisive rule: a perfect loop has an end frame identical to its start, which is right for a self-playing ambient background and WRONG for scroll scrubbing, because start and end look the same and the page reads as frozen while the user scrolls. Scroll-driven footage needs directional movement via generate_video with an endImage (push-in/dolly is the most reliable, then reveal, pull-back, slow tilt); avoid orbits and any movement that returns to its origin. Client architectural renders are animated with img2vid, never AI-recreated. Human faces repeatedly trip moderation (E005), so crop the face out of frame (neck down, hands, product) and reserve faces for static image generation. Always climb the cost ladder: fast/480p/4s draft to judge framing and movement, 1080p only after approval, then re-extract frames with a bumped cache-bust. Prompts read like director notes with no hype words, and must reserve a calm dark region for the page copy with the subject on the opposite side. Generation is async: generate_video returns a request_id polled via get_video; list_videos reads local history and spends no credits."
|
|
2021
|
+
},
|
|
2022
|
+
{
|
|
2023
|
+
"id": "infrastructure-docker-local-compose-isolation",
|
|
2024
|
+
"name": "local compose isolation",
|
|
2025
|
+
"path": "infrastructure/docker/local-compose-isolation.md",
|
|
2026
|
+
"category": "infrastructure",
|
|
2027
|
+
"subcategory": "docker",
|
|
2028
|
+
"tags": [
|
|
2029
|
+
"infrastructure",
|
|
2030
|
+
"docker"
|
|
2031
|
+
],
|
|
2032
|
+
"stacks": [
|
|
2033
|
+
"docker"
|
|
2034
|
+
],
|
|
2035
|
+
"aliases": [
|
|
2036
|
+
"compose isolation",
|
|
2037
|
+
"worktree ports",
|
|
2038
|
+
"container_name",
|
|
2039
|
+
"POSTGRES_PORT",
|
|
2040
|
+
"COMPOSE_PROJECT_NAME",
|
|
2041
|
+
"port block",
|
|
2042
|
+
"local docker compose"
|
|
2043
|
+
],
|
|
2044
|
+
"anchors": {
|
|
2045
|
+
"layout": "#port-layout-one-contract-everywhere",
|
|
2046
|
+
"rules": "#core-rules",
|
|
2047
|
+
"enforcement": "#what-the-harness-enforces",
|
|
2048
|
+
"skeleton": "#minimal-compose-skeleton"
|
|
2049
|
+
},
|
|
2050
|
+
"digest": "Every worktree runs its OWN compose stack (project morph-{feature}, own postgres, own volumes). Ports come from the worktree block: PORT +0, API_PORT +1 (ASPNETCORE_URLS on .NET), POSTGRES_PORT +2, REDIS_PORT +3 — publish via ${VAR:-default}:container, never a fixed host port, never container_name (not prefixed by the project → collides). Stable POSTGRES_DB, healthcheck on every service, DATABASE_URL with an in-network default, playwright.config reads PLAYWRIGHT_BASE_URL. A non-isolable compose fails the verify e2e node inside a worktree. finish tears down with volumes (--keep-volumes opts out). Cloud DB credentials go in e2e.auth.envFile, never in .morph/worktree.env."
|
|
2021
2051
|
}
|
|
2022
2052
|
],
|
|
2023
2053
|
"sharedAliases": {
|
|
@@ -1,160 +1,160 @@
|
|
|
1
|
-
# Agent Session — Conversation state and chat reducers
|
|
2
|
-
|
|
3
|
-
> **Scope:** stacks=["dotnet"]
|
|
4
|
-
> **Layer:** 2 (on-keyword)
|
|
5
|
-
> **Keywords:** agent session, chat history, conversation state, chat reducer, history truncation, AgentThread
|
|
6
|
-
> **Read by Claude in:** implement
|
|
7
|
-
|
|
8
|
-
**Verified against:** MAF 1.0 GA. Last-verified: 2026-05-19.
|
|
9
|
-
|
|
10
|
-
---
|
|
11
|
-
|
|
12
|
-
## Quando usar AgentSession
|
|
13
|
-
|
|
14
|
-
Use `AgentSession` quando o agente é **conversacional** — há uma UI de chat que mantém histórico entre turnos do usuário.
|
|
15
|
-
|
|
16
|
-
**Use AgentSession quando:**
|
|
17
|
-
- Existe uma interface de chat (web, mobile, CLI interativo)
|
|
18
|
-
- O agente precisa lembrar o que foi dito nos turnos anteriores da mesma conversa
|
|
19
|
-
- Há perguntas de follow-up ("e agora?", "altere o segundo ponto", "lembra do que disse sobre X?")
|
|
20
|
-
|
|
21
|
-
**NÃO use AgentSession quando:**
|
|
22
|
-
- O agente é one-shot (gerador, executor, classificador) — recebe uma entrada, devolve uma saída, fim
|
|
23
|
-
- Agentes stateless em pipeline multi-agent — cada chamada é independente
|
|
24
|
-
- Jobs de batch/background — não há conversa; histórico não faz sentido
|
|
25
|
-
|
|
26
|
-
> "Add Memory/Session because agents need state" é um anti-pattern de `sweet-spot.md`.
|
|
27
|
-
> Só adicione quando uma UI de chat real existe.
|
|
28
|
-
|
|
29
|
-
---
|
|
30
|
-
|
|
31
|
-
## A API
|
|
32
|
-
|
|
33
|
-
**Pacote:** `Microsoft.Agents.AI` (base; já requerido por `ai-agents-setup`).
|
|
34
|
-
|
|
35
|
-
**Tipos confirmados via context7:**
|
|
36
|
-
- `AgentSession` — container leve de estado de conversa; obtido via `agent.CreateSessionAsync()`
|
|
37
|
-
- `AgentThread` — equivalente para agentes persistentes (PersistentAgentsClient); use `agent.GetNewThread()`
|
|
38
|
-
- `ChatClientAgentOptions` — aceita `ChatHistoryProvider` e `AIContextProviders`
|
|
39
|
-
- `InMemoryChatHistoryProvider` — implementação embutida de histórico em memória
|
|
40
|
-
- `AgentResponse` — tipo retornado por `AIAgent.RunAsync` (non-generic); acesse o texto via `.Text`
|
|
41
|
-
|
|
42
|
-
```csharp
|
|
43
|
-
// Construção do agente com histórico em memória
|
|
44
|
-
AIAgent agent = _modelRegistry.GetChatClient("text-default")
|
|
45
|
-
.AsAIAgent(new ChatClientAgentOptions
|
|
46
|
-
{
|
|
47
|
-
ChatOptions = new() { Instructions = "You are a helpful assistant." },
|
|
48
|
-
ChatHistoryProvider = new InMemoryChatHistoryProvider(),
|
|
49
|
-
});
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
---
|
|
53
|
-
|
|
54
|
-
## Exemplo C# — agente conversacional com session persistente entre turnos
|
|
55
|
-
|
|
56
|
-
```csharp
|
|
57
|
-
using Microsoft.Agents.AI;
|
|
58
|
-
using Microsoft.Extensions.AI;
|
|
59
|
-
|
|
60
|
-
// ── 1. Registrar o agente conversacional no DI ──
|
|
61
|
-
// Program.cs
|
|
62
|
-
builder.Services.AddSingleton<AIAgent>(sp =>
|
|
63
|
-
{
|
|
64
|
-
var registry = sp.GetRequiredService<ModelRegistry>();
|
|
65
|
-
return registry.GetChatClient("text-default")
|
|
66
|
-
.AsAIAgent(new ChatClientAgentOptions
|
|
67
|
-
{
|
|
68
|
-
ChatOptions = new() { Instructions = "You are a helpful customer support assistant." },
|
|
69
|
-
// InMemoryChatHistoryProvider: histórico vive em memória, por session.
|
|
70
|
-
// Seguro registrar como parte do singleton AIAgent: cada AgentSession criada via
|
|
71
|
-
// agent.CreateSessionAsync() isola o histórico de sua conversa — conversas distintas
|
|
72
|
-
// não compartilham estado. O provider em si é stateless; o estado fica na session.
|
|
73
|
-
// Para persistência entre restarts, substitua por um provider customizado (ex: DB).
|
|
74
|
-
ChatHistoryProvider = new InMemoryChatHistoryProvider(),
|
|
75
|
-
});
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
// ── 2. Criar uma session por conversa (ex: por conexão SignalR / por request de "start chat") ──
|
|
79
|
-
// ChatController.cs ou ChatHub.cs
|
|
80
|
-
public class ChatService(AIAgent _agent)
|
|
81
|
-
{
|
|
82
|
-
// Uma session por conversa ativa — armazene no escopo do usuário (cache, memória da conexão)
|
|
83
|
-
public async Task<AgentSession> StartConversationAsync()
|
|
84
|
-
=> await _agent.CreateSessionAsync();
|
|
85
|
-
|
|
86
|
-
// Cada mensagem do usuário passa a mesma session
|
|
87
|
-
public async Task<string> SendMessageAsync(AgentSession session, string userMessage)
|
|
88
|
-
{
|
|
89
|
-
AgentResponse response = await _agent.RunAsync(userMessage, session);
|
|
90
|
-
return response.Text;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
// ── 3. Uso no controller/hub ──
|
|
95
|
-
// Primeiro turno
|
|
96
|
-
AgentSession session = await chatService.StartConversationAsync();
|
|
97
|
-
string reply1 = await chatService.SendMessageAsync(session, "Meu pedido #1234 está atrasado.");
|
|
98
|
-
// reply1: "Vou verificar o pedido #1234 para você..."
|
|
99
|
-
|
|
100
|
-
// Segundo turno — o agente lembra do contexto anterior
|
|
101
|
-
string reply2 = await chatService.SendMessageAsync(session, "E quando foi despachado?");
|
|
102
|
-
// reply2: "O pedido #1234 foi despachado em..." ← contexto mantido pela session
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
---
|
|
106
|
-
|
|
107
|
-
## History management
|
|
108
|
-
|
|
109
|
-
O histórico cresce a cada turno. Quando estoura o context window do modelo, as chamadas falham ou truncam silenciosamente.
|
|
110
|
-
|
|
111
|
-
### Estratégias
|
|
112
|
-
|
|
113
|
-
| Estratégia | Quando usar | Como implementar |
|
|
114
|
-
|------------|-------------|------------------|
|
|
115
|
-
| **Sliding window** | Conversas longas com contexto recente suficiente | Limitar `InMemoryChatHistoryProvider` a N mensagens mais recentes |
|
|
116
|
-
| **Token budget** | Modelos com context window pequeno | Contar tokens acumulados; truncar quando ultrapassa threshold |
|
|
117
|
-
| **Summarization** | Histórico precisa de contexto antigo comprimido | Agente periódico que resume N turnos anteriores em uma mensagem única |
|
|
118
|
-
|
|
119
|
-
> **Custom history management:** Para o caso comum, `InMemoryChatHistoryProvider` cobre a
|
|
120
|
-
> necessidade de histórico em memória por sessão. Se o projeto exigir truncation customizada
|
|
121
|
-
> (ex: sliding window limitando a N mensagens mais recentes ou por token budget), o mecanismo
|
|
122
|
-
> de extensão correto — seja subclasse de `ChatHistoryProvider`, um `IChatReducer`, ou outro
|
|
123
|
-
> ponto de override — deve ser verificado contra a versão instalada de `Microsoft.Agents.AI`.
|
|
124
|
-
> Consulte a documentação MAF atual antes de implementar um provider customizado, pois a API
|
|
125
|
-
> exata de extensão não foi confirmada na versão GA e pode variar entre releases.
|
|
126
|
-
|
|
127
|
-
---
|
|
128
|
-
|
|
129
|
-
## Anti-patterns
|
|
130
|
-
|
|
131
|
-
| Anti-pattern | Problema |
|
|
132
|
-
|-------------|----------|
|
|
133
|
-
| Adicionar session em agente one-shot (gerador, executor) | Complexidade desnecessária; estado nunca é usado |
|
|
134
|
-
| Histórico ilimitado sem truncation | Context window estoura; custo aumenta linearmente com a conversa |
|
|
135
|
-
| Compartilhar uma `AgentSession` entre múltiplos usuários | Histórico de um usuário vaza para outro |
|
|
136
|
-
| Usar `InMemoryChatHistoryProvider` sem criar uma `AgentSession` por conversa | Sem `AgentSession` por conversa, o histórico é compartilhado entre todos os usuários; a isolation depende de `AgentSession` — sempre crie uma session por conversa via `agent.CreateSessionAsync()` |
|
|
137
|
-
| Usar `AgentThread` (PersistentAgentsClient) sem necessidade | `AgentThread` requer hosted agent service; prefira `AgentSession` com direct model |
|
|
138
|
-
|
|
139
|
-
---
|
|
140
|
-
|
|
141
|
-
## Checklist (verifiable by morph-eval)
|
|
142
|
-
|
|
143
|
-
- [ ] `AgentSession` usada somente em agentes conversacionais com UI de chat real
|
|
144
|
-
- [ ] `InMemoryChatHistoryProvider` (ou equivalente) registrado em `ChatClientAgentOptions`
|
|
145
|
-
- [ ] Uma `AgentSession` por conversa/usuário — nunca compartilhada
|
|
146
|
-
- [ ] Estratégia de truncation definida (sliding window, token budget ou summarization)
|
|
147
|
-
- [ ] Agentes one-shot (gerador, executor, classificador) **não** recebem session
|
|
148
|
-
|
|
149
|
-
---
|
|
150
|
-
|
|
151
|
-
## References
|
|
152
|
-
|
|
153
|
-
- `ai-agents-setup` — packages e DI base
|
|
154
|
-
- `ai-agents-sweet-spot` — decisão de quando adicionar estado ao agente
|
|
155
|
-
- `ai-agents-middleware-patterns` (Onda 2) — pipeline de contexto e middleware
|
|
156
|
-
- MAF Conversations docs: https://learn.microsoft.com/en-us/agent-framework/agents/conversations/
|
|
157
|
-
|
|
158
|
-
---
|
|
159
|
-
|
|
160
|
-
*MORPH-SPEC by Polymorphism Tech — ai-agents/agent-session.md v1.0 (2026-05-19)*
|
|
1
|
+
# Agent Session — Conversation state and chat reducers
|
|
2
|
+
|
|
3
|
+
> **Scope:** stacks=["dotnet"]
|
|
4
|
+
> **Layer:** 2 (on-keyword)
|
|
5
|
+
> **Keywords:** agent session, chat history, conversation state, chat reducer, history truncation, AgentThread
|
|
6
|
+
> **Read by Claude in:** implement
|
|
7
|
+
|
|
8
|
+
**Verified against:** MAF 1.0 GA. Last-verified: 2026-05-19.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Quando usar AgentSession
|
|
13
|
+
|
|
14
|
+
Use `AgentSession` quando o agente é **conversacional** — há uma UI de chat que mantém histórico entre turnos do usuário.
|
|
15
|
+
|
|
16
|
+
**Use AgentSession quando:**
|
|
17
|
+
- Existe uma interface de chat (web, mobile, CLI interativo)
|
|
18
|
+
- O agente precisa lembrar o que foi dito nos turnos anteriores da mesma conversa
|
|
19
|
+
- Há perguntas de follow-up ("e agora?", "altere o segundo ponto", "lembra do que disse sobre X?")
|
|
20
|
+
|
|
21
|
+
**NÃO use AgentSession quando:**
|
|
22
|
+
- O agente é one-shot (gerador, executor, classificador) — recebe uma entrada, devolve uma saída, fim
|
|
23
|
+
- Agentes stateless em pipeline multi-agent — cada chamada é independente
|
|
24
|
+
- Jobs de batch/background — não há conversa; histórico não faz sentido
|
|
25
|
+
|
|
26
|
+
> "Add Memory/Session because agents need state" é um anti-pattern de `sweet-spot.md`.
|
|
27
|
+
> Só adicione quando uma UI de chat real existe.
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## A API
|
|
32
|
+
|
|
33
|
+
**Pacote:** `Microsoft.Agents.AI` (base; já requerido por `ai-agents-setup`).
|
|
34
|
+
|
|
35
|
+
**Tipos confirmados via context7:**
|
|
36
|
+
- `AgentSession` — container leve de estado de conversa; obtido via `agent.CreateSessionAsync()`
|
|
37
|
+
- `AgentThread` — equivalente para agentes persistentes (PersistentAgentsClient); use `agent.GetNewThread()`
|
|
38
|
+
- `ChatClientAgentOptions` — aceita `ChatHistoryProvider` e `AIContextProviders`
|
|
39
|
+
- `InMemoryChatHistoryProvider` — implementação embutida de histórico em memória
|
|
40
|
+
- `AgentResponse` — tipo retornado por `AIAgent.RunAsync` (non-generic); acesse o texto via `.Text`
|
|
41
|
+
|
|
42
|
+
```csharp
|
|
43
|
+
// Construção do agente com histórico em memória
|
|
44
|
+
AIAgent agent = _modelRegistry.GetChatClient("text-default")
|
|
45
|
+
.AsAIAgent(new ChatClientAgentOptions
|
|
46
|
+
{
|
|
47
|
+
ChatOptions = new() { Instructions = "You are a helpful assistant." },
|
|
48
|
+
ChatHistoryProvider = new InMemoryChatHistoryProvider(),
|
|
49
|
+
});
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## Exemplo C# — agente conversacional com session persistente entre turnos
|
|
55
|
+
|
|
56
|
+
```csharp
|
|
57
|
+
using Microsoft.Agents.AI;
|
|
58
|
+
using Microsoft.Extensions.AI;
|
|
59
|
+
|
|
60
|
+
// ── 1. Registrar o agente conversacional no DI ──
|
|
61
|
+
// Program.cs
|
|
62
|
+
builder.Services.AddSingleton<AIAgent>(sp =>
|
|
63
|
+
{
|
|
64
|
+
var registry = sp.GetRequiredService<ModelRegistry>();
|
|
65
|
+
return registry.GetChatClient("text-default")
|
|
66
|
+
.AsAIAgent(new ChatClientAgentOptions
|
|
67
|
+
{
|
|
68
|
+
ChatOptions = new() { Instructions = "You are a helpful customer support assistant." },
|
|
69
|
+
// InMemoryChatHistoryProvider: histórico vive em memória, por session.
|
|
70
|
+
// Seguro registrar como parte do singleton AIAgent: cada AgentSession criada via
|
|
71
|
+
// agent.CreateSessionAsync() isola o histórico de sua conversa — conversas distintas
|
|
72
|
+
// não compartilham estado. O provider em si é stateless; o estado fica na session.
|
|
73
|
+
// Para persistência entre restarts, substitua por um provider customizado (ex: DB).
|
|
74
|
+
ChatHistoryProvider = new InMemoryChatHistoryProvider(),
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
// ── 2. Criar uma session por conversa (ex: por conexão SignalR / por request de "start chat") ──
|
|
79
|
+
// ChatController.cs ou ChatHub.cs
|
|
80
|
+
public class ChatService(AIAgent _agent)
|
|
81
|
+
{
|
|
82
|
+
// Uma session por conversa ativa — armazene no escopo do usuário (cache, memória da conexão)
|
|
83
|
+
public async Task<AgentSession> StartConversationAsync()
|
|
84
|
+
=> await _agent.CreateSessionAsync();
|
|
85
|
+
|
|
86
|
+
// Cada mensagem do usuário passa a mesma session
|
|
87
|
+
public async Task<string> SendMessageAsync(AgentSession session, string userMessage)
|
|
88
|
+
{
|
|
89
|
+
AgentResponse response = await _agent.RunAsync(userMessage, session);
|
|
90
|
+
return response.Text;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// ── 3. Uso no controller/hub ──
|
|
95
|
+
// Primeiro turno
|
|
96
|
+
AgentSession session = await chatService.StartConversationAsync();
|
|
97
|
+
string reply1 = await chatService.SendMessageAsync(session, "Meu pedido #1234 está atrasado.");
|
|
98
|
+
// reply1: "Vou verificar o pedido #1234 para você..."
|
|
99
|
+
|
|
100
|
+
// Segundo turno — o agente lembra do contexto anterior
|
|
101
|
+
string reply2 = await chatService.SendMessageAsync(session, "E quando foi despachado?");
|
|
102
|
+
// reply2: "O pedido #1234 foi despachado em..." ← contexto mantido pela session
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## History management
|
|
108
|
+
|
|
109
|
+
O histórico cresce a cada turno. Quando estoura o context window do modelo, as chamadas falham ou truncam silenciosamente.
|
|
110
|
+
|
|
111
|
+
### Estratégias
|
|
112
|
+
|
|
113
|
+
| Estratégia | Quando usar | Como implementar |
|
|
114
|
+
|------------|-------------|------------------|
|
|
115
|
+
| **Sliding window** | Conversas longas com contexto recente suficiente | Limitar `InMemoryChatHistoryProvider` a N mensagens mais recentes |
|
|
116
|
+
| **Token budget** | Modelos com context window pequeno | Contar tokens acumulados; truncar quando ultrapassa threshold |
|
|
117
|
+
| **Summarization** | Histórico precisa de contexto antigo comprimido | Agente periódico que resume N turnos anteriores em uma mensagem única |
|
|
118
|
+
|
|
119
|
+
> **Custom history management:** Para o caso comum, `InMemoryChatHistoryProvider` cobre a
|
|
120
|
+
> necessidade de histórico em memória por sessão. Se o projeto exigir truncation customizada
|
|
121
|
+
> (ex: sliding window limitando a N mensagens mais recentes ou por token budget), o mecanismo
|
|
122
|
+
> de extensão correto — seja subclasse de `ChatHistoryProvider`, um `IChatReducer`, ou outro
|
|
123
|
+
> ponto de override — deve ser verificado contra a versão instalada de `Microsoft.Agents.AI`.
|
|
124
|
+
> Consulte a documentação MAF atual antes de implementar um provider customizado, pois a API
|
|
125
|
+
> exata de extensão não foi confirmada na versão GA e pode variar entre releases.
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
## Anti-patterns
|
|
130
|
+
|
|
131
|
+
| Anti-pattern | Problema |
|
|
132
|
+
|-------------|----------|
|
|
133
|
+
| Adicionar session em agente one-shot (gerador, executor) | Complexidade desnecessária; estado nunca é usado |
|
|
134
|
+
| Histórico ilimitado sem truncation | Context window estoura; custo aumenta linearmente com a conversa |
|
|
135
|
+
| Compartilhar uma `AgentSession` entre múltiplos usuários | Histórico de um usuário vaza para outro |
|
|
136
|
+
| Usar `InMemoryChatHistoryProvider` sem criar uma `AgentSession` por conversa | Sem `AgentSession` por conversa, o histórico é compartilhado entre todos os usuários; a isolation depende de `AgentSession` — sempre crie uma session por conversa via `agent.CreateSessionAsync()` |
|
|
137
|
+
| Usar `AgentThread` (PersistentAgentsClient) sem necessidade | `AgentThread` requer hosted agent service; prefira `AgentSession` com direct model |
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
## Checklist (verifiable by morph-eval)
|
|
142
|
+
|
|
143
|
+
- [ ] `AgentSession` usada somente em agentes conversacionais com UI de chat real
|
|
144
|
+
- [ ] `InMemoryChatHistoryProvider` (ou equivalente) registrado em `ChatClientAgentOptions`
|
|
145
|
+
- [ ] Uma `AgentSession` por conversa/usuário — nunca compartilhada
|
|
146
|
+
- [ ] Estratégia de truncation definida (sliding window, token budget ou summarization)
|
|
147
|
+
- [ ] Agentes one-shot (gerador, executor, classificador) **não** recebem session
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
## References
|
|
152
|
+
|
|
153
|
+
- `ai-agents-setup` — packages e DI base
|
|
154
|
+
- `ai-agents-sweet-spot` — decisão de quando adicionar estado ao agente
|
|
155
|
+
- `ai-agents-middleware-patterns` (Onda 2) — pipeline de contexto e middleware
|
|
156
|
+
- MAF Conversations docs: https://learn.microsoft.com/en-us/agent-framework/agents/conversations/
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
*MORPH-SPEC by Polymorphism Tech — ai-agents/agent-session.md v1.0 (2026-05-19)*
|