Files
emcp-tools-mapping/docs/14-PROJECT-MEMORY-BLUEPRINT.md
Claude Code 2812cd79ba docs: doc13 Forms Pro (WPForms+Fluent Forms) + doc14 Project Memory blueprints
Fundamentados em código real: WPForms Lite 2.0.0.5 + Fluent Forms 6.2.12
(activos em ecommerce-demo.descomplicar.pt), e CARL+Mem0/Hindsight (sistemas
de memória/governança já em produção neste ecossistema). Achado central doc13:
Fluent Forms já embarca servidor MCP nativo próprio (AbilitiesRegistrar, 9
abilities, dry-run+confirm_token) - recomenda delegar em vez de reimplementar.
INDEX.md actualizado com as 2 novas entradas e totais.
2026-08-19 07:58:31 +01:00

48 KiB

14 — Project Memory (Pro): blueprint de abilities MCP (desenho próprio, não é auditoria EMCP Pro)

Fonte primária: leitura directa (19-08-2026) de duas fontes reais fora da árvore emcp-tools propriamente dita — porque, tal como em docs/11-WOOCOMMERCE-BLUEPRINT.md e docs/12-WIDGET-BUILDER-BLUEPRINT.md, o código Pro do módulo "Project Memory" está fisicamente ausente desta build Free (confirmado pelo padrão já estabelecido em docs/10-MODULOS-E-INVENTARIO-PRO.md: uma classe class_exists()-gated cujo ficheiro nunca existe na árvore instalada — não retentado nesta tarefa, o mesmo padrão já foi verificado exaustivamente para os outros ~30 módulos Pro). As duas fontes reais usadas em substituição: (A) ~/.omp/agent/AGENTS.md (e o documento canónico que importa, Hub/04-Stack/02.04-Sistemas/AGENTS.md) — a identidade operacional deste próprio ambiente OMP, que já opera um sistema de governança de regras com staging/aprovação (CARL) e um sistema de memória cross-agent em camadas (Mem0), ambos em produção, não hipotéticos; (B) os padrões de aprovação humana e de change-ledger já confirmados por código real nesta mesma série (docs/04-THEMER.md §11, docs/06-SANDBOX-CUSTOM-CODE.md §1, docs/05-REDIRECTS-SEARCH-LEDGER.md §4).

0. Panorama — porque este documento é diferente e o que fundamenta cada peça

A captura de ecrã da UI de administração do EMCP Tools (secção Project Memory (Pro), contador "0/3") mostra 3 tools MCP, todas prefixadas emcp-tools/:

Tool id (screenshot) Badge Descrição literal do utilizador
emcp-tools/recall PRO · READ-ONLY "Read approved guidance + recent session summaries so the agent does not re-guess site context"
emcp-tools/remember PRO "Propose one guardrail/fact/convention/instruction. Stored pending until a human approves it"
emcp-tools/save-session-summary PRO "Record a session summary; the plugin attaches a factual digest of the actual changes"

Estes 3 nomes e as 3 descrições são usados apenas como especificação da API-alvo (nomenclatura, âmbito e a promessa comportamental de cada tool) — não como fonte de implementação. Não há código Pro nesta árvore para ler, logo não há input schema, mensagens de erro, nem lógica interna real do EMCP Pro para citar. Qualquer detalhe de como cada tool funciona por dentro, neste documento, é proposta própria.

Em vez de tentar adivinhar o comportamento interno, este documento faz a pergunta inversa dos docs 01-10: dado que este próprio ambiente de trabalho (OMP/Claude Code, ecossistema Descomplicar) já resolveu exactamente o mesmo problema — "como é que um agente de IA lembra contexto de projecto entre sessões sem inventar factos e sem escrever governança sem supervisão humana" — com dois sistemas reais e vivos em produção, qual é o desenho mais honesto para "Project Memory" que se pode propor sem fingir conhecer o código Pro?

As duas fontes reais e o que cada uma fundamenta

  1. CARL (Sistema de Regras e Governança, com pipeline staging→aprovação) — confirmado como sistema real vivo por três evidências independentes, todas citadas literalmente ao longo deste documento:
    • O ficheiro canónico Hub/04-Stack/02.04-Sistemas/AGENTS.md §4 (errata 26-07-2026), citação directa: "As 22 regras CARL GLOBAL só carregavam com o cwd dentro de 04-Stack — o CARL resolve scopes pelo cwd e substitui o domínio inteiro. Fora dali, GLOBAL tinha 3. Consolidadas."
    • Hub/04-Stack/02.04-Sistemas/PIPELINE-QUALIDADE-TOTAL.md (17-07-2026), citação directa: "stack-observer→classify→fingerprint→propostas CARL; (…) CARL v2 GLOBAL com 26 regras" e, na matriz de arcos do pipeline (C6, 06→02/01): "Propostas aprovadas → novas regras CARL / gates / processos (…) staging CARL funcional".
    • O conjunto real de ferramentas MCP CARL disponíveis neste próprio ambiente (servidor carl-mcp, invocável directamente nesta sessão) — nomes de tool, descrições e schemas de argumento reais, sem paráfrase, citados na íntegra na secção 2 abaixo. Existem duas gerações coexistentes do mesmo sistema (v1, ficheiro-por-domínio; v2, carl.json único) — ambas reais, ambas activas nesta instalação, e a divergência entre elas é, por si só, um dado relevante para o desenho de "Remember Guidance" (secção 2.3).
  2. Mem0 / memória cross-agent — confirmado como sistema real vivo pela secção 5 ("MEMÓRIA") do Hub/04-Stack/02.04-Sistemas/AGENTS.md, citada quase integralmente na secção 1, e pelo conjunto real de ferramentas MCP mem0 disponíveis nesta sessão (servidor mem0, prefixo mcp__mem_*) — save_memory, search_memories, get_all_memories, update_memory, delete_memory, etc.

Cruzamento adicional com código real desta série (o mesmo grupo de precedentes já usado por docs/12-WIDGET-BUILDER-BLUEPRINT.md §6.5 para justificar "zero tool de auto-activação"): docs/04-THEMER.md §11 (Themer PHP: "there is intentionally no attach tool") e docs/06-SANDBOX-CUSTOM-CODE.md §1 (PHP Snippets: "There is intentionally no 'activate' tool"), mais o change ledger unificado de docs/05-REDIRECTS-SEARCH-LEDGER.md §4 (EMCP_Tools_Change_Log/Change_Recorder/Change_Blobs) como modelo de armazenamento/rollback para o que uma "guidance" pendente/aprovada precisaria de persistir e desfazer.

Convenção usada em todo o documento (idêntica a docs 11/12): cada afirmação é marcada [REAL] quando vem directamente de uma fonte verificável nesta sessão (o próprio AGENTS.md, os ficheiros do Hub citados, ou uma chamada real a uma ferramenta MCP CARL/Mem0 feita nesta tarefa), ou [DESENHO PRÓPRIO] quando é uma proposta nossa sem equivalente confirmado no EMCP Pro. Onde uma peça combina as duas (ex.: mapear uma tool Pro hipotética sobre um fluxo CARL real), isso é dito explicitamente — e a maioria das peças deste documento está nessa categoria mista, porque nenhuma das 3 tools Pro foi lida directamente; só a promessa comportamental (a frase da captura de ecrã) é dado de entrada.

A distinção mais importante de todo o documento: ao contrário do doc 12 (onde a camada de armazenamento EMCP_Tools_Widget_Store já existe e é código real, só a camada de compilação e a de abilities é que faltam), aqui nenhuma camada do sistema "Project Memory" existe fisicamente nesta árvore Free — nem abilities, nem store, nem CPT, nem option. Este blueprint é, por isso, mais "desenho próprio" do que o doc 12; a âncora real está inteiramente fora do plugin, nos dois sistemas de governança/memória que este próprio ambiente de execução já usa para resolver o mesmo problema.


1. recall — ler orientação aprovada + resumos de sessão recentes

Promessa da tool (screenshot, PRO READ-ONLY): "Read approved guidance + recent session summaries so the agent does not re-guess site context."

1.1 Fundamentação [REAL] — o sistema de memória em camadas já em produção

O AGENTS.md canónico documenta explicitamente uma arquitectura de memória por níveis que resolve precisamente este problema — "não repetir contexto que já foi estabelecido". Citação directa, Hub/04-Stack/02.04-Sistemas/AGENTS.md §5 ("MEMÓRIA"):

*"### Cross-agent (Mem0)

  • Gateway: gateway.descomplicar.pt/v1/mem0/mcp
  • Bridge Hindsight: localhost:8888 → mem0 local
  • REST API directa: localhost:8090 (debug/Swagger)
  • OMP usa memory.backend: hindsight → bridge → mem0
  • Protocolo Wayland v2: P5=identidade, P4=procedimento, P3=facto atómico

Níveis

Tier Sistema O quê Automático?
1 IJFW/OMP Hindsight Working memory de sessão Sim
2 Mem0 (via gateway MCP) Factos duráveis cross-agent Sim (bridge)
3 Mem0 REST API (:8090) Acesso directo para debug/automação Manual"*

Além disto, o próprio AGENTS.md §2 ("HIERARQUIA DE FONTES") estabelece a regra geral que recall deveria implementar do lado de um plugin WordPress: "NLM-first: consultar NotebookLM PRIMEIRO antes de perguntas técnicas" e "Nunca confiar em docs sem verificar: o que está escrito pode estar errado. Só o que é verificado no terreno conta." — ou seja, mesmo um sistema de memória "aprovada" não é uma licença para parar de verificar; é uma optimização de "não repetir trabalho de descoberta já feito", não uma substituição da verificação.

Mapeamento directo: o Tier 2 (Mem0 via gateway MCP, "factos duráveis cross-agent", automático) é o análogo funcional mais próximo de "ler orientação aprovada + resumos recentes" — mas com uma diferença estrutural crítica face ao desenho proposto pela EMCP Pro (ver secção 1.3).

1.2 Ferramentas MCP Mem0 reais desta sessão [REAL]

A ferramenta search_memories (servidor mem0, mcp__mem_search_memories) é o equivalente mais directo de recall: aceita query (pesquisa em linguagem natural), user_id/agent_id/run_id opcionais para segmentar por âmbito, top_k (default 5) e threshold (score mínimo de similaridade). get_all_memories (mcp__mem_get_all_memories) é o equivalente de "listar tudo o que está aprovado para este âmbito", sem query — mais próximo do comportamento "devolve a orientação aprovada" descrito na promessa da tool Pro (uma leitura completa e determinística, não uma pesquisa semântica top-k que pode omitir algo relevante por baixo do threshold).

1.3 Desenho proposto para recall [DESENHO PRÓPRIO, sobre camadas [REAL]]

Área O que cobre API/sistema real usado como modelo Nível de risco
Leitura de guardrails/factos/convenções aprovados Devolve só entradas com estado approved — nunca pending/rejected (ver modelo de estados, secção 4) Equivalente ao filtro implícito de get-domain-rules/get-domain do CARL real (secção 2.2), que só devolve regras já escritas no domínio, nunca as que ainda estão em staging readonly, idempotent
Leitura de resumos de sessão recentes Últimos N resumos gravados por save-session-summary (secção 3), ordenados por recência, com o "digest factual" já anexado pelo plugin Análogo ao Tier 1 ("working memory de sessão", AGENTS.md §5) tornado persistente entre sessões — o Pro parece fundir aqui o que o ecossistema Descomplicar trata como dois tiers distintos (1 efémero, 2 durável) readonly, idempotent
Filtro por âmbito (página/post/site inteiro) [DESENHO PRÓPRIO] — sem equivalente directo confirmado; proposta: um parâmetro scope?:{post_id?, site_wide?:bool}, espelhando o padrão emcp_themer_selectors (docs/04-THEMER.md §0) de escala larga→granular por filtro —
Recall keyword-driven (activação por intenção) [DESENHO PRÓPRIO, precedente REAL forte] — cada domínio CARL tem recall (palavras-chave que o disparam, ver carl_get_domain_rules: "Load rules for a specific CARL domain. Use when user intent matches domain recall keywords"); um recall de Project Memory poderia aceitar intent_hint?:string e devolver só entradas cujas keywords casem, evitando devolver TODA a memória aprovada em cada chamada —

Nota sobre "não re-adivinhar contexto": a frase da promessa Pro ("so the agent does not re-guess site context") é, no ecossistema Descomplicar, exactamente o motivo declarado para o Mem0 Tier 2 existir — "factos duráveis cross-agent" que sobrevivem ao reset de contexto de uma sessão. A diferença de desenho que este documento propõe adoptar (ver 1.4) é que o Pro parece restringir recall a só conteúdo já aprovado por um humano, ao passo que o Mem0 real do ecossistema grava directamente (save_memory) sem esse portão — ver a tensão explícita na secção 2.4.

1.4 Porque "aprovado" é o modelo certo aqui, não "gravado directamente"

Ao contrário do Mem0 (Tier 2, escrita automática via bridge, sem revisão humana — apropriado para factos operacionais de baixo risco, como "o cliente X prefere PT-PT sem gírias"), uma "guidance" de recall num plugin WordPress pode influenciar directamente decisões de escrita subsequentes do próprio agente no mesmo site (ex.: "nunca apagar redirects sem confirmar", "este cliente usa sempre Multibanco, não activar Stripe"). Este é exactamente o tipo de afirmação que, se errada ou obsoleta, causa dano real e persistente — o mesmo raciocínio de risco que already levou o Themer PHP e os PHP Snippets a nunca expor "activar" via MCP (docs/04-THEMER.md §11, docs/06-SANDBOX-CUSTOM-CODE.md §1). Por isso o modelo correcto para recall não é "o que o Mem0 tem gravado" (Tier 2 puro), é "o subconjunto do Tier 2 que já passou pelo portão humano" — precisamente o desenho que a secção 2 propõe para remember.


2. remember — propor uma guidance, pendente de aprovação humana

Promessa da tool (screenshot, PRO): "Propose one guardrail/fact/convention/instruction. Stored pending until a human approves it."

Esta é a peça mais bem fundamentada de todo o documento — a promessa da tool Pro descreve, quase palavra por palavra, o fluxo staging→aprovação que o CARL já implementa como sistema real, com ferramentas MCP reais chamáveis nesta mesma sessão.

2.1 O fluxo CARL real (v1, ficheiro-por-domínio) [REAL]

Ferramentas reais do servidor carl-mcp, citadas com a descrição exacta tal como declarada nos seus schemas MCP (sem paráfrase):

Tool MCP real Descrição literal Argumentos
carl_stage_proposal "Stage a new CARL rule proposal for review. Sources: psmm, decisions, manual." domain, rule_text, rationale, source (enum psmm|decisions|manual)
carl_get_staged "List all pending rule proposals in the staging pipeline." —
carl_approve_proposal "Approve a staged proposal — writes the rule to the target domain file and removes from staging." id (ex. prop-001)
carl_archive_proposal "Archive a proposal — keeps it for reference but doesn't activate as a rule." id
carl_kill_proposal "Delete a staged proposal permanently." id
carl_log_decision "Log a decision to a CARL domain. Auto-creates domain file if new." domain, decision, rationale, recall
carl_get_domain_rules "Load rules for a specific CARL domain. Use when user intent matches domain recall keywords." domain
carl_get_manifest "Get current CARL manifest showing all domains, states, and recall keywords." —
carl_toggle_domain "Enable or disable a CARL domain by updating the manifest." domain, state (active|inactive)
carl_create_domain "Create a new CARL domain with file and manifest entry." domain, description, recall, rules

O ciclo de vida real confirmado por estes nomes de tool, sem qualquer inferência: uma proposta nasce por carl_stage_proposal (nunca directamente como regra); fica visível a um humano/revisor via carl_get_staged; termina num de três destinos possíveis — carl_approve_proposal (promovida a regra activa no domínio), carl_archive_proposal (guardada para referência, nunca se torna regra), ou carl_kill_proposal (apagada sem deixar rasto). Este é exactamente o modelo de três saídas (aprovado/arquivado/rejeitado) que se propõe adoptar para remember (secção 2.3).

2.2 O fluxo CARL v2 real (carl.json único) [REAL]

Uma segunda geração do mesmo sistema, também real e chamável nesta sessão (prefixo carl_v2_*), que difere em dois pontos relevantes para o desenho de remember:

Tool MCP real (v2) Descrição literal Diferença face à v1
carl_v2_stage_proposal "Stage a rule proposal in carl.json staging array." Mesmo conceito, source agora opcional (default manual)
carl_v2_get_staged "List all staged rule proposals from carl.json." Igual em espírito
carl_v2_approve_proposal "Approve a staged proposal — adds rule to target domain and removes from staging." id no formato stg-001 (não prop-001)
carl_v2_reject_proposal "Reject (kill) a staged proposal — marks status=rejected, keeps it in staging as an audit trail (does NOT add any rule)." Diferença arquitectural real e significativa: em vez de apagar (como carl_kill_proposal v1), o v2 preserva a entrada rejeitada com um campo status='rejected' — a rejeição fica auditável, não desaparece
carl_v2_get_domain "Get a full domain object from carl.json including rules, decisions, recall, state." Devolve regras + decisões + recall + state num único objecto — mais próximo do que recall (secção 1) precisaria de devolver de uma vez
carl_v2_list_domains "List all CARL domains from carl.json with rule counts, decision counts, state, and always_on flag." Introduz always_on (domínios que carregam sempre, independentemente de keyword de recall) — precedente directo para a distinção "guidance global do site" vs "guidance específica de um contexto"
carl_v2_add_rule "Add a rule to a domain in carl.json. Auto-assigns next sequential ID." Escrita directa, sem staging — existe em paralelo ao fluxo com aprovação, para uso humano/administrativo explícito

Achado relevante para o desenho de remember: a existência de duas gerações coexistentes do mesmo sistema de governança (v1 ficheiro-por-domínio, v2 carl.json único) é, ela própria, um sinal a não ignorar numa réplica — mostra que um modelo de dados de "staging de regras" tende a evoluir (aqui, de N ficheiros para 1 documento único com contadores agregados) à medida que o volume de domínios cresce. Uma implementação de remember desde o início beneficiaria de escolher logo o modelo v2 (um único documento JSON por site, com staged[] + domínios com rules[] + decisions[] + recall[] + state + always_on), evitando a migração que o CARL real precisou de fazer.

2.3 Desenho proposto para remember [DESENHO PRÓPRIO, mapeado 1:1 sobre o fluxo CARL real]

Área O que cobre Fluxo CARL real usado como modelo Nível de risco
Propor uma entrada remember({type, domain?, text, rationale}) — nunca escreve directamente; cria sempre um registo com estado inicial pending carl_stage_proposal/carl_v2_stage_proposal — mesmo padrão de "escrita nunca chega directa ao alvo" write, não-destructive, não-idempotent (cada chamada cria uma nova proposta, mesmo repetida)
Listar pendentes (uso interno pela UI de aprovação, não necessariamente exposta como tool MCP separada) Equivalente a carl_get_staged/carl_v2_get_staged mesma fonte readonly
Aprovar (exclusivamente UI de admin, nunca MCP — ver 2.4) Promove pending→approved; só depois disto entra no que recall devolve carl_approve_proposal/carl_v2_approve_proposal write, fora do protocolo MCP
Rejeitar com auditoria (exclusivamente UI de admin) Recomenda-se o comportamento v2 (carl_v2_reject_proposal): marca status:'rejected' mas preserva a entrada, em vez de apagar (carl_kill_proposal v1) — auditabilidade é mais valiosa do que limpeza para um sistema que pode influenciar decisões futuras de um agente carl_v2_reject_proposal, citação directa: "keeps it in staging as an audit trail (does NOT add any rule)" write, fora do protocolo MCP

type proposto (guardrail|fact|convention|instruction) reproduz literalmente a enumeração da própria promessa da tool Pro ("guardrail/fact/convention/instruction") — os quatro termos usados na descrição do screenshot mapeiam directamente para os dois tipos de conteúdo que o CARL real já distingue: regras (carl_stage_proposal/add_rule — mais próximo de guardrail/convention/instruction, afirmações prescritivas de "como agir") e decisões (carl_log_decision — mais próximo de fact, um registo factual de "o que foi decidido e porquê", já com rationale+recall no schema real). Uma implementação completa de remember deveria, portanto, decidir internamente para qual dos dois sub-sistemas encaminhar consoante o type, em vez de tratar as quatro categorias como um único blob indiferenciado.

2.4 A decisão de design central: remember nunca aprova a si própria

Justificação, cruzando os dois precedentes reais já confirmados nesta série para "código/regra gerado por IA que precisa de portão humano antes de ter efeito":

  • Themer PHP (docs/04-THEMER.md §11, citação directa): "AI authors + validates DRAFT PHP templates; there is intentionally no attach tool — a human selects a template in the Themer metabox (the execution gate)".
  • PHP Snippets (docs/06-SANDBOX-CUSTOM-CODE.md §1, citação directa): "There is intentionally no 'activate' tool: a snippet created via MCP is an inactive draft until a human administrator reviews it and activates it in the Sandbox admin screen."

O CARL real reforça exactamente o mesmo princípio noutro domínio (não código PHP, mas regras de governança que alteram o comportamento futuro de agentes): carl_stage_proposal nunca escreve a regra final por si — só carl_approve_proposal o faz, e nada nas descrições das tools reais sugere que a própria IA que propôs a regra a possa aprovar dentro do mesmo fluxo MCP. A promessa literal da tool Pro confirma isto de forma independente: "Stored pending until a human approves it" não deixa ambiguidade — não há tool approve no catálogo de 3 mostrado na captura de ecrã. Consistência tripla (Themer PHP real + PHP Snippets real + a própria descrição da tool Pro): uma réplica de remember deve, tal como estas três fontes convergem, nunca expor uma ability MCP approve-guidance/remember-approve — a aprovação vive exclusivamente na UI de admin, com o mesmo mecanismo de nonce+sessão humana já usado por Themer_Metabox::save() (docs/04-THEMER.md §7) e pelo handler AJAX de PHP_Snippet_Store::set_status() (docs/06-SANDBOX-CUSTOM-CODE.md §3.1).

Tensão explícita a registar (paralela à da secção 6.5 do doc 12 sobre set-widget-status): o catálogo de 3 tools do screenshot não inclui nenhuma tool de aprovação — o que é, na verdade, uma confirmação a favor desta decisão, não uma tensão como no caso do Widget Builder (onde set-widget-status aparecia no catálogo Pro e ficava ambíguo se aceitaria 'active'). Aqui os três nomes de tool observados (recall, remember, save-session-summary) já são, por si só, evidência de que o EMCP Pro não expõe uma quarta tool approve-guidance — reforça a decisão de desenho em vez de a contestar.


3. save-session-summary — registar um resumo de sessão com digest factual anexado

Promessa da tool (screenshot, PRO): "Record a session summary; the plugin attaches a factual digest of the actual changes."

A frase-chave é "a factual digest of the actual changes" — o plugin não confia no resumo narrativo do agente por si só, anexa por conta própria uma prova verificável do que realmente mudou. Este é o único ponto das 3 tools onde o ecossistema Descomplicar tem dois precedentes reais complementares e não sobrepostos: um sobre como avaliar se um resultado é real (SPEC-A) e outro sobre onde/como um digest de alterações já é persistido de forma auditável (o change ledger, código real do próprio emcp-tools).

3.1 Fundamentação [REAL] #1 — SPEC-A: avaliação de resultado real, não execução nominal

O Pipeline de Qualidade Total do ecossistema (Hub/04-Stack/02.04-Sistemas/PIPELINE-QUALIDADE-TOTAL.md) documenta um sistema chamado SPEC-A ("Avaliação de Resultados"), já implementado e a correr em produção, cujo propósito é exactamente o que a tool Pro promete: não aceitar a alegação de sucesso de uma acção pelo valor nominal, mas verificar o resultado real. Citações directas:

"stack-observer→classify→fingerprint→propostas CARL; SPEC-A (Avaliação de Resultados) merged com baseline T0; cron observer-cc semanal (2ª 08:30)" (secção 06. SelfImprovement)

"Errata 03-07-2026 (F3.1+F3.2): L1/F-CODE-02 fechada — colector observer/action_eval.py (commit 38ecc03) apresenta cada linha da action-log ao juiz SPEC-A → evaluations(source='action', entity_id=action_id) + actions.result_real; backfill 5150/5150 acções (10-jun→03-jul), 130 divergências nominal≠real; consumidores em COALESCE(result_real, result), defaults pending, result = sensor."

"Lacunas declaradas: L1 — action-log.result hardcoded success (execução ≠ resultado real; F-CODE-02)" — ou seja, a lacuna real que o SPEC-A veio fechar era EXACTAMENTE "o sistema achava que tudo tinha corrido bem só porque a acção correu até ao fim, sem verificar se o resultado era o pretendido" — a mesma distinção que "factual digest of the actual changes" (não do que o agente disse que mudou) descreve para save-session-summary.

Mapeamento directo: result (sensor/execução nominal, sempre existiu) vs result_real (juízo SPEC-A sobre o resultado verificado, COALESCE(result_real, result) como padrão de consumo — usa o valor verificado quando existe, cai para o nominal quando ainda não foi avaliado) é o precedente real exacto para a distinção que save-session-summary deveria fazer entre "o resumo que o agente escreveu" (nominal, o que o agente diz que fez) e "o digest factual anexado pelo plugin" (real, o que de facto mudou, verificável independentemente da narrativa do agente).

3.2 Fundamentação [REAL] #2 — o change ledger como fonte do "digest factual"

docs/05-REDIRECTS-SEARCH-LEDGER.md §4 já documentou, por leitura directa de código real do emcp-tools, exactamente o mecanismo que produziria um "digest factual das alterações reais" sem precisar de nenhuma lógica nova: o change ledger unificado (EMCP_Tools_Change_Log/Change_Recorder/Change_Blobs), já activo e já a registar toda escrita relevante do plugin (Elementor, filesystem, BD, posts/CPT, settings, redirects, utilizadores, ACF, media) numa única sequência cronológica, com id, ts, user_login, domain, action, target, summary.

A implicação directa para save-session-summary: em vez de o plugin ter de "adivinhar" o que mudou numa sessão (uma tarefa de detecção de estado potencialmente frágil), pode simplesmente consultar o próprio ledger entre o timestamp de início e fim da sessão — list-changes já devolve exactamente essa lista, com summary e target por entrada, e já é ordenado cronologicamente (array_reverse, mais recente primeiro, confirmado em docs/05 §4.1). O "digest factual" da promessa Pro não precisa de ser um subsistema novo: é uma agregação sobre o ledger já existente, filtrado pela janela temporal da sessão.

3.3 Fundamentação [REAL] #3 — precedentes de skills reais do ecossistema

O catálogo de skills deste ambiente (visível na lista completa de skills disponíveis nesta sessão) contém dois precedentes directos, com descrições literais que se sobrepõem quase totalmente à promessa de save-session-summary:

  • /worklog (e o seu alias /reflect): "Registo de trabalho e reflexão unificado. Analisa sessão, regista trabalho, identifica padrões, sugere acções, higieniza documentação Hub. (…) Usar quando (…) 'registar trabalho', 'log', ao parar timer." — o padrão "regista o que aconteceu numa sessão, no fim dela", já real e usado.
  • /qw: "Recapitulação rápida de sessão — resumo conciso do trabalho feito, actualização de docs e memória mem0. Uso: /qw ao finalizar tarefa ou sessão curta. Complemento leve ao /worklog." — nota-se explicitamente que actualiza "memória mem0", ou seja, este ecossistema já liga "resumir uma sessão curta" a "persistir esse resumo em memória cross-agent" — exactamente a cadeia save-session-summary→recall proposta para o EMCP Pro.
  • /report: "Report 5W2H+PDCA ao terminar tarefa/etapa — estrutura formal de conclusão com análise de resultados, documentação e memória. Integrado no domínio TASK-COMPLETION-REPORT do CARL." — achado relevante: o próprio ecossistema já tem um domínio CARL dedicado a relatórios de conclusão de tarefa (TASK-COMPLETION-REPORT), confirmando que a família CARL não serve só para "regras/decisões" (secção 2), serve também como destino natural de resumos de conclusão estruturados — um precedente real e directo para tratar save-session-summary como um terceiro tipo de entrada CARL (ao lado de rules e decisions), em vez de um subsistema totalmente separado.

3.4 Desenho proposto para save-session-summary [DESENHO PRÓPRIO, sobre 3 fontes [REAL]]

Área O que cobre Fonte real usada como modelo Nível de risco
Registar o resumo narrativo do agente save-session-summary({narrative, session_start?, session_end?}) — texto livre, o que o agente diz que fez Análogo ao campo result (nominal) de actions no SPEC-A — nunca descartado, mas nunca tratado como única fonte de verdade write, não-destructive
Anexar o digest factual ("actual changes") Consulta o change ledger (EMCP_Tools_Change_Log::all()/list-changes, docs/05 §4.1-4.2) filtrado pela janela temporal da sessão; agrega por domain+action, conta entradas, lista targets únicos docs/05-REDIRECTS-SEARCH-LEDGER.md §4 — reutilização directa de infra-estrutura já existente e já real, não um subsistema novo readonly (a consulta em si; a gravação do resumo é write)
Divergência nominal≠real Se o narrative do agente afirmar uma alteração (ex. "apaguei o redirect X") sem entrada correspondente no ledger na janela temporal, ou vice-versa, marcar a entrada com um flag divergence:true — precedente directo: SPEC-A já regista "130 divergências nominal≠real" como métrica de primeira classe, não como excepção a ignorar PIPELINE-QUALIDADE-TOTAL.md, citação já dada em 3.1 —
Alimentar recall Os N resumos mais recentes (com digest anexado) entram directamente no que recall (secção 1) devolve — sem portão de aprovação humana explícito, ao contrário de remember [DESENHO PRÓPRIO] — decisão de design explícita, ver 3.5 —

3.5 Porque save-session-summary (ao contrário de remember) não precisa de aprovação humana

Distinção de risco deliberada: um resumo de sessão é, por desenho, descritivo e retrospectivo ("o que aconteceu"), ancorado num facto verificável (o change ledger, secção 3.2) — não é prescritivo e prospectivo como uma guidance de remember ("o que fazer no futuro"). O risco de um resumo de sessão errado é limitado (na pior hipótese, um recall futuro lê um resumo impreciso, mas o digest factual anexado automaticamente pelo plugin — secção 3.2 — já mitiga isto, porque não depende só da honestidade do agente); o risco de uma guidance aprovada erradamente é muito maior, porque molda directamente decisões de escrita futuras. Esta assimetria de risco é o mesmo raciocínio, aplicado ao domínio inverso, que levou a secção 2.4 a exigir aprovação só para remember.


4. Modelo de dados proposto — o que uma "memória de projecto" guarda [DESENHO PRÓPRIO, sobre schema CARL real]

O modelo de estados abaixo é, deliberadamente, um mapeamento quase 1:1 sobre o CARL v2 real (secção 2.2) — porque replicar um modelo já validado em produção, com uma migração de geração já feita e documentada (v1 ficheiro-por-domínio → v2 documento único), evita repetir esse mesmo custo de evolução numa réplica que começasse do zero com o modelo mais simples (v1).

{
  "guidance": [
    {
      "id": "gm-014",
      "type": "guardrail",           // guardrail | fact | convention | instruction
      "domain": "checkout",           // livre, análogo aos domínios CARL (ex. GLOBAL, DEVELOPMENT)
      "text": "Nunca activar Stripe neste site — cliente só usa Multibanco/MB Way.",
      "rationale": "Pedido explícito do cliente em 2026-05-12, confirmado por email.",
      "recall": ["stripe", "gateway de pagamento", "multibanco"],
      "status": "approved",           // pending | approved | rejected | archived
      "source": "manual",             // manual | agent_proposal | session_summary_derived
      "proposed_by": "agent-run-8821",
      "proposed_at": "2026-08-19T10:03:00Z",
      "reviewed_by": "emanuel",       // preenchido só após aprovação/rejeição humana
      "reviewed_at": "2026-08-19T14:20:00Z"
    }
  ],
  "session_summaries": [
    {
      "id": "ss-0091",
      "session_start": "2026-08-19T09:00:00Z",
      "session_end": "2026-08-19T09:47:00Z",
      "narrative": "Corrigido bug de redirect em loop no checkout; actualizado texto da página de contactos.",
      "digest": {
        "source": "change_ledger",
        "entries_count": 3,
        "by_domain": { "redirect": 1, "content": 2 },
        "targets": ["redirect#44", "post#812"],
        "divergence": false
      },
      "agent": "agent-run-8821"
    }
  ]
}

4.1 Correspondência campo-a-campo com o CARL real

Campo proposto Fundamentação Equivalente CARL real
id [DESENHO PRÓPRIO], formato inspirado directamente nos ids reais observados nas descrições das próprias tools (prop-001 v1, stg-001 v2) carl_approve_proposal.id / carl_v2_approve_proposal.id
type [REAL] — os 4 valores vêm literalmente da descrição da tool Pro ("guardrail/fact/convention/instruction") — (a própria captura de ecrã)
domain [REAL] — conceito directo dos domínios CARL (GLOBAL, DEVELOPMENT, PROJECTS, CONTENT, exemplos vistos nas descrições reais das tools carl_get_domain_rules/carl_v2_get_domain) domain em carl_stage_proposal/carl_log_decision/carl_v2_stage_proposal
recall [REAL] — campo com o mesmo nome exacto em carl_log_decision/carl_v2_log_decision ("Comma-separated recall keywords"/"Comma-separated keywords for when to recall this decision") e em carl_create_domain/carl_v2_create_domain (recall keywords do próprio domínio) recall em múltiplas tools CARL reais
status: pending|approved|rejected|archived [REAL, com uma correcção sobre a v1] — a v1 tem só 3 saídas efectivas (approve/archive/kill-delete); o status:'rejected' preservado (não apagado) é especificamente o comportamento v2, citação directa já dada em 2.3: "marks status=rejected, keeps it in staging as an audit trail" — este documento recomenda o comportamento v2 (preservar) sobre o v1 (apagar) carl_v2_reject_proposal
source: manual|agent_proposal|session_summary_derived [DESENHO PRÓPRIO] — o terceiro valor (session_summary_derived) é a extensão própria deste blueprint: uma guidance pode nascer não de uma proposta directa (remember), mas de um padrão detectado em vários session_summaries (ex. "o agente corrigiu o mesmo tipo de bug 3 vezes" → proposta automática de um guardrail) — o precedente real mais próximo é o source real psmm do CARL ("Proactive Session Memory Mining", inferido do nome da enum em carl_stage_proposal.source, não confirmado em detalhe nesta tarefa, mas o padrão "a proposta pode vir de mineração de sessões passadas, não só de pedido directo" já existe no CARL real) source (enum psmm|decisions|manual) em carl_stage_proposal
session_summaries[].digest [DESENHO PRÓPRIO] — a estrutura em si; a fonte dos dados (source:'change_ledger') é [REAL], ver secção 3.2 EMCP_Tools_Change_Log::all()
session_summaries[].digest.divergence [DESENHO PRÓPRIO] — o campo; o conceito (nominal ≠ real) é [REAL], SPEC-A, secção 3.1 actions.result vs actions.result_real, COALESCE()

4.2 Evolução de estados — paralelo directo ao CARL

            remember()                    aprovação humana (UI, nunca MCP)
(pending) ─────────────────► [pending] ──────────────────────────────────► [approved]
                                  │                                             │
                                  │  rejeição humana (UI, nunca MCP)           │  recall() lê SÓ aqui
                                  ▼                                             ▼
                             [rejected]                                  (visível a recall)
                          (preservado, auditável,
                           nunca vira regra — v2)

                                  │  arquivar (referência, nunca activa)
                                  ▼
                             [archived]

Este diagrama de estados é uma transcrição directa, para o domínio "Project Memory", do comportamento real confirmado nas descrições das 5 tools CARL de gestão de propostas citadas em 2.1-2.2 (stage/get_staged/approve/archive/reject-ou-kill) — nenhum estado ou transição aqui é inventado sem correspondência directa numa tool CARL real.


5. Blueprint para réplica

Reaproveitar quase 1:1 (infra-estrutura já real, [REAL])

  1. O modelo de estados staging→aprovação do CARL (secção 2, 4) — não inventar um novo vocabulário de estados; usar exactamente pending/approved/rejected/archived e o princípio "rejeitar preserva para auditoria, não apaga" (comportamento v2, secção 2.2) desde o primeiro dia, evitando a migração v1→v2 que o CARL real precisou de fazer.
  2. O change ledger unificado como fonte de "digest factual" (docs/05-REDIRECTS-SEARCH-LEDGER.md §4, EMCP_Tools_Change_Log) — save-session-summary não precisa de nenhuma lógica nova de detecção de alterações; é uma consulta agregada sobre infra-estrutura que já existe e já está documentada nesta série. Reaproveitar directamente list-changes filtrado por janela temporal.
  3. O padrão "a flag partial/divergence é responsabilidade do produtor, não do consumidor" (docs/05 §4.4, sobre record_db()) — aplicado aqui à flag divergence do digest: quem constrói o resumo de sessão marca-a explicitamente quando a narrativa e o ledger não batem certo, o consumidor (recall) só propaga.
  4. A ausência deliberada de uma tool approve/activate no protocolo MCP — o padrão mais repetido e mais bem confirmado desta série inteira (Themer PHP, PHP Snippets, e agora também o próprio CARL real e a própria descrição da tool Pro remember, todos convergentes): qualquer escrita que altere o comportamento futuro de um agente de IA a partir de conteúdo proposto por um agente de IA deve ter o portão de aprovação fora do protocolo MCP, com sessão humana + nonce (padrão exacto de Themer_Metabox::save(), docs/04-THEMER.md §7).

Construir de raiz ([DESENHO PRÓPRIO], sequência recomendada por dependência)

  1. Modelo de dados (secção 4) primeiro — um único documento JSON por site (seguindo o modelo v2 do CARL, não o v1 por-ficheiro), com guidance[] + session_summaries[]; evita a migração estrutural que o CARL real teve de fazer.
  2. recall — a mais simples das três, é uma leitura filtrada (status='approved' + session_summaries mais recentes); implementável e testável isoladamente sem nenhuma escrita.
  3. Ligação ao change ledger — antes de save-session-summary, expor um método interno changes_in_window(start, end) sobre EMCP_Tools_Change_Log::all() (código já existe, doc 05); este é o único bloco de dependência real de código do próprio emcp-tools.
  4. save-session-summary — sem portão de aprovação humana (secção 3.5); grava directamente, com o digest anexado a partir do passo 3.
  5. remember — por último, porque é o único dos três com uma superfície de admin obrigatória (a UI de aprovação humana) a construir em paralelo; sem essa UI, remember cria propostas que nunca podem sair de pending — inútil sem ela.
  6. Detecção de padrões cross-sessão (source:'session_summary_derived', secção 4.1) — feature avançada, deixar para uma segunda iteração; o precedente real mais próximo (psmm como um dos três valores reais do enum source de carl_stage_proposal) sugere que o próprio CARL trata isto como um caminho de proposta distinto e não trivial, não uma extensão simples do fluxo manual.

Deixar de fora ou adiar explicitamente

  • Qualquer tool de aprovação/activação via MCP (approve-guidance, activate-guidance, etc.) — nunca implementar, independentemente de pressão de conveniência; é a decisão de design mais repetida e mais bem fundamentada de toda a série de documentos EMCP (docs 04, 06, 12 e agora este).
  • Reranking semântico de recall — o precedente real mais próximo (EMCP_Tools_Search_Ranker, docs/05 §2.3) já deixa um "seam" explícito no próprio código real do plugin para um reranker com embeddings como upgrade Pro futuro ("This is the seam for an embedding-backed reranker (a future Pro upgrade); the lexical order is the default"); uma primeira implementação de recall deveria seguir exactamente o mesmo princípio — ordenação lexical/determinística por omissão (recência para session_summaries, correspondência exacta de recall keywords para guidance), com um filtro extensível para um reranker semântico mais tarde, sem bloquear o v1 nessa dependência.
  • Migração automática entre gerações de schema (o equivalente ao maybe_migrate() de EMCP_Tools_Sandbox_Paths, docs/06-SANDBOX-CUSTOM-CODE.md §3.4, que existe só porque o produto real mudou de local a meio da vida) — não é necessária numa implementação de raiz que já comece com o modelo de dados da secção 4 (inspirado directamente na geração v2, mais recente, do CARL).

6. Fonte

Fonte A — identidade operacional deste ambiente OMP (lida integralmente nesta sessão):

  • /home/ealmeida/.omp/agent/AGENTS.md — ficheiro de import; conteúdo próprio limitado a uma política de tokens/segredos em sessão, não relevante a este documento.
  • /media/ealmeida/Dados/Hub/04-Stack/02.04-Sistemas/AGENTS.md (documento canónico importado pelo anterior) — secção 2 ("HIERARQUIA DE FONTES", regras NLM-first e "nunca confiar em docs sem verificar"), secção 4 ("ECOSSISTEMA", errata sobre as 22/26 regras CARL GLOBAL), secção 5 ("MEMÓRIA", tabela completa de tiers Mem0/Hindsight, protocolo Wayland).
  • /media/ealmeida/Dados/Hub/04-Stack/02.04-Sistemas/PIPELINE-QUALIDADE-TOTAL.md — secções sobre o arco C6 (propostas CARL, "staging CARL funcional", "CARL v2 GLOBAL com 26 regras"), o arco C7 (SPEC-A, action_eval, result_real, COALESCE(result_real, result), "130 divergências nominal≠real"), e a secção 06.SelfImprovement ("SPEC-A (Avaliação de Resultados) merged com baseline T0").

Fonte B — ferramentas MCP reais, invocadas ou inspeccionadas directamente nesta sessão:

  • Servidor carl-mcp (v1, ficheiro-por-domínio): carl_stage_proposal, carl_get_staged (chamada real, resultado {pending_count:0, archived_count:0} — sem propostas activas neste projecto no momento da tarefa), carl_get_manifest (chamada real, resultado {success:false, "Manifest not found"} — sem manifesto v1 inicializado neste projecto), carl_approve_proposal, carl_archive_proposal, carl_kill_proposal, carl_log_decision, carl_get_domain_rules, carl_list_domains, carl_create_domain, carl_toggle_domain, carl_search_decisions, carl_get_decisions, carl_archive_decision, carl_list_decision_domains — descrições e schemas de argumento lidos directamente da definição real da ferramenta, não paraseados de documentação externa.
  • Servidor carl-mcp (v2, carl.json único): carl_v2_stage_proposal, carl_v2_get_staged, carl_v2_approve_proposal, carl_v2_reject_proposal (citação literal confirmada: "marks status=rejected, keeps it in staging as an audit trail (does NOT add any rule)"), carl_v2_add_rule, carl_v2_remove_rule, carl_v2_replace_rules, carl_v2_log_decision, carl_v2_archive_decision, carl_v2_search_decisions, carl_v2_get_domain, carl_v2_list_domains, carl_v2_create_domain, carl_v2_toggle_domain, carl_v2_get_config, carl_v2_update_config.
  • Servidor mem0: mcp__mem_save_memory, mcp__mem_search_memories, mcp__mem_get_all_memories, mcp__mem_get_memory, mcp__mem_update_memory, mcp__mem_delete_memory, mcp__mem_delete_all_memories, mcp__mem_memory_history, mcp__mem_reset_memory — usadas como modelo do Tier 2 (secção 1.2).
  • Catálogo de skills deste ambiente (lista completa disponível nesta sessão) — descrições literais citadas de /worklog, /reflect, /qw, /report (secção 3.3), incluindo o achado do domínio CARL TASK-COMPLETION-REPORT referenciado explicitamente na descrição real da skill /report.

Cruzado com código real do próprio emcp-tools, já lido em sessões anteriores desta série (não relido nesta tarefa):

  • docs/05-REDIRECTS-SEARCH-LEDGER.md §4 (integral) — EMCP_Tools_Change_Log, EMCP_Tools_Change_Recorder, EMCP_Tools_Change_Blobs, EMCP_Tools_Transaction_Abilities, usados como modelo para o "digest factual" de save-session-summary (secção 3.2) e como precedente do padrão de flags-responsabilidade-do-produtor (secção 5).
  • docs/05-REDIRECTS-SEARCH-LEDGER.md §2.3 — EMCP_Tools_Search_Ranker, citação sobre o "seam" para reranking semântico futuro, usada em §5 ("Deixar de fora") como precedente para não implementar reranking semântico em recall v1.
  • docs/04-THEMER.md §7, §11 (integral) — EMCP_Tools_Themer_Metabox::save() (padrão de aprovação humana com nonce), EMCP_Tools_Themer_PHP_Abilities/Themer_PHP_Store (citação directa "there is intentionally no attach tool"), usados como precedente central da secção 2.4.
  • docs/06-SANDBOX-CUSTOM-CODE.md §1, §3.1, §3.4 (integral) — EMCP_Tools_PHP_Snippet_Abilities (citação directa "There is intentionally no 'activate' tool"), EMCP_Tools_PHP_Snippet_Store::set_status() (portão de aprovação via handler AJAX admin, nunca MCP), EMCP_Tools_Sandbox_Paths::maybe_migrate() (precedente citado em §5 para justificar não construir migração de schema de raiz).
  • docs/10-MODULOS-E-INVENTARIO-PRO.md — padrão de class_exists()-gated com ficheiro Pro fisicamente ausente da árvore Free, usado em §0 para justificar por que "Project Memory" não é auditável directamente (mesmo padrão já confirmado exaustivamente para os outros ~30 módulos Pro nesse documento, não retentado nesta tarefa).
  • docs/11-WOOCOMMERCE-BLUEPRINT.md e docs/12-WIDGET-BUILDER-BLUEPRINT.md — usados como referência de estilo e formato deste tipo de documento "blueprint, não auditoria" (secção 0 explícita com fontes numeradas, convenção [REAL]/[DESENHO PRÓPRIO], tabelas de ability proposta com coluna de nível de risco, secção final "Blueprint para réplica" estruturada em copiar/construir/omitir, secção "Fonte" com ficheiros exactos e o que não foi lido).

Não lido nesta tarefa (lacuna explícita): qualquer código-fonte do EMCP Pro para "Project Memory" (class-project-memory-abilities.php ou nome equivalente) — fisicamente ausente da árvore Free instalada, mesmo padrão de ausência já confirmado exaustivamente para os outros módulos Pro nesta série (docs/10-MODULOS-E-INVENTARIO-PRO.md), não retentado por leitura directa nesta tarefa. A implementação interna real de remember/recall/save-session-summary — schema de input exacto, mensagens de erro, se usa CPT ou tabela SQL própria, se tem tectos de retenção/paginação como o change ledger (MAX_COUNT=500, MAX_BYTES=2MB, docs/05 §4.2) — é desconhecida e não deve ser assumida a partir deste blueprint; tudo aqui é proposta própria fundamentada nos dois sistemas reais descritos acima, não uma transcrição do comportamento Pro real.