@thiagodiogo/pscode 1.0.0 → 1.0.1
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/README.md +2 -2
- package/dist/cli/index.js +6 -6
- package/dist/commands/config.d.ts +4 -12
- package/dist/commands/config.js +69 -242
- package/dist/core/change-metadata/schema.d.ts +1 -0
- package/dist/core/change-metadata/schema.js +1 -0
- package/dist/core/{archive.d.ts → complete.d.ts} +2 -2
- package/dist/core/{archive.js → complete.js} +28 -5
- package/dist/core/completions/command-registry.js +5 -5
- package/dist/core/config-schema.d.ts +1 -5
- package/dist/core/config-schema.js +2 -5
- package/dist/core/global-config.d.ts +1 -3
- package/dist/core/global-config.js +1 -1
- package/dist/core/init.d.ts +2 -0
- package/dist/core/init.js +81 -20
- package/dist/core/jira-transition.d.ts +16 -0
- package/dist/core/jira-transition.js +29 -0
- package/dist/core/migration.d.ts +3 -12
- package/dist/core/migration.js +10 -72
- package/dist/core/presets/dixi.d.ts +32 -0
- package/dist/core/presets/dixi.js +405 -0
- package/dist/core/profile-sync-drift.js +9 -1
- package/dist/core/profiles.d.ts +23 -21
- package/dist/core/profiles.js +28 -24
- package/dist/core/shared/skill-generation.js +3 -3
- package/dist/core/shared/tool-detection.d.ts +1 -1
- package/dist/core/shared/tool-detection.js +1 -1
- package/dist/core/templates/skill-templates.d.ts +1 -1
- package/dist/core/templates/skill-templates.js +1 -1
- package/dist/core/templates/workflows/apply-change.js +3 -3
- package/dist/core/templates/workflows/archive-change.d.ts +2 -2
- package/dist/core/templates/workflows/archive-change.js +10 -10
- package/dist/core/templates/workflows/onboard.js +9 -9
- package/dist/core/update.d.ts +1 -6
- package/dist/core/update.js +5 -29
- package/dist/core/workspace/foundation.d.ts +1 -1
- package/dist/core/workspace/foundation.js +1 -1
- package/dist/core/workspace/legacy-state.js +1 -1
- package/dist/core/workspace/skills.d.ts +4 -3
- package/dist/core/workspace/skills.js +3 -3
- package/package.json +4 -3
- package/pscode/content/dixi/architectures/feature-sliced-react/eslint-architecture.mjs.template +44 -0
- package/pscode/content/dixi/architectures/feature-sliced-react/features/README.md.template +30 -0
- package/pscode/content/dixi/architectures/feature-sliced-react/skeleton.yaml +8 -0
- package/pscode/content/dixi/architectures/hexagonal-spring/ArchitectureTest.java.template +41 -0
- package/pscode/content/dixi/architectures/hexagonal-spring/skeleton.yaml +11 -0
- package/pscode/content/dixi/claude-runtime/CLAUDE.md.java.template +62 -0
- package/pscode/content/dixi/claude-runtime/CLAUDE.md.react.template +74 -0
- package/pscode/content/dixi/claude-runtime/commands/adr.md +75 -0
- package/pscode/content/dixi/claude-runtime/commands/arch-check.md +64 -0
- package/pscode/content/dixi/claude-runtime/commands/dod.md +66 -0
- package/pscode/content/dixi/claude-runtime/commands/jira-draft.md +80 -0
- package/pscode/content/dixi/claude-runtime/commands/jira-setup.md +105 -0
- package/pscode/content/dixi/claude-runtime/commands/jira-sync.md +69 -0
- package/pscode/content/dixi/claude-runtime/commands/rfc.md +73 -0
- package/pscode/content/dixi/claude-runtime/hooks/arch-guard.mjs +101 -0
- package/pscode/content/dixi/claude-runtime/hooks/jira-context.mjs +60 -0
- package/pscode/content/dixi/claude-runtime/skills/pstld-arch-guardian.md +101 -0
- package/pscode/content/dixi/claude-runtime/skills/pstld-commit-crafter.md +98 -0
- package/pscode/content/dixi/claude-runtime/skills/pstld-jira-context.md +64 -0
- package/pscode/content/dixi/context/java/architecture.md +143 -0
- package/pscode/content/dixi/context/java/naming.md +62 -0
- package/pscode/content/dixi/context/java/testing.md +162 -0
- package/pscode/content/dixi/context/react/architecture.md +119 -0
- package/pscode/content/dixi/context/react/naming.md +129 -0
- package/pscode/content/dixi/context/react/testing.md +141 -0
- package/pscode/content/dixi/context/shared/commits.md +47 -0
- package/pscode/content/dixi/context/shared/dev-flow.md +53 -0
- package/pscode/content/dixi/context/shared/dod.md +38 -0
- package/pscode/content/dixi/context/shared/pr-flow.md +53 -0
- package/pscode/content/dixi/kit/java/.editorconfig +25 -0
- package/pscode/content/dixi/kit/java/.github/workflows/ci-java.yml +68 -0
- package/pscode/content/dixi/kit/java/.husky/commit-msg +2 -0
- package/pscode/content/dixi/kit/react/.editorconfig +20 -0
- package/pscode/content/dixi/kit/react/.github/workflows/ci-react.yml +80 -0
- package/pscode/content/dixi/kit/react/.husky/commit-msg +2 -0
- package/pscode/content/dixi/kit/react/.husky/pre-commit +2 -0
- package/pscode/content/dixi/kit/react/lint-staged.config.mjs +4 -0
- package/pscode/content/dixi/kit/shared/.commitlintrc.yml +15 -0
- package/pscode/content/dixi/kit/shared/.github/pull_request_template.md +24 -0
- package/schemas/pstld-workflow/schema.yaml +67 -0
- package/schemas/pstld-workflow/templates/design.md +15 -0
- package/schemas/pstld-workflow/templates/rfc.md +26 -0
- package/schemas/pstld-workflow/templates/tasks.md +15 -0
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# /pstld:adr — Geração de Architecture Decision Record
|
|
2
|
+
|
|
3
|
+
Você é um arquiteto técnico criando um ADR (Architecture Decision Record) formal para documentar uma decisão arquitetural.
|
|
4
|
+
|
|
5
|
+
## Passos
|
|
6
|
+
|
|
7
|
+
1. **Colete a decisão**
|
|
8
|
+
|
|
9
|
+
Se o usuário descreveu a decisão como argumento, use-a. Caso contrário, pergunte:
|
|
10
|
+
- Qual decisão arquitetural precisa ser documentada?
|
|
11
|
+
- Por que essa decisão está sendo tomada agora?
|
|
12
|
+
- Quais alternativas foram ou poderiam ser consideradas?
|
|
13
|
+
|
|
14
|
+
2. **Contextualize com o projeto** (opcional)
|
|
15
|
+
|
|
16
|
+
- Leia `.pscode-dixi.yaml` se existir para identificar stack e família do projeto.
|
|
17
|
+
- Isso ajuda a formatar o ADR com referências corretas à arquitetura do projeto.
|
|
18
|
+
|
|
19
|
+
3. **Gere o ADR**
|
|
20
|
+
|
|
21
|
+
Crie o documento no seguinte formato:
|
|
22
|
+
|
|
23
|
+
```markdown
|
|
24
|
+
# ADR-NNN: <título descritivo e conciso>
|
|
25
|
+
|
|
26
|
+
**Status:** Aceita | Proposta | Obsoleta | Substituída por ADR-XXX
|
|
27
|
+
**Data:** <data atual>
|
|
28
|
+
**Contexto:** <stack/módulo afetado, se aplicável>
|
|
29
|
+
|
|
30
|
+
## Contexto
|
|
31
|
+
|
|
32
|
+
<Descreve a situação atual, o problema a resolver e as forças em jogo.
|
|
33
|
+
Inclui restrições técnicas, de negócio ou operacionais relevantes.>
|
|
34
|
+
|
|
35
|
+
## Decisão
|
|
36
|
+
|
|
37
|
+
<Enuncia a decisão tomada de forma afirmativa e clara.
|
|
38
|
+
Ex: "Usaremos X para Y porque Z.">
|
|
39
|
+
|
|
40
|
+
## Alternativas Consideradas
|
|
41
|
+
|
|
42
|
+
### Opção A: <nome>
|
|
43
|
+
- **Prós:** ...
|
|
44
|
+
- **Contras:** ...
|
|
45
|
+
|
|
46
|
+
### Opção B: <nome>
|
|
47
|
+
- **Prós:** ...
|
|
48
|
+
- **Contras:** ...
|
|
49
|
+
|
|
50
|
+
## Consequências
|
|
51
|
+
|
|
52
|
+
### Positivas
|
|
53
|
+
- ...
|
|
54
|
+
|
|
55
|
+
### Negativas / Trade-offs
|
|
56
|
+
- ...
|
|
57
|
+
|
|
58
|
+
### Neutras / Observações
|
|
59
|
+
- ...
|
|
60
|
+
|
|
61
|
+
## Referências
|
|
62
|
+
- <links, docs, issues relacionadas>
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
4. **Numbering**
|
|
66
|
+
|
|
67
|
+
Pergunte ao usuário qual número usar para o ADR (ADR-001, ADR-002, etc.) ou sugira verificar o diretório `docs/adr/` para o próximo número disponível.
|
|
68
|
+
|
|
69
|
+
5. **Salvar o arquivo**
|
|
70
|
+
|
|
71
|
+
Pergunte se o usuário quer salvar o ADR em:
|
|
72
|
+
- `docs/adr/ADR-NNN-<slug>.md` (padrão recomendado)
|
|
73
|
+
- Outro local preferido pelo time
|
|
74
|
+
|
|
75
|
+
Se o usuário confirmar, crie o arquivo no local indicado.
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# /pstld:arch-check — Verificação de conformidade arquitetural
|
|
2
|
+
|
|
3
|
+
Você é um guardião de arquitetura verificando se o código atual respeita as regras definidas para o projeto.
|
|
4
|
+
|
|
5
|
+
## Passos
|
|
6
|
+
|
|
7
|
+
1. **Leia o contexto do projeto**
|
|
8
|
+
|
|
9
|
+
- Leia `.pscode-dixi.yaml` na raiz do projeto para determinar `stack` e `family`.
|
|
10
|
+
- Leia `pastelsdd/context/architecture.md` para carregar as regras arquiteturais vigentes.
|
|
11
|
+
- Se `pastelsdd/context/architecture.md` não existir, informe o usuário e sugira `pscode init --profile dixi` para instalar os context docs.
|
|
12
|
+
|
|
13
|
+
2. **Determine o escopo da verificação**
|
|
14
|
+
|
|
15
|
+
Se o usuário especificou um escopo (arquivo, módulo, camada), foque nele.
|
|
16
|
+
Caso contrário, pergunte: verificação pontual (mudança atual) ou varredura ampla (módulo/serviço)?
|
|
17
|
+
|
|
18
|
+
3. **Execute a verificação de acordo com a stack**
|
|
19
|
+
|
|
20
|
+
### Java / Spring (Arquitetura Hexagonal)
|
|
21
|
+
|
|
22
|
+
Verifique as seguintes regras (conforme `pastelsdd/context/architecture.md`):
|
|
23
|
+
|
|
24
|
+
- **Regra de dependência:** `infrastructure → application → domain`. Imports proibidos:
|
|
25
|
+
- `domain.*` importando `application.*` ou `infrastructure.*`
|
|
26
|
+
- `application.*` importando `infrastructure.*`
|
|
27
|
+
- **Nomenclatura por camada:** entidades sem sufixo em `domain/entity/`, use cases em `application/usecase/`, ports em `application/port/in/` e `application/port/out/`, adapters em `infrastructure/adapter/`
|
|
28
|
+
- **Pureza do domínio:** `domain/` sem anotações de framework (Spring, JPA, etc.)
|
|
29
|
+
- **Acesso via interfaces:** adapters acessam `application` somente via ports
|
|
30
|
+
|
|
31
|
+
### React / Next.js (Feature-Sliced Design)
|
|
32
|
+
|
|
33
|
+
Verifique as seguintes regras (conforme `pastelsdd/context/architecture.md`):
|
|
34
|
+
|
|
35
|
+
- **Isolamento de features:** imports cruzados entre features são proibidos (feature A não importa de feature B)
|
|
36
|
+
- **Camadas permitidas:** `app → pages → widgets → features → entities → shared`
|
|
37
|
+
- **Shared é agnóstico:** `shared/` não importa de nenhuma outra camada
|
|
38
|
+
- **Lógica em pages/app:** lógica de negócio inline em `pages/` ou `app/` é um warning
|
|
39
|
+
|
|
40
|
+
### Stack não detectada
|
|
41
|
+
|
|
42
|
+
Execute verificações genéricas: acoplamento excessivo, imports circulares, violações de separação de responsabilidades visíveis no código.
|
|
43
|
+
|
|
44
|
+
4. **Reporte os resultados**
|
|
45
|
+
|
|
46
|
+
```markdown
|
|
47
|
+
## Resultado da Verificação Arquitetural
|
|
48
|
+
|
|
49
|
+
**Stack:** <detectada>
|
|
50
|
+
**Escopo:** <arquivos/módulos analisados>
|
|
51
|
+
|
|
52
|
+
### Violações Encontradas
|
|
53
|
+
| Arquivo | Linha | Regra Violada | Severidade |
|
|
54
|
+
|---------|-------|---------------|------------|
|
|
55
|
+
| ... | ... | ... | ERRO/WARN |
|
|
56
|
+
|
|
57
|
+
### Conformidades Verificadas ✅
|
|
58
|
+
- <regra OK>
|
|
59
|
+
|
|
60
|
+
### Recomendações
|
|
61
|
+
- <ação corretiva para cada violação>
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
5. **Se não houver violações**, confirme que o código está em conformidade com `pastelsdd/context/architecture.md`.
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# /pstld:dod — Verificação de Definition of Done
|
|
2
|
+
|
|
3
|
+
Você é um quality gate verificando se o item de trabalho corrente atende todos os critérios de Definition of Done do projeto.
|
|
4
|
+
|
|
5
|
+
## Passos
|
|
6
|
+
|
|
7
|
+
1. **Leia os critérios de DoD**
|
|
8
|
+
|
|
9
|
+
- Leia `pastelsdd/context/dod.md` para carregar os critérios oficiais de DoD do projeto.
|
|
10
|
+
- Se `pastelsdd/context/dod.md` não existir, informe o usuário:
|
|
11
|
+
```
|
|
12
|
+
ℹ️ Arquivo pastelsdd/context/dod.md não encontrado.
|
|
13
|
+
Execute pscode init --profile dixi para instalar os context docs da Dixi.
|
|
14
|
+
Enquanto isso, usarei critérios genéricos de DoD.
|
|
15
|
+
```
|
|
16
|
+
Use os critérios genéricos listados no passo 3.
|
|
17
|
+
|
|
18
|
+
2. **Identifique o item em progresso**
|
|
19
|
+
|
|
20
|
+
Pergunte ao usuário (se não fornecido como argumento):
|
|
21
|
+
- Qual é o item sendo avaliado? (nome da feature, ticket JIRA, change do pscode)
|
|
22
|
+
- Há contexto adicional relevante (PR aberto, branch, change name)?
|
|
23
|
+
|
|
24
|
+
3. **Verifique cada critério**
|
|
25
|
+
|
|
26
|
+
Para cada critério em `pastelsdd/context/dod.md` (ou os genéricos abaixo), avalie o estado atual:
|
|
27
|
+
|
|
28
|
+
**Critérios genéricos (usados quando dod.md não existe):**
|
|
29
|
+
- Código implementado e funcionando
|
|
30
|
+
- Testes unitários escritos e passando
|
|
31
|
+
- Testes de integração cobrindo o fluxo principal
|
|
32
|
+
- Code review realizado ou solicitado
|
|
33
|
+
- Documentação atualizada (se aplicável)
|
|
34
|
+
- Sem violações de arquitetura detectadas
|
|
35
|
+
- Build passando sem erros
|
|
36
|
+
- Deploy em ambiente de testes validado
|
|
37
|
+
|
|
38
|
+
4. **Produza o relatório de DoD**
|
|
39
|
+
|
|
40
|
+
```markdown
|
|
41
|
+
## Definition of Done — <nome do item>
|
|
42
|
+
|
|
43
|
+
**Data:** <data atual>
|
|
44
|
+
**Fonte dos critérios:** pastelsdd/context/dod.md | critérios genéricos
|
|
45
|
+
|
|
46
|
+
| Critério | Status | Observação |
|
|
47
|
+
|----------|--------|------------|
|
|
48
|
+
| <critério 1> | ✅ Atendido | ... |
|
|
49
|
+
| <critério 2> | ❌ Pendente | <o que falta> |
|
|
50
|
+
| <critério 3> | ⚠️ Parcial | <o que está incompleto> |
|
|
51
|
+
|
|
52
|
+
### Resumo
|
|
53
|
+
- ✅ Atendidos: N
|
|
54
|
+
- ❌ Pendentes: N
|
|
55
|
+
- ⚠️ Parciais: N
|
|
56
|
+
|
|
57
|
+
### Próximos Passos
|
|
58
|
+
<lista das ações necessárias para completar os critérios pendentes>
|
|
59
|
+
|
|
60
|
+
**Conclusão:** ✅ Pronto para entrega | ❌ Não está pronto — N critérios pendentes
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
5. **Orientação final**
|
|
64
|
+
|
|
65
|
+
- Se todos os critérios estiverem atendidos: sugira `/ps:complete` para arquivar a change.
|
|
66
|
+
- Se houver pendências: liste as ações prioritárias para concluir o item.
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# /pstld:jira-draft — Criar rascunho de issue JIRA
|
|
2
|
+
|
|
3
|
+
Você é um assistente de integração JIRA criando uma issue a partir do contexto da change atual.
|
|
4
|
+
|
|
5
|
+
## Passos
|
|
6
|
+
|
|
7
|
+
1. **Leia a configuração JIRA local**
|
|
8
|
+
|
|
9
|
+
Leia o arquivo `pastelsdd/jira.yaml` na raiz do projeto.
|
|
10
|
+
|
|
11
|
+
- **Se o arquivo não existir ou `configured: false`:**
|
|
12
|
+
```
|
|
13
|
+
ℹ️ Integração JIRA não configurada.
|
|
14
|
+
Execute /pstld:jira-setup para configurar o projeto, tipo de issue e transição "done".
|
|
15
|
+
```
|
|
16
|
+
Encerre aqui.
|
|
17
|
+
|
|
18
|
+
2. **Identifique a change ativa**
|
|
19
|
+
|
|
20
|
+
Verifique se há uma change ativa em `pscode/changes/`. Se houver exatamente uma, use-a. Se houver várias, peça ao usuário para especificar. Se não houver nenhuma, solicite título e descrição manualmente.
|
|
21
|
+
|
|
22
|
+
- **Se a change for identificada:** leia `proposal.md` e `.pscode.yaml` para extrair título e contexto.
|
|
23
|
+
- **Se não houver change:** solicite título e descrição ao usuário antes de continuar.
|
|
24
|
+
|
|
25
|
+
3. **Verifique disponibilidade do MCP Atlassian**
|
|
26
|
+
|
|
27
|
+
Tente obter informações do usuário autenticado:
|
|
28
|
+
|
|
29
|
+
```tool
|
|
30
|
+
mcp__atlassian__get_current_user
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
- **Se falhar:**
|
|
34
|
+
```
|
|
35
|
+
⚠️ MCP Atlassian não está disponível nesta sessão.
|
|
36
|
+
Verifique se o servidor MCP está configurado em .mcp.json e reinicie o Claude Code.
|
|
37
|
+
```
|
|
38
|
+
Encerre aqui.
|
|
39
|
+
|
|
40
|
+
4. **Crie a issue JIRA**
|
|
41
|
+
|
|
42
|
+
Use os dados de `jira.yaml` (`projectKey`, `defaultIssueType`) e o contexto da change para criar a issue:
|
|
43
|
+
|
|
44
|
+
```tool
|
|
45
|
+
mcp__atlassian__create_issue
|
|
46
|
+
project: <projectKey de jira.yaml>
|
|
47
|
+
summary: <título da change>
|
|
48
|
+
description: <descrição derivada do proposal.md ou fornecida pelo usuário>
|
|
49
|
+
issuetype: <defaultIssueType de jira.yaml>
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
5. **Vincule a issue à change**
|
|
53
|
+
|
|
54
|
+
Se a issue for criada com sucesso e a change for identificada, grave o `jiraIssueKey` no `.pscode.yaml` da change:
|
|
55
|
+
|
|
56
|
+
- Leia o `.pscode.yaml` atual
|
|
57
|
+
- Adicione ou atualize o campo `jiraIssueKey` com a chave retornada (ex: `PROJ-123`)
|
|
58
|
+
- Salve o arquivo
|
|
59
|
+
|
|
60
|
+
6. **Exiba o resultado**
|
|
61
|
+
|
|
62
|
+
```markdown
|
|
63
|
+
## Issue JIRA Criada ✅
|
|
64
|
+
|
|
65
|
+
**Issue:** <jiraIssueKey>
|
|
66
|
+
**Título:** <summary>
|
|
67
|
+
**Projeto:** <projectKey>
|
|
68
|
+
**Tipo:** <defaultIssueType>
|
|
69
|
+
**Link:** <url da issue>
|
|
70
|
+
|
|
71
|
+
O campo `jiraIssueKey` foi gravado em `.pscode.yaml`.
|
|
72
|
+
Ao executar `pscode complete`, a issue será transitada para "done" automaticamente.
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
7. **Tratamento de erros**
|
|
76
|
+
|
|
77
|
+
Para qualquer falha não coberta acima, exiba uma mensagem descritiva e sugira:
|
|
78
|
+
- Verificar conectividade de rede
|
|
79
|
+
- Confirmar permissões do token Atlassian
|
|
80
|
+
- Verificar `projectKey` e `defaultIssueType` em `pastelsdd/jira.yaml`
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# /pstld:jira-setup — Configurar integração JIRA
|
|
2
|
+
|
|
3
|
+
Você é um assistente de configuração JIRA guiando o desenvolvedor na criação ou atualização de `pastelsdd/jira.yaml`.
|
|
4
|
+
|
|
5
|
+
## Passos
|
|
6
|
+
|
|
7
|
+
1. **Verifique disponibilidade do MCP Atlassian**
|
|
8
|
+
|
|
9
|
+
Tente obter informações do usuário autenticado:
|
|
10
|
+
|
|
11
|
+
```tool
|
|
12
|
+
mcp__atlassian__get_current_user
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
- **Se falhar:**
|
|
16
|
+
```
|
|
17
|
+
⚠️ MCP Atlassian não está disponível nesta sessão.
|
|
18
|
+
Para configurar, adicione ao .mcp.json do projeto:
|
|
19
|
+
|
|
20
|
+
{
|
|
21
|
+
"mcpServers": {
|
|
22
|
+
"atlassian": {
|
|
23
|
+
"command": "npx",
|
|
24
|
+
"args": ["-y", "mcp-remote", "https://mcp.atlassian.com/v1/sse"]
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
Reinicie o Claude Code após adicionar a configuração.
|
|
30
|
+
```
|
|
31
|
+
Encerre aqui.
|
|
32
|
+
|
|
33
|
+
2. **Leia configuração existente (se houver)**
|
|
34
|
+
|
|
35
|
+
Tente ler `pastelsdd/jira.yaml`. Se existir e tiver valores, exiba-os como ponto de partida:
|
|
36
|
+
```
|
|
37
|
+
Configuração atual encontrada:
|
|
38
|
+
Projeto: <projectKey>
|
|
39
|
+
Tipo de issue: <defaultIssueType>
|
|
40
|
+
Transição "done": <transitions.done>
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
3. **Selecione o projeto JIRA**
|
|
44
|
+
|
|
45
|
+
Liste os projetos acessíveis:
|
|
46
|
+
|
|
47
|
+
```tool
|
|
48
|
+
mcp__atlassian__list_projects
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Apresente a lista ao usuário e peça para selecionar o projeto padrão para novas issues.
|
|
52
|
+
Se já houver um `projectKey` configurado, destaque-o como opção atual.
|
|
53
|
+
|
|
54
|
+
4. **Selecione o tipo de issue padrão**
|
|
55
|
+
|
|
56
|
+
Liste os tipos de issue disponíveis para o projeto selecionado:
|
|
57
|
+
|
|
58
|
+
```tool
|
|
59
|
+
mcp__atlassian__get_issue_types
|
|
60
|
+
project: <projectKey selecionado>
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Apresente a lista. O tipo padrão usual é "Story" ou "Task" — destaque se disponível.
|
|
64
|
+
|
|
65
|
+
5. **Selecione a transição "done"**
|
|
66
|
+
|
|
67
|
+
Liste as transições disponíveis no workflow do projeto:
|
|
68
|
+
|
|
69
|
+
```tool
|
|
70
|
+
mcp__atlassian__get_transitions
|
|
71
|
+
project: <projectKey selecionado>
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Apresente as transições e peça ao usuário para identificar qual representa "concluído/done".
|
|
75
|
+
Grave o **ID numérico** da transição escolhida (não o nome, pois IDs são estáveis).
|
|
76
|
+
|
|
77
|
+
6. **Grave pastelsdd/jira.yaml**
|
|
78
|
+
|
|
79
|
+
Crie ou sobrescreva o arquivo com as escolhas:
|
|
80
|
+
|
|
81
|
+
```yaml
|
|
82
|
+
project_key: "<projectKey>"
|
|
83
|
+
default_issue_type: "<defaultIssueType>"
|
|
84
|
+
configured: true
|
|
85
|
+
transitions:
|
|
86
|
+
done: "<ID da transição done>"
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Preserve quaisquer campos adicionais existentes no arquivo que não foram alterados.
|
|
90
|
+
|
|
91
|
+
7. **Exiba resumo da configuração**
|
|
92
|
+
|
|
93
|
+
```markdown
|
|
94
|
+
## Integração JIRA Configurada ✅
|
|
95
|
+
|
|
96
|
+
**Projeto:** <projectKey>
|
|
97
|
+
**Tipo de issue padrão:** <defaultIssueType>
|
|
98
|
+
**Transição "done":** <nome> (ID: <id>)
|
|
99
|
+
|
|
100
|
+
### Próximos passos
|
|
101
|
+
- Use /pstld:jira-draft para criar uma issue JIRA a partir da change atual
|
|
102
|
+
- Adicione `jiraIssueKey` ao .pscode.yaml de uma change para vinculá-la a uma issue existente
|
|
103
|
+
- Ao executar `pscode complete`, a issue vinculada será transitada para "done" automaticamente
|
|
104
|
+
- Use /pstld:jira-sync para verificar a conexão a qualquer momento
|
|
105
|
+
```
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# /pstld:jira-sync — Verificação e sincronização com JIRA
|
|
2
|
+
|
|
3
|
+
Você é um assistente de integração JIRA verificando a configuração e conexão com o projeto atual.
|
|
4
|
+
|
|
5
|
+
## Passos
|
|
6
|
+
|
|
7
|
+
1. **Leia a configuração JIRA local**
|
|
8
|
+
|
|
9
|
+
Leia o arquivo `pastelsdd/jira.yaml` na raiz do projeto.
|
|
10
|
+
|
|
11
|
+
- **Se o arquivo não existir:** informe o usuário de forma amigável:
|
|
12
|
+
```
|
|
13
|
+
ℹ️ Integração JIRA não configurada.
|
|
14
|
+
Para configurar, rode: /pstld:jira-setup
|
|
15
|
+
O arquivo pastelsdd/jira.yaml será criado com suas preferências.
|
|
16
|
+
```
|
|
17
|
+
Encerre aqui.
|
|
18
|
+
|
|
19
|
+
- **Se `configured: false`:** informe:
|
|
20
|
+
```
|
|
21
|
+
⚠️ Integração JIRA presente mas não ativada (configured: false).
|
|
22
|
+
Edite pastelsdd/jira.yaml e defina configured: true após preencher os campos.
|
|
23
|
+
```
|
|
24
|
+
Mostre o conteúdo atual do arquivo para o usuário revisar. Encerre aqui.
|
|
25
|
+
|
|
26
|
+
2. **Teste a conexão via MCP Atlassian**
|
|
27
|
+
|
|
28
|
+
Se `configured: true`, tente obter informações do usuário autenticado:
|
|
29
|
+
|
|
30
|
+
```tool
|
|
31
|
+
mcp__atlassian__get_current_user
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
- **Se o MCP não estiver disponível ou falhar:** informe:
|
|
35
|
+
```
|
|
36
|
+
⚠️ MCP Atlassian não está disponível nesta sessão.
|
|
37
|
+
Verifique se o MCP está configurado em .mcp.json e reinicie o Claude Code.
|
|
38
|
+
Configuração esperada: pastelsdd/jira.yaml → cloudId: <seu-cloud-id>
|
|
39
|
+
```
|
|
40
|
+
Encerre aqui.
|
|
41
|
+
|
|
42
|
+
3. **Exiba o status da integração**
|
|
43
|
+
|
|
44
|
+
Produza um resumo claro:
|
|
45
|
+
|
|
46
|
+
```markdown
|
|
47
|
+
## Status da Integração JIRA ✅
|
|
48
|
+
|
|
49
|
+
**Usuário autenticado:** <nome do usuário>
|
|
50
|
+
**Cloud ID:** <cloudId de pastelsdd/jira.yaml>
|
|
51
|
+
**Projeto padrão:** <projectKey de pastelsdd/jira.yaml>
|
|
52
|
+
**Tipo de issue padrão:** <defaultIssueType>
|
|
53
|
+
|
|
54
|
+
### Verificações
|
|
55
|
+
- ✅ pastelsdd/jira.yaml encontrado e configurado
|
|
56
|
+
- ✅ MCP Atlassian disponível e autenticado
|
|
57
|
+
- ✅ Conexão com JIRA estabelecida
|
|
58
|
+
|
|
59
|
+
### Próximos passos
|
|
60
|
+
- Use /pstld:jira-draft para criar um rascunho de issue JIRA
|
|
61
|
+
- Vincule uma change ao JIRA adicionando jiraIssueKey ao .pscode.yaml
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
4. **Exibição de erros inesperados**
|
|
65
|
+
|
|
66
|
+
Para qualquer falha não coberta acima, mostre uma mensagem descritiva e sugira verificar:
|
|
67
|
+
- A conectividade de rede
|
|
68
|
+
- As permissões do token Atlassian
|
|
69
|
+
- O `cloudId` em `pastelsdd/jira.yaml`
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# /pstld:rfc — Abertura de RFC estruturado
|
|
2
|
+
|
|
3
|
+
Você é um arquiteto técnico conduzindo um processo de RFC (Request for Comments) estruturado para o projeto atual.
|
|
4
|
+
|
|
5
|
+
## Passos
|
|
6
|
+
|
|
7
|
+
1. **Leia o contexto do projeto**
|
|
8
|
+
|
|
9
|
+
- Leia `.pscode-dixi.yaml` na raiz do projeto para determinar `stack` e `family` (java | react | null).
|
|
10
|
+
- Leia `pastelsdd/context/dev-flow.md` para entender o fluxo de desenvolvimento e as etapas do RFC.
|
|
11
|
+
- Se `pastelsdd/context/` não existir, continue com orientações genéricas e informe o usuário que os context docs não estão instalados (sugira `pscode init --profile dixi`).
|
|
12
|
+
|
|
13
|
+
2. **Colete o escopo da mudança**
|
|
14
|
+
|
|
15
|
+
Pergunte ao usuário (se não fornecido como argumento):
|
|
16
|
+
- Qual é o problema ou oportunidade que motiva a mudança?
|
|
17
|
+
- Qual é o escopo estimado (componente, módulo, serviço, cross-cutting)?
|
|
18
|
+
- Há restrições de prazo ou dependências externas?
|
|
19
|
+
|
|
20
|
+
3. **Gere o documento RFC**
|
|
21
|
+
|
|
22
|
+
Produza um documento RFC com a seguinte estrutura:
|
|
23
|
+
|
|
24
|
+
```markdown
|
|
25
|
+
# RFC: <título descritivo>
|
|
26
|
+
|
|
27
|
+
**Status:** Rascunho
|
|
28
|
+
**Autor:** <solicitar ao usuário>
|
|
29
|
+
**Data:** <data atual>
|
|
30
|
+
**Stack:** <detectada via .pscode-dixi.yaml ou "não detectada">
|
|
31
|
+
|
|
32
|
+
## Problema
|
|
33
|
+
<descrição clara do problema ou oportunidade>
|
|
34
|
+
|
|
35
|
+
## Contexto
|
|
36
|
+
<situação atual, histórico relevante, dependências>
|
|
37
|
+
|
|
38
|
+
## Solução Proposta
|
|
39
|
+
<descrição da abordagem escolhida>
|
|
40
|
+
|
|
41
|
+
## Alternativas Consideradas
|
|
42
|
+
| Alternativa | Prós | Contras |
|
|
43
|
+
|-------------|------|---------|
|
|
44
|
+
| ... | ... | ... |
|
|
45
|
+
|
|
46
|
+
## Impacto Arquitetural
|
|
47
|
+
<camadas afetadas, contratos modificados, migrações necessárias>
|
|
48
|
+
<adaptar com base na stack: hexagonal (Java) ou feature-sliced (React) conforme dev-flow.md>
|
|
49
|
+
|
|
50
|
+
## Plano de Implementação
|
|
51
|
+
<fases, dependências, marcos>
|
|
52
|
+
|
|
53
|
+
## Critérios de Aceitação
|
|
54
|
+
- [ ] ...
|
|
55
|
+
|
|
56
|
+
## Riscos
|
|
57
|
+
| Risco | Probabilidade | Mitigação |
|
|
58
|
+
|-------|---------------|-----------|
|
|
59
|
+
| ... | ... | ... |
|
|
60
|
+
|
|
61
|
+
## Referências
|
|
62
|
+
- pastelsdd/context/dev-flow.md
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
4. **Adapte por stack**
|
|
66
|
+
|
|
67
|
+
- **Java/Spring:** mencione impacto em camadas hexagonais (domain/application/infrastructure) e ports afetados.
|
|
68
|
+
- **React/Next:** mencione impacto em features, shared e páginas (feature-sliced).
|
|
69
|
+
- **Null/desconhecida:** use seções genéricas sem referência a padrões específicos.
|
|
70
|
+
|
|
71
|
+
5. **Próximos passos**
|
|
72
|
+
|
|
73
|
+
Ao final, liste as próximas ações: refinamento com o time, criação de change via `pscode propose`, ou implementação direta.
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { readFileSync, existsSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
|
|
4
|
+
function readStdin() {
|
|
5
|
+
try {
|
|
6
|
+
return readFileSync(0, 'utf-8');
|
|
7
|
+
} catch {
|
|
8
|
+
return '';
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const cwd = process.cwd();
|
|
13
|
+
const dixiYamlPath = join(cwd, '.pscode-dixi.yaml');
|
|
14
|
+
|
|
15
|
+
// Gate: exit 0 silently when .pscode-dixi.yaml is absent (non-Dixi projects unaffected)
|
|
16
|
+
if (!existsSync(dixiYamlPath)) {
|
|
17
|
+
process.exit(0);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
let family = null;
|
|
21
|
+
try {
|
|
22
|
+
const yaml = readFileSync(dixiYamlPath, 'utf-8');
|
|
23
|
+
const m = yaml.match(/^family:\s*(\S+)/m);
|
|
24
|
+
if (m) family = m[1].trim();
|
|
25
|
+
} catch {
|
|
26
|
+
process.exit(0);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (family !== 'java' && family !== 'react') {
|
|
30
|
+
process.exit(0);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
let input = {};
|
|
34
|
+
try {
|
|
35
|
+
const raw = readStdin();
|
|
36
|
+
if (raw.trim()) input = JSON.parse(raw);
|
|
37
|
+
} catch {
|
|
38
|
+
process.exit(0);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const toolInput = input.tool_input ?? {};
|
|
42
|
+
const rawFilePath = String(toolInput.file_path ?? '');
|
|
43
|
+
const newContent = String(toolInput.new_string ?? toolInput.content ?? '');
|
|
44
|
+
const filePath = rawFilePath.replace(/\\/g, '/');
|
|
45
|
+
|
|
46
|
+
if (family === 'java') {
|
|
47
|
+
// Check files in src/**/infrastructure/**
|
|
48
|
+
if (/\/infrastructure\//.test(filePath)) {
|
|
49
|
+
const importLines = newContent.split('\n').filter(l => /^\s*import\s+/.test(l));
|
|
50
|
+
// Violation: import from domain.* but NOT domain.port.*
|
|
51
|
+
const hasDirectDomainImport = importLines.some(
|
|
52
|
+
l => /\.domain\./.test(l) && !/\.domain\.port/.test(l)
|
|
53
|
+
);
|
|
54
|
+
if (hasDirectDomainImport) {
|
|
55
|
+
process.stdout.write(
|
|
56
|
+
`Violação hexagonal: ${rawFilePath} importa diretamente de domain sem porta. Consulte pastelsdd/context/architecture.md\n`
|
|
57
|
+
);
|
|
58
|
+
process.exit(2);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
process.exit(0);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (family === 'react') {
|
|
65
|
+
// Cross-feature import check for files in src/features/**
|
|
66
|
+
const featureMatch = filePath.match(/\/features\/([^/]+)/);
|
|
67
|
+
if (featureMatch) {
|
|
68
|
+
const currentFeature = featureMatch[1];
|
|
69
|
+
const importRegex = /from\s+['"]([^'"]+)['"]/g;
|
|
70
|
+
let m;
|
|
71
|
+
while ((m = importRegex.exec(newContent)) !== null) {
|
|
72
|
+
const importPath = m[1];
|
|
73
|
+
const featureInImport = importPath.match(/features\/([^/']+)/);
|
|
74
|
+
if (featureInImport && featureInImport[1] !== currentFeature) {
|
|
75
|
+
process.stdout.write(
|
|
76
|
+
`Violação feature-sliced: importação cruzada entre features. Consulte pastelsdd/context/architecture.md\n`
|
|
77
|
+
);
|
|
78
|
+
process.exit(2);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Warning: combined useState+useEffect with large body in src/app/** or src/pages/**
|
|
84
|
+
if (/\/(app|pages)\//.test(filePath)) {
|
|
85
|
+
const lines = newContent.split('\n');
|
|
86
|
+
if (
|
|
87
|
+
lines.length > 10 &&
|
|
88
|
+
/useState/.test(newContent) &&
|
|
89
|
+
/useEffect/.test(newContent)
|
|
90
|
+
) {
|
|
91
|
+
process.stdout.write(
|
|
92
|
+
`Aviso: lógica inline detectada em page/app. Considere extrair para um hook ou service.\n`
|
|
93
|
+
);
|
|
94
|
+
process.exit(1);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
process.exit(0);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
process.exit(0);
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { readFileSync, existsSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
|
|
4
|
+
function readStdin() {
|
|
5
|
+
try {
|
|
6
|
+
return readFileSync(0, 'utf-8');
|
|
7
|
+
} catch {
|
|
8
|
+
return '';
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const cwd = process.cwd();
|
|
13
|
+
|
|
14
|
+
let input = {};
|
|
15
|
+
try {
|
|
16
|
+
const raw = readStdin();
|
|
17
|
+
if (raw.trim()) input = JSON.parse(raw);
|
|
18
|
+
} catch {
|
|
19
|
+
process.exit(0);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const prompt = String(input.prompt ?? '');
|
|
23
|
+
const ticketMatch = prompt.match(/[A-Z]+-\d+/);
|
|
24
|
+
if (!ticketMatch) {
|
|
25
|
+
process.exit(0);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const jiraYamlPath = join(cwd, 'pastelsdd', 'jira.yaml');
|
|
29
|
+
if (!existsSync(jiraYamlPath)) {
|
|
30
|
+
process.exit(0);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
let jiraContent = '';
|
|
34
|
+
try {
|
|
35
|
+
jiraContent = readFileSync(jiraYamlPath, 'utf-8');
|
|
36
|
+
} catch {
|
|
37
|
+
process.exit(0);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const projectKeyMatch = jiraContent.match(/^project_key:\s*(\S+)/m);
|
|
41
|
+
if (!projectKeyMatch) {
|
|
42
|
+
process.exit(0);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const ticket = ticketMatch[0];
|
|
46
|
+
const projectKey = projectKeyMatch[1];
|
|
47
|
+
const boardUrlMatch = jiraContent.match(/^board_url:\s*(.+)/m);
|
|
48
|
+
const boardUrl = boardUrlMatch ? boardUrlMatch[1].trim() : null;
|
|
49
|
+
|
|
50
|
+
const lines = [
|
|
51
|
+
`[Contexto JIRA]`,
|
|
52
|
+
`Ticket detectado: ${ticket}`,
|
|
53
|
+
`Projeto: ${projectKey}`,
|
|
54
|
+
];
|
|
55
|
+
if (boardUrl) {
|
|
56
|
+
lines.push(`Board: ${boardUrl}`);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
process.stdout.write(lines.join('\n') + '\n');
|
|
60
|
+
process.exit(0);
|