aios-core 4.0.1 → 4.0.2

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.
@@ -7,8 +7,8 @@
7
7
  # - SHA256 hashes for change detection
8
8
  # - File types for categorization
9
9
  #
10
- version: 4.0.1
11
- generated_at: "2026-02-13T01:17:14.079Z"
10
+ version: 4.0.2
11
+ generated_at: "2026-02-13T01:40:56.998Z"
12
12
  generator: scripts/generate-install-manifest.js
13
13
  file_count: 971
14
14
  files:
@@ -0,0 +1,169 @@
1
+ # Claude Code Hooks
2
+
3
+ Sistema de governança automática para regras do CLAUDE.md.
4
+
5
+ ## Arquitetura
6
+
7
+ ```
8
+ PreToolUse Hooks
9
+ ├── Read → read-protection.py
10
+ ├── Write|Edit → enforce-architecture-first.py
11
+ │ → write-path-validation.py
12
+ │ → mind-clone-governance.py
13
+ └── Bash → sql-governance.py
14
+ → slug-validation.py
15
+ ```
16
+
17
+ ## Hooks Disponíveis
18
+
19
+ ### 1. read-protection.py
20
+ **Trigger:** `Read`
21
+ **Comportamento:** BLOQUEIA (exit 2)
22
+
23
+ Impede leitura parcial (`limit`/`offset`) em arquivos protegidos:
24
+ - `.claude/CLAUDE.md`
25
+ - `.claude/rules/*.md`
26
+ - `.aios-core/development/agents/*.md`
27
+ - `supabase/docs/SCHEMA.md`
28
+ - `package.json`, `tsconfig.json`
29
+ - `app/components/ui/icons/icon-map.ts`
30
+
31
+ ### 2. enforce-architecture-first.py
32
+ **Trigger:** `Write|Edit`
33
+ **Comportamento:** BLOQUEIA (exit 2)
34
+
35
+ Exige documentação aprovada antes de criar código em paths protegidos:
36
+ - `supabase/functions/` → requer doc em `docs/architecture/` ou `docs/approved-plans/`
37
+ - `supabase/migrations/` → requer doc ou permite edição de arquivo existente
38
+
39
+ ### 3. write-path-validation.py
40
+ **Trigger:** `Write|Edit`
41
+ **Comportamento:** AVISA (exit 0 + stderr)
42
+
43
+ Avisa quando documentos parecem estar no path errado:
44
+ - Sessions/handoffs → `docs/sessions/YYYY-MM/`
45
+ - Architecture → `docs/architecture/`
46
+ - Guides → `docs/guides/`
47
+
48
+ ### 4. sql-governance.py
49
+ **Trigger:** `Bash`
50
+ **Comportamento:** BLOQUEIA (exit 2)
51
+
52
+ Intercepta comandos SQL perigosos:
53
+ - `CREATE TABLE/VIEW/FUNCTION/TRIGGER`
54
+ - `ALTER TABLE`
55
+ - `DROP TABLE/VIEW/FUNCTION`
56
+ - `CREATE TABLE AS SELECT` (backup proibido)
57
+
58
+ **Exceções permitidas:**
59
+ - `supabase migration` (CLI oficial)
60
+ - `pg_dump` (backup/export)
61
+
62
+ ### 5. slug-validation.py
63
+ **Trigger:** `Bash`
64
+ **Comportamento:** BLOQUEIA (exit 2)
65
+
66
+ Valida formato snake_case em slugs:
67
+ - Pattern: `^[a-z0-9]+(_[a-z0-9]+)*$`
68
+ - ✅ `jose_carlos_amorim`
69
+ - ❌ `jose-carlos-amorim` (hyphen)
70
+ - ❌ `JoseAmorim` (camelCase)
71
+
72
+ ### 6. mind-clone-governance.py
73
+ **Trigger:** `Write|Edit`
74
+ **Comportamento:** BLOQUEIA (exit 2)
75
+
76
+ Impede criação de mind clones sem DNA extraído previamente.
77
+
78
+ **O que é bloqueado:**
79
+ - Criar novo arquivo `squads/*/agents/*.md` que pareça ser um mind clone
80
+ - Mind clones = agents baseados em pessoas reais (não funcionais)
81
+
82
+ **O que NÃO é bloqueado:**
83
+ - Editar arquivos existentes (permite updates)
84
+ - Agents funcionais (identificados por sufixo):
85
+ - `-chief`, `-orchestrator`, `-chair`
86
+ - `-validator`, `-calculator`, `-generator`, `-extractor`, `-analyzer`
87
+ - `-architect`, `-mapper`, `-designer`, `-engineer`
88
+ - `tools-*`, `process-*`, `workflow-*`
89
+
90
+ **Locais de DNA verificados:**
91
+ - `squads/{pack}/data/minds/{agent_id}_dna.yaml`
92
+ - `squads/{pack}/data/minds/{agent_id}_dna.md`
93
+ - `squads/{pack}/data/{agent_id}-dna.yaml`
94
+ - `outputs/minds/{agent_id}/`
95
+
96
+ **Solução quando bloqueado:**
97
+ 1. Execute o pipeline de extração de DNA: `/squad-creator` → `*collect-sources` → `*extract-voice-dna` → `*extract-thinking-dna`
98
+ 2. OU se é agent funcional, renomeie com sufixo apropriado
99
+
100
+ ## Exit Codes
101
+
102
+ | Code | Significado |
103
+ |------|-------------|
104
+ | 0 | Permitido (operação continua) |
105
+ | 2 | Bloqueado (operação cancelada, mostra stderr) |
106
+ | Outro | Erro não-bloqueante |
107
+
108
+ ## Input Format
109
+
110
+ Hooks recebem JSON via stdin:
111
+
112
+ ```json
113
+ {
114
+ "session_id": "abc123",
115
+ "hook_event_name": "PreToolUse",
116
+ "tool_name": "Read",
117
+ "tool_input": {
118
+ "file_path": "/path/to/file",
119
+ "limit": 100
120
+ },
121
+ "cwd": "/Users/alan/Code/mmos"
122
+ }
123
+ ```
124
+
125
+ ## Debugging
126
+
127
+ Para testar um hook manualmente:
128
+
129
+ ```bash
130
+ echo '{"tool_name": "Read", "tool_input": {"file_path": ".claude/CLAUDE.md", "limit": 100}}' | python3 .claude/hooks/read-protection.py
131
+ echo $? # Deve retornar 2 (bloqueado)
132
+ ```
133
+
134
+ ## Configuração
135
+
136
+ Hooks são configurados em `.claude/settings.local.json`:
137
+
138
+ ```json
139
+ {
140
+ "hooks": {
141
+ "PreToolUse": [
142
+ {
143
+ "matcher": "Read",
144
+ "hooks": [
145
+ {
146
+ "type": "command",
147
+ "command": "python3 \"$CLAUDE_PROJECT_DIR/.claude/hooks/read-protection.py\"",
148
+ "timeout": 5
149
+ }
150
+ ]
151
+ }
152
+ ]
153
+ }
154
+ }
155
+ ```
156
+
157
+ ## Manutenção
158
+
159
+ Para adicionar novo hook:
160
+
161
+ 1. Criar arquivo `.claude/hooks/novo-hook.py`
162
+ 2. Adicionar entrada em `.claude/settings.local.json`
163
+ 3. Documentar neste README
164
+ 4. Testar com casos reais
165
+
166
+ ---
167
+
168
+ *Criado: 2026-01-24*
169
+ *Arquitetura: docs/architecture/claude-md-governance-system.md*
@@ -0,0 +1,46 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Claude Code Hook: PreCompact Session Digest
4
+ *
5
+ * This hook is registered with Claude Code to trigger before context compact.
6
+ * It delegates to the unified hook runner in aios-core.
7
+ *
8
+ * Installation:
9
+ * - Claude Code automatically discovers hooks in .claude/hooks/
10
+ * - Hook naming: {event}-{name}.js (e.g., precompact-session-digest.js)
11
+ *
12
+ * @see .aios-core/hooks/unified/runners/precompact-runner.js
13
+ * @see Story MIS-3 - Session Digest (PreCompact Hook)
14
+ */
15
+
16
+ 'use strict';
17
+
18
+ const path = require('path');
19
+
20
+ // Resolve path to the unified hook runner
21
+ const PROJECT_ROOT = path.resolve(__dirname, '..', '..');
22
+ const runnerPath = path.join(
23
+ PROJECT_ROOT,
24
+ '.aios-core',
25
+ 'hooks',
26
+ 'unified',
27
+ 'runners',
28
+ 'precompact-runner.js',
29
+ );
30
+
31
+ // Load and execute the hook runner
32
+ try {
33
+ const { onPreCompact } = require(runnerPath);
34
+
35
+ // Export the hook handler for Claude Code
36
+ module.exports = async (context) => {
37
+ return await onPreCompact(context);
38
+ };
39
+ } catch (error) {
40
+ console.error('[PreCompact Hook] Failed to load hook runner:', error.message);
41
+
42
+ // Graceful degradation - export no-op function
43
+ module.exports = async () => {
44
+ console.log('[PreCompact Hook] Hook runner not available, skipping');
45
+ };
46
+ }
@@ -0,0 +1,87 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ /**
5
+ * SYNAPSE Hook Entry Point — UserPromptSubmit
6
+ *
7
+ * Thin wrapper that reads JSON from stdin, delegates to SynapseEngine,
8
+ * and writes <synapse-rules> context to stdout.
9
+ *
10
+ * - Silent exit on missing .synapse/ directory
11
+ * - Silent exit on any error (never blocks the user prompt)
12
+ * - All errors logged to stderr with [synapse-hook] prefix
13
+ * - 5s safety timeout as defense-in-depth
14
+ *
15
+ * @module synapse-engine-hook
16
+ */
17
+
18
+ const path = require('path');
19
+ const fs = require('fs');
20
+
21
+ /** Safety timeout (ms) — defense-in-depth; Claude Code also manages hook timeout. */
22
+ const HOOK_TIMEOUT_MS = 5000;
23
+
24
+ /**
25
+ * Read all data from stdin as a JSON object.
26
+ * @returns {Promise<object>} Parsed JSON input
27
+ */
28
+ function readStdin() {
29
+ return new Promise((resolve, reject) => {
30
+ let data = '';
31
+ process.stdin.setEncoding('utf8');
32
+ process.stdin.on('error', (e) => reject(e));
33
+ process.stdin.on('data', (chunk) => { data += chunk; });
34
+ process.stdin.on('end', () => {
35
+ try { resolve(JSON.parse(data)); }
36
+ catch (e) { reject(e); }
37
+ });
38
+ });
39
+ }
40
+
41
+ /** Main hook execution pipeline. */
42
+ async function main() {
43
+ const input = await readStdin();
44
+ const { sessionId, cwd, prompt } = input;
45
+ if (!cwd) return;
46
+ const synapsePath = path.join(cwd, '.synapse');
47
+ if (!fs.existsSync(synapsePath)) return;
48
+
49
+ const { loadSession } = require(
50
+ path.join(cwd, '.aios-core', 'core', 'synapse', 'session', 'session-manager.js')
51
+ );
52
+ const { SynapseEngine } = require(
53
+ path.join(cwd, '.aios-core', 'core', 'synapse', 'engine.js')
54
+ );
55
+
56
+ const sessionsDir = path.join(synapsePath, 'sessions');
57
+ const session = loadSession(sessionId, sessionsDir) || { prompt_count: 0 };
58
+ const engine = new SynapseEngine(synapsePath);
59
+ const result = await engine.process(prompt, session);
60
+
61
+ process.stdout.write(JSON.stringify({
62
+ hookSpecificOutput: { additionalContext: result.xml || '' },
63
+ }));
64
+ }
65
+
66
+ /**
67
+ * Safely exit the process — no-op inside Jest workers to prevent worker crashes.
68
+ * @param {number} code - Exit code
69
+ */
70
+ function safeExit(code) {
71
+ if (process.env.JEST_WORKER_ID) return;
72
+ process.exit(code);
73
+ }
74
+
75
+ /** Entry point runner — sets safety timeout and executes main(). */
76
+ function run() {
77
+ const timer = setTimeout(() => safeExit(0), HOOK_TIMEOUT_MS);
78
+ timer.unref();
79
+ main().catch((err) => {
80
+ console.error(`[synapse-hook] ${err.message}`);
81
+ safeExit(0);
82
+ });
83
+ }
84
+
85
+ if (require.main === module) run();
86
+
87
+ module.exports = { readStdin, main, run, HOOK_TIMEOUT_MS };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aios-core",
3
- "version": "4.0.1",
3
+ "version": "4.0.2",
4
4
  "description": "Synkra AIOS: AI-Orchestrated System for Full Stack Development - Core Framework",
5
5
  "bin": {
6
6
  "aios": "bin/aios.js",
@@ -18,6 +18,9 @@
18
18
  ".aios-core/",
19
19
  ".claude/CLAUDE.md",
20
20
  ".claude/rules/",
21
+ ".claude/hooks/synapse-engine.js",
22
+ ".claude/hooks/precompact-session-digest.js",
23
+ ".claude/hooks/README.md",
21
24
  "README.md",
22
25
  "LICENSE"
23
26
  ],
@@ -324,8 +324,9 @@ async function installAiosCore(options = {}) {
324
324
  // BUG-2 fix (INS-1): Install .aios-core dependencies after copy
325
325
  // The copied .aios-core/package.json has dependencies (js-yaml, execa, etc.)
326
326
  // that must be installed for the activation pipeline to work
327
- if (await fs.pathExists(path.join(targetAiosCore, 'package.json'))) {
328
- spinner.text = 'Installing .aios-core dependencies...';
327
+ const aiosCorePackageJson = path.join(targetAiosCore, 'package.json');
328
+ if (await fs.pathExists(aiosCorePackageJson)) {
329
+ spinner.text = 'Installing .aios-core dependencies (js-yaml, etc.)...';
329
330
  try {
330
331
  const { exec } = require('child_process');
331
332
  const { promisify } = require('util');
@@ -334,8 +335,11 @@ async function installAiosCore(options = {}) {
334
335
  cwd: targetAiosCore,
335
336
  timeout: 60000,
336
337
  });
338
+ spinner.succeed('Installed .aios-core dependencies');
339
+ spinner.start('Finishing installation...');
337
340
  } catch (depError) {
338
- // Non-fatal: dependencies may already exist or network unavailable
341
+ spinner.warn(`Could not install .aios-core dependencies: ${depError.message}`);
342
+ spinner.start('Continuing installation...');
339
343
  result.errors.push(`Dependencies warning: ${depError.message}`);
340
344
  }
341
345
  }