expxdev 0.1.0 → 0.2.0

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 (60) hide show
  1. package/README.md +580 -81
  2. package/dist/cli/init.js +6 -2
  3. package/dist/cli/init.js.map +1 -1
  4. package/dist/cli/subcomandos.js +1 -1
  5. package/dist/doctor/verificadores.js +97 -1
  6. package/dist/doctor/verificadores.js.map +1 -1
  7. package/dist/harness/hooks.d.ts +27 -0
  8. package/dist/harness/hooks.js +36 -0
  9. package/dist/harness/hooks.js.map +1 -0
  10. package/dist/harness/settings.d.ts +2 -1
  11. package/dist/harness/settings.js +40 -2
  12. package/dist/harness/settings.js.map +1 -1
  13. package/dist/nucleo/caminhos.d.ts +1 -1
  14. package/dist/nucleo/catalogo.d.ts +1 -1
  15. package/dist/nucleo/catalogo.js +7 -1
  16. package/dist/nucleo/catalogo.js.map +1 -1
  17. package/dist/nucleo/layout.d.ts +3 -2
  18. package/dist/nucleo/layout.js +37 -1
  19. package/dist/nucleo/layout.js.map +1 -1
  20. package/dist/nucleo/versao.d.ts +1 -1
  21. package/dist/parser/conformidade/regras.d.ts +1 -0
  22. package/dist/parser/conformidade/regras.js +24 -0
  23. package/dist/parser/conformidade/regras.js.map +1 -1
  24. package/dist/parser/esquema/enums.d.ts +19 -0
  25. package/dist/parser/esquema/enums.js +18 -0
  26. package/dist/parser/esquema/enums.js.map +1 -1
  27. package/dist/parser/esquema/evento.d.ts +123 -0
  28. package/dist/parser/esquema/evento.js +141 -0
  29. package/dist/parser/esquema/evento.js.map +1 -0
  30. package/dist/parser/leitura/rejeicao.d.ts +9 -0
  31. package/dist/parser/leitura/rejeicao.js +56 -0
  32. package/dist/parser/leitura/rejeicao.js.map +1 -1
  33. package/dist/parser/memoria/ler.d.ts +38 -0
  34. package/dist/parser/memoria/ler.js +46 -0
  35. package/dist/parser/memoria/ler.js.map +1 -0
  36. package/dist/parser/memoria/projetar.d.ts +3 -0
  37. package/dist/parser/memoria/projetar.js +132 -0
  38. package/dist/parser/memoria/projetar.js.map +1 -0
  39. package/dist/parser/memoria/tipos.d.ts +155 -0
  40. package/dist/parser/memoria/tipos.js +97 -0
  41. package/dist/parser/memoria/tipos.js.map +1 -0
  42. package/dist/parser/projeto/montar.d.ts +17 -0
  43. package/dist/parser/projeto/montar.js +17 -0
  44. package/dist/parser/projeto/montar.js.map +1 -1
  45. package/dist/plugin/montagem.d.ts +7 -0
  46. package/dist/plugin/montagem.js +22 -2
  47. package/dist/plugin/montagem.js.map +1 -1
  48. package/dist/servidor/http.js +5 -0
  49. package/dist/servidor/http.js.map +1 -1
  50. package/dist/servidor/observador.js +5 -1
  51. package/dist/servidor/observador.js.map +1 -1
  52. package/dist/teste/repo-fixture.d.ts +7 -0
  53. package/dist/teste/repo-fixture.js +18 -0
  54. package/dist/teste/repo-fixture.js.map +1 -1
  55. package/nucleo/README.md +79 -0
  56. package/nucleo/hooks/expx-rastro.sh +261 -0
  57. package/package.json +6 -4
  58. package/ui/dist/assets/index-BNE_RJrV.js +15 -0
  59. package/ui/dist/index.html +1 -1
  60. package/ui/dist/assets/index-BmDTogQZ.js +0 -14
package/README.md CHANGED
@@ -1,137 +1,636 @@
1
- # expxdev
1
+ <div align="center">
2
2
 
3
- CLI do método Expx. Instala, atualiza e diagnostica o ecossistema de skills por projeto,
4
- e sobe o painel de operação que lê a pasta `docs/`.
3
+ <picture>
4
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/bittencourtthulio/expxdev/main/.github/assets/banner-dark.svg">
5
+ <source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/bittencourtthulio/expxdev/main/.github/assets/banner-light.svg">
6
+ <img alt="expx — o CLI do metodo Expx" src="https://raw.githubusercontent.com/bittencourtthulio/expxdev/main/.github/assets/banner-light.svg" width="100%">
7
+ </picture>
5
8
 
6
- ## Instalação das skills
9
+ <p>
10
+ <a href="https://www.npmjs.com/package/expxdev"><img alt="npm: expxdev" src="https://raw.githubusercontent.com/bittencourtthulio/expxdev/main/.github/assets/badge-npm.svg"></a>
11
+ <img alt="harness: Claude Code" src="https://raw.githubusercontent.com/bittencourtthulio/expxdev/main/.github/assets/badge-claude.svg">
12
+ <img alt="harness: OpenCode" src="https://raw.githubusercontent.com/bittencourtthulio/expxdev/main/.github/assets/badge-opencode.svg">
13
+ <img alt="testes: 231 passed" src="https://raw.githubusercontent.com/bittencourtthulio/expxdev/main/.github/assets/badge-testes.svg">
14
+ <img alt="schema expx v1" src="https://raw.githubusercontent.com/bittencourtthulio/expxdev/main/.github/assets/badge-schema.svg">
15
+ <img alt="node >=20.19" src="https://raw.githubusercontent.com/bittencourtthulio/expxdev/main/.github/assets/badge-node.svg">
16
+ <img alt="licenca MIT" src="https://raw.githubusercontent.com/bittencourtthulio/expxdev/main/.github/assets/badge-license.svg">
17
+ </p>
18
+
19
+ <strong>O CLI do método Expx</strong> — instala, atualiza e diagnostica o ecossistema<br>
20
+ de skills para <a href="https://claude.com/claude-code">Claude Code</a> e <a href="https://opencode.ai">OpenCode</a>, e sobe o painel de operação.
21
+
22
+ </div>
7
23
 
8
24
  ```bash
9
25
  npx expxdev init
10
26
  ```
11
27
 
12
- O `init` busca as skills escolhidas nos repositórios oficiais, empacota as selecionadas
13
- como um plugin local chamado `expx` e configura o harness. Os comandos ficam com namespace
14
- no Claude Code (`/expx:sprintx-sprints`) e sem namespace no OpenCode (`/sprintx-sprints`).
28
+ O `init` busca as skills que você escolher nos repositórios oficiais, empacota apenas as
29
+ selecionadas como um plugin local chamado `expx` e configura o harness. Os comandos ficam
30
+ com namespace no Claude Code (`/expx:sprintx-sprints`) e sem namespace no OpenCode
31
+ (`/sprintx-sprints`).
32
+
33
+ > **A instalação é travada por lock; a atualização é um ato explícito.**
34
+ > Quem clona o projeto recebe exatamente as mesmas skills que o time está usando, sem rede e
35
+ > sem rodar nada. Quem atualiza decide quando, vendo antes o que muda.
36
+
37
+ ---
38
+
39
+ ## Índice
15
40
 
16
- | Skill | O que faz |
41
+ | | |
17
42
  |---|---|
18
- | [`sprintx`](https://github.com/bittencourtthulio/sprintx) | planeja e executa features novas |
19
- | [`runx`](https://github.com/bittencourtthulio/runx) | ocorrências de manutenção do dia a dia |
20
- | [`legadox`](https://github.com/bittencourtthulio/legadox) | camada para projetos legados |
21
- | [`stackx`](https://github.com/bittencourtthulio/stackx) | descobre o dialeto técnico do repositório |
22
- | [`mergex`](https://github.com/bittencourtthulio/mergex) | versionamento, entrega e revisão de PRs |
43
+ | **[O problema que o método resolve](#o-problema-que-o-método-resolve)** | por que existe um método, e não um prompt melhor |
44
+ | **[O ecossistema](#o-ecossistema)** | as seis skills, o que cada uma faz e quando usar |
45
+ | **[Como as peças se encaixam](#como-as-peças-se-encaixam)** | o fluxo de ponta a ponta, com o diagrama |
46
+ | **[As três camadas de garantia](#as-três-camadas-de-garantia)** | skill, hook e agente da mais fraca à mais forte |
47
+ | **[Os dois contratos](#os-dois-contratos-compartilhados)** | `expx-schema` e `expx-eventos`, o que faz tudo se encaixar |
48
+ | **[O que fica no seu projeto](#o-que-fica-no-seu-projeto)** | cada pasta, quem escreve e quem lê |
49
+ | **[Subcomandos](#subcomandos)** · **[Lock e atualização](#versão-lock-e-atualização)** · **[Doctor](#o-que-o-doctor-verifica)** · **[Painel](#o-painel)** | a referência do CLI |
50
+ | **[Anatomia do `init`](#anatomia-do-init-passo-a-passo)** | o que roda, em que ordem, e por quê |
51
+ | **[A memória do projeto](#a-memória-do-projeto)** | o que já se sabe sobre este arquivo, antes de mexer nele |
52
+ | **[Segurança](#segurança-e-limites)** · **[Desenvolvimento](#desenvolvimento)** | limites e arquitetura interna |
53
+
54
+ ---
55
+
56
+ ## O problema que o método resolve
57
+
58
+ Pedir a um agente de IA para construir uma feature funciona — até a segunda hora. O plano era
59
+ vago o bastante para o agente ter que decidir sozinho no meio da implementação, então ele
60
+ decide: escolhe um padrão que não é o do projeto, escreve o teste na pasta que o runner não
61
+ olha, refatora três arquivos que ninguém pediu, e entrega um diff de 600 linhas em que as
62
+ quatro que importam estão perdidas. Nada disso exige um modelo ruim — exige um modelo
63
+ prestativo trabalhando sem as restrições que um desenvolvedor experiente aplicaria por
64
+ instinto.
65
+
66
+ O método Expx é o conjunto dessas restrições, escrito. Ele parte de quatro apostas:
67
+
68
+ 1. **Todo o esforço vai para o planejamento.** Uma pergunta feita durante a execução é sempre
69
+ uma falha da fase de planejamento. Se a ambiguidade foi eliminada antes, a execução pode
70
+ ser autônoma sem virar aposta.
71
+ 2. **Nada avança sem critério verificável.** Task, fase e sprint têm portão de aceite binário,
72
+ sem adjetivo. TDD não é sugestão: o teste vem antes, e a task só fecha com a suíte inteira
73
+ verde.
74
+ 3. **O escopo é travado no que a investigação provou.** O que não está no plano não é tocado.
75
+ Melhoria avulsa vira registro de dívida, nunca um brinde no diff.
76
+ 4. **Quem implementa não aprova.** O QA e a auditoria são papéis distintos, e os agentes que
77
+ os executam têm acesso somente de leitura — o que transforma "aponta, não corrige" de
78
+ promessa em impossibilidade técnica.
79
+
80
+ Este repositório é o **centro** do ecossistema: o CLI que instala e mantém as skills, e o
81
+ painel que lê o que elas gravam.
82
+
83
+ ---
84
+
85
+ ## O ecossistema
86
+
87
+ <picture>
88
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/bittencourtthulio/expxdev/main/.github/assets/ecossistema-dark.svg">
89
+ <source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/bittencourtthulio/expxdev/main/.github/assets/ecossistema-light.svg">
90
+ <img alt="O CLI busca as seis skills, empacota como plugin e configura os dois harnesses" src="https://raw.githubusercontent.com/bittencourtthulio/expxdev/main/.github/assets/ecossistema-light.svg" width="100%">
91
+ </picture>
92
+
93
+ | Skill | O que faz | Quando usar |
94
+ |---|---|---|
95
+ | **[sprintx](https://github.com/bittencourtthulio/sprintx)** | Planeja e executa **features novas** em seis fases: ingestão → descoberta → plano → orquestrador → auditoria → execução. Todo o esforço vai para o planejamento, e a execução é autônoma porque a ambiguidade já foi eliminada. | Construir algo que não existe |
96
+ | **[runx](https://github.com/bittencourtthulio/runx)** | A metade **Run**: ocorrências de manutenção em produção, em cinco estágios — investigação com causa raiz comprovada, plano, fix sob TDD, QA independente e relatórios de fechamento. | Corrigir, ajustar ou investigar o que já está no ar |
97
+ | **[legadox](https://github.com/bittencourtthulio/legadox)** | **Camada** que endurece o trabalho em projetos legados. Não acrescenta fase: muda o *rigor* de cada uma, proporcional ao raio de impacto da mudança. | Mexer em código sem testes ou sem dono |
98
+ | **[stackx](https://github.com/bittencourtthulio/stackx)** | **Camada** que descobre o dialeto técnico do repositório — convenções, padrões e aderência — para o código novo parecer com o que já existe. | Entrar em base desconhecida |
99
+ | **[mergex](https://github.com/bittencourtthulio/mergex)** | Versionamento, entrega e revisão: branch, um commit por task, portão de prontidão, descrição de PR, pacote de QA e abertura do pull request. | Levar o trabalho pronto até o merge |
100
+ | **[memox](https://github.com/bittencourtthulio/MemoX)** | **Camada** de memória: indexa os artefatos já fechados — relatórios, causas raiz, decisões, QA, entregas — e responde o que já se sabe sobre um arquivo antes de alguém mexer nele. | Saber se este arquivo já quebrou antes |
101
+
102
+ **Camadas** (`legadox`, `stackx`, `memox`) sozinhas não fazem nada — elas modificam o
103
+ comportamento de `sprintx` e `runx`. O CLI avisa se você selecionar uma camada sem base, mas
104
+ nunca impede.
105
+
106
+ ### Build e Run são a mesma disciplina
107
+
108
+ `sprintx` e `runx` não são dois métodos: são o mesmo método com gatilhos diferentes.
109
+
110
+ | | **sprintx** (Build) | **runx** (Run) |
111
+ |---|---|---|
112
+ | **Gatilho** | feature nova, planejada do zero | ocorrência num sistema em produção |
113
+ | **Entrada** | uma ideia, um requisito | um chamado, ticket ou relato de cliente |
114
+ | **Estágios** | F1…F6 (ingestão → execução) | E1…E5 (investigação → relatório) |
115
+ | **Saída** | a feature entregue | a ocorrência encerrada, com dois relatórios |
116
+
117
+ As duas compartilham **exatamente** os mesmos contratos: base de conhecimento antes de
118
+ qualquer plano, hierarquia sprint → fase → task, TDD obrigatório com no mínimo dois testes por
119
+ task, critério de aceite verificável em toda transição, paralelismo declarado no plano e
120
+ execução autônoma guiada por um arquivo orquestrador.
121
+
122
+ **Muda o gatilho e o tamanho. Nunca o rigor.**
123
+
124
+ ---
125
+
126
+ ## Como as peças se encaixam
127
+
128
+ <picture>
129
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/bittencourtthulio/expxdev/main/.github/assets/metodo-dark.svg">
130
+ <source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/bittencourtthulio/expxdev/main/.github/assets/metodo-light.svg">
131
+ <img alt="O metodo Expx de ponta a ponta: o gatilho escolhe entre sprintx e runx, as camadas stackx e legadox modificam as duas, a mergex entrega e o painel le tudo" src="https://raw.githubusercontent.com/bittencourtthulio/expxdev/main/.github/assets/metodo-light.svg" width="100%">
132
+ </picture>
133
+
134
+ Em uma frase: **`stackx` diz como este projeto escreve código, `legadox` diz o quanto ter
135
+ medo, `sprintx` e `runx` fazem o trabalho, `mergex` entrega, e o `expxdev` instala todos e
136
+ mostra o andamento.**
137
+
138
+ A composição concreta, skill a skill:
139
+
140
+ | Quando a camada existe | O que muda na `sprintx` | O que muda na `runx` |
141
+ |---|---|---|
142
+ | **`docs/stack/CONVENCOES.md`** *(stackx)* | a ingestão lê as convenções; a descoberta transforma cada PROPOSTA em pergunta; o plano define caminho do teste, camada e padrão de erro **por task**, em vez de deixar para o executor; a auditoria roda a verificação de aderência | a investigação consulta o cartucho conforme o sintoma; o fix obedece o padrão de teste e o isolamento de banco |
143
+ | **`docs/legado/PERFIL.md`** *(legadox)* | cada fase ganha rigor proporcional ao raio: caracterização antes de alterar, orçamento de diff por task, plano de reversão, aprovação humana em raio ALTO | idem, sobre os cinco estágios |
144
+ | **`mergex` instalada** | abre a branch no início da F6, commita cada task, e entrega ao fim | abre a branch no início do E3, e entrega entre o E4 e o E5 |
145
+
146
+ > **A ausência nunca quebra.** Sem `CONVENCOES.md`, sem `PERFIL.md` ou sem a `mergex`, as
147
+ > outras skills se comportam exatamente como se comportariam sem elas. Insumo que não existe
148
+ > vira aviso do que falta — nunca invenção, e nunca um erro que trava o trabalho.
149
+
150
+ ### Uma regra de precedência que evita o pior colateral
151
+
152
+ `stackx` descreve **o que deve ser seguido daqui pra frente**. `legadox` descreve **o que
153
+ existe hoje**, incluindo os dialetos conflitantes. Em projeto novo, só o `stackx` governa. **Em
154
+ projeto legado, na área tocada manda o padrão local descrito no `PERFIL.md`; o `stackx` governa
155
+ apenas código novo, em arquivo novo.**
156
+
157
+ Sem essa regra, a IA "moderniza" arquivo antigo achando que está obedecendo convenção — o
158
+ colateral mais perigoso que existe, porque vem com a justificativa de estar seguindo uma regra.
159
+
160
+ ---
161
+
162
+ ## As três camadas de garantia
163
+
164
+ <picture>
165
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/bittencourtthulio/expxdev/main/.github/assets/camadas-dark.svg">
166
+ <source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/bittencourtthulio/expxdev/main/.github/assets/camadas-light.svg">
167
+ <img alt="As tres camadas que garantem o metodo: a skill instrui, o hook barra de forma deterministica, e o agente julga em contexto proprio" src="https://raw.githubusercontent.com/bittencourtthulio/expxdev/main/.github/assets/camadas-light.svg" width="100%">
168
+ </picture>
169
+
170
+ Uma regra escrita na skill é uma instrução — e instrução é coisa que o modelo pode esquecer na
171
+ task 14 de uma execução longa, justamente quando o trabalho é grande e o risco é maior. Por
172
+ isso o método tem três camadas, e cada uma cobre o que a anterior não garante:
173
+
174
+ - **A skill instrui.** É o método escrito: fases, contratos, regras invioláveis, templates.
175
+ - **O hook barra.** Script determinístico, executado pelo harness e não pelo modelo. Roda
176
+ sempre, porque não depende de ninguém lembrar.
177
+ - **O agente julga.** Roda em contexto próprio, com ferramentas restritas — não vê o raciocínio
178
+ de quem produziu o trabalho, e não tem como corrigir o que encontra.
179
+
180
+ ### Todo hook de método nasce em modo aviso
181
+
182
+ | Modo | Comportamento | Quando promover |
183
+ |---|---|---|
184
+ | `aviso` | registra no rastro, não bloqueia | estado inicial de todo hook de método |
185
+ | `bloqueio` | barra a ação e devolve o motivo ao modelo | só depois de rodar semanas sem falso positivo |
186
+
187
+ A razão é prática: **hook que dá falso positivo é desinstalado, e junto com ele vão os que
188
+ funcionavam.** A exceção são os hooks de segurança, que nascem em `bloqueio` e falham fechados
189
+ — segredo commitado não tem volta, e o falso positivo ali é raro.
190
+
191
+ A promoção é decisão humana, tomada olhando as violações que o rastro acumulou. O modo de cada
192
+ hook vive em `.expx/hooks.json`, e cada skill traz um `doctor` que mostra o estado atual.
193
+
194
+ ### Os agentes do ecossistema
195
+
196
+ | Agente | Usado por | Ferramentas | Papel |
197
+ |---|---|---|---|
198
+ | `auditor-plano` | sprintx F5 | **leitura apenas** | Fura o plano antes de ele virar código |
199
+ | `revisor-testes` | sprintx, runx | **leitura apenas** | Responde: esse teste passaria com a implementação errada? |
200
+ | `qa` | runx E4 | leitura + rodar suíte | Valida contra os critérios; não corrige |
201
+ | `investigador` | runx E1, legadox | leitura + busca | Monta a base e prova a causa raiz |
202
+ | `cartografo` | stackx, legadox | leitura + histórico | Varre o repositório e extrai convenção ou perfil |
203
+
204
+ > Os agentes de veredito — `auditor-plano`, `revisor-testes`, `qa` — têm acesso **somente de
205
+ > leitura**. Um agente sem restrição declarada **herda todas as ferramentas** no Claude Code,
206
+ > o que destruiria exatamente a garantia que justifica o agente existir.
207
+
208
+ **Hooks e agentes vivem hoje nos repositórios das skills**, instalados a partir de cada um. O
209
+ `init` monta o plugin com as skills e os comandos; a camada determinística de cada skill segue
210
+ o contrato `expx-eventos`, documentado abaixo.
211
+
212
+ ---
213
+
214
+ ## Os dois contratos compartilhados
215
+
216
+ As seis skills não se conhecem por código: elas se encontram em dois contratos escritos. É
217
+ isso que permite instalar três delas e não as outras duas, atualizar uma sem tocar nas demais,
218
+ ou escrever uma sexta amanhã.
219
+
220
+ | Contrato | O que padroniza | Quem escreve | Quem lê hoje |
221
+ |---|---|---|---|
222
+ | **[`expx-schema` v1](docs/contrato/CONTRATO-expx-schema-v1.md)** | o frontmatter YAML de todo arquivo de estado — plano, tasks, bloqueios, QA, relatórios | as skills | **o painel** |
223
+ | **[`expx-eventos` v1](docs/contrato/CONTRATO-expx-eventos.md)** | o rastro append-only `docs/eventos/<trabalho_id>.jsonl`, e o comportamento de hooks e agentes | as skills e os hooks | as próprias skills e o `doctor` de cada uma |
224
+
225
+ > O painel desta versão lê **apenas o `expx-schema`** — o estado. A leitura do rastro de
226
+ > eventos está especificada no contrato e ainda não implementada no painel.
227
+
228
+ **O estado responde "onde está"; o rastro responde "o que aconteceu e quando".**
229
+
230
+ ```yaml
231
+ ---
232
+ expx_schema: 1
233
+ expx_tool: runx # sprintx | runx — quem escreveu
234
+ kind: tasks
235
+ trabalho_id: OC-2026-0142
236
+ atualizado_em: 2026-08-29
237
+ tasks:
238
+ - id: T-01.01
239
+ status: concluida
240
+ criterio_aceite: O teste falha antes do fix e passa depois
241
+ suite: verde
242
+ ---
243
+ ```
244
+
245
+ ```json
246
+ {"ts":"2026-08-29T14:32:10Z","expx_eventos":1,"trabalho_id":"OC-2026-0142",
247
+ "ferramenta":"runx","origem":"hook","evento":"task_concluida","fase":"e3",
248
+ "task":"T-01.02","agente":"principal","resultado":"ok","detalhe":"suite verde, 14 testes"}
249
+ ```
23
250
 
24
- ### Subcomandos
251
+ Os kinds compartilhados entre `sprintx` e `runx` — `orquestrador`, `sprint`, `fases`, `tasks`,
252
+ `bloqueios`, `base_indice` — são **idênticos campo por campo**; o campo `expx_tool` diz qual
253
+ das duas escreveu. A máquina lê o YAML e o JSONL; a pessoa lê a prosa abaixo deles.
254
+
255
+ Uma consequência que não estava prevista: o rastro dá o **esforço real por task sem ninguém
256
+ anotar nada**, e é isso que calibra a estimativa da `sprintx` nas features seguintes.
257
+
258
+ ---
259
+
260
+ ## O que fica no seu projeto
261
+
262
+ <picture>
263
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/bittencourtthulio/expxdev/main/.github/assets/disco-dark.svg">
264
+ <source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/bittencourtthulio/expxdev/main/.github/assets/disco-light.svg">
265
+ <img alt="O que cada skill grava no seu projeto e quem le o que: as skills escrevem, os hooks acrescentam o rastro, e o painel apenas le" src="https://raw.githubusercontent.com/bittencourtthulio/expxdev/main/.github/assets/disco-light.svg" width="100%">
266
+ </picture>
267
+
268
+ `<trabalho_id>` é o mesmo identificador em todas as skills: o `<slug-da-feature>` da `sprintx`
269
+ ou o `<OC-ID>-<slug>` da `runx`. **Um trabalho, um nome, do plano até a entrega** — é o que
270
+ permite ao painel juntar o plano, o raio de impacto, a entrega e o rastro numa linha do tempo
271
+ só.
272
+
273
+ ---
274
+
275
+ ## Subcomandos
25
276
 
26
277
  | Comando | O que faz |
27
278
  |---|---|
28
- | `expx init` | instala as skills escolhidas neste projeto |
29
- | `expx panel` | sobe o painel lendo o `docs/` do projeto |
30
- | `expx add <skill...>` | acrescenta skills à seleção |
31
- | `expx remove <skill...>` | remove skills da seleção |
32
- | `expx update [skill...]` | atualiza as skills instaladas |
33
- | `expx doctor` | diagnostica uma instalação quebrada |
279
+ | `expx init` | Instala as skills escolhidas neste projeto |
280
+ | `expx panel` | Sobe o painel de operação lendo o `docs/` do projeto |
281
+ | `expx add <skill...>` | Acrescenta skills à seleção e remonta o plugin |
282
+ | `expx remove <skill...>` | Remove skills da seleção e remonta o plugin |
283
+ | `expx update [skill...]` | Atualiza as skills instaladas |
284
+ | `expx doctor` | Diagnostica uma instalação quebrada |
285
+
286
+ O painel funciona **sem `init`**: ele não precisa de nada instalado.
287
+
288
+ ### Flags do `init`
289
+
290
+ A seleção é feita por flag — a escolha é declarativa, o que faz a mesma linha servir ao seu
291
+ terminal e ao CI:
34
292
 
35
- O painel funciona sem `init`: ele não precisa de nada instalado.
293
+ ```bash
294
+ npx expxdev init --skills sprintx,runx,mergex --harness claude,opencode --yes
295
+ ```
36
296
 
37
- Flags do `init` (todas as perguntas têm equivalente por flag, para uso em script):
38
- `--skills sprintx,runx` · `--harness claude,opencode` · `--painel` · `--yes`
297
+ | Flag | Efeito |
298
+ |---|---|
299
+ | `--skills <lista>` | Skills a instalar, separadas por vírgula. Repetível |
300
+ | `--harness <lista>` | `claude`, `opencode`, ou os dois. Padrão: `claude` |
301
+ | `--yes` / `--sim` | Aplica sem exigir terminal interativo |
39
302
 
40
- Flags do `update`: `--check` (só mostra) · `--to <ref>` · `--latest` · `--yes`
303
+ Todas aceitam também a forma `--flag=valor`.
41
304
 
42
- ### Versão, lock e atualização
305
+ **Sem terminal interativo e sem `--yes`**, o `init` imprime o que instalaria e sai **sem
306
+ escrever nada** — é o modo de simulação, e é o que protege um CI de escrever por engano.
43
307
 
44
- A instalação é travada por `.expx/expx-lock.json`, que é **commitado** junto com `.expx/`.
45
- Quem clona o projeto recebe as skills em disco. Por padrão o CLI busca a maior tag de
46
- versão semântica de cada repositório; sem nenhuma tag, segue a branch padrão e **avisa**
47
- que a skill não está travada em versão publicada.
308
+ > A seleção interativa escolher as skills numa lista, em vez de digitá-las — está planejada
309
+ > e ainda não implementada; o plano vive em [`docs/selecao-interativa-init/`](docs/selecao-interativa-init/).
310
+ > Hoje o `init` não faz nenhuma pergunta: com `--yes` ou com TTY, ele aplica direto.
48
311
 
49
- O `update` compara com o lock, mostra o que mudou e pede confirmação antes de aplicar.
50
- Se algum arquivo da skill foi alterado à mão, ele **não sobrescreve**: lista os arquivos e
51
- pede a decisão. Para desfazer uma atualização, reverta o `.expx/` pelo versionador.
312
+ ---
52
313
 
53
- > **Registro do plugin no Claude Code.** Declarar o marketplace no `settings.json` do
54
- > projeto não instala o plugin — o `init` chama `claude plugin marketplace add` e
55
- > `claude plugin install`. Como esse registro grava um caminho absoluto na configuração do
56
- > usuário, ele não viaja no commit: cada pessoa roda `expx init` na própria máquina.
314
+ ## Anatomia do `init`, passo a passo
315
+
316
+ <picture>
317
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/bittencourtthulio/expxdev/main/.github/assets/plugin-dark.svg">
318
+ <source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/bittencourtthulio/expxdev/main/.github/assets/plugin-light.svg">
319
+ <img alt="Anatomia do que o expx init monta: o marketplace local, o plugin expx com so as skills escolhidas, e o lock que trava versao e hash de cada arquivo" src="https://raw.githubusercontent.com/bittencourtthulio/expxdev/main/.github/assets/plugin-light.svg" width="100%">
320
+ </picture>
321
+
322
+ Para cada skill selecionada, em ordem:
323
+
324
+ 1. **Resolve a versão alvo.** Busca a **maior tag de versão semântica** do repositório —
325
+ comparando número a número, porque ordenar como texto colocaria `v1.10.0` antes de
326
+ `v1.2.0`. Pré-lançamento (`-rc.1`) é ignorado: não é versão publicada. Sem nenhuma tag, cai
327
+ para a branch padrão e **avisa explicitamente** que aquela skill não está travada.
328
+ 2. **Busca o conteúdo** com `git clone --depth 1 --branch <referência>` — clone raso, usando o
329
+ `git` do sistema. É de propósito: assim ele aproveita a credencial já configurada na
330
+ máquina (repositório privado funciona sem CLI nenhum saber de token) e não esbarra em
331
+ limite de requisição de API.
332
+ 3. **Detecta o layout.** Os repositórios das skills não têm todos a mesma forma: alguns trazem
333
+ a skill embutida em `.claude/skills/<nome>/`, outros numa pasta `skill/` na raiz. O CLI não
334
+ assume caminho: procura o **`SKILL.md` mais raso** e adota a pasta dele como raiz, depois
335
+ confere que o `name:` do frontmatter é mesmo a skill pedida. Um layout novo passa a
336
+ funcionar sem tocar nesta camada.
337
+ 4. **Verifica os caminhos.** Recusa qualquer skill que referencie caminho **fora da própria
338
+ pasta** — a razão está logo abaixo.
339
+ 5. **Calcula o hash de cada arquivo** e registra no lock, junto com repositório, referência,
340
+ commit e a data de resolução.
341
+
342
+ **Uma skill que falha não derruba as outras**: o erro dela é reportado nominalmente e o `init`
343
+ segue com as demais. Você fica sabendo exatamente qual não entrou e por quê.
344
+
345
+ Só depois do loop é que a escrita acontece, e ela é **atômica**: a montagem inteira ocorre numa
346
+ pasta temporária **ao lado do destino** — não em `/tmp`, porque `rename` só é atômico dentro do
347
+ mesmo sistema de arquivos — e é trocada por `rename` ao final. Se falhar no meio, o `.expx/`
348
+ anterior é devolvido ao lugar e permanece intacto.
349
+
350
+ Por fim, o harness é configurado: `.claude/settings.json` é **mesclado** — com backup datado,
351
+ preservando todo o resto, e recusando-se a "consertar" JSON inválido — e o `.opencode/` é
352
+ materializado se você escolheu o OpenCode.
353
+
354
+ > **Sobre o registro do plugin.** Declarar o marketplace no `settings.json` do projeto **não
355
+ > instala** o plugin — isso foi verificado em execução, não presumido da documentação. O `init`
356
+ > chama `claude plugin marketplace add` e `claude plugin install`. Como esse registro grava um
357
+ > caminho absoluto na configuração do usuário, ele não viaja no commit: cada pessoa roda
358
+ > `expx init` na própria máquina. Sem o binário `claude` no PATH, o `.expx/` é montado
359
+ > normalmente e o CLI imprime os dois comandos para você rodar à mão.
57
360
 
58
361
  ---
59
362
 
60
- # O painel
363
+ ## Versão, lock e atualização
61
364
 
62
- Lê a pasta `docs/` de um projeto, descobre os trabalhos gravados pelas skills
63
- [`sprintx`](https://github.com/bittencourtthulio/sprintx) e
64
- [`runx`](https://github.com/bittencourtthulio/runx), e mostra no navegador o que foi
65
- planejado, o que está em execução, o que travou e o histórico do que já foi entregue.
365
+ <picture>
366
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/bittencourtthulio/expxdev/main/.github/assets/lock-dark.svg">
367
+ <source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/bittencourtthulio/expxdev/main/.github/assets/lock-light.svg">
368
+ <img alt="Instalacao travada por lock; atualizacao explicita que nunca sobrescreve trabalho local" src="https://raw.githubusercontent.com/bittencourtthulio/expxdev/main/.github/assets/lock-light.svg" width="100%">
369
+ </picture>
66
370
 
67
- **Somente leitura.** O painel nunca escreve nos arquivos do projeto e nunca executa comando algum.
371
+ O `expx-lock.json` guarda, por skill: o repositório, a referência resolvida, se ela está
372
+ travada em versão publicada, o commit exato, a data e **o hash de cada arquivo**. É esse
373
+ último campo que permite detectar modificação local sem consultar a rede.
68
374
 
69
- ## Uso
375
+ ### O que o `update` faz
376
+
377
+ 1. Descobre a versão alvo de cada skill instalada
378
+ 2. Compara com o lock — skill já em dia é reportada e **não é tocada**
379
+ 3. **Detecta modificação local**: se os arquivos divergirem do lock, não sobrescreve
380
+ 4. Mostra o resumo por skill: versão atual, versão nova, e o que mudou
381
+ 5. Bloqueia skill que exija uma versão de `expx-schema` maior que a suportada
382
+ 6. Pede confirmação e aplica
383
+ 7. Remonta o plugin do zero, reescreve o lock e valida
384
+
385
+ | Flag | Efeito |
386
+ |---|---|
387
+ | *(sem argumento)* | Atualiza todas as skills instaladas |
388
+ | `<skill...>` | Atualiza apenas as nomeadas |
389
+ | `--check` | Só mostra o que mudaria, não aplica nada |
390
+ | `--to <ref>` | Fixa uma skill numa tag ou commit específico — exige nomear exatamente uma skill |
391
+ | `--yes` / `--sim` | Aplica sem exigir terminal interativo |
392
+
393
+ A aplicação **remonta o plugin do zero** com a seleção inteira do lock, em vez de editar a
394
+ árvore montada. É mais lento e é de propósito: editar no lugar deixa arquivo órfão quando uma
395
+ skill encolhe entre versões.
396
+
397
+ > `--latest` é aceito pelo parser mas hoje **não altera o comportamento** — a resolução segue
398
+ > sempre a maior tag, ou a branch padrão quando não há tag.
399
+
400
+ > **Rollback.** Como `.expx/` é commitado, desfazer uma atualização é revertê-lo pelo
401
+ > versionador (`git checkout -- .expx`). O `update` diz isso em toda execução que aplica.
402
+
403
+ ---
404
+
405
+ ## O que o `doctor` verifica
406
+
407
+ ```bash
408
+ npx expxdev doctor
409
+ ```
410
+
411
+ Quatorze verificações, cada uma com severidade e correção sugerida. Achado de severidade `aviso`
412
+ não derruba a saída; `erro` sim.
413
+
414
+ | Verificação | Severidade |
415
+ |---|---|
416
+ | `.expx/` existe | erro |
417
+ | lock legível | erro |
418
+ | lock não é de uma versão futura do CLI | erro |
419
+ | `plugin.json` válido | erro |
420
+ | `marketplace.json` válido | erro |
421
+ | skill do lock presente em disco | erro |
422
+ | nenhuma skill referencia caminho **fora da própria pasta** | erro |
423
+ | `.claude/settings.json` presente | erro |
424
+ | plugin habilitado no `settings.json` | erro |
425
+ | sem colisão de nome entre Claude Code e OpenCode | erro |
426
+ | hook instalado tem o motor da skill ao lado | erro |
427
+ | `.gitignore` não ignora o `.expx/` | erro |
428
+ | disco não divergiu do lock (modificação local) | aviso |
429
+ | skill travada em versão publicada | aviso |
430
+
431
+ > **Por que "hook sem motor" é erro.** Todo caminho de falha dos hooks do memox termina em
432
+ > `exit 0`, de propósito: falha aberta nunca trava o prompt de quem está trabalhando. O preço é
433
+ > que uma instalação quebrada fica indistinguível de um projeto sem artefatos — silêncio dos
434
+ > dois lados. O `doctor` é o único lugar onde a diferença aparece.
435
+
436
+ > **Por que "caminho fora da própria pasta" importa.** Ao instalar, o Claude Code **copia** o
437
+ > plugin para `~/.claude/plugins/cache/<marketplace>/<plugin>/<versão>/`, e só a pasta do
438
+ > plugin vai junto. Qualquer `../` dentro de uma skill sai da árvore copiada e deixa de
439
+ > resolver — silenciosamente. O CLI recusa instalar uma skill assim, tanto no `init` quanto no
440
+ > `doctor`.
441
+
442
+ ---
443
+
444
+ ## O painel
70
445
 
71
446
  ```bash
72
447
  npx expxdev panel
73
448
  ```
74
449
 
450
+ Lê a pasta `docs/` do projeto, descobre os trabalhos gravados pelas skills e mostra no
451
+ navegador o que foi planejado, o que está em execução, o que travou e o histórico do que já foi
452
+ entregue. Ele lê o **estado** gravado sob o contrato `expx-schema`: o frontmatter YAML de cada
453
+ arquivo de plano, task, bloqueio, QA e relatório.
454
+
455
+ **Somente leitura, e não só por convenção.** Qualquer requisição que não seja `GET` recebe
456
+ `405` com a mensagem `o painel e somente leitura`. O servidor escuta exclusivamente em
457
+ `127.0.0.1` — o host é constante no código, sem flag, opção ou variável de ambiente que mude
458
+ isso.
459
+
460
+ Ele observa o `docs/` e atualiza sozinho: quando um arquivo muda, o navegador recebe o estado
461
+ novo por websocket, sem recarregar a página. A cada mudança o projeto é **relido inteiro**, não
462
+ em pedaços — as regras de conformidade cruzam referências entre arquivos, e uma leitura parcial
463
+ produziria violação falsa.
464
+
465
+ ### O que ele reconhece
466
+
467
+ O painel não varre todo `.md` do projeto: procura **os nomes de arquivo do contrato** —
468
+ `ORQUESTRADOR.md`, `tasks.md`, `fases.md`, `sprint.md`, `01-CAUSA-RAIZ.md`, `QA.md`,
469
+ `tecnico.md`, `uso.md` e os demais. A razão é que muitos `.md` legítimos não têm frontmatter, e
470
+ varrer por extensão encheria a tela de "fora do schema" com ruído.
471
+
472
+ Um trabalho é uma pasta com `ORQUESTRADOR.md` de frontmatter válido — a regra é sobre o
473
+ conteúdo, não sobre o caminho. Pasta sem orquestrador é ignorada em silêncio.
474
+
475
+ Além do estado, o painel lê o índice da [`memox`](#a-memória-do-projeto), quando ele existe, e
476
+ o mostra na seção **Memória** — o que já se sabe sobre cada arquivo antes de alguém mexer nele.
477
+ Ele **não** observa `.expx/`: é lá que o índice é gravado, e observá-lo faria a reindexação
478
+ realimentar a recarga da tela sem dado novo nenhum.
479
+
480
+ ### Ele também aponta violações do método
481
+
482
+ Além de mostrar o andamento, o painel confere o que leu contra as regras do método e lista o
483
+ que não bate:
484
+
485
+ | Violação | O que significa |
486
+ |---|---|
487
+ | `teste_ausente` | task sem teste de integração ou funcional declarado |
488
+ | `regressao_ausente` | ocorrência do tipo `bug` sem o teste que reproduz |
489
+ | `concluida_sem_verde` | task marcada como concluída sem a suíte verde |
490
+ | `paralela_com_dependencia` | task declarada paralelizável mas com dependência aberta |
491
+ | `sem_criterio_saida` | fase ou sprint sem critério de saída |
492
+ | `dependencia_inexistente` | task que depende de um id que não existe |
493
+ | `ciclo_dependencia` | duas ou mais tasks que se esperam em círculo |
494
+ | `estagio_incoerente` | estágio declarado que não combina com o estado dos arquivos |
495
+ | `bloqueio_antigo` | bloqueio parado há mais dias que o limite configurado |
496
+
497
+ A distinção importa e tem duas telas separadas:
498
+
499
+ - **Violação** — o painel *leu* o arquivo, e o conteúdo desobedece uma regra do método. Isso é
500
+ um achado sobre o trabalho.
501
+ - **Rejeição** — o painel *não conseguiu* ler: sem frontmatter, YAML inválido, `kind`
502
+ desconhecido, ou versão de schema mais nova que a suportada. Isso é um achado sobre o
503
+ arquivo, e ele fica de fora do painel até ser corrigido.
504
+
505
+ Cada regra tem escopo estreito de propósito, porque violação falsa é pior que violação
506
+ ausente: regressão não é cobrada de trabalho da `sprintx` nem de ocorrência que não é bug, e
507
+ critério de saída não é exigido de fase que não o declara por não existir.
508
+
75
509
  | Flag | Padrão | O que faz |
76
510
  |---|---|---|
77
511
  | `--porta <n>` | `4000` | porta do servidor local |
78
512
  | `--dir <caminho>` | `./docs` | pasta de documentação a observar |
79
513
  | `--no-open` | — | não abre o navegador |
80
- | `--dias-bloqueio <n>` | `7` | a partir de quantos dias um bloqueio aberto é "antigo" |
81
- | `--ajuda` | — | mostra a ajuda |
514
+ | `--dias-bloqueio <n>` | `7` | dias a partir dos quais um bloqueio é antigo |
82
515
 
83
- ## O que o painel mostra
516
+ ---
84
517
 
85
- - **Visão global** trabalhos em planejamento, execução, bloqueados e concluídos, separando feature de ocorrência; bloqueios abertos; ocorrências por tipo.
86
- - **Quadro por estágio** — 11 colunas (`f1`–`f6` da sprintx, `e1`–`e5` da runx), com filtro por ferramenta, tipo e status.
87
- - **Detalhe do trabalho** — sprints, fases e tasks com barra de progresso, dependências, destaque do paralelizável e do caminho crítico, bloqueios em evidência.
88
- - **Conformidade com o método** — violações mecanicamente detectáveis pelo frontmatter, cada uma apontando arquivo e linha.
89
- - **Histórico** — linha do tempo de `docs/relatorios/`, com busca por módulo e tipo. O relatório de uso fica em aba própria, com botão de copiar: é o texto que o suporte devolve ao cliente.
90
- - **Fora do schema** — arquivos que não puderam ser lidos, com o motivo. Nunca derrubam o servidor.
518
+ ## A memória do projeto
91
519
 
92
- ## Segurança
520
+ Uma software house resolve o mesmo tipo de problema repetidamente. Bug de arredondamento numa
521
+ faixa de peso hoje; bug parecido no cálculo de comissão em três meses. Quem lembra do primeiro
522
+ resolve o segundo em vinte minutos — e quem não lembra não sabe que deveria perguntar.
93
523
 
94
- O servidor escuta **exclusivamente em `127.0.0.1`**. Não flag, variável de ambiente ou
95
- opção que mude isso: o painel serve documentação interna sem autenticação nenhuma, e expô-la
96
- na rede local entregaria o conteúdo a qualquer um no mesmo Wi-Fi. Todo método HTTP que não
97
- seja `GET` responde `405`.
524
+ A [`memox`](https://github.com/bittencourtthulio/MemoX) resolve isso indexando o que as outras
525
+ skills gravaram. Ela é um **índice invertido**, não uma busca semântica: a pergunta real não
526
+ é "o que é parecido com isto", é "quem mexeu neste arquivo e por quê" — e isso é uma string
527
+ exata. Resposta de índice aponta artefato e data, então dá para abrir e conferir; recuperação
528
+ semântica erra em silêncio, devolvendo algo plausível com a mesma confiança do certo.
98
529
 
99
- ## Desenvolvimento
530
+ O índice fica em `.expx/memoria/indice.json`, é **local e gitignorado**, e se reconstrói do
531
+ zero a qualquer momento:
100
532
 
101
533
  ```bash
102
- npm install
103
- npm test # 89 testes
104
- npm run build # tsc strict + vite
534
+ python3 .claude/skills/memox/assets/memox.py indexar
105
535
  ```
106
536
 
107
- O projeto segue o próprio método que ele exibe. O planejamento inteiro está em
108
- [`docs/expx-panel/`](docs/expx-panel/): base de conhecimento, decisões, plano de sprints,
109
- auditoria e orquestrador. Apontar o painel para o próprio `docs/` deste repositório é o
110
- teste de aceitação mais honesto que existe:
537
+ ### O que o painel mostra
538
+
539
+ A seção **Memória** do painel esse índice e mostra quatro coisas:
540
+
541
+ | Seção | O que responde |
542
+ |---|---|
543
+ | **Arquivos de risco** | quais arquivos acumulam sinal, ordenados por **regressões**, depois reprovações de QA, depois número de trabalhos |
544
+ | **Regressões** | onde um trabalho reabriu o que outro já tinha alterado — com a evidência e os dois artefatos de origem |
545
+ | **Coincidências de arquivo** | vínculos que **não** viraram regressão, com o motivo |
546
+ | **Artefatos contaminados** | onde o memox detectou segredo, para você ir corrigir na origem |
547
+
548
+ A ordenação por regressão, e não por movimento, é deliberada: um arquivo central é tocado por
549
+ dezenas de trabalhos sem nunca ter falhado. Ordenar por contagem colocaria justamente ele no
550
+ topo, enterrando embaixo o arquivo que já quebrou duas vezes.
551
+
552
+ **Coincidência não vira regressão por parecer plausível.** Um vínculo só é registrado como
553
+ regressão quando as três condições valem juntas: um arquivo apontado pela causa raiz do
554
+ trabalho posterior está entre os que o anterior alterou; a ordem cronológica está estabelecida;
555
+ e a causa do posterior é **comprovada**, não hipótese. Faltando qualquer uma, o vínculo aparece
556
+ na tabela de coincidências com o motivo escrito — é isso que impede o sinal mais valioso do
557
+ índice de virar ruído.
558
+
559
+ **Esta seção não respeita o filtro de período**, ao contrário das demais. O valor do sinal é
560
+ justamente o antigo: um arquivo que regrediu há dois anos continua sendo um arquivo que regride.
561
+
562
+ ### Quando não há índice
563
+
564
+ Este é o caso **comum**, não um erro: o índice é local e não vai para o repositório, então um
565
+ clone recém-feito não tem nenhum. A tela mostra o comando que o gera e não reclama de nada. O
566
+ painel nunca invoca o motor — ele é Python, roda fora do painel, e o painel é somente leitura.
567
+
568
+ Índice corrompido (lido no instante em que o motor o reescreve) ou gravado numa versão de
569
+ formato desconhecida cai no mesmo estado: a memória fica vazia, o resto do painel segue
570
+ funcionando. Degradar mostrando, nunca quebrar.
571
+
572
+ ## Segurança e limites
573
+
574
+ - **Nunca pede nem armazena credencial.** Repositório privado usa a credencial de git já
575
+ configurada na máquina.
576
+ - **Nunca escreve fora da raiz do projeto.**
577
+ - **Nunca escreve uma skill.** O CLI busca e empacota; jamais edita conteúdo de skill.
578
+ - **Escrita atômica.** A montagem acontece em pasta temporária e é trocada por `rename` ao
579
+ final: se falhar no meio, o `.expx/` anterior permanece intacto.
580
+ - **O painel é somente leitura**, e escuta apenas em `127.0.0.1`.
581
+ - Toda escrita destrutiva pede confirmação, com flag para pular em ambiente não interativo.
582
+
583
+ ---
584
+
585
+ ## Desenvolvimento
111
586
 
112
587
  ```bash
113
- node dist/cli/principal.js --dir docs
588
+ npm install
589
+ npm test # 295 testes, sem acesso à rede
590
+ npm run typecheck
591
+ npm run build
114
592
  ```
115
593
 
116
- ### Arquitetura
594
+ TypeScript strict + ESM, Node ≥ 20.19, Vitest em três projetos (`servidor`, `ui`, `cli`). A
595
+ suíte roda contra repositórios git locais criados em tempo de teste — nenhum teste depende de
596
+ rede nem do estado do GitHub.
117
597
 
118
- Três camadas, sem regra de negócio vazando para cima:
598
+ Arquitetura em camadas isoladas, uma pasta por responsabilidade. **Nenhuma regra de negócio
599
+ vive no código de linha de comando:**
119
600
 
120
601
  ```
121
- src/parser/ recebe um caminho, devolve objeto tipado + rejeições + violações
122
- src/servidor/ expõe a API de leitura, observa o disco, difunde por websocket
123
- ui/src/ consome a API e renderiza nenhuma regra de negócio aqui
602
+ src/
603
+ nucleo/ catálogo das skills, resolução de versão, busca, layout, lock, integridade
604
+ plugin/ montagem do plugin e dos manifestos, com escrita atômica
605
+ harness/ configuração de Claude Code e OpenCode, merge de settings, backup
606
+ doctor/ os quatorze verificadores e o efeito de cada achado
607
+ update/ comparação com o lock, detecção de modificação local, compatibilidade de schema
608
+ parser/ leitura do expx-schema — frontmatter, kinds, enums, descoberta e conformidade
609
+ e a leitura do índice da memox (memoria/), com falha aberta
610
+ servidor/ o painel: HTTP, websocket e o observador de arquivos (somente leitura)
611
+ cli/ linha de comando: roteamento de subcomando, flags e seleção interativa
612
+ ui/ a interface do painel (React + Vite)
613
+ docs/contrato/ os dois contratos compartilhados pelas seis skills
124
614
  ```
125
615
 
126
- O parser é testável sozinho, contra `fixtures/` em disco: `projeto-ok` cobre os 13 kinds
127
- do contrato; `projeto-ruim` cobre YAML inválido, enum errado, chave ausente, versão de
128
- schema futura, pasta sem orquestrador e task paralelizável com dependência.
616
+ Este projeto foi planejado e executado com o próprio método o plano completo, a base de
617
+ conhecimento e as decisões estão em [`docs/expx-cli/`](docs/expx-cli/), e a integração da
618
+ memória em [`docs/memox-painel/`](docs/memox-painel/).
619
+
620
+ ---
129
621
 
130
- ### O contrato
622
+ ## Licença
623
+
624
+ MIT
625
+
626
+ ---
131
627
 
132
- [`docs/contrato/CONTRATO-expx-schema-v1.md`](docs/contrato/CONTRATO-expx-schema-v1.md) é a
133
- referência do formato. Onde ele diverge do que as skills realmente gravam, o painel segue
134
- as **skills** — elas é que escrevem os arquivos que ele lê. As duas divergências estão
135
- registradas em [`docs/expx-panel/00-DECISOES.md`](docs/expx-panel/00-DECISOES.md) (D-01 e
136
- D-02) e o parser aceita o superconjunto, de modo que nenhum arquivo real se perde seja qual
137
- for o lado que venha a ser atualizado.
628
+ <div align="center">
629
+ <sub>Parte do método <strong>Expx</strong> ·
630
+ expxdev ·
631
+ <a href="https://github.com/bittencourtthulio/sprintx">sprintx</a> ·
632
+ <a href="https://github.com/bittencourtthulio/runx">runx</a> ·
633
+ <a href="https://github.com/bittencourtthulio/legadox">legadox</a> ·
634
+ <a href="https://github.com/bittencourtthulio/stackx">stackx</a> ·
635
+ <a href="https://github.com/bittencourtthulio/mergex">mergex</a></sub>
636
+ </div>