spec-first-claude 0.5.0-beta.18 → 0.5.0-beta.19

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spec-first-claude",
3
- "version": "0.5.0-beta.18",
3
+ "version": "0.5.0-beta.19",
4
4
  "description": "Spec-first workflow kit for Claude Code — AI-driven development with specs, not guesswork",
5
5
  "bin": {
6
6
  "spec-first-claude": "bin/cli.js"
@@ -121,3 +121,12 @@ status: "design_done"
121
121
  ultima_skill: "/design"
122
122
  atualizado_em: "{{ISO_DATETIME}}"
123
123
  ```
124
+
125
+ ### 9. Publicar SDD no(s) backend(s)
126
+
127
+ Se existe `sfw.config.yml` com `output.targets[]` ativo:
128
+ - Executar `/publish $ARGUMENTS SDD`
129
+ - O `/publish` respeita o `mode` (auto/manual/off) de cada target
130
+ - Se não existe `sfw.config.yml` → pular silenciosamente
131
+
132
+ Ver `.claude/commands/publish.md`.
@@ -122,6 +122,15 @@ ultima_skill: "/extract"
122
122
  atualizado_em: "{{ISO_DATETIME}}"
123
123
  ```
124
124
 
125
+ ### 7. Publicar artefato no(s) backend(s)
126
+
127
+ Se existe `sfw.config.yml` com `output.targets[]` ativo:
128
+ - Executar `/publish $ARGUMENTS TRD` (setup) ou `/publish $ARGUMENTS PRD` (feature)
129
+ - O `/publish` respeita o `mode` (auto/manual/off) de cada target
130
+ - Se não existe `sfw.config.yml` → pular silenciosamente (projeto 100% local)
131
+
132
+ Ver `.claude/commands/publish.md`.
133
+
125
134
  ## Re-extração
126
135
  - Merge ADITIVO com documento existente (nunca remove info de inalterados)
127
136
  - Seções afetadas marcadas com `<!-- ATUALIZADO: re-extração -->`
@@ -88,6 +88,16 @@ status: "plan_done"
88
88
  ultima_skill: "/plan"
89
89
  ```
90
90
 
91
+ ### 7. Publicar Progresso no(s) backend(s)
92
+
93
+ Se existe `sfw.config.yml` com `output.targets[]` ativo:
94
+ - Executar `/publish $ARGUMENTS Progresso`
95
+ - O `/publish` respeita o `mode` (auto/manual/off) de cada target
96
+ - Se não existe `sfw.config.yml` → pular silenciosamente
97
+ - **Nota**: `tasks.md`, `specs/`, `docs/`, `projetos.yaml` são LOCAL ONLY — nunca publicados
98
+
99
+ Ver `.claude/commands/publish.md`.
100
+
91
101
  ## Saídas
92
102
  - `specs/{nome}/tasks.md` — tabela única
93
103
  - `workspace/Output/{nome}/Progresso.md` — tracking
@@ -0,0 +1,144 @@
1
+ # /publish <nome> <tipo>
2
+
3
+ Publica um artefato gerado localmente no(s) backend(s) configurado(s) como `output.targets[]` no `sfw.config.yml`.
4
+
5
+ ## Argumentos
6
+
7
+ - `<nome>` = scope do artefato (ex: `app_barbearia`, `feat_login`)
8
+ - `<tipo>` = tipo do artefato: `PRD` | `TRD` | `SDD` | `Progresso`
9
+
10
+ ## Quando é chamado
11
+
12
+ Automaticamente pelos commands:
13
+ - `/extract` → publica `TRD` ou `PRD` no fim
14
+ - `/design` → publica `SDD` no fim
15
+ - `/plan` → publica `Progresso` no fim
16
+
17
+ Manualmente: quando o usuário quer re-publicar um artefato após editar local.
18
+
19
+ ## Modo (`mode` no sfw.config.yml)
20
+
21
+ | Mode | Comportamento |
22
+ |------|---------------|
23
+ | `auto` | Publica sem perguntar (default) |
24
+ | `manual` | Gera artefato local, pergunta "Publicar no {target.name}? (s/n)" |
25
+ | `off` | Ignora o target completamente |
26
+
27
+ ## Pré-condições
28
+
29
+ | # | Validação | Se falhar |
30
+ |---|-----------|-----------|
31
+ | 1 | `sfw.config.yml` existe | Parar → "Sem sfw.config.yml, publish desabilitado. Artefato local está em workspace/Output/{nome}/{tipo}.md" |
32
+ | 2 | Tipo está na `publishes` do target | Pular target, informar |
33
+ | 3 | Arquivo local existe em `workspace/Output/{nome}/{tipo}.md` (ou .lower) | Parar → "Arquivo não encontrado" |
34
+
35
+ ## Execução
36
+
37
+ ### 1. Carregar configuração
38
+
39
+ - Ler `sfw.config.yml`
40
+ - Para cada target em `output.targets[]`:
41
+ - Verificar `mode` (se `off` → pular)
42
+ - Verificar `publishes` inclui `<tipo>` (se não → pular)
43
+ - Se `mode: manual` → perguntar ao usuário
44
+
45
+ ### 2. Ler artefato local
46
+
47
+ Ler `workspace/Output/{nome}/{arquivo}` onde arquivo depende do tipo:
48
+ - `TRD` → `TRD.md`
49
+ - `PRD` → `PRD.md`
50
+ - `SDD` → `sdd.md`
51
+ - `Progresso` → `Progresso.md`
52
+
53
+ ### 3. Aplicar naming
54
+
55
+ Usar templates do `naming` no `sfw.config.yml`:
56
+ - `containerTitle = applyNaming(naming.output_container, {scope: nome})`
57
+ - Ex: `"out_app_barbearia"`
58
+ - `artifactTitle = applyNaming(naming.output_artifact, {scope: nome, type: tipo})`
59
+ - Ex: `"app_barbearia - TRD"`
60
+
61
+ ### 4. Para cada target ativo — publicar
62
+
63
+ **Confluence**:
64
+
65
+ 1. Listar filhos de `target.config.parent_page_id` (Output)
66
+ 2. Buscar container pelo `containerTitle`:
67
+ - **Não existe** → `mcp__atlassian__confluence_create_page` como filho de Output
68
+ - **Existe** → pegar `container.id`
69
+ 3. Listar filhos do container
70
+ 4. Buscar artefato pelo `artifactTitle`:
71
+ - **Não existe** → `mcp__atlassian__confluence_create_page` com `content=markdown local`
72
+ - **Existe** → precisa atualizar (próximo passo)
73
+
74
+ ### 5. Conflict detection (update)
75
+
76
+ Se artefato existe no backend:
77
+
78
+ 1. Ler `.ai/publish-log.md` pra pegar a última `version` publicada desse artefato
79
+ 2. Chamar `mcp__atlassian__confluence_get_page(page_id=artifact.id)` → pega `currentVersion`
80
+ 3. **Se `currentVersion != lastPublishedVersion`** → DRIFT detectado
81
+ - Alguém editou no Confluence depois do último publish
82
+ - Mostrar ao usuário:
83
+ ```
84
+ CONFLITO: "{artifactTitle}" foi editada no Confluence desde o último publish.
85
+
86
+ Última version publicada por nós: {last}
87
+ Version atual no Confluence: {current}
88
+
89
+ Opções:
90
+ 1. Sobrescrever (perde edição manual)
91
+ 2. Abortar (edita local depois)
92
+ 3. Ver diff
93
+ ```
94
+ - Esperar decisão
95
+ 4. Se sem drift → `mcp__atlassian__confluence_update_page(page_id, content)`
96
+ 5. Ler nova `version` retornada
97
+
98
+ ### 6. Registrar em `.ai/publish-log.md`
99
+
100
+ Formato append-only:
101
+
102
+ ```markdown
103
+ ## Publish: {nome} {tipo} — {ISO_DATETIME}
104
+
105
+ | Target | Container | Artifact ID | Version | Status |
106
+ |--------|-----------|-------------|---------|--------|
107
+ | confluence-mirror | out_app_barbearia (393220) | 393238 | 3 | UPDATED |
108
+ ```
109
+
110
+ Status: `CREATED`, `UPDATED`, `SKIPPED` (se INALTERADO), `CONFLICT` (se drift não resolvido)
111
+
112
+ ### 7. Informar o usuário
113
+
114
+ ```
115
+ Publicado: {nome} {tipo}
116
+
117
+ confluence-mirror: app_barbearia - TRD (v3) — UPDATED
118
+
119
+ Link: https://empresa.atlassian.net/wiki/spaces/ST/pages/393238
120
+ ```
121
+
122
+ ## Erros
123
+
124
+ | Erro | Ação |
125
+ |------|------|
126
+ | `sfw.config.yml` não existe | Skippa todos os targets, só salva local |
127
+ | Target MCP não disponível | Avisar, pular target |
128
+ | Sem permissão de escrita | Avisar, pular target |
129
+ | Conflict não resolvido | Não publicar, salvar como CONFLICT no log |
130
+ | Container Output não existe | Criar automaticamente como filho de `output.parent_page_id` |
131
+
132
+ ## Notas
133
+
134
+ - O `/publish` é **idempotente** pra content sem mudanças — detecta hash igual e marca `SKIPPED`
135
+ - `naming.output_container` e `naming.output_artifact` são aplicados em TODOS os targets
136
+ - Cada target pode ter `publishes: []` diferente (permite segmentar: Confluence recebe 4 artefatos, filesystem recebe todos)
137
+ - `.ai/publish-log.md` é essencial pro conflict detection funcionar
138
+ - Nunca publica tasks.md, docs/, specs/, projetos.yaml — esses são LOCAL ONLY
139
+
140
+ ## Referências
141
+
142
+ - Adapter interface: `.claude/adapters/interface.md`
143
+ - Confluence adapter: `.claude/adapters/confluence.md`
144
+ - Naming engine: `.claude/adapters/naming.md`
@@ -20,12 +20,13 @@
20
20
 
21
21
  ### 2. Validar acesso a todos commands
22
22
 
23
- Verificar que TODOS os 11 commands estão acessíveis:
23
+ Verificar que TODOS os 12 commands estão acessíveis:
24
24
 
25
25
  | Command | Caminho |
26
26
  |---------|---------|
27
27
  | `/mcp` | `.claude/commands/mcp.md` |
28
28
  | `/load` | `.claude/commands/load.md` |
29
+ | `/publish` | `.claude/commands/publish.md` |
29
30
  | `/new-project` | `.claude/commands/new-project.md` |
30
31
  | `/feature` | `.claude/commands/feature.md` |
31
32
  | `/discovery` | `.claude/commands/discovery.md` |
@@ -97,7 +98,8 @@ ESTE REPO (projeto-base) = ORQUESTRADOR
97
98
  | Command | Tipo | O que faz |
98
99
  |---------|------|-----------|
99
100
  | `/mcp <provider>` | Setup | Configura backend externo interativamente. Cria .mcp.json + sfw.config.yml + ajusta .gitignore |
100
- | `/load <nome>` | Utilitária | Puxa insumos do backend (Confluence/filesystem) para workspace/Input/{nome}/. Incremental |
101
+ | `/load <nome> \| --all` | Utilitária | Puxa Input + Output do backend. Incremental |
102
+ | `/publish <nome> <tipo>` | Utilitária | Publica artefato (PRD/TRD/SDD/Progresso) nos output.targets[]. Chamado auto por extract/design/plan |
101
103
  | `/new-project <nome>` | Orquestrador | Bootstrap técnico: cria .context.md tipo TRD, chama /extract, para no checkpoint |
102
104
  | `/feature <nome>` | Orquestrador | Feature: cria .context.md tipo PRD, chama /extract, para no checkpoint |
103
105
  | `/discovery <path>` | Utilitária | Análise profunda dos insumos (RECOMENDADO antes do /extract) |