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.
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
- 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 CARLGLOBALsó carregavam com o cwd dentro de04-Stack— o CARL resolve scopes pelo cwd e substitui o domínio inteiro. Fora dali,GLOBALtinha 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).
- O ficheiro canónico
- 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 MCPmem0disponíveis nesta sessão (servidormem0, prefixomcp__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óprioAGENTS.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-ccsemanal (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(commit38ecc03) 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 emCOALESCE(result_real, result), defaultspending,result= sensor."
"Lacunas declaradas: L1 —
action-log.resulthardcodedsuccess(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 parasave-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 cadeiasave-session-summary→recallproposta 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 tratarsave-session-summarycomo 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])
- 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/archivede 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. - O change ledger unificado como fonte de "digest factual" (
docs/05-REDIRECTS-SEARCH-LEDGER.md§4,EMCP_Tools_Change_Log) —save-session-summarynã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 directamentelist-changesfiltrado por janela temporal. - O padrão "a flag
partial/divergenceé responsabilidade do produtor, não do consumidor" (docs/05§4.4, sobrerecord_db()) — aplicado aqui à flagdivergencedo 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. - A ausência deliberada de uma tool
approve/activateno 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 Proremember, 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 deThemer_Metabox::save(),docs/04-THEMER.md§7).
Construir de raiz ([DESENHO PRÓPRIO], sequência recomendada por dependência)
- 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. recall— a mais simples das três, é uma leitura filtrada (status='approved'+session_summariesmais recentes); implementável e testável isoladamente sem nenhuma escrita.- Ligação ao change ledger — antes de
save-session-summary, expor um método internochanges_in_window(start, end)sobreEMCP_Tools_Change_Log::all()(código já existe, doc 05); este é o único bloco de dependência real de código do próprioemcp-tools. 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.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,remembercria propostas que nunca podem sair depending— inútil sem ela.- 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 (psmmcomo um dos três valores reais do enumsourcedecarl_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 derecalldeveria seguir exactamente o mesmo princípio — ordenação lexical/determinística por omissão (recência parasession_summaries, correspondência exacta derecallkeywords paraguidance), 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()deEMCP_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 CARLGLOBAL), 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 CARLTASK-COMPLETION-REPORTreferenciado 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" desave-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 emrecallv1.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 declass_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.mdedocs/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.