Metadata-Version: 2.4
Name: laiss-docs
Version: 1.5.0
Summary: Documentos Laiss Labs em A4, a partir de JSON. Sistema de design, motor e CLI.
Author-email: Júlio Papel <julio@laisslabs.com>
Maintainer: Laiss Labs
License: MIT
Project-URL: Homepage, https://github.com/JulioPapel/laiss-docs
Project-URL: Documentation, https://github.com/JulioPapel/laiss-docs/tree/main/docs
Project-URL: Issues, https://github.com/JulioPapel/laiss-docs/issues
Project-URL: Changelog, https://github.com/JulioPapel/laiss-docs/blob/main/CHANGELOG.md
Keywords: latex,lualatex,pdf,documentation,mcp,design-system
Classifier: Development Status :: 5 - Production/Stable
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: POSIX :: Linux
Classifier: Operating System :: MacOS
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Documentation
Classifier: Topic :: Text Processing :: Markup :: LaTeX
Classifier: Typing :: Typed
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Provides-Extra: dev
Requires-Dist: build>=1.0; extra == "dev"
Requires-Dist: twine>=5.0; extra == "dev"
Dynamic: license-file

# laiss-docs

Gera documentos PDF em A4 a partir de um ficheiro JSON, com um design fixo:
tipografia, paleta, capa e grelha iguais em todos os documentos. O corpo é
escrito em blocos JSON, nunca em LaTeX, e o motor compõe e verifica o PDF.

## Instalação

```bash
pip install laiss-docs
```

O pacote não tem dependências Python, mas precisa de três coisas do sistema que
o pip não instala: LuaLaTeX, `pdftotext` e `pdfinfo`.

A primeira compilação verifica o que falta na máquina e mostra o plano antes de
mexer no sistema. Se houver terminal, instala o que falta (o `sudo` pede a
password). Num sítio sem terminal, como um pipeline de CI, não instala nada e
diz o que instalar. Para tratar disto antes do primeiro documento:

```bash
laiss-docs deps --dry-run    # o que falta e que comandos seriam corridos
laiss-docs deps              # instala, depois de perguntar
laiss-docs deps -y           # instala sem perguntar (CI)
laiss-docs doctor            # confirma o que está pronto
```

O `deps` reconhece Debian, Ubuntu, Arch, Fedora, openSUSE, Alpine, macOS e
NixOS. Em CI, a instalação automática só acontece com
`LAISSDOCS_AUTO_INSTALL=1`.

## Requisitos de sistema

- **Python 3.9 ou mais recente**, para correr o programa.
- **LuaLaTeX** (TeX Live, MacTeX ou MiKTeX), para compor o PDF. Não é opcional
  e não pode ser trocado por Tectonic, que usa outro motor: a razão está em
  `docs/porque-lualatex.md`, no repositório.
- **`pdftotext` e `pdfinfo`** (poppler), para verificar o PDF produzido.

O `deps` instala os três. Instala também, se os pedires, o Graphviz e o
mermaid-cli, que só são necessários para diagramas.

## Início rápido

```bash
laiss-docs templates                        # 8 estruturas prontas
laiss-docs new relatorio --template relatorio-tecnico --title "Relatório Técnico"
laiss-docs build relatorio
laiss-docs preview relatorio
```

O `new` cria a pasta com o `doc.json` e o `src/`. O `build` compila e verifica:

```
a compilar /caminho/relatorio ...
  ✓ pages        4 paginas
  ✓ a4           A4
  ✓ text-layer   sem glifos colados
  ✓ refs         todas as referencias resolvidas
  ✓ toc          5 entradas conferidas

/caminho/relatorio/out/relatorio-tecnico.pdf
```

Um documento criado com `--template` nasce com a estrutura certa e vazia. Cada
secção traz um `guidance`, que diz o que escrever ali. Vê-lo com:

```bash
laiss-docs outline relatorio
```

```
   1. Âmbito e método  ambito-e-metodo  0 blocos
      O que ficou dentro e o que ficou fora. Como se mediu, com que versões e em que
      ambiente. Sem isto, nenhum número do resto do relatório é verificável.
```

O `guidance` é instrução para quem escreve e **não aparece no PDF**. Escreve o
conteúdo de cada secção no `doc.json` e compila de novo. Se alguma verificação
falhar, o comando sai com código 1, e é isso que o torna utilizável em CI.

## Estilos e templates

Duas coisas que se combinam:

- Um **template** diz a **forma**: as secções, a ordem, o que cada uma deve dizer.
- Um **estilo** diz **como é**: o arranque (capa ou não), as cores, a tipografia.

O mesmo `study` sai como artigo arXiv (sem capa, título no topo da página 1) ou
como capa da Laiss Labs, só mudando o estilo.

```bash
laiss-docs themes                    # lista
laiss-docs themes --show academico   # as cores e as fontes
```

Escolhe-se no `doc.json`:

```json
{ "title": "Um estudo", "theme": "academico" }
```

Os cinco que vêm com o pacote:

| Estilo | Arranque | Para quê |
|---|---|---|
| `laiss` | capa | A identidade da casa: Inter, laranja no acento, barra e marca |
| `book` | capa | Livro genérico: serifada, capa sóbria sem cor de marca |
| `arxiv` | título no topo | Artigo científico: sem capa, resumo na página 1, serifada |
| `academico` | capa | Serifada com capa sóbria |
| `corporativo` | capa | Azul-marinho de marca, títulos em maiúsculas |

A coluna «arranque» é a diferença de fundo. `capa` é uma página de rosto
inteira, com barra, marca e caixa de autor, e o resumo numa página a seguir ao
índice. `título no topo` põe o título, os autores e o resumo no alto da página
1, e o texto começa logo a seguir: é o que distingue um artigo científico de um
livro, e não é uma questão de cor.

Sem `theme`, o documento sai com a identidade Laiss, exactamente como antes.

### As cores são papéis, não valores

O motor nunca sabe que o acento é laranja: pergunta por `accent`. Um tema
académico define `accent` a preto e o documento inteiro acompanha, sem uma
linha de LaTeX mudar. Os nomes que se podem definir:

| Papel | O que pinta |
|---|---|
| `ink`, `ink3`, `ink4` | Texto principal, secundário, terciário |
| `accent`, `accentstrong`, `accentsoft`, `accentline` | Destaque: números de secção, filetes |
| `deep`, `deepdeep`, `deepsoft`, `deepline` | Subtítulos e caixas de informação |
| `paper1`, `paper2`, `paper3` | Fundos |
| `hairline`, `hairlinestrong` | Filetes |
| `greenok`, `redno` | Confirmação e risco |

Um nome desconhecido falha na leitura, com a lista dos que existem. Um typo
numa cor não é ignorado: o documento sairia com o valor da casa e ninguém
dava por isso.

### Extrair e personalizar

Os templates e os estilos vêm dentro do pacote. Para os editar:

```bash
laiss-docs eject            # copia templates/ e themes/ para a pasta actual
```

Ficam em ficheiros que se abrem num editor. **O motor procura primeiro nesta
pasta e só depois no pacote**, por isso o que mudares ganha, sem mais nenhum
passo. Põe-nos ao lado do `doc.json` e viajam com o projecto.

Um estilo novo é um ficheiro em `themes/`; um template novo é um ficheiro em
`templates/`. O motor descobre-os sozinho e **valida-os antes de compor**:

```bash
laiss-docs themes     # um estilo inválido aparece marcado com !
```

A validação não é só de forma. Verifica que o layout existe, que o ficheiro de
layout está instalado, e que a fonte pedida existe no sistema ou na árvore do
TeX. Um estilo que não compõe é recusado no `build`, com o motivo, em vez de
falhar a meio do LaTeX com um erro que não aponta para o tema.

### O teu tema

```bash
laiss-docs theme "Cliente XPTO" --from arxiv
```

Cria o JSON em `~/.local/share/laiss-docs/themes` (ou numa pasta `themes/` ao
lado do documento, que tem prioridade). Muda as cores e as fontes no ficheiro;
o resto do documento acompanha.

Para uma marca que precisa de uma fonte própria, põe os `.otf` numa pasta e
declara o prefixo e o caminho:

```json
{
  "fonts": {
    "body": "MinhaMarca",
    "body_file": "minhamarca",
    "body_path": "/caminho/para/fontes/"
  }
}
```

Uma fonte que exista na árvore do TeX não precisa de ser distribuída: o motor
encontra-a com o `kpsewhich` e usa-a. É assim que o tema académico usa a Tex
Gyre Termes, que já vem com qualquer instalação.

## Templates

Um template é a forma de um documento: a ordem das secções, o que cada uma deve
dizer, e os metadados do género. Não tem texto, tem intenção.

```bash
laiss-docs templates                       # lista, por género
laiss-docs templates --show proposta-comercial   # estrutura completa
```

Os onze que vêm com o pacote. As três primeiras são as formas longas, e vão do
maior para o menor: um livro, um paper, um estudo.

| Template | Género | Para quê |
|---|---|---|
| `book` | livro | Um livro em partes e capítulos, para ler do princípio ao fim |
| `laiss-paper` | paper | Um paper técnico: contribuição, método, avaliação, resultados |
| `study` | paper | Forma de paper arXiv, em inglês: related work, method, experiments |
| `relatorio-tecnico` | tecnico | Estado de um sistema, com medições e recomendações |
| `nota-decisao` | tecnico | Uma decisão tomada, as alternativas, e o motivo |
| `manual-utilizador` | tecnico | Como se faz uma tarefa, passo a passo |
| `estudo-tecnico` | academico | Uma pergunta, a evidência, e uma resposta argumentada |
| `proposta-comercial` | negocio | O que se propõe a um cliente, por quanto, e em quanto tempo |
| `apresentacao-projecto` | negocio | O produto, o fluxo, e onde ganha dinheiro |
| `runbook-operacoes` | operacional | O que fazer quando algo falha, às três da manhã |
| `politica-interna` | juridico | Uma regra da organização, com âmbito e consequências |

### Livro, paper ou estudo

Os três parecem próximos e não são. A diferença está no que o leitor faz com o
documento:

- **`book`** é lido de seguida, por alguém que quer aprender o assunto. Tem
  partes, capítulos numerados, prefácio sem número, colofão, e uma conclusão
  que também não numera. Se o leitor consulta em vez de ler, é um manual.
- **`laiss-paper`** é avaliado por um par. Tem uma secção de avaliação com
  linha de base, porque um número sem comparação não diz se é bom. A discussão
  diz o que os resultados não provam.
- **`study`** é a forma do arXiv, em inglês: Related Work, Method, Experiments,
  Results, Discussion. É escrito para ser lido e citado fora da organização.

O `study` nasce em `en-US` mesmo que o teu sistema esteja em português. O
idioma do template ganha ao `--lang` por omissão; um `--lang` explícito ganha
ao do template.

### Os teus templates

Põe ficheiros `.json` em `~/.local/share/laiss-docs/templates`
(`~/Library/Application Support/laiss-docs/templates` no macOS). Também podes
pôr uma pasta `templates/` ao lado do documento, e essa ganha às outras: serve
para um documento fixar a sua versão de um template.

Um template do utilizador com o mesmo `id` de um do pacote **substitui-o**. O
`laiss-docs templates` mostra `[utilizador]` ao lado, para se saber qual está a
ganhar.

```bash
laiss-docs template "Relatório de obra" --genre operacional        # do zero
laiss-docs template "Da apresentação" --from-doc examples/habitera-apresentacao
```

O segundo copia a forma de um documento que já existe, com as secções e os
metadados, e deixa o `guidance` vazio para preencheres. A partir de um
documento bom, é o caminho mais rápido para repetir a estrutura.

Um template mal escrito **não é ignorado em silêncio**: aparece em
`laiss-docs templates` com o motivo, e os outros continuam a funcionar.

## Os comandos

Todos aceitam `--json`, que imprime o resultado em JSON em vez de texto.

| Comando | O que faz | Exemplo |
|---|---|---|
| `doctor` | Diz o que falta nesta máquina: motor, poppler, fontes, pacotes LaTeX, idiomas. | `laiss-docs doctor` |
| `deps` | Instala as dependências de sistema com o gestor da distribuição. | `laiss-docs deps --dry-run` |
| `templates` | Lista as estruturas de documento disponíveis. | `laiss-docs templates` |
| `template` | Cria um template novo, do zero ou a partir de um documento. | `laiss-docs template "Relatório" --from-doc doc/` |
| `new` | Cria um documento. Aceita `--template`, `--title`, `--subtitle`, `--lang`, `--from-json`, `--brief`. | `laiss-docs new relatorio --template relatorio-tecnico` |
| `build` | Compila o documento e corre as cinco verificações. | `laiss-docs build relatorio` |
| `check` | Verifica o PDF que já existe, sem recompilar. | `laiss-docs check relatorio` |
| `preview` | Abre o PDF no leitor do sistema. | `laiss-docs preview relatorio` |
| `outline` | Lista as secções com o `id` e o número de blocos. | `laiss-docs outline relatorio` |
| `add` | Acrescenta uma secção, com blocos vindos de um ficheiro JSON. | `laiss-docs add relatorio "Anexo" --blocks b.json` |
| `read` | Mostra o conteúdo de uma secção, bloco a bloco. | `laiss-docs read relatorio introducao` |
| `generate` | Pede texto a um modelo, para uma secção existente ou nova. | `laiss-docs generate relatorio --section introducao --instruction "acrescenta um exemplo"` |
| `ai` | Testa a ligação ao endpoint de IA, sem gerar documento. | `laiss-docs ai` |
| `schema` | Imprime o JSON Schema do `doc.json`. | `laiss-docs schema` |
| `locales` | Lista os idiomas suportados. | `laiss-docs locales` |
| `init` | Instala ou actualiza as fontes e os estilos. | `laiss-docs init` |
| `mcp` | Arranca o servidor MCP em stdio, para agentes AI. | `laiss-docs mcp` |

Sem nome de documento, `build`, `check`, `preview`, `outline`, `add`, `read` e
`generate` usam o documento da pasta actual, ou a única pasta que ali tenha um
`doc.json`.

## Como se escreve um documento

O `doc.json` tem os metadados e as secções. Cada secção tem um `title` e uma
lista de `blocks`. Este ficheiro compila e produz quatro páginas:

```json
{
  "title": "Relatório de Novembro",
  "subtitle": "O que mudou no motor de compilação.",
  "language": "pt-PT",
  "sections": [
    {
      "title": "Estado actual",
      "label": "PARTE 1",
      "blocks": [
        {"type": "p", "text": "O motor compila três vezes e verifica o PDF no fim. Um **parágrafo** aceita `código` e *ênfase*."},
        {"type": "h", "level": 2, "text": "O que foi feito"},
        {"type": "ul", "items": ["Blocos passaram a JSON", "Design fixo", "Cinco idiomas"]},
        {"type": "note", "title": "Uma nota", "text": "As fontes vão dentro do pacote."},
        {"type": "chart", "caption": "Tempo por passagem", "unit": " s", "labels": ["1ª", "2ª", "3ª"], "values": [3, 2, 2]}
      ]
    }
  ]
}
```

Guarda-o e corre `laiss-docs new relatorio --from-json modelo.json`, seguido de
`laiss-docs build relatorio`. Os campos de topo mais usados são `title`
(obrigatório), `subtitle`, `language`, `date` (`AAAA-MM-DD`), `classification`,
`coverFrom`, `coverTo`, `keywords`, `toc` (índice, ligado por omissão) e
`colophon` (página final, desligada por omissão).

Os blocos disponíveis:

| Tipo | Campos | Para quê |
|---|---|---|
| `p` | `text` | Um parágrafo. |
| `h` | `text`, `level` (2 ou 3) | Subtítulo dentro de uma secção. |
| `ul`, `ol` | `items` (lista de textos) | Lista com marcas ou numerada. |
| `dl` | `items` (`term` e `def`) | Lista de definições. |
| `note`, `warn`, `rule` | `text`, `title` opcional | Caixa azul (informação), laranja (risco), cinza (norma). |
| `code`, `output` | `text`, `label` opcional | Bloco verbatim: o que o leitor escreve, e o que ele vê. |
| `table` | `columns`, `rows`, `caption` e `widths` opcionais | Tabela com cabeçalho repetido quando passa de página. |
| `quote` | `text`, `source` opcional | Citação. |
| `pagebreak` | nenhum | Força página nova. |
| `mermaid`, `graphviz` | `source`, `caption` | Diagrama desenhado a partir de código. |
| `chart` | `labels`, `values`, `caption` | Gráfico de barras a partir de números. |
| `figure` | `path`, `caption` | Imagem que já existe. |
| `refs` | `items` (`text`, `url`, `note`) | Lista de referências. |

Dentro dos blocos de texto há quatro marcas: `**forte**`, `*ênfase*`,
`` `código` `` e `[[caminho/ficheiro]]`. Tudo o resto é texto literal, incluindo
`_`, `%` e `#`. Não escrevas comandos LaTeX: apareceriam no PDF como texto.

O `caption` das quatro famílias de figura é obrigatório. Um documento também
pode ter `abstract` (resumo, depois do índice e sem número) e `appendices`
(anexos numerados ANEXO A, B). A referência completa está em `docs/blocos.md`,
no repositório.

## Figuras e diagramas

| Tipo | O que precisa de estar instalado |
|---|---|
| `chart` | Nada. É desenhado pelo próprio motor, com TikZ, a partir dos números. |
| `figure` com PNG, JPEG ou PDF | Nada. |
| `figure` com SVG | O `rsvg-convert` (pacote `librsvg2-bin` em Debian e Ubuntu). |
| `graphviz` | O `dot`, do pacote Graphviz. |
| `mermaid` | O `@mermaid-js/mermaid-cli` e um browser headless. |

Para saber o que está disponível nesta máquina antes de escrever o bloco, usa a
ferramenta `laiss_diagrams` do servidor MCP, ou simplesmente escolhe `chart`,
que funciona sempre.

Os caminhos das figuras são relativos à pasta do documento. Quando há figuras, o
índice de figuras é gerado automaticamente; `"listOfFigures": false` desliga-o.

## Idiomas

```bash
laiss-docs locales
```

| Código | Idioma | Também aceita |
|---|---|---|
| `pt-PT` | Português (Portugal) | `pt`, `portugues` |
| `en-US` | English (US) | `en`, `english` |
| `es-ES` | Español (España) | `es`, `spanish` |
| `fr-FR` | Français (France) | `fr`, `french` |
| `de-DE` | Deutsch (Deutschland) | `de`, `german` |

O idioma muda a hifenização, a data por extenso, o título do índice, as
etiquetas da capa e os títulos por omissão das caixas. Não muda o design: a
tipografia e a paleta são as mesmas em todos os idiomas.

## Uso por agentes AI

O `laiss-docs mcp` arranca um servidor MCP sobre stdio, sem dependências. No
Cursor, cria `.cursor/mcp.json`:

```json
{
  "mcpServers": {
    "laiss-docs": {
      "command": "laiss-docs",
      "args": ["mcp"]
    }
  }
}
```

O servidor expõe 25 ferramentas: escolher um template, criar documento, ler e
editar secções e blocos, gerir resumo e anexos, compilar e verificar.

Um agente começa por `laiss_guide`, que devolve o processo inteiro, os tipos de
bloco, a marcação permitida e os erros comuns. Sem ela, um agente tenta
escrever LaTeX e conclui que a ferramenta está avariada.

O passo seguinte, e o que faz a diferença, é a escolha da estrutura:

| Ferramenta | O que devolve |
|---|---|
| `laiss_templates` | Os templates que existem, por género, com descrição |
| `laiss_template` | A estrutura de um, com o `guidance` de cada secção |
| `laiss_create_from_template` | O documento criado já com essa estrutura |

O `laiss_create_from_template` devolve cada secção com a instrução do que
escrever ali, e é o caminho recomendado para começar: o agente recebe a forma
e a intenção de uma vez, em vez de inventar secções. A alternativa,
`laiss_add_section`, continua disponível para documentos fora de qualquer
molde.

O resto do ciclo é `laiss_outline` (que `id` existe), `laiss_add_blocks` e
`laiss_build`, que devolve as verificações e os erros no formato
`ficheiro:linha: mensagem`. O contrato completo está em `docs/mcp.md`, no
repositório.

Também podes gerar texto com um modelo, por endpoint compatível com a API de
chat completions (OpenAI, Ollama, LM Studio, vLLM, llama.cpp):

```bash
export LAISSDOCS_BASE_URL="http://localhost:1234/v1"
export LAISSDOCS_MODEL="o-modelo-que-usas"
laiss-docs ai
laiss-docs generate relatorio --section introducao --instruction "acrescenta um exemplo"
```

## Limites conhecidos

- **Só A4 retrato.** Outros formatos e orientação não estão previstos.
- **O corpo são blocos JSON, não Markdown livre.** A estrutura é escolhida num
  campo `type`; um ficheiro Markdown não se converte.
- **Sem índice remissivo nem bibliografia.** Há lista de referências num anexo,
  formatada como texto, sem citações numeradas no corpo.
- **O design não se edita num documento.** Um aspecto diferente é um parâmetro
  do `doc.json`, ou não é possível.

## Licença

MIT, Laiss Labs. As fontes mantêm as suas licenças: Inter e JetBrains Mono, OFL
1.1.
