Mapa de atividades do Construtor

Cada item do book de aprendizado aponta para uma destas âncoras (docId). Manutenção: app/docs/AI_CONSTRUTOR.md.

intent-info

Pedido de informação

Perguntas do tipo «gere a URL», «quais variáveis», «explique». Devolver só reply (e plan se ajudar).

intent: "info"
surveyJson: null
settingsPatch: null
surveyMeta: null
createSurvey: false
changes: []

O Studio não autosava e não mostra recibo «O que mudei».

intent-mutate

Pedido de alteração

Só quando o humano pediu mudar o form ou settings. Devolver JSON completo e/ou settingsPatch com diff real. Título ecoado (igual ao atual) não é mudança.

surveyjson-form

Form (surveyJson)

Páginas, perguntas, visibleIf / enableIf / requiredIf, tipos SurveyJS. Merge no JSON atual. Nomes em snake_case. Não inventar triggers[]. title, description, html e choices[].text são string em português — não mapa { "pt": "…" } / { "default", "pt" } a menos que o humano peça tradução. survey.locale: "pt" no root pode ficar.

Runtime: Form Library 2.5.39 (paridade com comentário por opção do Creator). choices[].showCommentArea, isCommentRequired e commentPlaceholder no item são válidos. O valor gravado passa a { value, comment } (CSV: nome_value + nome_comment). visibleIf {radio} = '1' continua comparando o value.

Pergunta type: "html": a propriedade html é uma string JSON (ou mapa locale { "default": "…" }). Proibido array de linhas, objeto {iframe:…} ou markdown. Iframe de mapa usa srcdoc='…' (aspas simples); JS/CSS internos com aspas duplas. Não reescrever um srcdoc já válido. Não inventar Leaflet no JSON — colar o template da biblioteca. O pin grava em perguntas type: "text" cujos name batem com data-lat-name / data-lng-name / data-addr-name. Calculada (expression) não recebe o pin. survey.setValue funciona com visible: false; o fallback via DOM exige o input no layout.

{
  "type": "html",
  "name": "mapa_coordenadas",
  "html": "<iframe title=\"…\" allow=\"geolocation\" data-lat-name=\"latitude_g6\" data-lng-name=\"longitude_g6\" data-addr-name=\"endereco_g6\" srcdoc='<!DOCTYPE html>…'></iframe>"
}
{ "type": "text", "name": "latitude_g6", "title": "Latitude" }
{ "type": "text", "name": "longitude_g6", "title": "Longitude" }
{ "type": "text", "name": "endereco_g6", "title": "Endereço" }

Expressão não é JavaScript. Token completo em { }: {q} notempty, {matrix[0].col} notempty, countInArray({m}, 'col') > 0 (dois argumentos). Proibido {q}.length, coluna ano, e not(expr) — a inversa é !(expr) ou countInArray({m}, 'col') = 0. XOR: radiogroup + choices[].visibleIf. Expressão inválida ou not(…) esconde todas as opções.

settings-filters

Filtros

settingsPatch.filters[] com expression, code, label. O Studio projeta triggers type=complete. O Construtor não edita surveyJson.triggers[].

settings-quotas

Cotas

settingsPatch.quotas[]. Nunca trigger complete para cota. Arrays substituem a lista (incluir itens que devem permanecer).

settings-automations

Automações

settingsPatch.automations[] When/Then (webhook, redirect, email, ai…). Webhook HTTPS. Arrays substituem a lista.

settings-messages

Encerramento

settingsPatch.messages.{filtered|overlimit|completed} = texto (mode: custom) ou redirect (mode: redirect, URL absoluta). Não usar path relativo. Não escrever o redirect só no reply.

create-survey

Pesquisa nova

createSurvey=true somente se o humano pediu pesquisa nova ou o form atual está vazio (0 perguntas). Se já há perguntas e o pedido é alterar, createSurvey=false e merge no JSON atual.

prefill-url

URL de prefill

Formato: https://r.gmrpesquisa.com.br/{publicName}?nome=VALOR_REAL (host público, nunca survey.gmrpesquisa.com.br/{slug} — isso devolve {"error":"not_found"}).

Query com {token} no redirect de encerramento é preenchida no complete com a resposta (data, senão customs). Host público: https://r.gmrpesquisa.com.br/{slug}?campo={campo}. Nunca survey.gmrpesquisa.com.br/{slug} ({"error":"not_found"}). Link colado no browser sem passar pelo complete não substitui as chaves.

public-name

Slug / base da URL

O contexto do turno já traz publicName. Nunca peça «a URL de entrada» se o slug estiver preenchido. Monte a URL pública (PUBLIC_BASE_URL, hoje https://r.gmrpesquisa.com.br/{publicName}). Proibido survey.gmrpesquisa.com.br/{slug}.

plan-then-verify

Planejar, executar, conferir

  1. Efeitos do pedido
  2. Onde mora (schema vs settings vs API que você não chama)
  3. Ordem das alterações
  4. Lista de tarefas no plan[] — no mesmo JSON que já traz o patch. Não esperar um segundo «pode executar».
  5. Conferir se o pedido foi feito (não só JSON válido)
  6. Se travar de verdade (dado ausente no contexto): fulfillment.ok=false, blocker, orientação manual — sem patch. Revisão de cliente não é travamento.

skipversion

Autosave vs Salvar

O Construtor pode gravar draft com skipVersion: true quando houve mutate + diff. Isso não entra no ledger de aprendizado. Instrução aceita = botão Salvar (note: studio_json), que gera versão e alimenta classificador → book.