funifier-mcp 0.3.18 → 0.3.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (144) hide show
  1. package/.cursor/rules/funifier.mdc +2 -1
  2. package/.github/copilot-instructions.md +2 -1
  3. package/AGENTS.md +2 -1
  4. package/CHANGELOG.md +59 -0
  5. package/README.md +1 -1
  6. package/datasource-funifier-docs/.coverage.json +4 -1
  7. package/datasource-funifier-docs/.validation.json +12 -7
  8. package/datasource-funifier-docs/knowledge/guides/aggregates.md +13 -6
  9. package/datasource-funifier-docs/knowledge/index.md +2 -2
  10. package/dist/cli/init.d.ts.map +1 -1
  11. package/dist/cli/init.js +3 -1
  12. package/dist/cli/init.js.map +1 -1
  13. package/dist/core/api-client.d.ts +2 -0
  14. package/dist/core/api-client.d.ts.map +1 -1
  15. package/dist/core/api-client.js +98 -47
  16. package/dist/core/api-client.js.map +1 -1
  17. package/dist/core/api-client.test.js +27 -0
  18. package/dist/core/api-client.test.js.map +1 -1
  19. package/dist/core/constants.d.ts +4 -0
  20. package/dist/core/constants.d.ts.map +1 -1
  21. package/dist/core/constants.js +8 -0
  22. package/dist/core/constants.js.map +1 -1
  23. package/dist/core/logger.d.ts +9 -0
  24. package/dist/core/logger.d.ts.map +1 -0
  25. package/dist/core/logger.js +50 -0
  26. package/dist/core/logger.js.map +1 -0
  27. package/dist/mcp/api-holder.test.d.ts +2 -0
  28. package/dist/mcp/api-holder.test.d.ts.map +1 -0
  29. package/dist/mcp/api-holder.test.js +45 -0
  30. package/dist/mcp/api-holder.test.js.map +1 -0
  31. package/dist/mcp/bundle.js +103 -100
  32. package/dist/mcp/check-update.d.ts +9 -0
  33. package/dist/mcp/check-update.d.ts.map +1 -1
  34. package/dist/mcp/check-update.js +35 -9
  35. package/dist/mcp/check-update.js.map +1 -1
  36. package/dist/mcp/check-update.test.js +36 -6
  37. package/dist/mcp/check-update.test.js.map +1 -1
  38. package/dist/mcp/doc-path.d.ts +11 -0
  39. package/dist/mcp/doc-path.d.ts.map +1 -0
  40. package/dist/mcp/doc-path.js +66 -0
  41. package/dist/mcp/doc-path.js.map +1 -0
  42. package/dist/mcp/doc-path.test.d.ts +2 -0
  43. package/dist/mcp/doc-path.test.d.ts.map +1 -0
  44. package/dist/mcp/doc-path.test.js +77 -0
  45. package/dist/mcp/doc-path.test.js.map +1 -0
  46. package/dist/mcp/index.js +19 -0
  47. package/dist/mcp/index.js.map +1 -1
  48. package/dist/mcp/resources/documentation.d.ts.map +1 -1
  49. package/dist/mcp/resources/documentation.js +7 -3
  50. package/dist/mcp/resources/documentation.js.map +1 -1
  51. package/dist/mcp/tools/_backup.d.ts.map +1 -1
  52. package/dist/mcp/tools/_backup.js +5 -3
  53. package/dist/mcp/tools/_backup.js.map +1 -1
  54. package/dist/mcp/tools/_char-guard.d.ts +2 -1
  55. package/dist/mcp/tools/_char-guard.d.ts.map +1 -1
  56. package/dist/mcp/tools/_char-guard.js +10 -3
  57. package/dist/mcp/tools/_char-guard.js.map +1 -1
  58. package/dist/mcp/tools/_fetch-current.d.ts +2 -1
  59. package/dist/mcp/tools/_fetch-current.d.ts.map +1 -1
  60. package/dist/mcp/tools/_fetch-current.js +2 -74
  61. package/dist/mcp/tools/_fetch-current.js.map +1 -1
  62. package/dist/mcp/tools/_registry.d.ts +183 -0
  63. package/dist/mcp/tools/_registry.d.ts.map +1 -0
  64. package/dist/mcp/tools/_registry.js +88 -0
  65. package/dist/mcp/tools/_registry.js.map +1 -0
  66. package/dist/mcp/tools/_registry.test.d.ts +2 -0
  67. package/dist/mcp/tools/_registry.test.d.ts.map +1 -0
  68. package/dist/mcp/tools/_registry.test.js +103 -0
  69. package/dist/mcp/tools/_registry.test.js.map +1 -0
  70. package/dist/mcp/tools/database.d.ts +4 -0
  71. package/dist/mcp/tools/database.d.ts.map +1 -1
  72. package/dist/mcp/tools/database.js +23 -4
  73. package/dist/mcp/tools/database.js.map +1 -1
  74. package/dist/mcp/tools/database.test.js +19 -0
  75. package/dist/mcp/tools/database.test.js.map +1 -1
  76. package/dist/mcp/tools/delete.d.ts.map +1 -1
  77. package/dist/mcp/tools/delete.js +3 -98
  78. package/dist/mcp/tools/delete.js.map +1 -1
  79. package/dist/mcp/tools/execute.d.ts.map +1 -1
  80. package/dist/mcp/tools/execute.js +36 -4
  81. package/dist/mcp/tools/execute.js.map +1 -1
  82. package/dist/mcp/tools/execute.test.d.ts +2 -0
  83. package/dist/mcp/tools/execute.test.d.ts.map +1 -0
  84. package/dist/mcp/tools/execute.test.js +87 -0
  85. package/dist/mcp/tools/execute.test.js.map +1 -0
  86. package/dist/mcp/tools/get.d.ts.map +1 -1
  87. package/dist/mcp/tools/get.js +4 -93
  88. package/dist/mcp/tools/get.js.map +1 -1
  89. package/dist/mcp/tools/index.d.ts.map +1 -1
  90. package/dist/mcp/tools/index.js +42 -1
  91. package/dist/mcp/tools/index.js.map +1 -1
  92. package/dist/mcp/tools/list.d.ts.map +1 -1
  93. package/dist/mcp/tools/list.js +3 -91
  94. package/dist/mcp/tools/list.js.map +1 -1
  95. package/dist/mcp/tools/logs.d.ts.map +1 -1
  96. package/dist/mcp/tools/logs.js +5 -3
  97. package/dist/mcp/tools/logs.js.map +1 -1
  98. package/dist/mcp/tools/read-doc.d.ts.map +1 -1
  99. package/dist/mcp/tools/read-doc.js +10 -28
  100. package/dist/mcp/tools/read-doc.js.map +1 -1
  101. package/dist/mcp/tools/save.d.ts.map +1 -1
  102. package/dist/mcp/tools/save.js +4 -81
  103. package/dist/mcp/tools/save.js.map +1 -1
  104. package/package.json +3 -2
  105. package/skills/funifier/SKILL.md +2 -1
  106. package/skills/funifier/references/audit-permissions.md +8 -0
  107. package/skills/funifier/references/configure-security.md +6 -0
  108. package/skills/funifier/references/create-action.md +7 -0
  109. package/skills/funifier/references/create-aggregate.md +99 -79
  110. package/skills/funifier/references/create-audit.md +8 -0
  111. package/skills/funifier/references/create-challenge.md +7 -0
  112. package/skills/funifier/references/create-competition.md +7 -0
  113. package/skills/funifier/references/create-crossword.md +6 -0
  114. package/skills/funifier/references/create-custom-object.md +6 -0
  115. package/skills/funifier/references/create-custom-page.md +6 -0
  116. package/skills/funifier/references/create-folder.md +7 -0
  117. package/skills/funifier/references/create-lastmile.md +6 -0
  118. package/skills/funifier/references/create-leaderboard.md +6 -0
  119. package/skills/funifier/references/create-level.md +7 -0
  120. package/skills/funifier/references/create-lottery.md +7 -0
  121. package/skills/funifier/references/create-mystery.md +6 -0
  122. package/skills/funifier/references/create-notification.md +6 -0
  123. package/skills/funifier/references/create-point.md +7 -0
  124. package/skills/funifier/references/create-quiz.md +7 -0
  125. package/skills/funifier/references/create-scheduler.md +6 -0
  126. package/skills/funifier/references/create-story.md +6 -0
  127. package/skills/funifier/references/create-swap.md +6 -0
  128. package/skills/funifier/references/create-trigger.md +8 -0
  129. package/skills/funifier/references/create-virtual-good.md +6 -0
  130. package/skills/funifier/references/create-webhook.md +6 -0
  131. package/skills/funifier/references/create-websocket.md +6 -0
  132. package/skills/funifier/references/create-widget.md +6 -0
  133. package/skills/funifier/references/date-handling.md +6 -0
  134. package/skills/funifier/references/debug.md +6 -0
  135. package/skills/funifier/references/help.md +6 -0
  136. package/skills/funifier/references/implement-frontend.md +7 -0
  137. package/skills/funifier/references/import-csv.md +6 -0
  138. package/skills/funifier/references/manage-indexes.md +6 -0
  139. package/skills/funifier/references/manage-player.md +7 -0
  140. package/skills/funifier/references/manage-team.md +6 -0
  141. package/skills/funifier/references/query-aggregate.md +111 -0
  142. package/skills/funifier/references/upload-file.md +6 -0
  143. package/datasource-funifier-docs/.search-index.json +0 -59345
  144. package/datasource-funifier-docs/.skills-map.json +0 -145
@@ -1,6 +1,6 @@
1
1
  # funifier-create-aggregate
2
2
 
3
- Create a Funifier prepared aggregate — guided workflow for building MongoDB aggregate pipelines for reports and dashboards
3
+ Create/edit a Funifier prepared aggregate — a saved pipeline with _id, $param placeholders, optional Groovy script, cache and execution via POST /v3/find/{id}; for reusable dashboards and parametrized reports
4
4
 
5
5
  ---
6
6
 
@@ -48,7 +48,7 @@ Note que `aggregate` é uma **string** contendo JSON serializado (com `\n` e `\"
48
48
  Use the `funifier_search_docs` MCP tool to load only what you need:
49
49
 
50
50
  ```
51
- funifier_search_docs "aggregate mongodb pipeline report dashboard query prepared"
51
+ funifier_search_docs "aggregate mongodb pipeline prepared dashboard param script find reusable"
52
52
  ```
53
53
 
54
54
  Then read the most relevant results with `funifier_read_doc path=<path>`.
@@ -63,118 +63,138 @@ If search returns insufficient results, read these directly:
63
63
 
64
64
  ## Steps
65
65
 
66
- > **Prepared aggregate** = pipeline MongoDB salvo na plataforma com `_id` e executado por ID via `POST /v3/find/<id>`, com parâmetros dinâmicos (`"$param:nome"`). Diferente do aggregate **ad-hoc** (`POST /v3/database/{collection}/aggregate`), usado para testar pipelines.
66
+ > **Prepared aggregate** = pipeline MongoDB **salvo** na plataforma (coleção `prepared_aggregate`) com `_id`, parâmetros dinâmicos (`"$param:nome"`) e um `script` Groovy opcional, executado por ID via `POST /v3/find/<id>`. Use para dashboards e relatórios **reutilizáveis**. Para uma consulta **pontual sem salvar**, use a skill `funifier-query-aggregate` (ad-hoc).
67
67
 
68
- ### Coleções principais
68
+ > ⚠️ **"Salvo" ≠ "funcionando".** O `funifier_save type=aggregate` persiste via `PUT /v3/database/prepared_aggregate` (upsert genérico de banco) e **NÃO compila** o `script`. Um script quebrado é "salvo com sucesso" e só falha — silenciosamente — na execução. Por isso o fluxo abaixo é **montar → salvar → verificar**, nunca só salvar.
69
69
 
70
- | Coleção | Conteúdo chave |
71
- |---|---|
72
- | `achievement` | Conquistas — `type`: 0=Point, 1=Challenge, 2=VirtualGood, 3=Level |
73
- | `action_log` | Ações executadas — `actionId`, `userId`, `attributes`, `time` |
74
- | `player` | Jogadores — `_id`, `name`, `teams`, `extra` |
75
- | `challenge` | Desafios — `_id`, `challenge`, `rules`, `points` |
76
- | `point_category` | Tipos de ponto — `_id`, `category`, `shortName` |
77
- | `catalog_item` | Loja virtual — `_id`, `catalogId`, `name`, `requires` |
70
+ ### 1. Definir a consulta e montar o pipeline
78
71
 
79
- Se o pipeline filtrar ou criar campos de data, leia também `references/date-handling.md` antes de montar o payload.
72
+ - Qual coleção, filtro, agrupamento, ordenação e limite? Quais valores serão **parâmetros** (`$param`)?
73
+ - Monte/teste o pipeline como uma consulta **ad-hoc** primeiro (skill `funifier-query-aggregate`) — não reensine a execução direta aqui. As relações de coleção para `$lookup` estão lá e em `aggregates.md` §3.
74
+ - Confira se já existe: `funifier_list type=aggregate search=<titulo>`.
80
75
 
81
- ### Expressões de data Funifier
76
+ ### 2. Campos do recurso
82
77
 
83
- Para regras completas de criação/edição/consulta de datas via REST, triggers, schedulers, aggregate e prepared aggregate, leia `references/date-handling.md`.
78
+ Todos embasados em `PreparedAggregate` (funifier-service). Apenas `_id`, `title`, `collection`, `aggregate` são essenciais; o resto é opcional.
84
79
 
85
- | Expressão | Significado |
80
+ | Campo | Semântica |
86
81
  |---|---|
87
- | `{"$date": "-0d-"}` | Início do dia atual |
88
- | `{"$date": "-0M-"}` | Início do mês atual |
89
- | `{"$date": "-0M+"}` | Fim do mês atual |
90
- | `{"$date": "-0y-"}` | Início do ano atual |
91
- | `{"$date": "-1d-"}` | Início do dia anterior |
82
+ | `_id` | Identificador do recurso (usado em `POST /v3/find/<id>`). |
83
+ | `title` | Nome legível. |
84
+ | `description` | Descrição livre (opcional). |
85
+ | `collection` | Coleção-base sobre a qual o pipeline roda. |
86
+ | `aggregate` | **String** contendo um array JSON válido (o pipeline). Ver §3. |
87
+ | `script` | Groovy opcional `void prepare(aggregations, params)` (`""` se não precisar). Ver §6. |
88
+ | `timeout` | Sobrescreve o timeout padrão de **5s** do script (em segundos). |
89
+ | `cache` | Expressão de duração Funifier (ex.: `"30m"`, `"3h"`) — TTL do resultado em cache, servido pelo mesmo `POST /v3/find/<id>`. |
90
+ | `cache_before_find` | Aplica o cache antes do find (caso avançado). |
91
+ | `parent` | Consulta o resultado **em cache de outro find** em vez de uma coleção (find-sobre-find, **um nível**; o parent deve usar `collection`). |
92
92
 
93
- **Importante:** em aggregate direto e prepared aggregate, prefira expressões relativas Funifier dentro de `$date` (`-0M-`, `-0M+`) ou timestamps em milissegundos para datas absolutas. Para datas absolutas parametrizadas em prepared aggregate, normalize no `script` com `DateUtil.parse(...)` e substitua diretamente em `$gte`/`$lte`.
93
+ ### 3. Formato do campo `aggregate` (string JSON)
94
94
 
95
- ---
95
+ O campo `aggregate` é uma **`String`** lida na execução com `JsonUtil.fromJson(aggregate, List.class)`. **Só importa a validade do JSON** — indentação, `\n` e minificação são irrelevantes. Construa um array nativo e serialize com `JSON.stringify(pipeline)`, deixando o escape com o MCP.
96
96
 
97
- ## Steps
97
+ > ⚠️ **Não envie um array JSON nativo** em `aggregate` — o campo da entidade é `String`; um array nativo gera um recurso que falha na execução. Minificado em uma linha **é aceito** (não existe regra de "identado, nunca minificado").
98
98
 
99
- ### 1. Identificar a necessidade
99
+ Exemplo (identado por legibilidade — minificado também funciona):
100
+ ```json
101
+ {
102
+ "_id": "top_players_month",
103
+ "title": "Top Players Month",
104
+ "collection": "achievement",
105
+ "aggregate": "[{\"$match\":{\"type\":0,\"item\":\"xp\"}},{\"$group\":{\"_id\":\"$player\",\"total\":{\"$sum\":\"$total\"}}},{\"$sort\":{\"total\":-1}},{\"$limit\":10}]",
106
+ "script": "",
107
+ "cache": "30m"
108
+ }
109
+ ```
100
110
 
101
- - Qual collection tem os dados? (ver tabela acima)
102
- - Qual o filtro? (período, jogador, tipo de conquista)
103
- - Qual o agrupamento? (por jogador, por dia, por equipe)
104
- - Qual ordenação e limite?
111
+ > Via `funifier_save type=aggregate file=...`, o pipeline pode vir do arquivo companheiro `.pipeline.json` — o MCP serializa e escapa para você.
105
112
 
106
- ### 2. Verificar se já existe
113
+ ### 4. Parâmetros `$param`
107
114
 
108
- ```
109
- funifier_list type=aggregate search=<titulo>
110
- ```
115
+ - Um placeholder deve ser o **valor de string JSON inteiro**: `"$param:nome"`. A substituição é a **nível de valor** (sem concatenação/interpolação de substring) e o valor assume o **tipo** do param: string, número, `Long` (millis), `Date`, array ou objeto.
116
+ - **Param ausente vira `null`** → filtro silenciosamente não casa nada. Confirme os nomes esperados com `funifier_execute type=aggregate id=<id> mode=params` (varredura literal de `"$param:NOME"` na string salva).
117
+ - Avançado: pode-se injetar um **sub-pipeline**, nome de **coleção** ou `Map`/`List` via param (ex.: `"$param:collection"`, `"$param:pipelineSearch"`) quando o `script` faz `params.put` de um valor real.
111
118
 
112
- ### 3. Construir e testar o pipeline
119
+ ### 5. Datas parametrizadas
113
120
 
114
- Top 10 jogadores com mais pontos no mês:
115
- ```json
116
- [
117
- {"$match": {"type": 0, "item": "xp", "time": {"$gte": {"$date": "-0M-"}, "$lte": {"$date": "-0M+"}}}},
118
- {"$group": {"_id": "$player", "total": {"$sum": "$total"}}},
119
- {"$sort": {"total": -1}},
120
- {"$lookup": {"from": "player", "localField": "_id", "foreignField": "_id", "as": "p"}},
121
- {"$unwind": "$p"},
122
- {"$project": {"_id": 1, "player": "$p.name", "total": 1}},
123
- {"$limit": 10}
124
- ]
125
- ```
121
+ A gramática `{"$date": "-0M-"}` (relativa, não-parametrizada) pode ir **direto** no pipeline salvo — detalhada em `aggregates.md` §4 (dono único; `funifier_read_doc path=guides/aggregates`). Para uma data **dinâmica vinda de param**, o padrão real é:
126
122
 
127
- Testar diretamente antes de registrar:
128
123
  ```
129
- POST /v3/database/achievement/aggregate
124
+ pipeline: { "$match": { "time": { "$gte": {"$date": "$param:start"}, "$lte": {"$date": "$param:end"} } } }
125
+ script: params.put("start", startDate.getTime()) // millis (Long) — ou injete um Date
130
126
  ```
131
127
 
132
- ### 4. Registrar como Prepared Aggregate
128
+ Omitir o param de data na execução → o engine substitui por `null` e o filtro não casa nada. Ver também a skill `funifier-date-handling`.
133
129
 
134
- **Formatação obrigatória:** o campo `aggregate` é o pipeline serializado como **string identada**, com `\n` ao fim de cada linha (equivalente a `JSON.stringify(pipeline, null, 4)`) — **nunca** minificado em uma linha única. O `script` Groovy também preserva indentação e `\n`. Os escapes (`\"`, `\\`) seguem a seção "Formato do payload" acima.
130
+ ### 6. Script Groovy `prepare()` (opcional)
135
131
 
136
- ```json
137
- {
138
- "_id": "top_players_month",
139
- "title": "Top Players Month",
140
- "collection": "achievement",
141
- "aggregate": "[\n {\n \"$match\": {\n \"type\": 0,\n \"item\": \"xp\"\n }\n },\n {\n \"$group\": {\n \"_id\": \"$player\",\n \"total\": {\n \"$sum\": \"$total\"\n }\n }\n },\n {\n \"$sort\": {\n \"total\": -1\n }\n },\n {\n \"$limit\": 10\n }\n]",
142
- "script": ""
132
+ Se o pipeline só usa placeholders `"$param:nome"`, `script: ""` é válido — não precisa de `prepare()`. Quando precisar de lógica (resolver janela de datas, guardas), o contrato é:
133
+
134
+ - **Assinatura de entrada:** `void prepare(aggregations, params)`. Métodos auxiliares extras são permitidos.
135
+ - **Ambiente:** roda dentro de uma `class FunifierTrigger` gerada, que já importa `DateUtil`, `JsonUtil`, `manager` (`ManagerFactory`), as entidades, e o default `java.util.*` do Groovy. O `context` expõe **apenas** `player`. `println(...)` é capturado (visível no `script_outputs` do analyze). **Timeout padrão 5s** (sobrescrevível via `timeout`).
136
+ - **Sandbox:** compilado sob um whitelist de tokens de operador (`SecureASTCustomizer` + `TriggerExpressionChecker`) — **sem ternário `?:`**, **sem bitwise**. Mantenha a lógica simples.
137
+
138
+ Exemplo (resolve janela do mês e guarda usuário inativo):
139
+ ```groovy
140
+ void prepare(aggregations, params) {
141
+ params.put("start", DateUtil.fromKeyword("-0M-").getTime());
142
+ params.put("end", DateUtil.fromKeyword("-0M+").getTime());
143
+ String player = context.get("player");
144
+ if (player == null || isInactive(player)) {
145
+ params.put("player", "__none__"); // sentinela → resultado vazio controlado
146
+ } else {
147
+ params.put("player", player);
148
+ }
143
149
  }
144
- ```
145
150
 
146
- ```
147
- funifier_save type=aggregate payload=<json>
151
+ boolean isInactive(String player) {
152
+ def p = manager.getJongoConnection().getCollection("player").findOne("{_id:#}", player).as(Map.class);
153
+ return p == null;
154
+ }
148
155
  ```
149
156
 
150
- ### 5. Validar
157
+ ### 7. Antes de salvar: índices e forma da query
158
+
159
+ 1. Liste os campos que dirigem o plano: filtros de `$match`, campos de `$sort`, e `localField`/`foreignField` de cada `$lookup` (atenção ao `foreignField` na coleção `from`).
160
+ 2. Cheque/crie índices: `funifier_index action=list collection=<coll>`; crie os single-field faltantes com `funifier_index action=create`. Índice **composto** (ex.: `{player:1,time:-1}`) → REST é single-field apenas; use o caminho Groovy `createIndex(...append...)` (ver skill `funifier-manage-indexes`).
161
+ 3. Boas práticas: `$match` cedo · reduzir com `$project`/`$match` antes do `$lookup` · `$sort` seguido de `$limit` · cuidado com explosão do `$unwind` · `$lookup.foreignField` indexado.
162
+ 4. Prepared usa `allowDiskUse(true)`; ainda assim raciocine a cobertura de índice sobre o **`aggregate_step_3`** (pipeline já com `$param` resolvido), pois os valores de param mudam o filtro efetivo. Ao **editar** um aggregate, refaça esta checagem nos estágios alterados.
163
+
164
+ ### 8. Salvar
151
165
 
152
166
  ```
153
- funifier_list type=aggregate search=<titulo>
167
+ funifier_save type=aggregate payload=<json>
154
168
  ```
155
169
 
156
- ### 6. Executar o Prepared Aggregate
170
+ Isto persiste, mas **não verifica** nada (ver aviso no topo). "Salvo" é um estado; "verificado funcionando" é outro, alcançado no passo 9.
157
171
 
158
- **Endpoint correto:** `POST /v3/find/<id>` com os parâmetros no corpo JSON.
172
+ ### 9. Verificar (obrigatório)
159
173
 
160
- > ⚠️ NÃO use `GET /v3/database/aggregate/{id}` retorna null/405 silenciosamente, sem mensagem de erro. O endpoint de execução foge do padrão CRUD da plataforma.
174
+ Use os modos do `funifier_execute` (o REST cru é fallback):
161
175
 
162
- Via MCP (`params` é uma string JSON):
163
176
  ```
164
- funifier_execute type=aggregate id=<id> params={"player":"abc"}
177
+ funifier_execute type=aggregate id=<id> mode=params # nomes de $param esperados
178
+ funifier_execute type=aggregate id=<id> mode=analyze params={...} # dry-run: NÃO roda no Mongo
179
+ funifier_execute type=aggregate id=<id> params={...} # mode=run (default): resultado real
165
180
  ```
166
181
 
167
- Via frontend:
168
- ```js
169
- api.post('/v3/find/<id>', { player: 'abc' })
170
- ```
182
+ O `mode=analyze` é uma **inspeção (dry-run)** — compila/roda o `script`, aplica a substituição de `$param` e devolve:
183
+
184
+ | Campo | Conteúdo |
185
+ |---|---|
186
+ | `script_exceptions` | Erros de compilação/execução do Groovy — **vazio = script ok** |
187
+ | `script_outputs` | Saídas de `println` do `prepare()` |
188
+ | `obj` | A **definição salva** (a entidade, não os resultados) |
189
+ | `aggregate_step_2` | Pipeline **após** o `prepare()` |
190
+ | `aggregate_step_3` | Pipeline **após** a substituição dos `"$param:nome"` |
191
+
192
+ Diagnóstico: resultado de `mode=run` vazio **ou** recurso com `script` não-vazio → rode `mode=analyze` e leia `script_exceptions` (script quebrado) e `aggregate_step_3` (se um param virou `null`, o `$match` não casa nada — isso distingue "script quebrado" de "resultado legitimamente vazio").
193
+
194
+ > ⚠️ NÃO execute via `GET /v3/database/aggregate/{id}` — retorna null/405 silenciosamente. A execução é `POST /v3/find/<id>` (corpo JSON, nunca query string). Via frontend: `api.post('/v3/find/<id>', { player: 'abc' })`.
171
195
 
172
- | Regra | Detalhe |
173
- |-------|---------|
174
- | Método HTTP | POST obrigatório |
175
- | Params | No corpo JSON — não na query string |
176
- | Substituição | Cada chave do corpo substitui `"$param:<chave>"` no pipeline diretamente |
177
- | `context` no Groovy | Só expõe o player autenticado — `context.get("outro")` retorna `null` |
178
- | Script vazio | Se o pipeline só usa `"$param:nome"`, o `script` pode ser `""` — não precisa de `prepare()` |
196
+ ## Verified References
179
197
 
180
- Se o resultado vier vazio ou inesperado: `GET /v3/find/<id>/params` lista os params que o pipeline espera, e `POST /v3/prepared/aggregate/<id>/analyze` (mesmo corpo da execução) retorna outputs/exceções do script e o resultado de cada etapa do pipeline (`aggregate_step_N`) — veja `references/debug.md`.
198
+ | Claim | Status | Evidence |
199
+ |-------|--------|----------|
200
+ | DatabaseManager provides MongoDB connection and collection access for aggregate queries in Groovy scripts | ✓ verified | Class:src/main/java/com/funifier/engine/database/DatabaseManager.java:DatabaseManager |
@@ -113,3 +113,11 @@ Filtros combináveis em `$match`: `user`/`login` (ator), `type` (`studio`/`playe
113
113
  ### 6. Exclusão (cuidado)
114
114
 
115
115
  `funifier_delete type=audit id=<id>` remove a config **e todos os seus logs em cascata**. Confirme com o usuário antes.
116
+
117
+ ## Verified References
118
+
119
+ | Claim | Status | Evidence |
120
+ |-------|--------|----------|
121
+ | Audit config fields are _id, title, active, entity, event, clean, type with event constants create/update/delete and type constants studio/player/all | ✓ verified | Class:src/main/java/com/funifier/engine/audit/Audit.java:Audit |
122
+ | AuditManager.log only writes an AuditLog when an active Audit matches entity+event and the config type matches the operation origin | ✓ verified | Class:src/main/java/com/funifier/engine/audit/AuditManager.java:AuditManager |
123
+ | clearExpiredLogs purges audit_log entries older than each config's clean retention and is invoked from AsyncProcessor | ✓ verified | Method:src/main/java/com/funifier/engine/audit/AuditManager.java:AuditManager.clearExpiredLogs#0 |
@@ -114,3 +114,10 @@ funifier_get type=challenge id=<_id>
114
114
  ```
115
115
 
116
116
  Não use `funifier_logs` — isso é só para triggers e schedulers.
117
+
118
+ ## Verified References
119
+
120
+ | Claim | Status | Evidence |
121
+ |-------|--------|----------|
122
+ | Challenge is the core entity class storing action rules and reward configuration in funifier-service | ✓ verified | Class:src/main/java/com/funifier/engine/challenge/Challenge.java:Challenge |
123
+ | ChallengeManager manages challenge lifecycle including progress checking and achievement dispatch | ✓ verified | Class:src/main/java/com/funifier/engine/challenge/ChallengeManager.java:ChallengeManager |
@@ -96,3 +96,10 @@ POST /v3/competition/join { "competition": "<_id>", "player": "<player_id>" }
96
96
  POST /v3/competition/leader/aggregate?id=<_id>
97
97
  GET /v3/competition/<_id>/execute (manual execution only)
98
98
  ```
99
+
100
+ ## Verified References
101
+
102
+ | Claim | Status | Evidence |
103
+ |-------|--------|----------|
104
+ | Competition is the entity class for timed ranking contests with enrollment and position-based rewards in funifier-service | ✓ verified | Class:src/main/java/com/funifier/engine/competition/Competition.java:Competition |
105
+ | CompetitionManager manages competition execution, ranking computation, and reward distribution in funifier-service | ✓ verified | Class:src/main/java/com/funifier/engine/competition/CompetitionManager.java:CompetitionManager |
@@ -572,3 +572,9 @@ funifier_list type=crossword search=<titulo>
572
572
  ```
573
573
 
574
574
  Teste o jogo no Studio e verifique que as dicas e palavras estão corretas.
575
+
576
+ ## Verified References
577
+
578
+ | Claim | Status | Evidence |
579
+ |-------|--------|----------|
580
+ | Crossword is the entity class for word puzzle games with title, words, and clue positions in funifier-service | ✓ verified | Class:src/main/java/com/funifier/engine/crossword/Crossword.java:Crossword |
@@ -89,3 +89,9 @@ DELETE /v3/database/car__c?q=_id:'car001'
89
89
  ### 7. Usar em triggers
90
90
 
91
91
  Para executar trigger em eventos da coleção, use `entity: "car__c"` no payload do trigger.
92
+
93
+ ## Verified References
94
+
95
+ | Claim | Status | Evidence |
96
+ |-------|--------|----------|
97
+ | DatabaseManager provides MongoDB connection for custom __c collection CRUD operations in funifier-service | ✓ verified | Class:src/main/java/com/funifier/engine/database/DatabaseManager.java:DatabaseManager |
@@ -133,3 +133,9 @@ PUT /v3/database/studio_page { "_id": "...", "display": true, "title": "...",
133
133
 
134
134
  Acesse `/studio/custom/<slug>` no browser para testar.
135
135
  Para CRUD completo: crie página de lista (`display: true`) + formulário (`display: false`, slug com `/:id`).
136
+
137
+ ## Verified References
138
+
139
+ | Claim | Status | Evidence |
140
+ |-------|--------|----------|
141
+ | DatabaseManager provides MongoDB connection access for aggregate-backed Studio custom pages | ✓ verified | Class:src/main/java/com/funifier/engine/database/DatabaseManager.java:DatabaseManager |
@@ -102,3 +102,10 @@ funifier_save type=folder-log payload=<json>
102
102
  funifier_folder operation=progress { "folder": "<root_id>", "player": "player123" }
103
103
  funifier_folder operation=inside { "folder": "<root_id>" }
104
104
  ```
105
+
106
+ ## Verified References
107
+
108
+ | Claim | Status | Evidence |
109
+ |-------|--------|----------|
110
+ | Folder is the entity class for learning trail nodes with unlock_policy, parent, and position fields in funifier-service | ✓ verified | Class:src/main/java/com/funifier/engine/folder/Folder.java:Folder |
111
+ | FolderManager handles folder tree traversal, progress computation, and cascade deletion in funifier-service | ✓ verified | Class:src/main/java/com/funifier/engine/folder/FolderManager.java:FolderManager |
@@ -641,3 +641,9 @@ funifier_list type=lastmile
641
641
  ```
642
642
 
643
643
  Simule progresso do jogador até 80% do desafio e verifique se a mensagem é disparada.
644
+
645
+ ## Verified References
646
+
647
+ | Claim | Status | Evidence |
648
+ |-------|--------|----------|
649
+ | LastMile is the entity class for threshold-triggered motivational messages linked to challenge progress in funifier-service | ✓ verified | Class:src/main/java/com/funifier/engine/lastmile/LastMile.java:LastMile |
@@ -124,3 +124,9 @@ funifier_list type=leaderboard search=<title>
124
124
  ```
125
125
 
126
126
  If scores look wrong, reset cache: `GET /v3/leaderboard/reset`
127
+
128
+ ## Verified References
129
+
130
+ | Claim | Status | Evidence |
131
+ |-------|--------|----------|
132
+ | LeaderBoardManager manages leaderboard ranking computation and cache reset in funifier-service | ✓ verified | Class:src/main/java/com/funifier/engine/leader/LeaderBoardManager.java:LeaderBoardManager |
@@ -92,3 +92,10 @@ funifier_list type=level
92
92
  ```
93
93
 
94
94
  Confirme que os níveis estão em ordem crescente de `minPoints`.
95
+
96
+ ## Verified References
97
+
98
+ | Claim | Status | Evidence |
99
+ |-------|--------|----------|
100
+ | Level is the entity class defining level thresholds and point item reference in funifier-service | ✓ verified | Class:src/main/java/com/funifier/engine/level/Level.java:Level |
101
+ | LevelManager tracks player level progression and threshold evaluation | ✓ verified | Class:src/main/java/com/funifier/engine/level/LevelManager.java:LevelManager |
@@ -911,3 +911,10 @@ GET /v3/lottery/participants?lottery=<_id>
911
911
  ```
912
912
 
913
913
  To undo: `DELETE /v3/lottery/:id/execute`
914
+
915
+ ## Verified References
916
+
917
+ | Claim | Status | Evidence |
918
+ |-------|--------|----------|
919
+ | Lottery is the entity class for ticket-based prize draws with drawDate, choiceMethod, and maxWinners in funifier-service | ✓ verified | Class:src/main/java/com/funifier/engine/lottery/Lottery.java:Lottery |
920
+ | LotteryManager handles ticket generation, draw execution, and winner selection in funifier-service | ✓ verified | Class:src/main/java/com/funifier/engine/lottery/LotteryManager.java:LotteryManager |
@@ -767,3 +767,9 @@ funifier_save type=mystery payload=<json>
767
767
  GET /v3/mystery/evaluate/<_id>?player=<player_id>
768
768
  GET /v3/mystery/execute/<_id>?player=<player_id>
769
769
  ```
770
+
771
+ ## Verified References
772
+
773
+ | Claim | Status | Evidence |
774
+ |-------|--------|----------|
775
+ | MysteryBox is the entity class for probability-based instant games with options, win_chart, and requirements in funifier-service | ✓ verified | Class:src/main/java/com/funifier/engine/mystery/MysteryBox.java:MysteryBox |
@@ -73,3 +73,9 @@ funifier_list type=notification
73
73
  ```
74
74
 
75
75
  Dispare o evento correspondente e verifique se a notificação é entregue.
76
+
77
+ ## Verified References
78
+
79
+ | Claim | Status | Evidence |
80
+ |-------|--------|----------|
81
+ | Notification is the entity class for automated player feedback messages with event, scope, and content fields in funifier-service | ✓ verified | Class:src/main/java/com/funifier/engine/notify/Notification.java:Notification |
@@ -93,3 +93,10 @@ funifier_list type=point search=<_id>
93
93
  ```
94
94
 
95
95
  Do NOT use `funifier_logs` — that is only for triggers and schedulers.
96
+
97
+ ## Verified References
98
+
99
+ | Claim | Status | Evidence |
100
+ |-------|--------|----------|
101
+ | PointCategory is the entity class with category, shortName, and techniques fields for defining point types | ✓ verified | Class:src/main/java/com/funifier/engine/point/PointCategory.java:PointCategory |
102
+ | PointManager manages point accumulation and balance queries in funifier-service | ✓ verified | Class:src/main/java/com/funifier/engine/point/PointManager.java:PointManager |
@@ -96,3 +96,10 @@ POST /v3/quiz/start { "quiz": "<id>", "player": "<player_id>" }
96
96
  POST /v3/question/log/bulk [{ "quiz": "<id>", "quiz_log": "<log_id>", "question": "<q_id>", "answer": ["1"], "player": "<player_id>" }]
97
97
  POST /v3/quiz/finish { "quiz_log": "<log_id>" }
98
98
  ```
99
+
100
+ ## Verified References
101
+
102
+ | Claim | Status | Evidence |
103
+ |-------|--------|----------|
104
+ | Quiz is the entity class storing questions and answer configuration in funifier-service | ✓ verified | Class:src/main/java/com/funifier/engine/quiz/Quiz.java:Quiz |
105
+ | QuizManager handles quiz scoring, lifecycle, and player response processing | ✓ verified | Class:src/main/java/com/funifier/engine/quiz/QuizManager.java:QuizManager |
@@ -139,3 +139,9 @@ funifier_logs type=scheduler id=<_id>
139
139
  ```
140
140
 
141
141
  Confirme que não há erros de compilação ou execução no stack trace.
142
+
143
+ ## Verified References
144
+
145
+ | Claim | Status | Evidence |
146
+ |-------|--------|----------|
147
+ | SchedulerManager is the class that manages cron-based script execution in funifier-service | ✓ verified | Class:src/main/java/com/funifier/engine/integration/scheduler/SchedulerManager.java:SchedulerManager |
@@ -634,3 +634,9 @@ GET /v3/story/<_id>
634
634
  ```
635
635
 
636
636
  Teste a navegação entre cenas no Studio antes de publicar.
637
+
638
+ ## Verified References
639
+
640
+ | Claim | Status | Evidence |
641
+ |-------|--------|----------|
642
+
@@ -93,3 +93,9 @@ POST /v3/swap/receive { "swap": "<swap_id>" }
93
93
  POST /v3/swap/counter/offer { "swap": "<swap_id>", "buyer": "jerry", "offer": [{ "total": 1, "type": 0, "item": "coin" }] }
94
94
  POST /v3/swap/counter/offer/accept { "offer": "<offer_id>" }
95
95
  ```
96
+
97
+ ## Verified References
98
+
99
+ | Claim | Status | Evidence |
100
+ |-------|--------|----------|
101
+ | Swap is the entity class for player-to-player trade offers with seller, rewards, and requires fields in funifier-service | ✓ verified | Class:src/main/java/com/funifier/engine/swap/Swap.java:Swap |
@@ -183,3 +183,11 @@ funifier_logs type=trigger id=<_id>
183
183
  ```
184
184
 
185
185
  Confirme que não há erros de compilação ou execução. Se houver, leia o stack trace e corrija o script.
186
+
187
+ ## Verified References
188
+
189
+ | Claim | Status | Evidence |
190
+ |-------|--------|----------|
191
+ | Achievement constants TYPE_POINT=0, TYPE_CHALLENGE=1, TYPE_VIRTUAL_GOOD=2, TYPE_LEVEL=3 are defined in the Achievement class | ✓ verified | Class:src/main/java/com/funifier/engine/achievement/Achievement.java:Achievement |
192
+ | ActionLog is the entity class for action triggers with fields actionId, userId, attributes (Map), time, and id | ✓ verified | Class:src/main/java/com/funifier/engine/action/ActionLog.java:ActionLog |
193
+ | TriggerManager is the class that manages trigger script execution and lifecycle in funifier-service | ✓ verified | Class:src/main/java/com/funifier/engine/integration/trigger/TriggerManager.java:TriggerManager |
@@ -94,3 +94,9 @@ Para testar uma compra:
94
94
  ```
95
95
  POST /v3/virtualgoods/purchase { "player": "<id>", "item": "<item_id>", "total": 1 }
96
96
  ```
97
+
98
+ ## Verified References
99
+
100
+ | Claim | Status | Evidence |
101
+ |-------|--------|----------|
102
+ | CatalogManager is the class managing virtual goods catalog items, pricing, and purchase lifecycle in funifier-service | ✓ verified | Class:src/main/java/com/funifier/engine/catalog/CatalogManager.java:CatalogManager |
@@ -70,3 +70,9 @@ funifier_list type=webhook
70
70
  ### 5. Testar
71
71
 
72
72
  Dispare um evento (ex: log uma ação que gera conquista) e verifique se o endpoint externo recebeu o payload.
73
+
74
+ ## Verified References
75
+
76
+ | Claim | Status | Evidence |
77
+ |-------|--------|----------|
78
+ | Webhook is the entity class for outbound event notifications to external HTTP endpoints in funifier-service | ✓ verified | Class:src/main/java/com/funifier/engine/webhook/Webhook.java:Webhook |
@@ -69,3 +69,9 @@ funifier_list type=websocket
69
69
  ```
70
70
 
71
71
  Conecte um cliente WebSocket e dispare um evento para confirmar que as mensagens chegam em tempo real.
72
+
73
+ ## Verified References
74
+
75
+ | Claim | Status | Evidence |
76
+ |-------|--------|----------|
77
+ | WebSocket is the entity class for real-time bidirectional communication configuration in funifier-service | ✓ verified | Class:src/main/java/com/funifier/engine/websocket/WebSocket.java:WebSocket |
@@ -74,3 +74,9 @@ Cole o código de embed na página destino (intranet, LMS, etc.) e verifique que
74
74
  funifier_list type=widget
75
75
  GET /v3/widget/<_id>
76
76
  ```
77
+
78
+ ## Verified References
79
+
80
+ | Claim | Status | Evidence |
81
+ |-------|--------|----------|
82
+ | Widget is the entity class for embeddable visual gamification components with type, configuration, and display settings in funifier-service | ✓ verified | Class:src/main/java/com/funifier/engine/widget/Widget.java:Widget |
@@ -170,3 +170,9 @@ Não coloque o parâmetro convertido para `Date` dentro de `{ "$date": "$param:s
170
170
  - [ ] Em prepared aggregate, usar `"$param:nome"` exatamente como string.
171
171
  - [ ] Para data absoluta em prepared aggregate, converter no `script` com `DateUtil.parse`, validar `null`, e substituir o `Date` diretamente em `$gte`/`$lte`.
172
172
  - [ ] Testar aggregate direto antes de salvar como prepared aggregate.
173
+
174
+ ## Verified References
175
+
176
+ | Claim | Status | Evidence |
177
+ |-------|--------|----------|
178
+
@@ -90,3 +90,9 @@ Leia o arquivo de doc específico para o módulo com problema:
90
90
  - Scheduler → `funifier_read_doc path=modules/scheduler`
91
91
  - Aggregate → `funifier_read_doc path=guides/aggregates`
92
92
  - Security/Auth → `funifier_read_doc path=modules/security`
93
+
94
+ ## Verified References
95
+
96
+ | Claim | Status | Evidence |
97
+ |-------|--------|----------|
98
+ | TriggerManager is the entry point for trigger script execution and error capture in funifier-service | ✓ verified | Class:src/main/java/com/funifier/engine/integration/trigger/TriggerManager.java:TriggerManager |
@@ -79,3 +79,9 @@ Baseado na tabela acima, instrua o usuário a usar a skill específica.
79
79
  ### 4. Se não encontrar skill específica
80
80
 
81
81
  Consulte `funifier_read_doc path=index` e leia o módulo relevante diretamente.
82
+
83
+ ## Verified References
84
+
85
+ | Claim | Status | Evidence |
86
+ |-------|--------|----------|
87
+ | Achievement is the core entity class representing all gamification rewards in funifier-service | ✓ verified | Class:src/main/java/com/funifier/engine/achievement/Achievement.java:Achievement |
@@ -122,3 +122,10 @@ await fetch('/v3/database/cycle__c?strict=true', {
122
122
  ### 5. Hospedar no Funifier (opcional)
123
123
 
124
124
  Para arquivos estáticos, leia `funifier_read_doc path=modules/static-repo`.
125
+
126
+ ## Verified References
127
+
128
+ | Claim | Status | Evidence |
129
+ |-------|--------|----------|
130
+ | PlayerManager handles player authentication and session management in funifier-service | ✓ verified | Class:src/main/java/com/funifier/engine/player/PlayerManager.java:PlayerManager |
131
+ | ActionManager processes action event registration from frontend clients | ✓ verified | Class:src/main/java/com/funifier/engine/action/ActionManager.java:ActionManager |
@@ -73,3 +73,9 @@ Após import, verifique se os registros foram criados:
73
73
  ```
74
74
  funifier_list type=player search=<nome_importado>
75
75
  ```
76
+
77
+ ## Verified References
78
+
79
+ | Claim | Status | Evidence |
80
+ |-------|--------|----------|
81
+
@@ -83,3 +83,9 @@ Get the index name from `action=list`. The `_id_` index cannot be dropped.
83
83
  | Unique email | `{"email": 1}` (uniqueness enforced by MongoDB, not this API) |
84
84
 
85
85
  For a composite (e.g. `{player: 1, time: -1}` to back filter+sort in one plan), use the Groovy/trigger path shown in the Limitation section — not this tool.
86
+
87
+ ## Verified References
88
+
89
+ | Claim | Status | Evidence |
90
+ |-------|--------|----------|
91
+
@@ -80,3 +80,10 @@ GET /v3/player/<_id>/status
80
80
  ```
81
81
  GET /v3/team/<team_id>/member/add/<player_id>
82
82
  ```
83
+
84
+ ## Verified References
85
+
86
+ | Claim | Status | Evidence |
87
+ |-------|--------|----------|
88
+ | Player is the entity class with _id, name, email, teams, extra fields in funifier-service | ✓ verified | Class:src/main/java/com/funifier/engine/player/Player.java:Player |
89
+ | PlayerManager handles player CRUD, authentication, and status queries in funifier-service | ✓ verified | Class:src/main/java/com/funifier/engine/player/PlayerManager.java:PlayerManager |
@@ -74,3 +74,9 @@ GET /v3/team/sales/status
74
74
  ```
75
75
  GET /v3/team/sales/member/remove/tom
76
76
  ```
77
+
78
+ ## Verified References
79
+
80
+ | Claim | Status | Evidence |
81
+ |-------|--------|----------|
82
+ | Team is the entity class for player groups with _id, name, members, owner fields in funifier-service | ✓ verified | Class:src/main/java/com/funifier/engine/team/Team.java:Team |