---
name: lumo-decks
description: Autoria headless de deck (slide document PPTist, com Gráficos BI vivos embutidos) e presentation (kiosk/telão que toca dashboards e/ou decks, publicado num link público) no Horus BI via Lumo CLI. Use sempre que o usuário pedir para criar ou editar um deck, apresentação, slide, telão, kiosk, "criar apresentação", "montar um kiosk", "editar slide", "pôr o deck no telão", "publicar deck" ou "publicar dashboard" (link público), ou mencionar PPTist. Ensina o modelo de documento (slides → elementos, com detalhe total do elemento horus-widget), o fluxo de autoria via YAML e a publicação em link público (deck e presentation) — preview/check são os gates de verificação que tornam a autoria headless segura. Não cobre a mecânica genérica do CLI (comandos, IDs, push/pull, publish de app) — isso é da skill lumo-cli.
---

# Lumo Decks

Você é quem monta apresentações e telões para um produto de BI whitelabel — o
mesmo motor (PPTist) que o editor visual do produto usa, só que você edita o
documento como YAML em vez de arrastar elementos na tela. O documento é JSON
real, versionável, e cada gráfico "vivo" embutido é uma referência a um widget
de verdade de um app — não uma imagem estática.

> Esta skill cuida do **modelo de documento e do fluxo de autoria** (deck,
> presentation, elementos, verificação). A **mecânica genérica** (comandos,
> `kind:id`, push/pull/diff, autenticação, publish de app/flow/table) é da
> skill `lumo-cli`. Use as duas juntas — carregue `lumo-cli` primeiro se ainda
> não estiver ativa.

## 1. Modelo mental: `deck` vs `presentation`

Dois recursos, dois papéis. Não confunda:

| | `deck` | `presentation` |
|---|---|---|
| O que é | Documento de slides desenhado (PPTist: `slides[].elements[]`) | Playlist/kiosk: uma sequência de **itens** que tocam em loop ou manualmente |
| Conteúdo | Elementos posicionados livremente (texto, imagem, forma, tabela, gráfico estático, **gráfico BI vivo**) | Itens que **apontam** para um `dashboard` inteiro OU para um `deck` inteiro |
| Publicação | `lumo deck publish` → URL pública `/p/<sqid>` (vai ao telão por si) | `lumo presentation publish` → URL pública `/p/<sqid>` |
| Analogia | Um arquivo `.pptx`/Keynote com slides desenhados à mão | O controle remoto de um telão de recepção, tocando várias telas em sequência |

**Quando usar cada um:**
- Peça um **relatório/apresentação executiva com narrativa** (capa, texto,
  gráficos posicionados, ordem de leitura) → `deck`.
- Peça um **telão/kiosk** que fica ligado tocando dashboards e/ou decks em
  loop (recepção, TV de sala, monitoramento) → `presentation`.
- Peça **"um link público para este dashboard"** → não existe publish direto
  de dashboard/app para link público. O caminho é criar (ou reaproveitar) uma
  `presentation` com um único item `type: dashboard` apontando pra ele, e
  publicar essa presentation.
- Peça **"põe esse deck no telão"** / "manda o link desse deck" → `lumo deck
  publish deck:<id>` (seção 4). Você não precisa montar presentation na mão.
- Uma `presentation` pode **misturar** dashboards e decks na mesma sequência
  (kiosk misto) — não precisa escolher um ou outro.

> **Modelo por baixo (não se confunda):** o kiosk continua sendo sempre uma
> *apresentação*. Publicar um deck cria (ou reusa) a apresentação que contém
> só aquele deck e publica ela. Por isso um `lumo presentation list` vai
> mostrar essa apresentação-embrulho — é esperado, não é bug (no webapp ela
> fica escondida, porque lá é encanamento, não conteúdo).

## 2. Fluxo de autoria — `deck`

```bash
lumo new deck --name "Vendas Q1"        # cria vazio (slides: [])
# ou: lumo pull deck:<id>               # editar um deck existente

$EDITOR decks/<slug>--<id>.yaml         # editar slides/elements
lumo lint decks/<slug>--<id>.yaml       # forma (schema) — rápido, offline
lumo push deck:<id>

lumo deck preview deck:<id>             # GATE: todo gráfico resolve contra dado real?
lumo deck export deck:<id> --format pdf # renderizar de verdade (headless)
lumo deck open deck:<id>                # abrir no editor visual (URL autenticada)
lumo deck publish deck:<id>             # põe no telão e imprime a URL pública /p/<sqid>
```

`lumo deck preview` chama o motor de BI de verdade para **cada** elemento
`horus-widget` do deck (todas as slides) e reporta OK+contagem de linhas ou o
erro do servidor. **Sai com código não-zero se qualquer elemento falhar** —
por isso é o gate que se roda logo depois de editar slides, antes de exportar
ou de colocar o deck dentro de uma presentation. `lint` só valida forma
(schema); `preview` valida que os dados realmente existem. Rode os dois.

## 3. Fluxo de autoria — `presentation`

```bash
lumo new presentation --name "Kiosk Loja"   # cria vazio (items: [])
$EDITOR presentations/<slug>--<id>.yaml     # items[]: dashboard e/ou deck
lumo lint presentations/<slug>--<id>.yaml
lumo push presentation:<id>

lumo presentation publish presentation:<id>  # imprime a URL pública /p/<sqid>
lumo presentation check presentation:<id>    # GATE: a URL pública resolve (2xx)?
lumo presentation unpublish presentation:<id> # tira do ar
lumo presentation open presentation:<id>     # editor autenticado (NÃO é a URL pública)
```

`lumo presentation check` faz uma leitura pura do link atual (`GET
/presentation/:id/url` — nunca republica) e um GET simples nele, reportando
OK/falha. **Sai com código não-zero se o link não resolver** — o gate que
confirma, de fora, que o que você acabou de editar está realmente no ar antes
de entregar o link para alguém.

## 4. Pôr no telão: publicar, checar, tirar do ar

Um deck vai ao telão por si — não monte presentation na mão para isso:

```bash
lumo deck publish deck:<id>               # publica e IMPRIME a URL pública /p/<sqid>
lumo deck publish deck:<id> --seconds 10  # 10s POR SLIDE (não é a duração total!)
lumo deck url deck:<id>                   # leitura pura: URL + estado (não publica nada)
lumo deck check deck:<id>                 # GATE de CI: a URL pública resolve (2xx)?
lumo deck unpublish deck:<id>             # tira do ar
```

- **`--seconds` é `secondsPerSlide`: segundos POR SLIDE.** O deck tem N slides;
  cada um fica esse tempo na tela. Omitindo o flag, o servidor decide (default
  5s, limitado a 1–3600). Um deck de 8 slides com `--seconds 10` roda 80s por
  volta.
- **`publish` é idempotente** e imprime a URL — republicar um deck já publicado
  reconfirma o mesmo link (e reaplica o `secondsPerSlide` que você mandar).
- **Para descobrir a URL sem republicar, use `url` ou `check`** — nunca
  `publish`. Os dois são leitura pura (`GET /deck/:id/url`): não exigem
  permissão de publish e não reescrevem o rastro de auditoria
  (`publicado_em`/`publicado_por`). É por isso que servem em CI/agente.
- `url` responde o **estado**: se o deck não está no telão, ele diz isso e sai
  com **sucesso** (não é erro, é o estado). `check` é o **gate**: além de ler o
  link, faz um GET nele e sai **não-zero** se o deck não estiver publicado ou
  se o link não resolver. Em CI, use `check`; para só perguntar "qual é o
  link?", use `url`.
- Mesma mecânica de `presentation` (seção 3) — inclusive o ponto do modelo:
  publicar um deck cria/reusa a apresentação-embrulho que contém só ele, e é
  ela que aparece em `lumo presentation list`.

## 5. Por que `preview`/`check` importam para autoria headless

Um agente sem esses dois comandos edita YAML "no escuro": `lint` garante que o
arquivo tem a forma certa, mas não sabe se o `appId`/`widgetGuid` referenciado
ainda existe, se o app foi deletado, ou se o link publicado realmente carrega.
**Sempre rode `deck preview` depois de tocar em elementos `horus-widget`, e
`deck check`/`presentation check` depois de publicar ou de editar slides/items**
— são os únicos sinais de verdade equivalentes a "olhar a tela" que um agente
headless tem disponível sem abrir um browser.

## 6. Sem marca visível (whitelabel)

O produto é whitelabel: nenhum cliente final vê a palavra "Horus" na tela. Ao
escrever **texto que aparece renderizado** para o usuário final — título de
slide, `title.custom` de um `horus-widget`, texto de um elemento `text`/
`shape`, `nome`/`title` de item de presentation — use termos genéricos
("Gráfico", "Painel", "Vendas Q1"), nunca "Gráfico Horus" ou "Dashboard
Horus". Isso é só sobre **conteúdo visível**: o identificador interno do
elemento continua sendo literalmente `type: horus-widget` no JSON — é um nome
de campo real do produto, documente-o como é, não invente um substituto.

## References

Carregue sob demanda:

- [`references/pptist-json.md`](references/pptist-json.md) — o modelo de documento do deck: viewport, slide, cada tipo de elemento, e o elemento `horus-widget` em detalhe total (campos, defaults, o que é server-owned).
- [`references/presentations.md`](references/presentations.md) — o corpo de `presentation`, o item (`dashboard`/`deck`), a regra condicional que o lint aplica, kiosk misto, `duration`/`mode`, publish/url/check (de deck e de presentation).
- [`references/authoring.md`](references/authoring.md) — receitas práticas: como achar `appId`/`widgetGuid` reais, matemática de layout no canvas 1000×562.5, e os modos de falha mais comuns (pegos por `deck preview`, não por `lint`).
