ganbatte-os 0.2.41 → 0.2.43

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 (78) hide show
  1. package/.gos/README.md +2 -6
  2. package/.gos/agents/profiles/ganbatte-os-master.md +91 -58
  3. package/.gos/agents/profiles/index.json +3 -1
  4. package/.gos/agents/profiles/perf-optimizer.md +10 -0
  5. package/.gos/agents/profiles/po.md +1 -1
  6. package/.gos/agents/profiles/security-auditor.md +11 -0
  7. package/.gos/agents/profiles/sm.md +4 -4
  8. package/.gos/agents/profiles/squad-creator.md +2 -2
  9. package/.gos/config.json +23 -2
  10. package/.gos/docs/curation.md +8 -6
  11. package/.gos/docs/gos_installation_guide.md +1 -1
  12. package/.gos/docs/plan-distribuicao-publica.md +2 -3
  13. package/.gos/docs/toolchain-map.md +2 -2
  14. package/.gos/libraries/doc-sync-policy.md +31 -0
  15. package/.gos/libraries/lazy-dev-policy.md +38 -0
  16. package/.gos/libraries/lucide-icons-policy.md +1 -1
  17. package/.gos/libraries/performance-audit-playbook.md +54 -0
  18. package/.gos/libraries/security-audit-playbook.md +63 -0
  19. package/.gos/manifests/g-os-runtime-manifest.json +29 -8
  20. package/.gos/playbooks/plan-creation-playbook.md +3 -5
  21. package/.gos/prompts/01-search.md +2 -2
  22. package/.gos/prompts/03-tasks.md +4 -4
  23. package/.gos/prompts/05-reviews.md +1 -1
  24. package/.gos/scripts/cli/gos-cli.js +16 -0
  25. package/.gos/scripts/hooks/claude-stop-summary.js +0 -16
  26. package/.gos/scripts/integrations/check-plan.js +15 -5
  27. package/.gos/scripts/integrations/setup-ide-adapters.js +72 -75
  28. package/.gos/scripts/tools/model-router.js +122 -0
  29. package/.gos/skills/execute-plan/SKILL.md +37 -23
  30. package/.gos/skills/perf-review/SKILL.md +58 -0
  31. package/.gos/skills/plan-blueprint/SKILL.md +26 -26
  32. package/.gos/skills/plan-to-tasks/SKILL.md +4 -1
  33. package/.gos/skills/progress-tracker/SKILL.md +3 -3
  34. package/.gos/skills/registry.json +3 -4
  35. package/.gos/skills/security-review/SKILL.md +59 -0
  36. package/.gos/skills/simplify-review/SKILL.md +59 -0
  37. package/.gos/skills/validate-plan/SKILL.md +29 -30
  38. package/.gos/squads/code-quality/README.md +20 -0
  39. package/.gos/squads/code-quality/squad.yaml +32 -0
  40. package/.gos/squads/code-quality/workflows/wf-code-quality.yaml +19 -0
  41. package/.gos/squads/design-delivery/README.md +1 -1
  42. package/.gos/squads/design-delivery/squad.yaml +4 -3
  43. package/.gos/squads/design-delivery/workflows/wf-design-delivery.yaml +6 -6
  44. package/.gos/templates/planTemplate.md +14 -5
  45. package/.gos/templates/specTemplate.md +68 -0
  46. package/.gos/templates/taskTemplate.md +8 -5
  47. package/AGENTS.md +30 -40
  48. package/CLAUDE.md +36 -14
  49. package/GEMINI.md +11 -5
  50. package/LICENSE +1 -1
  51. package/README.md +74 -442
  52. package/package.json +2 -3
  53. package/.gos/docs/slack-notifications.md +0 -219
  54. package/.gos/playbooks/sprint-planner-playbook.md +0 -127
  55. package/.gos/scripts/hooks/post-commit-notify.js +0 -175
  56. package/.gos/scripts/tools/clickup-preprocess.js +0 -218
  57. package/.gos/scripts/tools/clickup.js +0 -1058
  58. package/.gos/scripts/tools/slack-notify.js +0 -271
  59. package/.gos/skills/clickup/SKILL.md +0 -151
  60. package/.gos/skills/slack-review/SKILL.md +0 -91
  61. package/.gos/skills/sprint-planner/SKILL.md +0 -434
  62. package/.gos/skills/weekly-update/CHANGELOG.md +0 -165
  63. package/.gos/skills/weekly-update/SKILL.md +0 -361
  64. package/.gos/squads/sprint-planning/agents/sprint-chief.md +0 -47
  65. package/.gos/squads/sprint-planning/agents/sprint-planner-agent.md +0 -43
  66. package/.gos/squads/sprint-planning/agents/sprint-tracker.md +0 -43
  67. package/.gos/squads/sprint-planning/agents/task-importer.md +0 -44
  68. package/.gos/squads/sprint-planning/checklists/sprint-readiness.md +0 -27
  69. package/.gos/squads/sprint-planning/config/config.yaml +0 -65
  70. package/.gos/squads/sprint-planning/data/clickup-field-mapping.yaml +0 -94
  71. package/.gos/squads/sprint-planning/squad.yaml +0 -52
  72. package/.gos/squads/sprint-planning/tasks/close-sprint.md +0 -43
  73. package/.gos/squads/sprint-planning/tasks/create-sprint.md +0 -42
  74. package/.gos/squads/sprint-planning/tasks/import-tasks.md +0 -39
  75. package/.gos/squads/sprint-planning/tasks/sync-status.md +0 -31
  76. package/.gos/squads/sprint-planning/workflows/wf-sprint-creation.yaml +0 -59
  77. package/.gos/squads/sprint-planning/workflows/wf-sprint-sync.yaml +0 -35
  78. package/.gos/templates/sprint-clickup.template.md +0 -80
@@ -1,271 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- // slack-notify.js — Slack notification tool (zero-dep)
4
- // Usage: node slack-notify.js <command> [--options]
5
- // Auth:
6
- // - Webhook commands (send, task-done, sprint-summary): SLACK_WEBHOOK_URL
7
- // - Web API commands (fetch-thread, find-thread): SLACK_BOT_TOKEN
8
-
9
- const WEBHOOK_URL = process.env.SLACK_WEBHOOK_URL
10
- const BOT_TOKEN = process.env.SLACK_BOT_TOKEN
11
-
12
- function parseArgs(argv) {
13
- const result = { _: [] }
14
- for (let i = 0; i < argv.length; i++) {
15
- const arg = argv[i]
16
- if (arg.startsWith('--')) {
17
- const key = arg.slice(2)
18
- const next = argv[i + 1]
19
- if (next && !next.startsWith('--')) {
20
- result[key] = next
21
- i++
22
- } else {
23
- result[key] = true
24
- }
25
- } else {
26
- result._.push(arg)
27
- }
28
- }
29
- return result
30
- }
31
-
32
- const args = parseArgs(process.argv.slice(2))
33
- const [cmd, sub, ...rest] = args._
34
-
35
- const WEBHOOK_COMMANDS = new Set(['send', 'task-done', 'sprint-summary'])
36
- const API_COMMANDS = new Set(['fetch-thread', 'find-thread'])
37
-
38
- if (WEBHOOK_COMMANDS.has(cmd) && !WEBHOOK_URL) {
39
- console.log(JSON.stringify({ skipped: true, reason: 'SLACK_WEBHOOK_URL not set' }))
40
- process.exit(0)
41
- }
42
-
43
- if (API_COMMANDS.has(cmd) && !BOT_TOKEN) {
44
- console.log(JSON.stringify({ error: 'SLACK_BOT_TOKEN not set (required for Web API commands)' }))
45
- process.exit(0)
46
- }
47
-
48
- async function sendWebhook(payload) {
49
- if (args['dry-run']) {
50
- return { _dry_run: true, url: WEBHOOK_URL.replace(/\/[^/]{6,}$/, '/***'), payload }
51
- }
52
-
53
- const res = await fetch(WEBHOOK_URL, {
54
- method: 'POST',
55
- headers: { 'Content-Type': 'application/json' },
56
- body: JSON.stringify(payload),
57
- })
58
-
59
- const text = await res.text()
60
- if (res.ok) {
61
- return { sent: true, status: res.status }
62
- }
63
- return { sent: false, status: res.status, body: text }
64
- }
65
-
66
- async function slackApi(method, params) {
67
- if (args['dry-run']) {
68
- return { _dry_run: true, method, params: { ...params, token: '***' } }
69
- }
70
- const body = new URLSearchParams(params).toString()
71
- const res = await fetch(`https://slack.com/api/${method}`, {
72
- method: 'POST',
73
- headers: {
74
- 'Content-Type': 'application/x-www-form-urlencoded',
75
- 'Authorization': `Bearer ${BOT_TOKEN}`,
76
- },
77
- body,
78
- })
79
- return res.json()
80
- }
81
-
82
- function escapeSlack(text) {
83
- return text.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;')
84
- }
85
-
86
- function buildTaskDonePayload(taskId, commit, author, extra = {}) {
87
- const sprint = extra.sprint || ''
88
- const track = extra.track || ''
89
- const message = extra.message || ''
90
-
91
- const lines = [`*:white_check_mark: Task Concluída*`]
92
- lines.push(`>*Task:* ${escapeSlack(taskId)}${message ? ` — ${escapeSlack(message)}` : ''}`)
93
- if (sprint) lines.push(`>*Sprint:* ${escapeSlack(sprint)}`)
94
- if (track) lines.push(`>*Track:* ${escapeSlack(track)}`)
95
- lines.push(`>*Commit:* \`${escapeSlack(commit.slice(0, 7))}\`${message ? ` — ${escapeSlack(message)}` : ''}`)
96
- lines.push(`>*Author:* ${escapeSlack(author)}`)
97
-
98
- return { text: lines.join('\n') }
99
- }
100
-
101
- function buildSprintSummaryPayload(data) {
102
- const summary = data.summary || data
103
- const name = data.sprint?.name || data.name || 'Sprint'
104
- const now = Math.floor(Date.now() / 1000)
105
-
106
- return {
107
- blocks: [
108
- {
109
- type: 'header',
110
- text: { type: 'plain_text', text: `:bar_chart: ${name} — Status Update` }
111
- },
112
- {
113
- type: 'section',
114
- fields: [
115
- { type: 'mrkdwn', text: `*Total:*\n${summary.totalTasks || 0} tasks` },
116
- { type: 'mrkdwn', text: `*Done:*\n${summary.done || 0} (${summary.completionPct || 0}%)` }
117
- ]
118
- },
119
- {
120
- type: 'section',
121
- fields: [
122
- { type: 'mrkdwn', text: `*In Progress:*\n${summary.inProgress || 0}` },
123
- { type: 'mrkdwn', text: `*Blocked:*\n${summary.blocked || 0}` }
124
- ]
125
- },
126
- { type: 'divider' },
127
- {
128
- type: 'context',
129
- elements: [
130
- { type: 'mrkdwn', text: `Updated: <!date^${now}^{date_short} {time}|${new Date().toISOString()}>` }
131
- ]
132
- }
133
- ]
134
- }
135
- }
136
-
137
- async function main() {
138
- let result
139
-
140
- switch (cmd) {
141
- case 'send': {
142
- if (args.text) {
143
- result = await sendWebhook({ text: args.text })
144
- } else if (args['blocks-file']) {
145
- const { readFileSync } = require('node:fs')
146
- try {
147
- const payload = JSON.parse(readFileSync(args['blocks-file'], 'utf-8'))
148
- result = await sendWebhook(payload)
149
- } catch (e) {
150
- result = { error: `Failed to read ${args['blocks-file']}: ${e.message}` }
151
- }
152
- } else {
153
- result = { error: '--text or --blocks-file required' }
154
- }
155
- break
156
- }
157
-
158
- case 'task-done': {
159
- if (!args.task || !args.commit || !args.author) {
160
- result = { error: '--task, --commit, and --author required' }; break
161
- }
162
- const payload = buildTaskDonePayload(args.task, args.commit, args.author, {
163
- sprint: args.sprint,
164
- track: args.track,
165
- message: args.message,
166
- })
167
- result = await sendWebhook(payload)
168
- break
169
- }
170
-
171
- case 'sprint-summary': {
172
- if (!args.file) { result = { error: '--file (sprint status JSON) required' }; break }
173
- const { readFileSync } = require('node:fs')
174
- try {
175
- const data = JSON.parse(readFileSync(args.file, 'utf-8'))
176
- const payload = buildSprintSummaryPayload(data)
177
- result = await sendWebhook(payload)
178
- } catch (e) {
179
- result = { error: `Failed to read ${args.file}: ${e.message}` }
180
- }
181
- break
182
- }
183
-
184
- case 'fetch-thread': {
185
- const channel = args['channel-id'] || process.env.SLACK_CHANNEL_ID_WEEKLY
186
- const ts = args['thread-ts'] || args.ts
187
- if (!channel || !ts) {
188
- result = { error: '--channel-id (or SLACK_CHANNEL_ID_WEEKLY) and --thread-ts required' }
189
- break
190
- }
191
- const limit = args.limit || '100'
192
- const api = await slackApi('conversations.replies', { channel, ts, limit })
193
- if (!api.ok) {
194
- result = { ok: false, error: api.error, needed: api.needed }
195
- break
196
- }
197
- const messages = (api.messages || []).map(m => ({
198
- user: m.user,
199
- ts: m.ts,
200
- text: m.text || '',
201
- reply_count: m.reply_count,
202
- }))
203
- result = { ok: true, count: messages.length, messages }
204
- break
205
- }
206
-
207
- case 'find-thread': {
208
- const channel = args['channel-id'] || process.env.SLACK_CHANNEL_ID_WEEKLY
209
- const pattern = args.pattern
210
- if (!channel || !pattern) {
211
- result = { error: '--channel-id (or SLACK_CHANNEL_ID_WEEKLY) and --pattern required' }
212
- break
213
- }
214
- const api = await slackApi('conversations.history', { channel, limit: args.limit || '50' })
215
- if (!api.ok) {
216
- result = { ok: false, error: api.error, needed: api.needed }
217
- break
218
- }
219
- const re = new RegExp(pattern, 'i')
220
- const match = (api.messages || []).find(m => re.test(m.text || ''))
221
- if (!match) {
222
- result = { found: false }
223
- break
224
- }
225
- result = {
226
- found: true,
227
- ts: match.ts,
228
- text_preview: (match.text || '').slice(0, 200),
229
- }
230
- break
231
- }
232
-
233
- default:
234
- result = {
235
- error: cmd ? `Unknown command: ${cmd}` : 'No command provided',
236
- usage: {
237
- send: 'send --text "Hello *bold* _italic_" | send --blocks-file payload.json',
238
- 'task-done': 'task-done --task T-001 --commit abc1234 --author "Name" [--sprint "S01"] [--track backend] [--message "feat: ..."]',
239
- 'sprint-summary': 'sprint-summary --file sprint-status.json',
240
- 'fetch-thread': 'fetch-thread --channel-id C... --thread-ts 1234567890.123456 [--limit 100]',
241
- 'find-thread': 'find-thread --channel-id C... --pattern "regex" [--limit 50]',
242
- },
243
- auth: {
244
- webhook_commands: 'send, task-done, sprint-summary — require SLACK_WEBHOOK_URL',
245
- api_commands: 'fetch-thread, find-thread — require SLACK_BOT_TOKEN (scopes: groups:history for private channels)',
246
- },
247
- formatting: {
248
- bold: '*text*',
249
- italic: '_text_',
250
- strike: '~text~',
251
- code: '`code`',
252
- codeBlock: '```multi-line```',
253
- quote: '>quoted text',
254
- link: '<url|display text>',
255
- mention: '<@USER_ID>',
256
- channel: '<#CHANNEL_ID>',
257
- date: '<!date^UNIX_TS^{date_short} {time}|fallback>',
258
- },
259
- flags: {
260
- '--dry-run': 'Show payload without sending',
261
- }
262
- }
263
- }
264
-
265
- console.log(JSON.stringify(result, null, 2))
266
- }
267
-
268
- main().catch(err => {
269
- console.error(JSON.stringify({ error: err.message }))
270
- process.exit(0) // Always exit 0 — notification failure should never block
271
- })
@@ -1,151 +0,0 @@
1
- ---
2
- name: clickup
3
- description: >
4
- Manage ClickUp workspace, sprints (via folders), lists, tasks, subtasks and custom fields
5
- via MCP. Create and sync sprints, import tasks from markdown plans, track sprint status.
6
- description_pt-BR: >
7
- Gerenciar workspace, sprints (via folders), lists, tasks, subtasks e custom fields no
8
- ClickUp via MCP. Criar e sincronizar sprints, importar tasks de planos markdown, acompanhar status.
9
- argument-hint: "[e.g. 'criar sprint S04 com tasks do plano']"
10
- type: prompt
11
- version: "2.0.0"
12
- env:
13
- - CLICKUP_TRANSPORT
14
- categories: [project-management, tasks, sprint, agile, clickup]
15
- allowedTools: [Read, Glob, Grep, Write, Edit, AskUserQuestion, mcp__clickup__*]
16
- use-when:
17
- - criar sprint no ClickUp a partir de plano ou markdown
18
- - sincronizar stories/tasks locais com ClickUp
19
- - consultar status de sprint ou tasks no ClickUp
20
- - importar tasks de sprint-track markdown para ClickUp
21
- - listar workspaces, spaces, folders, lists
22
- - marcar task como concluida no ClickUp
23
- - criar subtasks
24
- do-not-use-for:
25
- - planejamento de sprint do zero (use /sprint-planner primeiro)
26
- - criacao de stories sem plano aprovado (use @sm ou @po)
27
- - hotfix ou ajuste pontual sem necessidade de sync
28
- - gantt charts ou burndown (nao disponivel via API)
29
- metadata:
30
- category: integration
31
- version: 2.0.0
32
- ---
33
-
34
- # clickup
35
-
36
- Voce esta executando a skill `clickup`. Transport: **MCP only**.
37
-
38
- ## Task
39
-
40
- $ARGUMENTS
41
-
42
- Se nenhum argumento foi fornecido, pergunte ao usuario o que deseja fazer.
43
-
44
- ## MCP Tools
45
-
46
- Todas as operacoes usam tools `mcp__clickup__*` (OAuth via MCP server).
47
-
48
- ### Discovery
49
-
50
- - Listar hierarchy: `clickup_get_workspace_hierarchy`
51
- - Buscar tasks: `clickup_search` com keywords
52
- - Filtrar tasks: `clickup_filter_tasks` com list_ids, assignees, statuses
53
- - Resolver assignees: `clickup_resolve_assignees` (nome/email -> user ID)
54
-
55
- ### Sprint (Folder + List)
56
-
57
- Sprints sao modelados como Folders no ClickUp:
58
-
59
- 1. Criar folder: `clickup_create_folder` com `space_id` e nome
60
- 2. Criar list: `clickup_create_list_in_folder` com `folder_id`
61
-
62
- Convencao de nomes:
63
- - Folder: `S04 -- Fractus: Fase 2a Coleta Templates`
64
- - List: `Backlog`
65
-
66
- ### Task Operations
67
-
68
- - **Criar:** `clickup_create_task` com `list_id`, `name`, `markdown_description`, `priority`, `assignees`, `start_date`, `due_date`
69
- - **Atualizar:** `clickup_update_task` com `task_id` + campos a alterar
70
- - **Subtask:** `clickup_create_task` com `parent` (task ID pai)
71
- - **Tags:** `clickup_add_tag_to_task`
72
- - **Dependencias:** `clickup_add_task_dependency`, `clickup_add_task_link`
73
- - **Comentarios:** `clickup_create_task_comment`
74
- - **Mover:** `clickup_move_task`
75
-
76
- ### Capabilities adicionais
77
-
78
- - Time tracking: `clickup_start_time_tracking`, `clickup_stop_time_tracking`, `clickup_add_time_entry`
79
- - Docs: `clickup_create_document`, `clickup_create_document_page`, `clickup_update_document_page`
80
- - Chat: `clickup_send_chat_message`, `clickup_get_chat_channels`
81
-
82
- ### Limitacoes do MCP
83
-
84
- O MCP nao suporta:
85
- - Checklist nativa (criar/editar)
86
- - Delete de folder
87
- - Delete de task
88
- - Create de tag (tag precisa existir no space)
89
-
90
- ## Regras de Formatacao
91
-
92
- Ao criar ou atualizar tasks no ClickUp via MCP, seguir:
93
-
94
- ### Descricao
95
-
96
- 1. **Idioma:** Secoes em portugues com acentos
97
- 2. **Sem emojis:** Nunca usar emojis/icones nos headers ou corpo
98
- 3. **Headers H3:** Usar `###` para secoes (nao H1 ou H2)
99
- 4. **Descricao primeiro:** Texto livre no topo, sem header proprio
100
- 5. **Separador:** `---` entre descricao e secoes estruturadas
101
- 6. **Formatacao inline:**
102
- - Arquivos em backticks: `` `lib/prisma.ts` ``
103
- - Business rules em backticks separados por ` . `: `` `BR-TPL-001` . `BR-TPL-002` ``
104
- - Criterios de aceite como checkboxes: `- [ ] Descricao do criterio`
105
- 7. **Ordem das secoes:** Regras de Negocio -> Arquivos -> Criterios de Aceite
106
- 8. **Usar `markdown_description`** (nao `description`) ao chamar `update_task` ou `create_task`
107
-
108
- ### Subtasks -- quando usar
109
-
110
- | Recurso | Quando usar | Exemplo |
111
- |---------|------------|---------|
112
- | **Subtask** | Trabalho decomponivel com status e assignee proprios | Cada endpoint de uma API CRUD, cada step de um wizard |
113
- | **Criterios na descricao** | Itens verificaveis sem workflow proprio | `- [ ] Testes passando`, `- [ ] Migration sem erros` |
114
-
115
- ### Template de referencia
116
-
117
- ```markdown
118
- Texto livre da descricao aqui.
119
-
120
- ---
121
-
122
- ### Regras de Negocio
123
- `BR-TPL-001` . `BR-TPL-002`
124
-
125
- ### Arquivos
126
- - `app/api/route.ts`
127
- - `lib/prisma.ts`
128
-
129
- ### Criterios de Aceite
130
- - [ ] Primeiro criterio
131
- - [ ] Segundo criterio
132
- ```
133
-
134
- ## Pre-processamento de Texto
135
-
136
- O script `scripts/tools/clickup-preprocess.js` pode ser usado para sanitizar textos antes de enviar ao MCP:
137
-
138
- ```bash
139
- echo '{"description":"texto","acceptanceCriteria":["item1"]}' | node scripts/tools/clickup-preprocess.js --json
140
- ```
141
-
142
- Output inclui `description` formatado com todas as secoes. Usar o campo `description` do output como `markdown_description` no MCP.
143
-
144
- No modo MCP direto (sem script), aplicar as mesmas regras manualmente.
145
-
146
- ## Error Handling
147
-
148
- - **Rate limit (429):** MCP retenta automaticamente
149
- - **Auth error:** Chamar `clickup_authenticate` para iniciar OAuth
150
- - **Not found (404):** Verificar IDs de space/folder/list/task
151
- - **Team not authorized:** Re-autenticar via `clickup_authenticate`
@@ -1,91 +0,0 @@
1
- ---
2
- name: slack-review
3
- description: Revisar, editar e aprovar drafts de notificações Slack pendentes em .gos/slack-queue/. Use quando o usuário pedir para "revisar notificações", "aprovar Slack", "enviar notificações pendentes" ou após commits que dispararam o hook post-commit-sync.
4
- argument-hint: "[opcional: id específico, --flush, --reject-all]"
5
- use-when:
6
- - usuário pediu para revisar/aprovar notificações Slack pendentes
7
- - após commit em branch com hook post-commit-sync instalado
8
- - fila .gos/slack-queue/ tem drafts pendentes
9
- - preciso enviar atualização de task para o Slack com aprovação humana
10
- do-not-use-for:
11
- - envio imediato sem revisão (use `node slack-notify.js --send-now`)
12
- - textos longos (propostas, emails) — use /humanizer primeiro
13
- - drafts em canal custom sem webhook configurado
14
- metadata:
15
- category: workflow
16
- version: "1.0.0"
17
- ---
18
-
19
- # Skill: /slack-review — Aprovar notificações Slack
20
-
21
- Revisar drafts enfileirados por `post-commit-sync.js` antes de enviar ao Slack. Aprovar, editar inline ou rejeitar cada um.
22
-
23
- ## Quando usar
24
-
25
- - Depois de um commit com `T-NNN` no message — hook enfileira draft em `.gos/slack-queue/`.
26
- - Usuário pediu para revisar ou aprovar notificações pendentes.
27
- - Antes de push/deploy quando vários commits foram feitos e é preciso consolidar notificações.
28
-
29
- ## Pré-requisitos
30
-
31
- - `SLACK_WEBHOOK_URL` configurado em `.env` na raiz.
32
- - Fila em `.gos/slack-queue/` existe (criada automaticamente pelo hook).
33
-
34
- ## Fluxo
35
-
36
- ### 1. Listar pendentes
37
-
38
- ```bash
39
- node .gos/scripts/tools/slack-queue.js list
40
- ```
41
-
42
- Saída esperada: lista de drafts com id, task, commit, author e primeira linha do payload.
43
-
44
- Se vazio → informar usuário e encerrar.
45
-
46
- ### 2. Iterar cada draft
47
-
48
- Para cada draft pendente:
49
-
50
- 1. Mostrar preview via `node .gos/scripts/tools/slack-queue.js show <id>`.
51
- 2. Renderizar o `payload.text` em bloco markdown para o usuário ver.
52
- 3. Via `AskUserQuestion`, perguntar: **aprovar · editar · rejeitar · pular**.
53
-
54
- ### 3. Ações
55
-
56
- - **Aprovar**: `node .gos/scripts/tools/slack-queue.js approve <id>` — envia e move para `sent/`.
57
- - **Editar**: propor reescrita do texto (aplicar princípios do `/humanizer` mentalmente se o texto tiver padrões IA residuais). Mostrar diff, pedir confirmação. Salvar via editar o JSON direto ou chamar `slack-queue.js edit <id>` (abre $EDITOR).
58
- - **Rejeitar**: `node .gos/scripts/tools/slack-queue.js reject <id> [--reason "..."]` — move para `rejected/`.
59
- - **Pular**: deixa pendente para próxima run.
60
-
61
- ### 4. Atalhos
62
-
63
- - `node .gos/scripts/tools/slack-queue.js flush` — aprova todos pendentes de uma vez (só usar quando já revisou visualmente e tem certeza).
64
- - `node .gos/scripts/tools/slack-queue.js list --json` — saída JSON para processamento programático.
65
-
66
- ## Exemplos
67
-
68
- ### Exemplo 1 — Revisão simples
69
-
70
- Usuário: "Revisa as notificações Slack pendentes"
71
-
72
- 1. `slack-queue.js list` → 2 drafts (T-110, T-082).
73
- 2. Para T-110: mostrar preview, perguntar. Usuário aprova → `approve`.
74
- 3. Para T-082: mostrar preview, usuário pede para editar "Commit: wip" → propor "Commit: progresso inicial", confirmar, aplicar, approve.
75
-
76
- ### Exemplo 2 — Edição com humanização leve
77
-
78
- Preview traz "Task concluida aprimorando a validacao". O `text-sanitize.js` já teria corrigido isso, mas se escapou (ex: texto veio via `send --text` sem pipeline), propor reescrita: "Task concluída: validação melhorada". Confirmar com usuário.
79
-
80
- ## Troubleshooting
81
-
82
- - **"SLACK_WEBHOOK_URL não configurado"** no approve: checar `.env` na raiz, recarregar env.
83
- - **Draft preso em pending após approve**: verificar se `sent/` foi criado e o arquivo foi movido. Se falhou no POST, ver status no output JSON.
84
- - **Lista vazia mas esperava drafts**: confirmar que commit usou `T-NNN` e hook rodou (`ls .git/hooks/post-commit`). Ver [docs/slack-notifications.md](../docs/slack-notifications.md).
85
-
86
- ## Referências
87
-
88
- - Pipeline completo: `.gos/docs/slack-notifications.md`
89
- - CLI: `.gos/scripts/tools/slack-queue.js`
90
- - Sanitização: `.gos/scripts/tools/text-sanitize.js`
91
- - Payload builders: `.gos/scripts/tools/slack-notify.js`