notion-starter 0.3.0__tar.gz
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.
- notion_starter-0.3.0/.editorconfig +15 -0
- notion_starter-0.3.0/.env.example +13 -0
- notion_starter-0.3.0/.github/workflows/ci.yml +27 -0
- notion_starter-0.3.0/.github/workflows/release.yml +68 -0
- notion_starter-0.3.0/.gitignore +14 -0
- notion_starter-0.3.0/AGENTS.md +33 -0
- notion_starter-0.3.0/CONTRIBUTING.md +95 -0
- notion_starter-0.3.0/IA.md +381 -0
- notion_starter-0.3.0/LICENSE +21 -0
- notion_starter-0.3.0/PKG-INFO +236 -0
- notion_starter-0.3.0/QUALIDADE.md +45 -0
- notion_starter-0.3.0/README.md +187 -0
- notion_starter-0.3.0/examples/check_schema.py +46 -0
- notion_starter-0.3.0/examples/coletar_mapa.py +82 -0
- notion_starter-0.3.0/examples/export_rows.py +68 -0
- notion_starter-0.3.0/examples/gerar_arvore_html.py +198 -0
- notion_starter-0.3.0/examples/gerenciar_tarefas.py +65 -0
- notion_starter-0.3.0/examples/listar_paginas.py +45 -0
- notion_starter-0.3.0/examples/relatorios_do_git.py +113 -0
- notion_starter-0.3.0/examples/sync_from_csv.py +103 -0
- notion_starter-0.3.0/pyproject.toml +54 -0
- notion_starter-0.3.0/src/notion_starter/__init__.py +104 -0
- notion_starter-0.3.0/src/notion_starter/client.py +1386 -0
- notion_starter-0.3.0/src/notion_starter/constants.py +43 -0
- notion_starter-0.3.0/src/notion_starter/content.py +766 -0
- notion_starter-0.3.0/src/notion_starter/exceptions.py +103 -0
- notion_starter-0.3.0/src/notion_starter/git_historico.py +209 -0
- notion_starter-0.3.0/src/notion_starter/github.py +421 -0
- notion_starter-0.3.0/src/notion_starter/inventory.py +319 -0
- notion_starter-0.3.0/src/notion_starter/logging.py +105 -0
- notion_starter-0.3.0/src/notion_starter/openrouter.py +294 -0
- notion_starter-0.3.0/src/notion_starter/properties.py +219 -0
- notion_starter-0.3.0/src/notion_starter/readers.py +181 -0
- notion_starter-0.3.0/src/notion_starter/schema.py +332 -0
- notion_starter-0.3.0/src/notion_starter/services/__init__.py +9 -0
- notion_starter-0.3.0/src/notion_starter/services/anexos.py +90 -0
- notion_starter-0.3.0/src/notion_starter/services/clonagem.py +306 -0
- notion_starter-0.3.0/src/notion_starter/services/conteudo.py +626 -0
- notion_starter-0.3.0/src/notion_starter/services/estrutura_projeto.py +341 -0
- notion_starter-0.3.0/src/notion_starter/services/exploracao.py +220 -0
- notion_starter-0.3.0/src/notion_starter/services/historico_repositorios.py +375 -0
- notion_starter-0.3.0/src/notion_starter/services/ia.py +203 -0
- notion_starter-0.3.0/src/notion_starter/services/importacao.py +125 -0
- notion_starter-0.3.0/src/notion_starter/services/ingestao.py +490 -0
- notion_starter-0.3.0/src/notion_starter/services/inventario_github.py +682 -0
- notion_starter-0.3.0/src/notion_starter/services/normalizacao.py +372 -0
- notion_starter-0.3.0/src/notion_starter/services/projetos.py +41 -0
- notion_starter-0.3.0/src/notion_starter/services/relacoes.py +234 -0
- notion_starter-0.3.0/src/notion_starter/services/relatorios_diarios.py +177 -0
- notion_starter-0.3.0/src/notion_starter/services/relatorios_docx.py +879 -0
- notion_starter-0.3.0/src/notion_starter/services/reordenacao.py +195 -0
- notion_starter-0.3.0/src/notion_starter/services/schema.py +108 -0
- notion_starter-0.3.0/src/notion_starter/services/sincronizar_github.py +168 -0
- notion_starter-0.3.0/src/notion_starter/services/tarefas.py +154 -0
- notion_starter-0.3.0/src/notion_starter/tasks.py +411 -0
- notion_starter-0.3.0/src/notion_starter/utils.py +112 -0
- notion_starter-0.3.0/src/notion_starter/valores_br.py +147 -0
- notion_starter-0.3.0/tests/conftest.py +11 -0
- notion_starter-0.3.0/tests/test_anexos.py +85 -0
- notion_starter-0.3.0/tests/test_client.py +514 -0
- notion_starter-0.3.0/tests/test_client_resiliencia.py +628 -0
- notion_starter-0.3.0/tests/test_content.py +576 -0
- notion_starter-0.3.0/tests/test_fonte_planilha.py +242 -0
- notion_starter-0.3.0/tests/test_git_historico.py +142 -0
- notion_starter-0.3.0/tests/test_importacao.py +91 -0
- notion_starter-0.3.0/tests/test_inventory.py +239 -0
- notion_starter-0.3.0/tests/test_properties.py +127 -0
- notion_starter-0.3.0/tests/test_readers.py +144 -0
- notion_starter-0.3.0/tests/test_schema.py +40 -0
- notion_starter-0.3.0/tests/test_schema_descricao.py +143 -0
- notion_starter-0.3.0/tests/test_services_conteudo_seguranca.py +241 -0
- notion_starter-0.3.0/tests/test_services_estrutura_projeto.py +163 -0
- notion_starter-0.3.0/tests/test_services_historico_repositorios.py +294 -0
- notion_starter-0.3.0/tests/test_services_relacoes.py +171 -0
- notion_starter-0.3.0/tests/test_services_relatorios_diarios.py +203 -0
- notion_starter-0.3.0/tests/test_services_relatorios_docx.py +360 -0
- notion_starter-0.3.0/tests/test_services_reordenacao.py +139 -0
- notion_starter-0.3.0/tests/test_services_schema.py +78 -0
- notion_starter-0.3.0/tests/test_tasks.py +489 -0
- notion_starter-0.3.0/tests/test_valores_br.py +75 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Token de integração do Notion — usado pelos exemplos em examples/.
|
|
2
|
+
# Crie uma integração em https://www.notion.so/my-integrations,
|
|
3
|
+
# compartilhe o database/página alvo com ela e cole o token aqui.
|
|
4
|
+
# O token deve começar com "ntn_".
|
|
5
|
+
NOTION_TOKEN=ntn_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
|
6
|
+
|
|
7
|
+
# ID do database de tarefas padrão (opcional — pode ser passado por chamada).
|
|
8
|
+
# NOTION_DATABASE_ID=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
|
9
|
+
|
|
10
|
+
# Token do GitHub (opcional; necessário só para repositórios privados nos
|
|
11
|
+
# serviços de inventário/sincronização GitHub).
|
|
12
|
+
# Prefira token fine-grained com acesso somente de leitura.
|
|
13
|
+
# GITHUB_TOKEN=
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
python:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
strategy:
|
|
12
|
+
fail-fast: false
|
|
13
|
+
matrix:
|
|
14
|
+
python-version: ["3.10", "3.11", "3.12", "3.13"]
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v4
|
|
17
|
+
- uses: actions/setup-python@v5
|
|
18
|
+
with:
|
|
19
|
+
python-version: ${{ matrix.python-version }}
|
|
20
|
+
- name: Install
|
|
21
|
+
run: |
|
|
22
|
+
python -m pip install --upgrade pip
|
|
23
|
+
pip install -e ".[dev]"
|
|
24
|
+
- name: Lint
|
|
25
|
+
run: ruff check .
|
|
26
|
+
- name: Test
|
|
27
|
+
run: pytest -q
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
name: Release Python package
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags: ["v*"]
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
build:
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v4
|
|
16
|
+
- uses: actions/setup-python@v5
|
|
17
|
+
with:
|
|
18
|
+
python-version: "3.13"
|
|
19
|
+
- name: Build and validate metadata
|
|
20
|
+
run: |
|
|
21
|
+
python -m pip install --upgrade build twine
|
|
22
|
+
python -m build
|
|
23
|
+
python -m twine check dist/*
|
|
24
|
+
- uses: actions/upload-artifact@v4
|
|
25
|
+
with:
|
|
26
|
+
name: notion-starter-dist
|
|
27
|
+
path: dist/*
|
|
28
|
+
|
|
29
|
+
smoke:
|
|
30
|
+
needs: build
|
|
31
|
+
strategy:
|
|
32
|
+
fail-fast: false
|
|
33
|
+
matrix:
|
|
34
|
+
os: [ubuntu-latest, windows-latest, macos-latest]
|
|
35
|
+
python-version: ["3.10", "3.13"]
|
|
36
|
+
runs-on: ${{ matrix.os }}
|
|
37
|
+
steps:
|
|
38
|
+
- uses: actions/checkout@v4
|
|
39
|
+
- uses: actions/download-artifact@v4
|
|
40
|
+
with:
|
|
41
|
+
name: notion-starter-dist
|
|
42
|
+
path: dist
|
|
43
|
+
- uses: actions/setup-python@v5
|
|
44
|
+
with:
|
|
45
|
+
python-version: ${{ matrix.python-version }}
|
|
46
|
+
- name: Install wheel and smoke
|
|
47
|
+
shell: bash
|
|
48
|
+
run: |
|
|
49
|
+
python -m pip install --upgrade pip
|
|
50
|
+
python -m pip install dist/*.whl
|
|
51
|
+
python -c "from notion_starter import NotionClient; print(NotionClient.__name__)"
|
|
52
|
+
|
|
53
|
+
publish:
|
|
54
|
+
needs: [build, smoke]
|
|
55
|
+
if: startsWith(github.ref, 'refs/tags/v')
|
|
56
|
+
runs-on: ubuntu-latest
|
|
57
|
+
environment: pypi
|
|
58
|
+
permissions:
|
|
59
|
+
id-token: write
|
|
60
|
+
steps:
|
|
61
|
+
- uses: actions/download-artifact@v4
|
|
62
|
+
with:
|
|
63
|
+
name: notion-starter-dist
|
|
64
|
+
path: dist
|
|
65
|
+
- name: Publish to PyPI with Trusted Publishing
|
|
66
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
67
|
+
with:
|
|
68
|
+
packages-dir: dist/
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# AGENTS.md — notion-starter
|
|
2
|
+
|
|
3
|
+
Biblioteca Python **base** do ecossistema [Automações do Notion](https://github.com/Felipe-Alcantara/Automa-es-do-Notion) — o hub tem o roteamento completo entre módulos; leia-o se a tarefa envolver o CLI ou o app.
|
|
4
|
+
|
|
5
|
+
## O que vive aqui
|
|
6
|
+
|
|
7
|
+
| Arquivo | Responsabilidade |
|
|
8
|
+
| --- | --- |
|
|
9
|
+
| `src/notion_starter/client.py` | Cliente HTTP resiliente (retries por semântica, rate limit, erros tipados); `obter_pagina`/`atualizar_pagina` leem e editam propriedades |
|
|
10
|
+
| `src/notion_starter/schema.py` | Leitura/comparação de schema de databases |
|
|
11
|
+
| `src/notion_starter/tasks.py` | `Tarefa`, `TaskList`, `CamposTarefa` |
|
|
12
|
+
| `src/notion_starter/content.py` + `properties.py` + `readers.py` | Conversão Markdown ↔ blocos (lógica pura); `properties.title`/`rich_text` fatiam texto >2000 (via `utils.fatiar_utf16`) |
|
|
13
|
+
| `src/notion_starter/inventory.py` | Mapeamento do workspace (lógica pura, sem rede) |
|
|
14
|
+
| `src/notion_starter/git_historico.py` | Histórico de um repositório git agrupado por dia (lógica pura, sem rede/Notion) |
|
|
15
|
+
| `src/notion_starter/github.py`, `openrouter.py` | Adaptadores externos compartilhados por CLI e app |
|
|
16
|
+
| `src/notion_starter/services/` | Casos de uso compartilhados entre CLI e app; defaults de ambiente continuam nos consumidores via `integrations.notion` |
|
|
17
|
+
| `src/notion_starter/utils.py` | Saneamento de texto/JSON (surrogates inválidos); `fatiar_utf16` (fatia por unidades UTF-16, teto em `constants.MAX_RICH_TEXT`) |
|
|
18
|
+
| `examples/` | Scripts de uso direto da lib |
|
|
19
|
+
|
|
20
|
+
## Regras
|
|
21
|
+
|
|
22
|
+
- Regra de negócio compartilhada entre CLI e app pode viver em `notion_starter.services`.
|
|
23
|
+
Bordas e configuração de ambiente continuam fora daqui (`cli/`, `api/`, `mcp_server`,
|
|
24
|
+
`integrations.notion` dos consumidores).
|
|
25
|
+
- Só o `NotionClient` fala com a API do Notion; módulos de lógica são puros.
|
|
26
|
+
- Código e mensagens em português; exceções derivam de `NotionSyncError`; Conventional Commits.
|
|
27
|
+
- **Mudança de API pública quebra dois repos consumidores** — mantenha compatibilidade ou avise nos dois.
|
|
28
|
+
|
|
29
|
+
## Testar
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
python -m pytest # não precisa instalar; tests/conftest.py adiciona src/ ao path
|
|
33
|
+
```
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# 🤝 Contribuindo com o notion-starter
|
|
2
|
+
|
|
3
|
+
Obrigado por querer contribuir! Este repositório é a biblioteca Python base do
|
|
4
|
+
ecossistema [Automações do Notion](https://github.com/Felipe-Alcantara/Automa-es-do-Notion):
|
|
5
|
+
cliente resiliente para a API do Notion, schema, tarefas, conteúdo, inventário e a
|
|
6
|
+
camada compartilhada `notion_starter.services`. Issues, correções de documentação,
|
|
7
|
+
novos helpers, exemplos, testes e melhorias de resiliência são bem-vindos.
|
|
8
|
+
|
|
9
|
+
> Contribuições devem preservar os contratos existentes, a documentação viva e o
|
|
10
|
+
> gate de qualidade descrito abaixo.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## 🚀 Como Contribuir
|
|
15
|
+
|
|
16
|
+
1. **Faça um fork** do repositório.
|
|
17
|
+
2. **Crie uma branch** descritiva (`fix/...`, `feat/...`, `docs/...`) para mudanças
|
|
18
|
+
grandes; correções pequenas podem ir direto no `main` de quem mantém.
|
|
19
|
+
3. **Faça suas mudanças** seguindo os padrões abaixo.
|
|
20
|
+
4. **Rode os testes e o lint** antes de abrir o PR.
|
|
21
|
+
5. **Abra um Pull Request** explicando o que mudou e por quê.
|
|
22
|
+
|
|
23
|
+
Não tem certeza por onde começar? Abra uma issue descrevendo a ideia — a gente
|
|
24
|
+
conversa antes de você investir tempo no código.
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## 🛠️ Ambiente de Desenvolvimento
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
git clone https://github.com/Felipe-Alcantara/notion-starter.git
|
|
32
|
+
cd notion-starter
|
|
33
|
+
python -m pip install -e ".[dev]"
|
|
34
|
+
|
|
35
|
+
# Gate de qualidade (HTTP é mockado — não precisa de token nem rede)
|
|
36
|
+
ruff check .
|
|
37
|
+
python -m pytest
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Requer Python 3.10+. Copie `.env.example` para `.env` apenas se for rodar os
|
|
41
|
+
exemplos de `examples/` contra um workspace real do Notion — nunca versione o `.env`.
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## ✅ Padrões de Qualidade
|
|
46
|
+
|
|
47
|
+
- **Entenda o padrão existente antes de alterar.** Módulos coesos por
|
|
48
|
+
responsabilidade: `client` (único que fala HTTP com o Notion), `schema`,
|
|
49
|
+
`properties`/`readers`, `content`, `tasks`, `inventory`, `services` (casos de uso,
|
|
50
|
+
sem HTTP próprio). Preserve essas fronteiras.
|
|
51
|
+
- **Prefira a solução mais simples** que resolva o problema real. A biblioteca tem
|
|
52
|
+
poucas dependências de runtime de propósito.
|
|
53
|
+
- **Preserve contratos.** Assinaturas públicas, objetos (`Tarefa`, `RepoInfo`, ...) e
|
|
54
|
+
exceções (`NotionSyncError` e derivadas) devem permanecer estáveis; mudança
|
|
55
|
+
quebradora precisa ser explícita e documentada.
|
|
56
|
+
- **Tipos e validação.** `TypedDict` para payloads, `dataclass` para resultados;
|
|
57
|
+
valide entradas externas.
|
|
58
|
+
- **Não exponha segredos.** Nada de tokens, IDs reais ou URLs privadas no código,
|
|
59
|
+
nos testes ou na documentação.
|
|
60
|
+
- **Teste o comportamento.** Bugs corrigidos viram caso de regressão; HTTP é sempre
|
|
61
|
+
mockado com `responses`.
|
|
62
|
+
- **Código, docstrings e mensagens de erro em português.**
|
|
63
|
+
- **Atualize a documentação viva** (`README.md` e `IA.md`) no mesmo passo quando a
|
|
64
|
+
mudança alterar comportamento, estrutura ou comandos.
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## ✍️ Padrões de Linguagem (Documentação e Logs)
|
|
69
|
+
|
|
70
|
+
- **Escreva para qualquer leitor** — linguagem geral e acessível, sem jargão interno.
|
|
71
|
+
- **Sem valores hardcoded** — use placeholders genéricos em vez de caminhos, tokens
|
|
72
|
+
ou IDs reais.
|
|
73
|
+
- **Enquadre o trabalho futuro como convite à contribuição** em vez de uma lista de
|
|
74
|
+
tarefas interna.
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## 🔄 Fluxo de Pull Request
|
|
79
|
+
|
|
80
|
+
Um bom PR responde claramente:
|
|
81
|
+
|
|
82
|
+
- **O que mudou?**
|
|
83
|
+
- **Por que mudou?**
|
|
84
|
+
- **Como foi validado?** (ex.: `ruff check .` + `python -m pytest`)
|
|
85
|
+
- **Qual risco sobrou?**
|
|
86
|
+
|
|
87
|
+
Mantenha o PR focado: evite misturar refatoração ampla com novas funcionalidades.
|
|
88
|
+
Use commits pequenos no formato `tipo: descrição` (`feat`/`fix`/`docs`/`refactor`/`chore`).
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## 💬 Código de Conduta
|
|
93
|
+
|
|
94
|
+
Seja respeitoso e acolhedor. Este é um espaço para aprender e construir juntos —
|
|
95
|
+
contribuições de pessoas de todos os níveis de experiência são bem-vindas.
|
|
@@ -0,0 +1,381 @@
|
|
|
1
|
+
# 🤖 IA.md — Contexto operacional do notion-starter
|
|
2
|
+
|
|
3
|
+
> **O que é**: Memória técnica deste repositório para retomada de contexto por IA ou
|
|
4
|
+
> por um novo mantenedor, sem reler todo o código. Baseado no template de contexto do
|
|
5
|
+
> Felixo System Design.
|
|
6
|
+
>
|
|
7
|
+
> **Histórico anterior**: este módulo nasceu da separação do monorepo
|
|
8
|
+
> [Automações do Notion](https://github.com/Felipe-Alcantara/Automa-es-do-Notion)
|
|
9
|
+
> em 2026-07-02. Toda a linha do tempo anterior (decisões de arquitetura, bugs e
|
|
10
|
+
> validações do core) permanece registrada no `IA.md` do hub — este arquivo cobre a
|
|
11
|
+
> vida do módulo a partir da separação.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## 📊 ESTADO ATUAL (RESUMO VIVO)
|
|
16
|
+
|
|
17
|
+
Última atualização: [2026-09-04]
|
|
18
|
+
|
|
19
|
+
- Fase: biblioteca base estável, preparada como pacote `notion-starter` para a
|
|
20
|
+
distribuição da CLI única.
|
|
21
|
+
- Qualidade: 355 testes verdes e `ruff` limpo; CI cobre Python 3.10–3.13.
|
|
22
|
+
- Documentação: README alinhado ao Felixo System Design e contrato de qualidade
|
|
23
|
+
centralizado em `QUALIDADE.md`.
|
|
24
|
+
- Próximos passos abertos: confirmação do contrato de publicação no PyPI e mais
|
|
25
|
+
tipos de propriedade/bloco e escrita em data sources.
|
|
26
|
+
- Risco conhecido: consumidores devem fixar suas próprias resoluções de
|
|
27
|
+
dependências quando precisarem de builds reproduzíveis.
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## 🎯 OBJETIVO DO PROJETO
|
|
32
|
+
|
|
33
|
+
[2026-07-02] `notion-starter` é a biblioteca Python base do ecossistema: cliente
|
|
34
|
+
resiliente para a API do Notion (retry/backoff, cache de schema), helpers de
|
|
35
|
+
propriedade e leitura, conversor Markdown ↔ blocos, camada de tarefas (`TaskList`),
|
|
36
|
+
inventário do workspace e a camada compartilhada `notion_starter.services`
|
|
37
|
+
(clonagem, conteúdo, ingestão, sincronização GitHub, exportação DOCX). É consumida
|
|
38
|
+
pelo `notion-tasks-cli` e pelo `notion-workspace-app`.
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## 📐 DECISÕES DE ARQUITETURA
|
|
43
|
+
|
|
44
|
+
- [2026-07-02] Fronteiras herdadas do monorepo (registradas no hub): só o
|
|
45
|
+
`NotionClient` fala HTTP com o Notion; `services` orquestra casos de uso sem
|
|
46
|
+
conhecer HTTP de borda; conversões e leituras (`content`, `properties`,
|
|
47
|
+
`readers`, `inventory`) são lógica pura testável sem rede.
|
|
48
|
+
- [2026-07-02] Exceções continuam derivando de `NotionSyncError` (compatibilidade).
|
|
49
|
+
- [2026-07-08] O repositório **não tem `start_app.py`**: é uma biblioteca importável,
|
|
50
|
+
não um programa. A porta de entrada interativa do ecossistema vive no hub
|
|
51
|
+
(`Automa-es-do-Notion/start_app.py`) e no `notion-workspace-app`. Os exemplos de
|
|
52
|
+
`examples/` são executados diretamente (`python examples/<nome>.py`) e documentados
|
|
53
|
+
no README. Exceção registrada conforme o padrão de qualidade.
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## 🛠️ STACK & DEPENDÊNCIAS
|
|
58
|
+
|
|
59
|
+
- Python 3.10+ (CI: 3.10–3.13). Runtime: `requests`, `python-docx` (exportação DOCX),
|
|
60
|
+
`typing_extensions` só em Python < 3.11.
|
|
61
|
+
- Dev: `pytest`, `responses` (HTTP mockado), `ruff`.
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## 🧪 TESTES & GATE
|
|
66
|
+
|
|
67
|
+
- Gate: `ruff check .` + `python -m pytest` (193 testes em 2026-07-13, sem rede).
|
|
68
|
+
- CI: GitHub Actions (`.github/workflows/ci.yml`) com matriz Python 3.10–3.13.
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## 🧠 LINHA DO TEMPO
|
|
73
|
+
|
|
74
|
+
- [2026-07-02] ✅ Módulo extraído do monorepo. Recebeu depois a consolidação da
|
|
75
|
+
camada compartilhada: `integrations` (GitHub/OpenRouter) e `services` comuns dos
|
|
76
|
+
consumidores viraram shims apontando para cá.
|
|
77
|
+
- [2026-07-08] ✅ Alinhamento ao padrão de qualidade Felixo: adicionados
|
|
78
|
+
`CONTRIBUTING.md`, `IA.md`, `.env.example` e CI GitHub Actions. Decisão registrada:
|
|
79
|
+
sem `start_app.py` por ser biblioteca. Validação: `ruff check .` limpo e 183 testes
|
|
80
|
+
verdes.
|
|
81
|
+
- [2026-07-13] ✅ Merge do PR #1 (contribuição externa): `mover_pagina`,
|
|
82
|
+
`mover_database` (re-parent, versão 2025-09-03 por chamada) e `enviar_arquivo`
|
|
83
|
+
(File Upload API) + `properties.arquivo_enviado`. Em seguida, hardening no
|
|
84
|
+
`main`: o passo multipart do upload passou a usar retry/backoff próprio
|
|
85
|
+
(`_enviar_multipart`, espelhando a política do `_request_json` — antes era um
|
|
86
|
+
`requests.post` cru, sem resiliência) e `enviar_arquivo` valida o limite de
|
|
87
|
+
20 MB (`NOTION_UPLOAD_MAX_BYTES`) antes de tocar a API. Motivo: migrações com
|
|
88
|
+
dezenas de uploads quebravam no primeiro 429 do `/send`. Validação:
|
|
89
|
+
`ruff check .` limpo e 193 testes verdes (3 novos: limite, retry em 429 e
|
|
90
|
+
retry em falha de rede).
|
|
91
|
+
- [2026-07-13] ✅ Fechadas as melhorias propostas no relatório de 10/07 (5.2):
|
|
92
|
+
`criar_database` estendido (is_inline, icone, descricao, prefixo_id/unique_id),
|
|
93
|
+
`valores_br` (números e datas BR), `FontePlanilha` (.xlsx via extra
|
|
94
|
+
`planilha`, .csv via stdlib) com `ItemColetado.propriedades` tipadas,
|
|
95
|
+
`services/importacao` (import em lote retomável por estado local),
|
|
96
|
+
`properties.schema_propriedade` e `services/anexos.anexar_arquivo` (upload +
|
|
97
|
+
propriedade files preservando anexos). Validação: 230 testes verdes, ruff
|
|
98
|
+
limpo, CI verde.
|
|
99
|
+
- [2026-07-18] ✅ Documentação alinhada ao Felixo System Design: README passou a
|
|
100
|
+
ter badges, índice, árvore real, guia de uso e rodapé open source;
|
|
101
|
+
`QUALIDADE.md` centralizou o gate e registrou a exceção motivada de versões
|
|
102
|
+
mínimas para uma biblioteca instalável. Motivo: tornar setup, manutenção e
|
|
103
|
+
critérios de pronto verificáveis sem quebrar a resolução dos consumidores.
|
|
104
|
+
Validação: 235 testes verdes e `ruff` limpo.
|
|
105
|
+
|
|
106
|
+
- [2026-07-23] ✅ `services/inventario_github.atualizar_repos`/`exportar_repos`
|
|
107
|
+
passam a aceitar um **repositório específico** em `contas` (`owner/repo` ou
|
|
108
|
+
URL completa do repo), além de contas inteiras. Nova função privada
|
|
109
|
+
`_repo_completo_da_entrada` distingue os dois formatos (via `_PADRAO_URL_REPO`
|
|
110
|
+
e checagem de `/` fora de URL de perfil) e `_listar_repos_da_entrada` chama
|
|
111
|
+
`GitHubClient.detalhar_repo` nesse caso, em vez de `listar_repos`. Motivo:
|
|
112
|
+
inventariar um projeto pontual de terceiros (ex.: um repo de outra conta)
|
|
113
|
+
sem trazer o resto dos repositórios dela para a database. Validação: 6 novos
|
|
114
|
+
testes em `notion-tasks-cli/tests/test_services_inventario_github.py`
|
|
115
|
+
(reconhecimento de owner/repo, URL de repo, URL de perfil sem repo, coleta
|
|
116
|
+
sem duplicar quando o mesmo repo aparece via conta e via entrada avulsa);
|
|
117
|
+
235 testes do notion-starter e 132 do notion-tasks-cli seguem verdes, ruff
|
|
118
|
+
limpo em ambos.
|
|
119
|
+
|
|
120
|
+
- [2026-07-23] ✅ Novo módulo `services/estrutura_projeto.py` com três casos de
|
|
121
|
+
uso para a moldura fixa de projeto do workspace (README + `## Acompanhamento`
|
|
122
|
+
com 4 subpáginas + `## Planejamento e documentação` com 2 databases, ver
|
|
123
|
+
`DESIGN-WORKSPACE-NOTION.md` no hub): `inspecionar_estrutura` (lê
|
|
124
|
+
recursivamente subpáginas/databases de uma página de referência, read-only),
|
|
125
|
+
`clonar_estrutura_projeto` (recria a forma — títulos de subpágina + schema de
|
|
126
|
+
databases via `clonar_database` — em outra página, sem herdar conteúdo) e
|
|
127
|
+
`montar_estrutura_projeto` (aplica o padrão do zero). Também
|
|
128
|
+
`services/conteudo.criar_subpagina`, que expõe `client.criar_subpagina` como
|
|
129
|
+
caso de uso reutilizável (antes só usado internamente pelo README do
|
|
130
|
+
GitHub). Motivo: montar essa estrutura manualmente (como feito para o
|
|
131
|
+
projeto Audiofy) exigiu inspecionar várias páginas de exemplo bloco a bloco,
|
|
132
|
+
sem nenhuma ferramenta reutilizável — o padrão documentado não tinha
|
|
133
|
+
automação correspondente. Validação: 9 novos testes em
|
|
134
|
+
`notion-tasks-cli/tests/test_services_estrutura_projeto.py`; 244 testes do
|
|
135
|
+
notion-starter e 137 do notion-tasks-cli seguem verdes, ruff limpo em ambos.
|
|
136
|
+
|
|
137
|
+
- [2026-07-23] ✅ `NotionClient.anexar_blocos` ganhou o parâmetro opcional
|
|
138
|
+
`apos_bloco_id`, usando `position: after_block` da API do Notion (confirmado
|
|
139
|
+
na doc oficial, `developers.notion.com/reference/patch-block-children` —
|
|
140
|
+
substitui o antigo `after` no nível raiz, hoje legado) para inserir blocos
|
|
141
|
+
novos depois de um irmão específico, não só no final. Novo
|
|
142
|
+
`services/reordenacao.py` com `reordenar_bloco`: como a API do Notion não
|
|
143
|
+
tem endpoint para mover um bloco existente, a implementação apaga e recria
|
|
144
|
+
na posição pedida — sempre grava um backup em JSON do bloco original antes
|
|
145
|
+
de apagar. **Risco documentado e ativamente bloqueado por padrão**: para
|
|
146
|
+
`child_page`/`child_database`, apagar e recriar gera um **ID novo**,
|
|
147
|
+
quebrando links/backlinks/referências externas salvas para o ID antigo; a
|
|
148
|
+
função levanta `BlocoArriscadoError` nesses tipos a menos que o chamador
|
|
149
|
+
passe `forcar_tipos_arriscados=True` explicitamente. Motivo: precisei
|
|
150
|
+
reordenar um database solto numa página de projeto (Audiofy) e não havia
|
|
151
|
+
ferramenta alguma para isso — o único caminho seria apagar manualmente e
|
|
152
|
+
reimportar dados. Validação: 7 novos testes em
|
|
153
|
+
`tests/test_services_reordenacao.py`, mais os testes existentes de
|
|
154
|
+
`anexar_blocos`; 251 testes do notion-starter e 140 do notion-tasks-cli
|
|
155
|
+
seguem verdes, ruff limpo em ambos.
|
|
156
|
+
|
|
157
|
+
- [2026-07-23] ✅ Correção: `montar_estrutura_projeto` criava "Próximos passos"
|
|
158
|
+
e "Documentações" com um schema mínimo genérico (título + Observações), que
|
|
159
|
+
não batia com o schema real observado nas páginas de projeto existentes do
|
|
160
|
+
workspace ("Próximos passos": Tarefa/Status/Prioridade/Concluída/
|
|
161
|
+
Observações; "Documentações": Documento/Tipo/Status/Criado em/Atualizado
|
|
162
|
+
em/URL/Observações — com `select` de opções coerentes, não `rich_text`
|
|
163
|
+
solto). `DATABASES_PLANEJAMENTO` virou um dict `título -> schema` em vez de
|
|
164
|
+
uma tupla de títulos. Motivo: ao aplicar a ferramenta na página real do
|
|
165
|
+
projeto Audiofy, os databases criados ficaram visivelmente fora do padrão
|
|
166
|
+
das páginas de referência lidas anteriormente. Validação: teste ajustado
|
|
167
|
+
para checar as colunas específicas de cada database (não mais um schema
|
|
168
|
+
genérico); 251 testes do notion-starter e 140 do notion-tasks-cli seguem
|
|
169
|
+
verdes, ruff limpo.
|
|
170
|
+
|
|
171
|
+
- [2026-07-23] ✅ Correção crítica em `services/reordenacao.reordenar_bloco`:
|
|
172
|
+
`child_database` foi movido de `_TIPOS_ARRISCADOS` (bloqueável com
|
|
173
|
+
`forcar_tipos_arriscados=True`) para uma nova categoria `_TIPOS_IMPOSSIVEIS`,
|
|
174
|
+
recusada **sempre**, sem flag de escape (`BlocoImpossivelError`, distinta de
|
|
175
|
+
`BlocoArriscadoError`). Motivo: confirmado em produção (workspace real da
|
|
176
|
+
Flávia) que apagar+recriar um `child_database` via `anexar_blocos` **nunca
|
|
177
|
+
funciona** — a API do Notion só cria databases por `POST /databases`, não
|
|
178
|
+
por `PATCH /blocks/.../children`; a implementação anterior prometia essa
|
|
179
|
+
capacidade com a flag de força e, ao ser usada, apagava o database original
|
|
180
|
+
(com linhas) e falhava ao recriá-lo, deixando-o arquivado até restauração
|
|
181
|
+
manual. `child_page` continua suportado com a flag (recriação real funciona,
|
|
182
|
+
só o ID muda). Validação: novo teste
|
|
183
|
+
`test_reordenar_bloco_rejeita_child_database_mesmo_com_forcar`; 252 testes
|
|
184
|
+
do notion-starter e 141 do notion-tasks-cli verdes, ruff limpo.
|
|
185
|
+
|
|
186
|
+
- [2026-07-24] ✅ Novo `services/schema.garantir_coluna`: adiciona uma coluna a
|
|
187
|
+
um database **já existente**, sem apagar nada. Generaliza o padrão que só
|
|
188
|
+
existia hardcoded em
|
|
189
|
+
`inventario_github.garantir_coluna_hash` (que só cuidava da coluna de hash
|
|
190
|
+
do README) para qualquer nome/tipo de coluna. Usa *data source* quando
|
|
191
|
+
disponível, cai para o endpoint clássico de `database` caso contrário —
|
|
192
|
+
mesma estratégia do original. Motivo: nenhuma ferramenta do ecossistema
|
|
193
|
+
evoluía o schema de um database depois de criado (`criar-database` só
|
|
194
|
+
define na criação; `editar-linha`/`importar-planilha` só escrevem em
|
|
195
|
+
colunas existentes) — faltou ao tentar adicionar uma coluna real (Idioma)
|
|
196
|
+
a um database do workspace da Flávia. TDD: testes escritos e confirmados
|
|
197
|
+
falhando antes da implementação existir, só então o módulo foi criado.
|
|
198
|
+
Validação: 4 novos testes em `test_services_schema.py`; 256 testes do
|
|
199
|
+
notion-starter seguem verdes, ruff limpo.
|
|
200
|
+
- [2026-07-27] ✅ Relatórios diários a partir do git: `git_historico.py` (módulo
|
|
201
|
+
puro — executa `git` e agrupa commits por dia, sem conhecer Notion nem rede) e
|
|
202
|
+
`services/relatorios_diarios.py` (upsert **por data**: se o dia já tem página,
|
|
203
|
+
o corpo é anexado em vez de duplicar a linha). A separação existe porque o
|
|
204
|
+
histórico serve a outros destinos além do Notion, e o upsert serve a conteúdo
|
|
205
|
+
de qualquer origem, não só git. Decisão: página existente **preserva** suas
|
|
206
|
+
propriedades por padrão (`atualizar_propriedades_existentes=False`) — um mesmo
|
|
207
|
+
dia costuma acumular trabalho de projetos diferentes, e sobrescrever o resumo
|
|
208
|
+
apagaria o registro do outro projeto. Nasceu de um script pontual que publicou
|
|
209
|
+
9 dias de trabalho de um repositório na database de relatórios. TDD: testes
|
|
210
|
+
antes da implementação, e um deles pegou um defeito real — mensagem de commit
|
|
211
|
+
contendo o byte separador fazia o registro ser descartado silenciosamente
|
|
212
|
+
(corrigido limitando as divisões do `split`). Exemplo executável em
|
|
213
|
+
`examples/relatorios_do_git.py`, com `--simular`. Validação: 30 testes novos,
|
|
214
|
+
286 do notion-starter verdes, ruff limpo, e execução real contra um
|
|
215
|
+
repositório de 9 dias.
|
|
216
|
+
|
|
217
|
+
- [2026-08-13] ✅ `DiaDeTrabalho` ganhou `duracao_minutos` e
|
|
218
|
+
`duracao_por_extenso()` (ex.: `"5h30"`, `"35 min"`, vazio com um único
|
|
219
|
+
commit), e `resumo_markdown()` passou a incluir a duração entre o primeiro
|
|
220
|
+
e o último commit do dia na linha de resumo, além da hora que já existia
|
|
221
|
+
(`"2 commits, das 09:00 às 14:30 (duração: 5h30)."`). Motivo: alguns
|
|
222
|
+
agentes já registravam hora e duração manualmente ao publicar relatórios
|
|
223
|
+
no Notion (ex.: "Commit automático do Fetch All das 08:36") — o padrão foi
|
|
224
|
+
formalizado em `docs/PADRAO-RELATORIOS.md` no hub, e este módulo passou a
|
|
225
|
+
gerar esse dado automaticamente em vez de depender de alguém lembrar.
|
|
226
|
+
Validação: 5 novos testes em `test_git_historico.py`; 295 testes do
|
|
227
|
+
notion-starter verdes, ruff limpo.
|
|
228
|
+
|
|
229
|
+
---
|
|
230
|
+
|
|
231
|
+
Ideias abertas à contribuição: cobertura de mais tipos de propriedade do Notion,
|
|
232
|
+
mais tipos de bloco no conversor Markdown, escrita de linhas em data sources.
|
|
233
|
+
|
|
234
|
+
---
|
|
235
|
+
|
|
236
|
+
## [2026-08-17] Operar Notion às cegas era o gargalo real — três defesas na biblioteca
|
|
237
|
+
|
|
238
|
+
**Contexto.** Uma sessão longa de trabalho real no workspace (criar 17 tarefas
|
|
239
|
+
ricas, reescrever 16 e montar 48 ligações entre elas) expôs o mesmo padrão em
|
|
240
|
+
todas as fricções: **a biblioteca não respondia perguntas que antecedem a
|
|
241
|
+
escrita**, e o custo aparecia depois, já gravado no Notion.
|
|
242
|
+
|
|
243
|
+
### 1. `descrever_database` — ler o schema sem chamar a API na mão
|
|
244
|
+
|
|
245
|
+
`schema.py` só sabia **comparar** um database com um schema esperado. Para
|
|
246
|
+
descobrir o nome exato de uma coluna, os valores aceitos por um select ou como
|
|
247
|
+
uma relação está configurada, era preciso chamar `/v1/databases/<id>` cru e ler
|
|
248
|
+
JSON — passo que se pula com pressa.
|
|
249
|
+
|
|
250
|
+
Entram `DescricaoDatabase`, `Coluna` e `Relacao` (funções puras, sem rede):
|
|
251
|
+
colunas ordenadas com o título primeiro, opções de select/status/multi_select,
|
|
252
|
+
`editavel` marcando os tipos que o Notion calcula e recusa em PATCH
|
|
253
|
+
(`TIPOS_SOMENTE_LEITURA`), e a configuração de cada relação com `auto_referente`
|
|
254
|
+
comparando IDs sem hífen.
|
|
255
|
+
|
|
256
|
+
### 2. `services/relacoes.py` — o tipo da relação não prevê o comportamento
|
|
257
|
+
|
|
258
|
+
Hipótese inicial: `single_property` = mão única, então uma ligação simétrica
|
|
259
|
+
exige gravar as duas pontas. **Medido no workspace real e a hipótese caiu
|
|
260
|
+
parcialmente.** Experimento: duas linhas novas no database `30296e2d…`, coluna
|
|
261
|
+
`Subtarefas relacionadas`, reportada como `single_property` pelas versões de API
|
|
262
|
+
`2022-06-28` **e** `2025-09-03`. PATCH só na ponta C→D; releitura de D **já
|
|
263
|
+
trazia C**. O Notion espelhou sem segunda escrita.
|
|
264
|
+
|
|
265
|
+
Conclusão registrada: **não dá para deduzir do tipo declarado se o espelho
|
|
266
|
+
acontece.** Assumir "espelha" deixa metade da malha faltando; assumir "não
|
|
267
|
+
espelha" gasta requisição e pode duplicar. `relacionar()` resolve conferindo —
|
|
268
|
+
escreve uma ponta, **relê a outra** e grava só o que faltar. Sai simétrico nos
|
|
269
|
+
dois mundos, é idempotente e o retorno diz quais páginas precisaram de escrita.
|
|
270
|
+
Relação para outro database e de mão única não tem coluna de volta: escreve só A.
|
|
271
|
+
|
|
272
|
+
### 3. Reescrita que não custa o que não sabe repor
|
|
273
|
+
|
|
274
|
+
`limpar_conteudo` apagava **todos** os blocos de topo, e `escrever(substituir=True)`
|
|
275
|
+
chamava isso em silêncio. Consequência real: reescrever o texto de uma página
|
|
276
|
+
apagava a imagem dela (URL do Notion é assinada e expira — a lixeira não devolve
|
|
277
|
+
o arquivo) e, pior, apagava `child_database`, **levando o database inteiro** com
|
|
278
|
+
ID novo ao restaurar e todo link salvo quebrado.
|
|
279
|
+
|
|
280
|
+
Agora `TIPOS_NAO_RECRIAVEIS` (imagem, arquivo, vídeo, PDF, áudio, embed,
|
|
281
|
+
bookmark, link_preview, `child_page`, `child_database`, synced_block, table,
|
|
282
|
+
column_list) é **preservado por padrão**; apagar exige `incluir_nao_recriaveis=True`.
|
|
283
|
+
Os retornos viraram `ResultadoLimpeza`/`ResultadoEscrita`, que implementam
|
|
284
|
+
`__int__`/`__eq__` contra `int` — quem usava só a contagem antiga não quebrou.
|
|
285
|
+
|
|
286
|
+
### 4. `EscritaAbaixoDeDatabaseError` — a regra que virou guarda
|
|
287
|
+
|
|
288
|
+
A "regra do link" (se o alvo é database, trabalhe nas linhas) existia só em
|
|
289
|
+
documentação, e modelos mais fracos a ignoravam: recebiam o link de uma página
|
|
290
|
+
que **contém** uma database e escreviam um parágrafo solto abaixo da tabela,
|
|
291
|
+
onde não vira linha nem aparece em view nenhuma.
|
|
292
|
+
|
|
293
|
+
`escrever_conteudo` agora chama `databases_da_pagina()` antes de qualquer escrita
|
|
294
|
+
e **recusa** com uma exceção que lista as databases encontradas com ID e traz os
|
|
295
|
+
comandos prontos (`linhas` → `conteudo` → `editar-linha`/`escrever <linha_id>`).
|
|
296
|
+
A checagem vive no serviço, não na borda, para valer também para MCP e scripts.
|
|
297
|
+
`mesmo_com_database=True` libera quando o bloco solto é mesmo a intenção.
|
|
298
|
+
|
|
299
|
+
**Validação real** (2026-08-17, workspace do usuário): `escrever` na página HOME
|
|
300
|
+
`1fc91f95…` foi recusado listando as três databases de dentro; uma database de
|
|
301
|
+
teste criada dentro de uma linha sobreviveu a `escrever --substituir`; as quatro
|
|
302
|
+
linhas de teste foram arquivadas ao fim. 329 testes verdes, `ruff` limpo.
|
|
303
|
+
|
|
304
|
+
---
|
|
305
|
+
|
|
306
|
+
## [2026-08-17] Histórico de vários repositórios, e a varredura que acha o dia esquecido
|
|
307
|
+
|
|
308
|
+
**Contexto.** `git_historico` já reconstruía o dia de trabalho de **um**
|
|
309
|
+
repositório. Mas um dia real quase nunca cabe num só — mexe-se na biblioteca, no
|
|
310
|
+
CLI que a consome e no app que a expõe — e o relatório precisa contar isso junto,
|
|
311
|
+
senão o mesmo dia vira três narrativas soltas que ninguém cruza depois.
|
|
312
|
+
|
|
313
|
+
`services/historico_repositorios.py` agrega os históricos e agrupa por data,
|
|
314
|
+
produzindo o texto no formato que os relatórios diários já usam: **hora e duração
|
|
315
|
+
por projeto**, nunca só a data. Acrescenta arquivos e linhas por commit, que
|
|
316
|
+
respondem a "foi ajuste ou reescrita?".
|
|
317
|
+
|
|
318
|
+
### `descobrir_repositorios` — o motivo de existir
|
|
319
|
+
|
|
320
|
+
O pedido original era registrar o histórico dos projetos citados numa conversa.
|
|
321
|
+
A pergunta por trás dele era outra: *existe algum dia de trabalho que ficou sem
|
|
322
|
+
registro?* Listar repositórios à mão só encontra o que já se lembra — e o
|
|
323
|
+
esquecido, por definição, não está nessa lista.
|
|
324
|
+
|
|
325
|
+
Medido na máquina de origem: a lista de memória tinha **15 repositórios**; a
|
|
326
|
+
varredura encontrou **47**, e o histórico saltou de 125 para **201 dias** com
|
|
327
|
+
commit, de 2024-03-26 a 2026-08-17.
|
|
328
|
+
|
|
329
|
+
### O corpo diz que é reconstruído
|
|
330
|
+
|
|
331
|
+
O texto gerado abre avisando que veio do git e que decisões e pendências sem
|
|
332
|
+
commit não aparecem ali. Inventar narrativa a partir de mensagem de commit é o
|
|
333
|
+
jeito mais fácil de povoar um relatório com ficção plausível; o aviso é o que
|
|
334
|
+
impede o leitor de tomar log por relato.
|
|
335
|
+
|
|
336
|
+
### Decisões de robustez
|
|
337
|
+
|
|
338
|
+
- Repositório inacessível é **pulado**, não fatal: numa lista de quinze, um
|
|
339
|
+
caminho que mudou não pode custar o histórico dos outros catorze.
|
|
340
|
+
- `--shortstat` tem formato irregular (omite a metade que é zero, e merge não
|
|
341
|
+
gera linha). O parser vive numa função pura, testada com os três formatos.
|
|
342
|
+
- `relatorios_diarios` voltou a converter o retorno de `escrever_conteudo` para
|
|
343
|
+
inteiro com `int(...)` em vez de ler `.anexados` — converter mantém válido
|
|
344
|
+
qualquer double de teste que devolva só o número.
|
|
345
|
+
|
|
346
|
+
**Validação:** 354 testes verdes, `ruff` limpo; publicação real de 201 dias no
|
|
347
|
+
workspace do usuário (115 páginas criadas, 86 complementadas).
|
|
348
|
+
|
|
349
|
+
---
|
|
350
|
+
|
|
351
|
+
## [2026-08-25] `TaskList.criar` descobre o título do database
|
|
352
|
+
|
|
353
|
+
**Sintoma.** A criação de uma linha em `Relatórios diários` falhava porque o
|
|
354
|
+
payload sempre enviava a propriedade `Tarefa`, embora o título real se chamasse
|
|
355
|
+
`Relatório`. A API aceitava criação direta com o schema correto; o defeito estava
|
|
356
|
+
no modelo compartilhado.
|
|
357
|
+
|
|
358
|
+
**Decisão.** `TaskList.criar` lê o schema antes do POST, encontra a única coluna
|
|
359
|
+
`title` com `descrever_database` e usa seu nome real. Os atalhos do modelo de
|
|
360
|
+
tarefas (`Etapa`, `Prazo`, `Esforço`, `Áreas da vida`) só entram quando a coluna
|
|
361
|
+
existe com tipo compatível. A assinatura e o retorno `Tarefa` foram preservados;
|
|
362
|
+
somente a criação ficou genérica, sem fingir que listar/editar databases
|
|
363
|
+
arbitrários também são operações de tarefas.
|
|
364
|
+
|
|
365
|
+
**Validação.** 355 testes verdes e `ruff` limpo. No workspace real, foram
|
|
366
|
+
criadas com sucesso uma linha em `Relatórios diários` (título `Relatório`) e
|
|
367
|
+
outra em `Tasks` (título `Tarefa`, com `Etapa`/`Esforço`); ambas foram arquivadas
|
|
368
|
+
ao fim.
|
|
369
|
+
|
|
370
|
+
## [2026-09-04] Pacote base preparado para a distribuição sem clone
|
|
371
|
+
|
|
372
|
+
O `pyproject.toml` foi alinhado ao contrato de distribuição da CLI única: a
|
|
373
|
+
versão candidata do `notion-starter` passou a ser `0.3.0`, com build Hatchling,
|
|
374
|
+
wheel e sdist. Nenhum código de domínio foi alterado nesta etapa; o pacote segue
|
|
375
|
+
sendo a fonte compartilhada para o CLI e o app, sem depender de uma URL Git nos
|
|
376
|
+
consumidores.
|
|
377
|
+
|
|
378
|
+
**Validação:** `ruff check .` limpo, **355 testes verdes**, `twine check` aprovado
|
|
379
|
+
para wheel e sdist e import validado em ambiente limpo. A publicação efetiva no
|
|
380
|
+
PyPI não foi executada: nome final, ownership e metadados legais ainda precisam
|
|
381
|
+
de confirmação explícita.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Felipe Alcantara
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|