create-genia-os 2.1.0 → 2.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 (89) hide show
  1. package/README.md +154 -106
  2. package/bin/index.js +240 -240
  3. package/package.json +42 -37
  4. package/template/.claude/CLAUDE.md +215 -215
  5. package/template/.claude/agent-memory/analyst/MEMORY.md +20 -20
  6. package/template/.claude/agent-memory/architect/MEMORY.md +20 -20
  7. package/template/.claude/agent-memory/dev/MEMORY.md +20 -20
  8. package/template/.claude/agent-memory/devops/MEMORY.md +20 -20
  9. package/template/.claude/agent-memory/pm/MEMORY.md +20 -20
  10. package/template/.claude/agent-memory/po/MEMORY.md +20 -20
  11. package/template/.claude/agent-memory/qa/MEMORY.md +20 -20
  12. package/template/.claude/agent-memory/reviewer/MEMORY.md +20 -20
  13. package/template/.claude/agent-memory/sm/MEMORY.md +20 -20
  14. package/template/.claude/hooks/enforce-git-push-authority.py +70 -70
  15. package/template/.claude/hooks/metrics-tracker.cjs +65 -0
  16. package/template/.claude/hooks/precompact-session-digest.cjs +87 -87
  17. package/template/.claude/hooks/sql-governance.py +65 -65
  18. package/template/.claude/hooks/synapse-engine.cjs +122 -122
  19. package/template/.claude/hooks/write-path-validation.py +59 -59
  20. package/template/.claude/rules/agent-authority.md +39 -39
  21. package/template/.claude/rules/agent-handoff.md +71 -71
  22. package/template/.claude/rules/agent-memory.md +61 -61
  23. package/template/.claude/rules/ids-principles.md +52 -52
  24. package/template/.claude/rules/mcp-usage.md +49 -49
  25. package/template/.claude/rules/new-project.md +157 -0
  26. package/template/.claude/rules/story-lifecycle.md +87 -87
  27. package/template/.claude/rules/workflow-execution.md +68 -68
  28. package/template/.claude/settings.json +58 -58
  29. package/template/.claude/settings.local.json +14 -14
  30. package/template/.genia/CONSTITUTION.md +129 -129
  31. package/template/.genia/contexts/api-patterns.md +134 -134
  32. package/template/.genia/contexts/nextjs-react.md +210 -210
  33. package/template/.genia/contexts/projeto.md +18 -18
  34. package/template/.genia/contexts/supabase.md +152 -152
  35. package/template/.genia/contexts/whatsapp-cloud.md +176 -176
  36. package/template/.genia/core-config.yaml +192 -192
  37. package/template/.genia/development/agents/analyst.md +138 -138
  38. package/template/.genia/development/agents/architect.md +171 -171
  39. package/template/.genia/development/agents/dev.md +160 -160
  40. package/template/.genia/development/agents/devops.md +200 -200
  41. package/template/.genia/development/agents/pm.md +142 -142
  42. package/template/.genia/development/agents/po.md +165 -165
  43. package/template/.genia/development/agents/qa.md +183 -183
  44. package/template/.genia/development/agents/reviewer.md +198 -198
  45. package/template/.genia/development/agents/sm.md +230 -230
  46. package/template/.genia/development/checklists/architecture-review.md +189 -189
  47. package/template/.genia/development/checklists/pre-commit.md +205 -205
  48. package/template/.genia/development/checklists/pre-deploy.md +230 -230
  49. package/template/.genia/development/checklists/qa-gate.md +216 -216
  50. package/template/.genia/development/checklists/story-dod.md +155 -155
  51. package/template/.genia/development/tasks/code-review.md +197 -197
  52. package/template/.genia/development/tasks/criar-prd.md +170 -170
  53. package/template/.genia/development/tasks/criar-spec.md +188 -188
  54. package/template/.genia/development/tasks/criar-story.md +185 -185
  55. package/template/.genia/development/tasks/debug-sistematico.md +230 -230
  56. package/template/.genia/development/tasks/dev-implement.md +199 -199
  57. package/template/.genia/development/tasks/qa-review.md +224 -224
  58. package/template/.genia/development/workflows/brownfield.md +178 -178
  59. package/template/.genia/development/workflows/delivery.md +208 -208
  60. package/template/.genia/development/workflows/development.md +189 -189
  61. package/template/.genia/development/workflows/greenfield.md +166 -166
  62. package/template/.genia/development/workflows/planning.md +167 -167
  63. package/template/.genia/development/workflows/qa-loop.md +179 -179
  64. package/template/.genia/development/workflows/spec-pipeline.md +192 -192
  65. package/template/.genia/development/workflows/story-development-cycle.md +252 -252
  66. package/template/.genia/guidelines/clean-code.md +98 -98
  67. package/template/.genia/guidelines/testing.md +176 -176
  68. package/template/.genia/skills/design/canvas-design.md +109 -109
  69. package/template/.genia/skills/design/frontend-design.md +140 -140
  70. package/template/.genia/skills/dev/mcp-builder.md +172 -172
  71. package/template/.genia/skills/dev/webapp-testing.md +150 -150
  72. package/template/.genia/skills/documents/docx.md +153 -153
  73. package/template/.genia/skills/documents/pdf.md +134 -134
  74. package/template/.genia/skills/documents/pptx.md +118 -118
  75. package/template/.genia/skills/documents/xlsx.md +140 -140
  76. package/template/.synapse/agent-analyst +8 -8
  77. package/template/.synapse/agent-architect +8 -8
  78. package/template/.synapse/agent-dev +8 -8
  79. package/template/.synapse/agent-devops +8 -8
  80. package/template/.synapse/agent-pm +8 -8
  81. package/template/.synapse/agent-po +7 -7
  82. package/template/.synapse/agent-qa +8 -8
  83. package/template/.synapse/agent-reviewer +7 -7
  84. package/template/.synapse/agent-sm +7 -7
  85. package/template/.synapse/constitution +7 -7
  86. package/template/.synapse/context +8 -8
  87. package/template/.synapse/global +8 -8
  88. package/template/.synapse/manifest +14 -14
  89. package/template/README.md +53 -53
@@ -1,20 +1,20 @@
1
- # MEMORY — @po (Pax)
2
- > Product Owner — {PROJECT_NAME}
3
- > Última atualização: {SETUP_DATE}
4
-
5
- ## Padrões Confirmados
6
-
7
- _Nenhum ainda._
8
-
9
- ## Preferências da Usuária
10
-
11
- - Idioma: {LANGUAGE}
12
- - Projeto: {PROJECT_NAME}
13
-
14
- ## Regra Crítica
15
-
16
- Story com menos de 8/10 pontos no checklist = REJEITADA.
17
-
18
- ## Gotchas
19
-
20
- _Nenhum ainda._
1
+ # MEMORY — @po (Pax)
2
+ > Product Owner — {PROJECT_NAME}
3
+ > Última atualização: {SETUP_DATE}
4
+
5
+ ## Padrões Confirmados
6
+
7
+ _Nenhum ainda._
8
+
9
+ ## Preferências da Usuária
10
+
11
+ - Idioma: {LANGUAGE}
12
+ - Projeto: {PROJECT_NAME}
13
+
14
+ ## Regra Crítica
15
+
16
+ Story com menos de 8/10 pontos no checklist = REJEITADA.
17
+
18
+ ## Gotchas
19
+
20
+ _Nenhum ainda._
@@ -1,20 +1,20 @@
1
- # MEMORY — @qa (Quinn)
2
- > QA Engineer — {PROJECT_NAME}
3
- > Última atualização: {SETUP_DATE}
4
-
5
- ## Padrões Confirmados
6
-
7
- _Nenhum ainda._
8
-
9
- ## Preferências da Usuária
10
-
11
- - Idioma: {LANGUAGE}
12
- - Projeto: {PROJECT_NAME}
13
-
14
- ## Regra Crítica
15
-
16
- Veredicto de qualidade é final. Aprovação obrigatória antes de @reviewer.
17
-
18
- ## Gotchas
19
-
20
- _Nenhum ainda._
1
+ # MEMORY — @qa (Quinn)
2
+ > QA Engineer — {PROJECT_NAME}
3
+ > Última atualização: {SETUP_DATE}
4
+
5
+ ## Padrões Confirmados
6
+
7
+ _Nenhum ainda._
8
+
9
+ ## Preferências da Usuária
10
+
11
+ - Idioma: {LANGUAGE}
12
+ - Projeto: {PROJECT_NAME}
13
+
14
+ ## Regra Crítica
15
+
16
+ Veredicto de qualidade é final. Aprovação obrigatória antes de @reviewer.
17
+
18
+ ## Gotchas
19
+
20
+ _Nenhum ainda._
@@ -1,20 +1,20 @@
1
- # MEMORY — @reviewer (Rev)
2
- > Code Reviewer — {PROJECT_NAME}
3
- > Última atualização: {SETUP_DATE}
4
-
5
- ## Padrões Confirmados
6
-
7
- _Nenhum ainda._
8
-
9
- ## Preferências da Usuária
10
-
11
- - Idioma: {LANGUAGE}
12
- - Projeto: {PROJECT_NAME}
13
-
14
- ## Regra Crítica
15
-
16
- LGTM ou CHANGES REQUESTED. Sem meio-termo.
17
-
18
- ## Gotchas
19
-
20
- _Nenhum ainda._
1
+ # MEMORY — @reviewer (Rev)
2
+ > Code Reviewer — {PROJECT_NAME}
3
+ > Última atualização: {SETUP_DATE}
4
+
5
+ ## Padrões Confirmados
6
+
7
+ _Nenhum ainda._
8
+
9
+ ## Preferências da Usuária
10
+
11
+ - Idioma: {LANGUAGE}
12
+ - Projeto: {PROJECT_NAME}
13
+
14
+ ## Regra Crítica
15
+
16
+ LGTM ou CHANGES REQUESTED. Sem meio-termo.
17
+
18
+ ## Gotchas
19
+
20
+ _Nenhum ainda._
@@ -1,20 +1,20 @@
1
- # MEMORY — @sm (Sami)
2
- > Scrum Master — {PROJECT_NAME}
3
- > Última atualização: {SETUP_DATE}
4
-
5
- ## Padrões Confirmados
6
-
7
- _Nenhum ainda._
8
-
9
- ## Preferências da Usuária
10
-
11
- - Idioma: {LANGUAGE}
12
- - Projeto: {PROJECT_NAME}
13
-
14
- ## Regra Crítica
15
-
16
- Único agente que cria STORY-*.md. Toda story vai para @po antes de @dev.
17
-
18
- ## Gotchas
19
-
20
- _Nenhum ainda._
1
+ # MEMORY — @sm (Sami)
2
+ > Scrum Master — {PROJECT_NAME}
3
+ > Última atualização: {SETUP_DATE}
4
+
5
+ ## Padrões Confirmados
6
+
7
+ _Nenhum ainda._
8
+
9
+ ## Preferências da Usuária
10
+
11
+ - Idioma: {LANGUAGE}
12
+ - Projeto: {PROJECT_NAME}
13
+
14
+ ## Regra Crítica
15
+
16
+ Único agente que cria STORY-*.md. Toda story vai para @po antes de @dev.
17
+
18
+ ## Gotchas
19
+
20
+ _Nenhum ainda._
@@ -1,70 +1,70 @@
1
- #!/usr/bin/env python3
2
- """
3
- GEN.IA OS — Hook: enforce-git-push-authority
4
- Trigger: PreToolUse (Bash)
5
- Ação: Bloqueia git push por agentes não-devops.
6
- Permite push quando @devops está autorizado via flag file.
7
- Artigo II da Constituição GEN.IA OS — NÃO-NEGOCIÁVEL.
8
-
9
- Protocolo de autorização:
10
- 1. Claude pergunta à usuária se quer invocar @devops
11
- 2. Se sim, @devops cria .genia/session/devops-active
12
- 3. Este hook lê o flag e permite o push (uma única vez)
13
- 4. Flag é removido automaticamente após uso
14
- """
15
- import json
16
- import os
17
- import sys
18
- import re
19
-
20
-
21
- PUSH_PATTERNS = [
22
- r"\bgit\s+push\b",
23
- r"\bgit\s+push\s+--force\b",
24
- r"\bgit\s+push\s+-f\b",
25
- r"\bgit\s+push\s+-u\b",
26
- ]
27
-
28
- FLAG_FILE = ".genia/session/devops-active"
29
-
30
-
31
- def main():
32
- try:
33
- raw = sys.stdin.read()
34
- data = json.loads(raw)
35
- except Exception:
36
- sys.exit(0)
37
-
38
- tool = data.get("tool_name", "")
39
- if tool != "Bash":
40
- sys.exit(0)
41
-
42
- command = data.get("tool_input", {}).get("command", "")
43
-
44
- for pattern in PUSH_PATTERNS:
45
- if re.search(pattern, command, re.IGNORECASE):
46
- # Verificar se @devops foi autorizado via flag file
47
- if os.path.exists(FLAG_FILE):
48
- try:
49
- os.remove(FLAG_FILE) # Consumir o flag (uso único)
50
- except Exception:
51
- pass
52
- print(
53
- "[GEN.IA OS] ✅ @devops (Gate) autorizado — executando push.",
54
- file=sys.stderr,
55
- )
56
- sys.exit(0) # Permitir
57
-
58
- # Sem autorização — bloquear
59
- print(
60
- "[GEN.IA OS] 🚫 BLOQUEADO — Artigo II: Apenas @devops pode executar git push.\n"
61
- "[GEN.IA OS] Diga: '@devops faça o push' para invocar Gate.",
62
- file=sys.stderr,
63
- )
64
- sys.exit(2) # exit 2 = BLOCK no Claude Code
65
-
66
- sys.exit(0)
67
-
68
-
69
- if __name__ == "__main__":
70
- main()
1
+ #!/usr/bin/env python3
2
+ """
3
+ GEN.IA OS — Hook: enforce-git-push-authority
4
+ Trigger: PreToolUse (Bash)
5
+ Ação: Bloqueia git push por agentes não-devops.
6
+ Permite push quando @devops está autorizado via flag file.
7
+ Artigo II da Constituição GEN.IA OS — NÃO-NEGOCIÁVEL.
8
+
9
+ Protocolo de autorização:
10
+ 1. Claude pergunta à usuária se quer invocar @devops
11
+ 2. Se sim, @devops cria .genia/session/devops-active
12
+ 3. Este hook lê o flag e permite o push (uma única vez)
13
+ 4. Flag é removido automaticamente após uso
14
+ """
15
+ import json
16
+ import os
17
+ import sys
18
+ import re
19
+
20
+
21
+ PUSH_PATTERNS = [
22
+ r"\bgit\s+push\b",
23
+ r"\bgit\s+push\s+--force\b",
24
+ r"\bgit\s+push\s+-f\b",
25
+ r"\bgit\s+push\s+-u\b",
26
+ ]
27
+
28
+ FLAG_FILE = ".genia/session/devops-active"
29
+
30
+
31
+ def main():
32
+ try:
33
+ raw = sys.stdin.read()
34
+ data = json.loads(raw)
35
+ except Exception:
36
+ sys.exit(0)
37
+
38
+ tool = data.get("tool_name", "")
39
+ if tool != "Bash":
40
+ sys.exit(0)
41
+
42
+ command = data.get("tool_input", {}).get("command", "")
43
+
44
+ for pattern in PUSH_PATTERNS:
45
+ if re.search(pattern, command, re.IGNORECASE):
46
+ # Verificar se @devops foi autorizado via flag file
47
+ if os.path.exists(FLAG_FILE):
48
+ try:
49
+ os.remove(FLAG_FILE) # Consumir o flag (uso único)
50
+ except Exception:
51
+ pass
52
+ print(
53
+ "[GEN.IA OS] ✅ @devops (Gate) autorizado — executando push.",
54
+ file=sys.stderr,
55
+ )
56
+ sys.exit(0) # Permitir
57
+
58
+ # Sem autorização — bloquear
59
+ print(
60
+ "[GEN.IA OS] 🚫 BLOQUEADO — Artigo II: Apenas @devops pode executar git push.\n"
61
+ "[GEN.IA OS] Diga: '@devops faça o push' para invocar Gate.",
62
+ file=sys.stderr,
63
+ )
64
+ sys.exit(2) # exit 2 = BLOCK no Claude Code
65
+
66
+ sys.exit(0)
67
+
68
+
69
+ if __name__ == "__main__":
70
+ main()
@@ -0,0 +1,65 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ /**
5
+ * GEN.IA OS — Metrics Tracker
6
+ * Trigger: PostToolUse(Write)
7
+ *
8
+ * Registra eventos de story e agente em .genia/metrics/YYYY-MM.jsonl
9
+ * Falha silenciosa — NUNCA bloqueia o fluxo principal.
10
+ */
11
+
12
+ const fs = require('fs');
13
+ const path = require('path');
14
+
15
+ const METRICS_DIR = path.join('.genia', 'metrics');
16
+
17
+ function getMetricsPath() {
18
+ const now = new Date();
19
+ const ym = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}`;
20
+ return path.join(METRICS_DIR, `${ym}.jsonl`);
21
+ }
22
+
23
+ function appendMetric(entry) {
24
+ fs.mkdirSync(METRICS_DIR, { recursive: true });
25
+ fs.appendFileSync(getMetricsPath(), JSON.stringify(entry) + '\n', 'utf8');
26
+ }
27
+
28
+ function extractField(content, field) {
29
+ const match = content.match(new RegExp(`\\*\\*${field}:\\*\\*\\s*(\\S+)`));
30
+ return match ? match[1] : null;
31
+ }
32
+
33
+ function extractStoryNumber(filePath) {
34
+ const match = path.basename(filePath).match(/STORY-(\d+)/i);
35
+ return match ? `STORY-${match[1]}` : null;
36
+ }
37
+
38
+ async function main() {
39
+ let raw = '';
40
+ for await (const chunk of process.stdin) raw += chunk;
41
+
42
+ const data = JSON.parse(raw);
43
+ const filePath = (data.tool_input || {}).file_path || '';
44
+
45
+ // Só processar STORY-*.md
46
+ if (!filePath.match(/STORY-\d+.*\.md$/i)) return;
47
+
48
+ const content = (data.tool_input || {}).content || '';
49
+ const story = extractStoryNumber(filePath);
50
+ const status = extractField(content, 'Status');
51
+ const agent = extractField(content, 'Agente');
52
+
53
+ if (!story || !status) return;
54
+
55
+ appendMetric({
56
+ ts: new Date().toISOString(),
57
+ event: 'story_update',
58
+ story,
59
+ status,
60
+ agent: agent || 'unknown',
61
+ file: path.basename(filePath),
62
+ });
63
+ }
64
+
65
+ main().catch(() => process.exit(0)); // Falha silenciosa
@@ -1,87 +1,87 @@
1
- #!/usr/bin/env node
2
- /**
3
- * GEN.IA OS — Session Digest
4
- * Trigger: PreCompact
5
- *
6
- * Salva um resumo da sessão antes do Claude compactar o contexto.
7
- * Preserva memória institucional entre sessões longas.
8
- * Inspirado no AIOS precompact-session-digest (MIT License, SynkraAI)
9
- */
10
-
11
- 'use strict';
12
-
13
- const fs = require('fs');
14
- const path = require('path');
15
- const readline = require('readline');
16
-
17
- async function main() {
18
- let inputData = '';
19
- try {
20
- const rl = readline.createInterface({ input: process.stdin, terminal: false });
21
- for await (const line of rl) {
22
- inputData += line + '\n';
23
- }
24
- } catch (_) {
25
- process.exit(0);
26
- }
27
-
28
- let data = {};
29
- try {
30
- data = JSON.parse(inputData);
31
- } catch (_) {
32
- process.exit(0);
33
- }
34
-
35
- const cwd = data.cwd || process.cwd();
36
- const sessionId = data.session_id || 'unknown';
37
- const timestamp = new Date()
38
- .toISOString()
39
- .slice(0, 19)
40
- .replace('T', '_')
41
- .replace(/:/g, '-');
42
-
43
- const digestDir = path.join(cwd, '.genia', 'session-digests');
44
- try {
45
- fs.mkdirSync(digestDir, { recursive: true });
46
- } catch (_) {
47
- process.exit(0);
48
- }
49
-
50
- const digestPath = path.join(digestDir, `digest-${timestamp}.md`);
51
-
52
- const content = `# Session Digest — ${timestamp}
53
-
54
- **Session ID:** ${sessionId}
55
- **Sistema:** GEN.IA OS — {{TEAM_NAME}}
56
-
57
- ## Contexto Compactado
58
-
59
- O Claude Code compactou o contexto desta sessão.
60
- Este arquivo preserva o estado para retomada.
61
-
62
- ## Como Retomar
63
-
64
- 1. Leia as stories ativas em \`docs/stories/\`
65
- 2. Verifique \`.genia/session/workflow-state.md\` para workflow em andamento
66
- 3. Consulte \`.claude/agent-memory/[agente]/MEMORY.md\` do agente ativo
67
- 4. Verifique git log para entender o que foi commitado
68
-
69
- ## Dica
70
-
71
- Ao retomar, informe ao agente:
72
- > "Estou retomando a sessão. [descreva o contexto brevemente]"
73
-
74
- ---
75
- *Gerado automaticamente pelo GEN.IA OS Synapse Engine*
76
- `;
77
-
78
- try {
79
- fs.writeFileSync(digestPath, content, 'utf8');
80
- } catch (_) {
81
- // Falha silenciosa — nunca bloquear o usuário
82
- }
83
-
84
- process.exit(0);
85
- }
86
-
87
- main().catch(() => process.exit(0));
1
+ #!/usr/bin/env node
2
+ /**
3
+ * GEN.IA OS — Session Digest
4
+ * Trigger: PreCompact
5
+ *
6
+ * Salva um resumo da sessão antes do Claude compactar o contexto.
7
+ * Preserva memória institucional entre sessões longas.
8
+ * Inspirado no AIOS precompact-session-digest (MIT License, SynkraAI)
9
+ */
10
+
11
+ 'use strict';
12
+
13
+ const fs = require('fs');
14
+ const path = require('path');
15
+ const readline = require('readline');
16
+
17
+ async function main() {
18
+ let inputData = '';
19
+ try {
20
+ const rl = readline.createInterface({ input: process.stdin, terminal: false });
21
+ for await (const line of rl) {
22
+ inputData += line + '\n';
23
+ }
24
+ } catch (_) {
25
+ process.exit(0);
26
+ }
27
+
28
+ let data = {};
29
+ try {
30
+ data = JSON.parse(inputData);
31
+ } catch (_) {
32
+ process.exit(0);
33
+ }
34
+
35
+ const cwd = data.cwd || process.cwd();
36
+ const sessionId = data.session_id || 'unknown';
37
+ const timestamp = new Date()
38
+ .toISOString()
39
+ .slice(0, 19)
40
+ .replace('T', '_')
41
+ .replace(/:/g, '-');
42
+
43
+ const digestDir = path.join(cwd, '.genia', 'session-digests');
44
+ try {
45
+ fs.mkdirSync(digestDir, { recursive: true });
46
+ } catch (_) {
47
+ process.exit(0);
48
+ }
49
+
50
+ const digestPath = path.join(digestDir, `digest-${timestamp}.md`);
51
+
52
+ const content = `# Session Digest — ${timestamp}
53
+
54
+ **Session ID:** ${sessionId}
55
+ **Sistema:** GEN.IA OS — {{TEAM_NAME}}
56
+
57
+ ## Contexto Compactado
58
+
59
+ O Claude Code compactou o contexto desta sessão.
60
+ Este arquivo preserva o estado para retomada.
61
+
62
+ ## Como Retomar
63
+
64
+ 1. Leia as stories ativas em \`docs/stories/\`
65
+ 2. Verifique \`.genia/session/workflow-state.md\` para workflow em andamento
66
+ 3. Consulte \`.claude/agent-memory/[agente]/MEMORY.md\` do agente ativo
67
+ 4. Verifique git log para entender o que foi commitado
68
+
69
+ ## Dica
70
+
71
+ Ao retomar, informe ao agente:
72
+ > "Estou retomando a sessão. [descreva o contexto brevemente]"
73
+
74
+ ---
75
+ *Gerado automaticamente pelo GEN.IA OS Synapse Engine*
76
+ `;
77
+
78
+ try {
79
+ fs.writeFileSync(digestPath, content, 'utf8');
80
+ } catch (_) {
81
+ // Falha silenciosa — nunca bloquear o usuário
82
+ }
83
+
84
+ process.exit(0);
85
+ }
86
+
87
+ main().catch(() => process.exit(0));
@@ -1,65 +1,65 @@
1
- #!/usr/bin/env python3
2
- """
3
- GEN.IA OS — Hook: sql-governance
4
- Trigger: PreToolUse (Bash)
5
- Ação: Bloqueia DDL SQL perigoso executado diretamente.
6
- Permite operações via supabase CLI, pg_dump e psql -f (migrations controladas).
7
- """
8
- import json
9
- import sys
10
- import re
11
-
12
-
13
- DANGEROUS_PATTERNS = [
14
- r"\bDROP\s+TABLE\b",
15
- r"\bDROP\s+DATABASE\b",
16
- r"\bDROP\s+SCHEMA\b",
17
- r"\bTRUNCATE\s+TABLE\b",
18
- r"\bTRUNCATE\b\s+\w+",
19
- r"\bALTER\s+TABLE\b.*\bDROP\s+COLUMN\b",
20
- r"DELETE\s+FROM\s+\w+\s*;?\s*$", # DELETE sem WHERE
21
- ]
22
-
23
- SAFE_PATTERNS = [
24
- r"supabase\s+(migration|db\s+push|db\s+diff)",
25
- r"pg_dump\b",
26
- r"psql\s+.*-f\s+",
27
- r"\.sql\s*$", # executar arquivo .sql explícito
28
- ]
29
-
30
-
31
- def main():
32
- try:
33
- raw = sys.stdin.read()
34
- data = json.loads(raw)
35
- except Exception:
36
- sys.exit(0)
37
-
38
- tool = data.get("tool_name", "")
39
- if tool != "Bash":
40
- sys.exit(0)
41
-
42
- command = data.get("tool_input", {}).get("command", "")
43
-
44
- # Verificar se é operação segura de migration
45
- for safe in SAFE_PATTERNS:
46
- if re.search(safe, command, re.IGNORECASE):
47
- sys.exit(0)
48
-
49
- # Verificar padrões perigosos
50
- cmd_upper = command.upper()
51
- for pattern in DANGEROUS_PATTERNS:
52
- if re.search(pattern, cmd_upper):
53
- print(
54
- "[GEN.IA OS] 🚫 BLOQUEADO — SQL destrutivo detectado.\n"
55
- "[GEN.IA OS] Use 'supabase migration new <nome>' para alterações de schema.\n"
56
- "[GEN.IA OS] Migrations controladas garantem rollback seguro.",
57
- file=sys.stderr,
58
- )
59
- sys.exit(2)
60
-
61
- sys.exit(0)
62
-
63
-
64
- if __name__ == "__main__":
65
- main()
1
+ #!/usr/bin/env python3
2
+ """
3
+ GEN.IA OS — Hook: sql-governance
4
+ Trigger: PreToolUse (Bash)
5
+ Ação: Bloqueia DDL SQL perigoso executado diretamente.
6
+ Permite operações via supabase CLI, pg_dump e psql -f (migrations controladas).
7
+ """
8
+ import json
9
+ import sys
10
+ import re
11
+
12
+
13
+ DANGEROUS_PATTERNS = [
14
+ r"\bDROP\s+TABLE\b",
15
+ r"\bDROP\s+DATABASE\b",
16
+ r"\bDROP\s+SCHEMA\b",
17
+ r"\bTRUNCATE\s+TABLE\b",
18
+ r"\bTRUNCATE\b\s+\w+",
19
+ r"\bALTER\s+TABLE\b.*\bDROP\s+COLUMN\b",
20
+ r"DELETE\s+FROM\s+\w+\s*;?\s*$", # DELETE sem WHERE
21
+ ]
22
+
23
+ SAFE_PATTERNS = [
24
+ r"supabase\s+(migration|db\s+push|db\s+diff)",
25
+ r"pg_dump\b",
26
+ r"psql\s+.*-f\s+",
27
+ r"\.sql\s*$", # executar arquivo .sql explícito
28
+ ]
29
+
30
+
31
+ def main():
32
+ try:
33
+ raw = sys.stdin.read()
34
+ data = json.loads(raw)
35
+ except Exception:
36
+ sys.exit(0)
37
+
38
+ tool = data.get("tool_name", "")
39
+ if tool != "Bash":
40
+ sys.exit(0)
41
+
42
+ command = data.get("tool_input", {}).get("command", "")
43
+
44
+ # Verificar se é operação segura de migration
45
+ for safe in SAFE_PATTERNS:
46
+ if re.search(safe, command, re.IGNORECASE):
47
+ sys.exit(0)
48
+
49
+ # Verificar padrões perigosos
50
+ cmd_upper = command.upper()
51
+ for pattern in DANGEROUS_PATTERNS:
52
+ if re.search(pattern, cmd_upper):
53
+ print(
54
+ "[GEN.IA OS] 🚫 BLOQUEADO — SQL destrutivo detectado.\n"
55
+ "[GEN.IA OS] Use 'supabase migration new <nome>' para alterações de schema.\n"
56
+ "[GEN.IA OS] Migrations controladas garantem rollback seguro.",
57
+ file=sys.stderr,
58
+ )
59
+ sys.exit(2)
60
+
61
+ sys.exit(0)
62
+
63
+
64
+ if __name__ == "__main__":
65
+ main()