sinapse-ai 7.6.0 → 7.7.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.
- package/.claude/hooks/secret-scanning.cjs +155 -0
- package/.claude/rules/cross-squad-routing.md +47 -0
- package/.claude/rules/hook-governance.md +61 -0
- package/.claude/rules/security-scanning.md +42 -0
- package/.sinapse-ai/cli/commands/health/index.js +237 -0
- package/.sinapse-ai/cli/commands/performance/index.js +157 -0
- package/.sinapse-ai/cli/commands/routing-intel/index.js +176 -0
- package/.sinapse-ai/install-manifest.yaml +15 -3
- package/bin/sinapse.js +34 -0
- package/package.json +1 -1
- package/squads/squad-claude/agents/swarm-orqx.md +28 -0
- package/squads/squad-claude/preferences/README.md +15 -0
- package/squads/squad-claude/squad.yaml +13 -0
- package/squads/squad-commercial/agents/commercial-orqx.md +44 -3
- package/squads/squad-commercial/squad.yaml +7 -0
- package/squads/squad-council/preferences/README.md +15 -0
- package/squads/squad-council/squad.yaml +7 -0
- package/squads/squad-cybersecurity/preferences/README.md +15 -0
- package/squads/squad-cybersecurity/squad.yaml +12 -0
- package/squads/squad-finance/preferences/README.md +15 -0
- package/squads/squad-growth/agents/growth-orqx.md +30 -0
- package/squads/squad-growth/squad.yaml +7 -0
- package/squads/squad-paidmedia/preferences/README.md +15 -0
- package/squads/squad-product/squad.yaml +7 -0
- package/squads/squad-storytelling/preferences/README.md +15 -0
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Hook: Secret Scanning
|
|
6
|
+
*
|
|
7
|
+
* RULE: Detect and block potential secrets/credentials from being written to files.
|
|
8
|
+
*
|
|
9
|
+
* Protocol (Claude Code PreToolUse):
|
|
10
|
+
* exit 0 → allow
|
|
11
|
+
* exit 2 → block (message shown to model via stderr)
|
|
12
|
+
*
|
|
13
|
+
* Fail-open: if parsing fails, allow.
|
|
14
|
+
*
|
|
15
|
+
* @module secret-scanning
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
const fs = require('fs');
|
|
19
|
+
const path = require('path');
|
|
20
|
+
|
|
21
|
+
// ---------------------------------------------------------------------------
|
|
22
|
+
// Secret Patterns — ordered by severity
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
|
|
25
|
+
const SECRET_PATTERNS = [
|
|
26
|
+
// API Keys & Tokens
|
|
27
|
+
{ name: 'AWS Access Key', pattern: /AKIA[0-9A-Z]{16}/ },
|
|
28
|
+
{ name: 'AWS Secret Key', pattern: /(?:aws_secret_access_key|secret_key)\s*[=:]\s*['"]?[A-Za-z0-9/+=]{40}['"]?/i },
|
|
29
|
+
{ name: 'GitHub Token', pattern: /gh[ps]_[A-Za-z0-9_]{36,}/ },
|
|
30
|
+
{ name: 'GitHub OAuth', pattern: /gho_[A-Za-z0-9_]{36,}/ },
|
|
31
|
+
{ name: 'Slack Token', pattern: /xox[bpors]-[0-9]{10,}-[A-Za-z0-9-]+/ },
|
|
32
|
+
{ name: 'Stripe Key', pattern: /[sr]k_(live|test)_[A-Za-z0-9]{20,}/ },
|
|
33
|
+
{ name: 'OpenAI Key', pattern: /sk-[A-Za-z0-9]{20,}/ },
|
|
34
|
+
{ name: 'Anthropic Key', pattern: /sk-ant-[A-Za-z0-9-]{20,}/ },
|
|
35
|
+
{ name: 'Supabase Key', pattern: /eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9\.[A-Za-z0-9_-]{50,}/ },
|
|
36
|
+
{ name: 'Google API Key', pattern: /AIza[0-9A-Za-z_-]{35}/ },
|
|
37
|
+
{ name: 'Vercel Token', pattern: /vercel_[A-Za-z0-9]{20,}/ },
|
|
38
|
+
|
|
39
|
+
// Private Keys
|
|
40
|
+
{ name: 'RSA Private Key', pattern: /-----BEGIN RSA PRIVATE KEY-----/ },
|
|
41
|
+
{ name: 'SSH Private Key', pattern: /-----BEGIN OPENSSH PRIVATE KEY-----/ },
|
|
42
|
+
{ name: 'PGP Private Key', pattern: /-----BEGIN PGP PRIVATE KEY BLOCK-----/ },
|
|
43
|
+
{ name: 'EC Private Key', pattern: /-----BEGIN EC PRIVATE KEY-----/ },
|
|
44
|
+
|
|
45
|
+
// Connection Strings
|
|
46
|
+
{ name: 'DB Connection String', pattern: /(?:postgres|mysql|mongodb|redis):\/\/[^:]+:[^@]+@[^/\s]+/i },
|
|
47
|
+
{ name: 'Supabase DB URL', pattern: /postgresql:\/\/postgres\.[A-Za-z0-9]+:[^@]+@/i },
|
|
48
|
+
|
|
49
|
+
// Generic Patterns (broader, lower confidence)
|
|
50
|
+
{ name: 'Hardcoded Password', pattern: /(?:password|passwd|pwd)\s*[=:]\s*['"][^'"]{8,}['"]/i },
|
|
51
|
+
{ name: 'Bearer Token', pattern: /[Bb]earer\s+[A-Za-z0-9_\-.]{20,}/ },
|
|
52
|
+
{ name: 'Basic Auth', pattern: /[Bb]asic\s+[A-Za-z0-9+/=]{20,}/ },
|
|
53
|
+
];
|
|
54
|
+
|
|
55
|
+
/** Files that are expected to contain secret-like patterns */
|
|
56
|
+
const EXEMPT_PATHS = [
|
|
57
|
+
'.env.example', '.env.template', '.env.sample',
|
|
58
|
+
'node_modules/', '.git/',
|
|
59
|
+
'.claude/hooks/', // Hook scripts may reference patterns
|
|
60
|
+
'test/', 'tests/', '__tests__/',
|
|
61
|
+
'.sinapse-ai/core/', // Framework core may have validators
|
|
62
|
+
];
|
|
63
|
+
|
|
64
|
+
/** File extensions to scan */
|
|
65
|
+
const SCANNABLE_EXTENSIONS = [
|
|
66
|
+
'.ts', '.tsx', '.js', '.jsx', '.cjs', '.mjs',
|
|
67
|
+
'.json', '.yaml', '.yml', '.toml',
|
|
68
|
+
'.env', '.sh', '.bash', '.py',
|
|
69
|
+
'.md', '.txt', '.cfg', '.conf', '.ini',
|
|
70
|
+
];
|
|
71
|
+
|
|
72
|
+
// ---------------------------------------------------------------------------
|
|
73
|
+
// Helpers
|
|
74
|
+
// ---------------------------------------------------------------------------
|
|
75
|
+
|
|
76
|
+
function projectRoot() {
|
|
77
|
+
return process.env.CLAUDE_PROJECT_DIR || process.cwd();
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function relativize(filePath, root) {
|
|
81
|
+
const normalized = filePath.replace(/\\/g, '/');
|
|
82
|
+
const normalizedRoot = root.replace(/\\/g, '/');
|
|
83
|
+
if (normalized.startsWith(normalizedRoot)) {
|
|
84
|
+
return normalized.slice(normalizedRoot.length).replace(/^\/+/, '');
|
|
85
|
+
}
|
|
86
|
+
return normalized;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function isExempt(rel) {
|
|
90
|
+
return EXEMPT_PATHS.some((ep) => rel.includes(ep));
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function isScannable(rel) {
|
|
94
|
+
return SCANNABLE_EXTENSIONS.some((ext) => rel.endsWith(ext));
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function scanForSecrets(content) {
|
|
98
|
+
const findings = [];
|
|
99
|
+
for (const { name, pattern } of SECRET_PATTERNS) {
|
|
100
|
+
if (pattern.test(content)) {
|
|
101
|
+
findings.push(name);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return findings;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// ---------------------------------------------------------------------------
|
|
108
|
+
// Main
|
|
109
|
+
// ---------------------------------------------------------------------------
|
|
110
|
+
|
|
111
|
+
function main() {
|
|
112
|
+
let input;
|
|
113
|
+
try {
|
|
114
|
+
input = JSON.parse(fs.readFileSync(0, 'utf8'));
|
|
115
|
+
} catch {
|
|
116
|
+
process.exit(0); // fail-open
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const toolName = input.tool_name || '';
|
|
120
|
+
if (toolName !== 'Write' && toolName !== 'Edit') {
|
|
121
|
+
process.exit(0);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const toolInput = input.tool_input || {};
|
|
125
|
+
const filePath = toolInput.file_path || '';
|
|
126
|
+
if (!filePath) process.exit(0);
|
|
127
|
+
|
|
128
|
+
const root = projectRoot();
|
|
129
|
+
const rel = relativize(filePath, root);
|
|
130
|
+
|
|
131
|
+
if (isExempt(rel)) process.exit(0);
|
|
132
|
+
if (!isScannable(rel)) process.exit(0);
|
|
133
|
+
|
|
134
|
+
// Scan content being written
|
|
135
|
+
const content = toolInput.content || toolInput.new_string || '';
|
|
136
|
+
if (!content) process.exit(0);
|
|
137
|
+
|
|
138
|
+
const findings = scanForSecrets(content);
|
|
139
|
+
if (findings.length === 0) process.exit(0);
|
|
140
|
+
|
|
141
|
+
// BLOCK
|
|
142
|
+
process.stderr.write(
|
|
143
|
+
`\nSECRET SCANNING BLOCK: Potential secrets detected!\n` +
|
|
144
|
+
`File: ${rel}\n` +
|
|
145
|
+
`Found: ${findings.join(', ')}\n` +
|
|
146
|
+
`\n` +
|
|
147
|
+
`DO NOT commit secrets to code. Instead:\n` +
|
|
148
|
+
` - Use environment variables (.env) for local dev\n` +
|
|
149
|
+
` - Use .env.example with placeholder values for templates\n` +
|
|
150
|
+
` - Use secret managers for production (Supabase Vault, etc.)\n`,
|
|
151
|
+
);
|
|
152
|
+
process.exit(2);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
main();
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Cross-Squad Routing Rules
|
|
2
|
+
|
|
3
|
+
> Applies to Imperator (sinapse-orqx) and ALL squad orchestrators (*-orqx).
|
|
4
|
+
|
|
5
|
+
## Single-Squad Requests
|
|
6
|
+
|
|
7
|
+
When a request maps cleanly to one domain, route directly:
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
"Crie um headline" → @copy-orqx → @headline-specialist
|
|
11
|
+
"Audite a marca" → @brand-orqx → @brand-auditor
|
|
12
|
+
"Otimize SEO" → @growth-orqx → @seo-specialist
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Multi-Squad Patterns
|
|
16
|
+
|
|
17
|
+
For requests spanning multiple domains, use established patterns:
|
|
18
|
+
|
|
19
|
+
| Pattern | Squads | Trigger |
|
|
20
|
+
|---------|--------|---------|
|
|
21
|
+
| `brand_launch` | brand + design + content + copy + animations | New brand from scratch |
|
|
22
|
+
| `go_to_market` | product + commercial + content + paidmedia + growth | Launch product/service |
|
|
23
|
+
| `strategic_pivot` | council + research + finance + product | Major direction change |
|
|
24
|
+
| `full_digital_presence` | brand + design + content + animations + growth + paidmedia | Complete digital setup |
|
|
25
|
+
| `security_compliance_audit` | cybersecurity + research | Security assessment |
|
|
26
|
+
| `content_campaign` | content + copy + growth + paidmedia | Multi-channel campaign |
|
|
27
|
+
| `course_launch` | courses + content + copy + commercial | Course/workshop launch |
|
|
28
|
+
|
|
29
|
+
## Routing Priority
|
|
30
|
+
|
|
31
|
+
1. **Exact match** — Request clearly belongs to one squad
|
|
32
|
+
2. **Pattern match** — Request matches a known multi-squad pattern
|
|
33
|
+
3. **Diagnostic** — Unclear request → Imperator diagnoses before routing
|
|
34
|
+
|
|
35
|
+
## Handoff Between Squads
|
|
36
|
+
|
|
37
|
+
When work flows from one squad to another:
|
|
38
|
+
1. Outgoing squad writes deliverables to `docs/` or project files
|
|
39
|
+
2. Outgoing orchestrator generates handoff artifact
|
|
40
|
+
3. Incoming orchestrator receives artifact + reads deliverables
|
|
41
|
+
4. Incoming orchestrator routes to appropriate specialist
|
|
42
|
+
|
|
43
|
+
## Anti-Patterns
|
|
44
|
+
|
|
45
|
+
- Never have two squads working on the same file simultaneously
|
|
46
|
+
- Never skip the orchestrator (user → specialist directly) for multi-squad work
|
|
47
|
+
- Never route to a squad without providing context from the previous squad
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# Hook Governance Rules
|
|
2
|
+
|
|
3
|
+
> Applies to ALL agents. Hooks are the enforcement layer of the Constitution.
|
|
4
|
+
|
|
5
|
+
## Active Hook Registry
|
|
6
|
+
|
|
7
|
+
### PreToolUse — Bash
|
|
8
|
+
| Hook | Purpose | Behavior |
|
|
9
|
+
|------|---------|----------|
|
|
10
|
+
| `enforce-git-push-authority.sh` | Art. II — Only @devops can push | BLOCK (deny) |
|
|
11
|
+
| `sql-governance.py` | Security — Block dangerous SQL | BLOCK (exit 2) |
|
|
12
|
+
| `enforce-delegation.cjs` | Art. VIII — Orchestrators can't execute | BLOCK (exit 2) |
|
|
13
|
+
|
|
14
|
+
### PreToolUse — Write|Edit
|
|
15
|
+
| Hook | Purpose | Behavior |
|
|
16
|
+
|------|---------|----------|
|
|
17
|
+
| `enforce-architecture-first.cjs` | Art. III — Docs before protected code | BLOCK (exit 2) |
|
|
18
|
+
| `write-path-validation.cjs` | Convention — Warn wrong doc paths | WARN (exit 0) |
|
|
19
|
+
| `enforce-story-gate.cjs` | Art. III — Story required for code | BLOCK (exit 2) |
|
|
20
|
+
| `slug-validation.py` | Convention — Validate naming | WARN (exit 0) |
|
|
21
|
+
| `mind-clone-governance.py` | Cloning — DNA required | BLOCK (exit 2) |
|
|
22
|
+
| `enforce-delegation.cjs` | Art. VIII — Orchestrators can't execute | BLOCK (exit 2) |
|
|
23
|
+
|
|
24
|
+
### PreToolUse — Read
|
|
25
|
+
| Hook | Purpose | Behavior |
|
|
26
|
+
|------|---------|----------|
|
|
27
|
+
| `read-protection.py` | Security — Control sensitive file access | WARN (exit 0) |
|
|
28
|
+
|
|
29
|
+
### UserPromptSubmit
|
|
30
|
+
| Hook | Purpose | Behavior |
|
|
31
|
+
|------|---------|----------|
|
|
32
|
+
| `synapse-wrapper.cjs` | SYNAPSE context injection | ALLOW (exit 0) |
|
|
33
|
+
|
|
34
|
+
### PreCompact
|
|
35
|
+
| Hook | Purpose | Behavior |
|
|
36
|
+
|------|---------|----------|
|
|
37
|
+
| `precompact-wrapper.cjs` | Session digest before compaction | ALLOW (exit 0) |
|
|
38
|
+
|
|
39
|
+
## Hook Design Principles
|
|
40
|
+
|
|
41
|
+
1. **Fail-open** — If a hook crashes or can't parse input, exit 0 (allow)
|
|
42
|
+
2. **Fast** — Each hook must complete in < 5 seconds
|
|
43
|
+
3. **Silent on success** — Only output on block or warning
|
|
44
|
+
4. **Deterministic** — Same input always produces same output
|
|
45
|
+
5. **No side effects** — Hooks read state but don't modify it
|
|
46
|
+
|
|
47
|
+
## Adding New Hooks
|
|
48
|
+
|
|
49
|
+
1. Create script in `.claude/hooks/` (prefer CJS for portability)
|
|
50
|
+
2. Add entry to `.claude/settings.json` under appropriate event
|
|
51
|
+
3. Document in this file (hook-governance.md)
|
|
52
|
+
4. Test with mock JSON via stdin
|
|
53
|
+
5. Verify fail-open behavior with invalid input
|
|
54
|
+
|
|
55
|
+
## Exit Code Protocol
|
|
56
|
+
|
|
57
|
+
| Code | Meaning | Effect |
|
|
58
|
+
|------|---------|--------|
|
|
59
|
+
| 0 | Allow | Operation proceeds |
|
|
60
|
+
| 2 | Block | Operation denied, message shown to model |
|
|
61
|
+
| Other | Ignored | Operation proceeds (treated as 0) |
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Security Scanning Rules
|
|
2
|
+
|
|
3
|
+
> Applies to ALL agents writing code or configuration files.
|
|
4
|
+
|
|
5
|
+
## Secret Detection
|
|
6
|
+
|
|
7
|
+
NEVER commit files containing:
|
|
8
|
+
- API keys, tokens, or passwords in plaintext
|
|
9
|
+
- `.env` files with real values (use `.env.example` with placeholders)
|
|
10
|
+
- OAuth credentials (`access_token`, `refresh_token`, `client_secret`)
|
|
11
|
+
- Private keys (RSA, SSH, PGP)
|
|
12
|
+
- Database connection strings with credentials
|
|
13
|
+
- Webhook URLs with embedded tokens
|
|
14
|
+
|
|
15
|
+
## Path Traversal Prevention
|
|
16
|
+
|
|
17
|
+
When handling file paths from user input or external sources:
|
|
18
|
+
- Reject paths containing `..` segments
|
|
19
|
+
- Reject absolute paths outside project root
|
|
20
|
+
- Normalize paths before validation (`path.resolve()` then check prefix)
|
|
21
|
+
- Never construct paths with string concatenation from untrusted input
|
|
22
|
+
|
|
23
|
+
## SQL Injection Prevention
|
|
24
|
+
|
|
25
|
+
- Always use parameterized queries — never string interpolation
|
|
26
|
+
- Supabase RPC functions must use `$1, $2` parameter placeholders
|
|
27
|
+
- Edge functions must validate and sanitize all query parameters
|
|
28
|
+
- `sql-governance.py` hook blocks dangerous SQL patterns automatically
|
|
29
|
+
|
|
30
|
+
## Dependency Security
|
|
31
|
+
|
|
32
|
+
- Review new dependencies before adding (`npm audit`)
|
|
33
|
+
- Prefer well-maintained packages (>1K weekly downloads, recent updates)
|
|
34
|
+
- Pin exact versions in production dependencies
|
|
35
|
+
- Never install packages with known critical vulnerabilities
|
|
36
|
+
|
|
37
|
+
## Hooks Enforcement
|
|
38
|
+
|
|
39
|
+
Active security hooks in `.claude/settings.json`:
|
|
40
|
+
- `sql-governance.py` — blocks dangerous SQL in Bash commands
|
|
41
|
+
- `read-protection.py` — controls access to sensitive config files
|
|
42
|
+
- `enforce-architecture-first.cjs` — requires docs before protected code paths
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* sinapse health — Framework Health Analytics
|
|
6
|
+
*
|
|
7
|
+
* Analyzes the health of a SINAPSE installation:
|
|
8
|
+
* - Hook connectivity (wired vs orphaned)
|
|
9
|
+
* - Squad completeness (metadata, preferences, KBs)
|
|
10
|
+
* - Rule coverage
|
|
11
|
+
* - Agent authority compliance
|
|
12
|
+
* - Skill activation coverage
|
|
13
|
+
*
|
|
14
|
+
* Usage:
|
|
15
|
+
* sinapse health # Full health report
|
|
16
|
+
* sinapse health --json # JSON output
|
|
17
|
+
* sinapse health --fix # Auto-fix common issues
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
const fs = require('fs');
|
|
21
|
+
const path = require('path');
|
|
22
|
+
|
|
23
|
+
function findProjectRoot() {
|
|
24
|
+
let dir = process.cwd();
|
|
25
|
+
while (dir !== path.dirname(dir)) {
|
|
26
|
+
if (fs.existsSync(path.join(dir, '.sinapse-ai'))) return dir;
|
|
27
|
+
dir = path.dirname(dir);
|
|
28
|
+
}
|
|
29
|
+
return process.cwd();
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function checkHooks(root) {
|
|
33
|
+
const results = { score: 0, max: 0, issues: [] };
|
|
34
|
+
const settingsPath = path.join(root, '.claude', 'settings.json');
|
|
35
|
+
|
|
36
|
+
results.max += 3;
|
|
37
|
+
if (!fs.existsSync(settingsPath)) {
|
|
38
|
+
results.issues.push({ severity: 'critical', msg: '.claude/settings.json not found' });
|
|
39
|
+
return results;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const settings = JSON.parse(fs.readFileSync(settingsPath, 'utf8'));
|
|
43
|
+
const hooks = settings.hooks || {};
|
|
44
|
+
|
|
45
|
+
// Check PreToolUse exists
|
|
46
|
+
if (hooks.PreToolUse && hooks.PreToolUse.length > 0) {
|
|
47
|
+
results.score += 1;
|
|
48
|
+
} else {
|
|
49
|
+
results.issues.push({ severity: 'high', msg: 'No PreToolUse hooks configured' });
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Check UserPromptSubmit exists
|
|
53
|
+
if (hooks.UserPromptSubmit && hooks.UserPromptSubmit.length > 0) {
|
|
54
|
+
results.score += 1;
|
|
55
|
+
} else {
|
|
56
|
+
results.issues.push({ severity: 'medium', msg: 'No UserPromptSubmit hooks configured' });
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Count total connected hooks
|
|
60
|
+
let connected = 0;
|
|
61
|
+
Object.values(hooks).forEach((matchers) =>
|
|
62
|
+
matchers.forEach((m) => (m.hooks || []).forEach(() => connected++)),
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
// Check hook files exist
|
|
66
|
+
const hooksDir = path.join(root, '.claude', 'hooks');
|
|
67
|
+
if (fs.existsSync(hooksDir)) {
|
|
68
|
+
const hookFiles = fs.readdirSync(hooksDir).filter((f) => f.endsWith('.cjs') || f.endsWith('.sh') || f.endsWith('.py'));
|
|
69
|
+
const orphaned = hookFiles.length - connected;
|
|
70
|
+
if (orphaned <= 5) results.score += 1; // Some orphaned is OK (utilities, legacy)
|
|
71
|
+
else results.issues.push({ severity: 'low', msg: `${orphaned} hook files not connected to settings.json` });
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
results.connected = connected;
|
|
75
|
+
return results;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function checkSquads(root) {
|
|
79
|
+
const results = { score: 0, max: 0, issues: [], squads: [] };
|
|
80
|
+
const squadsDir = path.join(root, 'squads');
|
|
81
|
+
|
|
82
|
+
if (!fs.existsSync(squadsDir)) {
|
|
83
|
+
results.issues.push({ severity: 'medium', msg: 'squads/ directory not found' });
|
|
84
|
+
return results;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const squadDirs = fs.readdirSync(squadsDir).filter((d) => d.startsWith('squad-') && fs.statSync(path.join(squadsDir, d)).isDirectory());
|
|
88
|
+
|
|
89
|
+
for (const squad of squadDirs) {
|
|
90
|
+
const dir = path.join(squadsDir, squad);
|
|
91
|
+
const checks = { name: squad, metadata: false, preferences: false, agents: 0, tasks: 0 };
|
|
92
|
+
results.max += 2;
|
|
93
|
+
|
|
94
|
+
// Check metadata
|
|
95
|
+
const yamlPath = path.join(dir, 'squad.yaml');
|
|
96
|
+
if (fs.existsSync(yamlPath)) {
|
|
97
|
+
const content = fs.readFileSync(yamlPath, 'utf8');
|
|
98
|
+
checks.metadata = /agents_count|total_files/.test(content);
|
|
99
|
+
if (checks.metadata) results.score += 1;
|
|
100
|
+
else results.issues.push({ severity: 'low', msg: `${squad}: missing metadata in squad.yaml` });
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Check preferences
|
|
104
|
+
checks.preferences = fs.existsSync(path.join(dir, 'preferences'));
|
|
105
|
+
if (checks.preferences) results.score += 1;
|
|
106
|
+
else results.issues.push({ severity: 'low', msg: `${squad}: missing preferences/ directory` });
|
|
107
|
+
|
|
108
|
+
// Count assets
|
|
109
|
+
const agentsDir = path.join(dir, 'agents');
|
|
110
|
+
const tasksDir = path.join(dir, 'tasks');
|
|
111
|
+
checks.agents = fs.existsSync(agentsDir) ? fs.readdirSync(agentsDir).filter((f) => f.endsWith('.md')).length : 0;
|
|
112
|
+
checks.tasks = fs.existsSync(tasksDir) ? fs.readdirSync(tasksDir).filter((f) => f.endsWith('.md')).length : 0;
|
|
113
|
+
|
|
114
|
+
results.squads.push(checks);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return results;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function checkRules(root) {
|
|
121
|
+
const results = { score: 0, max: 1, issues: [] };
|
|
122
|
+
const rulesDir = path.join(root, '.claude', 'rules');
|
|
123
|
+
|
|
124
|
+
if (!fs.existsSync(rulesDir)) {
|
|
125
|
+
results.issues.push({ severity: 'high', msg: '.claude/rules/ not found' });
|
|
126
|
+
return results;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const rules = fs.readdirSync(rulesDir).filter((f) => f.endsWith('.md'));
|
|
130
|
+
if (rules.length >= 13) results.score += 1;
|
|
131
|
+
else results.issues.push({ severity: 'medium', msg: `Only ${rules.length} rules (recommended: 16+)` });
|
|
132
|
+
|
|
133
|
+
results.count = rules.length;
|
|
134
|
+
return results;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function checkSkills(root) {
|
|
138
|
+
const results = { score: 0, max: 1, issues: [] };
|
|
139
|
+
const skillsDir = path.join(root, '.claude', 'skills');
|
|
140
|
+
|
|
141
|
+
if (!fs.existsSync(skillsDir)) {
|
|
142
|
+
results.issues.push({ severity: 'medium', msg: '.claude/skills/ not found' });
|
|
143
|
+
return results;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const skills = fs.readdirSync(skillsDir).filter((f) => f.endsWith('.md') || fs.statSync(path.join(skillsDir, f)).isDirectory());
|
|
147
|
+
// Check for path-activated skills
|
|
148
|
+
let pathActivated = 0;
|
|
149
|
+
for (const skill of skills) {
|
|
150
|
+
const skillPath = path.join(skillsDir, skill);
|
|
151
|
+
if (fs.statSync(skillPath).isFile()) {
|
|
152
|
+
const content = fs.readFileSync(skillPath, 'utf8');
|
|
153
|
+
if (/^paths:/m.test(content)) pathActivated++;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if (pathActivated >= 3) results.score += 1;
|
|
158
|
+
else results.issues.push({ severity: 'low', msg: `Only ${pathActivated} path-activated skills (recommended: 5+)` });
|
|
159
|
+
|
|
160
|
+
results.total = skills.length;
|
|
161
|
+
results.pathActivated = pathActivated;
|
|
162
|
+
return results;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
async function runHealth(options = {}) {
|
|
166
|
+
const root = findProjectRoot();
|
|
167
|
+
const pkg = JSON.parse(fs.readFileSync(path.join(root, 'package.json'), 'utf8'));
|
|
168
|
+
|
|
169
|
+
const hookResults = checkHooks(root);
|
|
170
|
+
const squadResults = checkSquads(root);
|
|
171
|
+
const ruleResults = checkRules(root);
|
|
172
|
+
const skillResults = checkSkills(root);
|
|
173
|
+
|
|
174
|
+
const totalScore = hookResults.score + squadResults.score + ruleResults.score + skillResults.score;
|
|
175
|
+
const totalMax = hookResults.max + squadResults.max + ruleResults.max + skillResults.max;
|
|
176
|
+
const percentage = Math.round((totalScore / totalMax) * 100);
|
|
177
|
+
|
|
178
|
+
const allIssues = [
|
|
179
|
+
...hookResults.issues,
|
|
180
|
+
...squadResults.issues,
|
|
181
|
+
...ruleResults.issues,
|
|
182
|
+
...skillResults.issues,
|
|
183
|
+
];
|
|
184
|
+
|
|
185
|
+
if (options.json) {
|
|
186
|
+
console.log(JSON.stringify({
|
|
187
|
+
version: pkg.version,
|
|
188
|
+
health: percentage,
|
|
189
|
+
score: `${totalScore}/${totalMax}`,
|
|
190
|
+
hooks: { connected: hookResults.connected, score: `${hookResults.score}/${hookResults.max}` },
|
|
191
|
+
squads: { count: squadResults.squads.length, score: `${squadResults.score}/${squadResults.max}` },
|
|
192
|
+
rules: { count: ruleResults.count, score: `${ruleResults.score}/${ruleResults.max}` },
|
|
193
|
+
skills: { total: skillResults.total, pathActivated: skillResults.pathActivated, score: `${skillResults.score}/${skillResults.max}` },
|
|
194
|
+
issues: allIssues,
|
|
195
|
+
}, null, 2));
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// Pretty output
|
|
200
|
+
const bar = (score, max) => {
|
|
201
|
+
const filled = Math.round((score / max) * 10);
|
|
202
|
+
return '█'.repeat(filled) + '░'.repeat(10 - filled);
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
console.log(`\n SINAPSE Health Report — v${pkg.version}`);
|
|
206
|
+
console.log(` ${'═'.repeat(50)}\n`);
|
|
207
|
+
console.log(` Overall Health: ${percentage}% ${bar(totalScore, totalMax)} (${totalScore}/${totalMax})\n`);
|
|
208
|
+
console.log(` Hooks: ${bar(hookResults.score, hookResults.max)} ${hookResults.connected || 0} connected`);
|
|
209
|
+
console.log(` Squads: ${bar(squadResults.score, squadResults.max)} ${squadResults.squads.length} squads`);
|
|
210
|
+
console.log(` Rules: ${bar(ruleResults.score, ruleResults.max)} ${ruleResults.count || 0} rules`);
|
|
211
|
+
console.log(` Skills: ${bar(skillResults.score, skillResults.max)} ${skillResults.pathActivated || 0} path-activated\n`);
|
|
212
|
+
|
|
213
|
+
if (allIssues.length > 0) {
|
|
214
|
+
console.log(` Issues (${allIssues.length}):`);
|
|
215
|
+
for (const issue of allIssues.slice(0, 10)) {
|
|
216
|
+
const icon = issue.severity === 'critical' ? '🔴' : issue.severity === 'high' ? '🟠' : issue.severity === 'medium' ? '🟡' : '🔵';
|
|
217
|
+
console.log(` ${icon} ${issue.msg}`);
|
|
218
|
+
}
|
|
219
|
+
if (allIssues.length > 10) console.log(` ... and ${allIssues.length - 10} more`);
|
|
220
|
+
console.log('');
|
|
221
|
+
} else {
|
|
222
|
+
console.log(' ✅ No issues found!\n');
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
module.exports = { runHealth };
|
|
227
|
+
|
|
228
|
+
if (require.main === module) {
|
|
229
|
+
const args = process.argv.slice(2);
|
|
230
|
+
runHealth({
|
|
231
|
+
json: args.includes('--json'),
|
|
232
|
+
fix: args.includes('--fix'),
|
|
233
|
+
}).catch((err) => {
|
|
234
|
+
console.error(`Error: ${err.message}`);
|
|
235
|
+
process.exit(1);
|
|
236
|
+
});
|
|
237
|
+
}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* sinapse performance — Squad & Agent Performance Ranking
|
|
6
|
+
*
|
|
7
|
+
* Analyzes squad and agent completeness, ranking by:
|
|
8
|
+
* - Asset coverage (agents, tasks, KBs, workflows, templates, checklists)
|
|
9
|
+
* - Metadata completeness
|
|
10
|
+
* - Preferences tracking
|
|
11
|
+
* - Orchestrator enrichment level
|
|
12
|
+
*
|
|
13
|
+
* Usage:
|
|
14
|
+
* sinapse performance # Full ranking
|
|
15
|
+
* sinapse performance --json # JSON output
|
|
16
|
+
* sinapse performance --top 5 # Top 5 only
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
const fs = require('fs');
|
|
20
|
+
const path = require('path');
|
|
21
|
+
|
|
22
|
+
function findProjectRoot() {
|
|
23
|
+
let dir = process.cwd();
|
|
24
|
+
while (dir !== path.dirname(dir)) {
|
|
25
|
+
if (fs.existsSync(path.join(dir, '.sinapse-ai'))) return dir;
|
|
26
|
+
dir = path.dirname(dir);
|
|
27
|
+
}
|
|
28
|
+
return process.cwd();
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function analyzeSquad(squadDir, squadName) {
|
|
32
|
+
const result = {
|
|
33
|
+
name: squadName,
|
|
34
|
+
agents: 0,
|
|
35
|
+
tasks: 0,
|
|
36
|
+
kbs: 0,
|
|
37
|
+
workflows: 0,
|
|
38
|
+
templates: 0,
|
|
39
|
+
checklists: 0,
|
|
40
|
+
hasMetadata: false,
|
|
41
|
+
hasPreferences: false,
|
|
42
|
+
orchestratorLines: 0,
|
|
43
|
+
score: 0,
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
// Count assets
|
|
47
|
+
const countMd = (subdir) => {
|
|
48
|
+
const dir = path.join(squadDir, subdir);
|
|
49
|
+
if (!fs.existsSync(dir)) return 0;
|
|
50
|
+
return fs.readdirSync(dir).filter((f) => f.endsWith('.md')).length;
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const countAny = (subdir) => {
|
|
54
|
+
const dir = path.join(squadDir, subdir);
|
|
55
|
+
if (!fs.existsSync(dir)) return 0;
|
|
56
|
+
return fs.readdirSync(dir).filter((f) => !f.startsWith('.')).length;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
result.agents = countMd('agents');
|
|
60
|
+
result.tasks = countMd('tasks');
|
|
61
|
+
// Try both naming conventions
|
|
62
|
+
result.kbs = countAny('knowledge-bases') || countAny('knowledge-base');
|
|
63
|
+
result.workflows = countAny('workflows');
|
|
64
|
+
result.templates = countMd('templates') || countAny('templates');
|
|
65
|
+
result.checklists = countMd('checklists') || countAny('checklists');
|
|
66
|
+
|
|
67
|
+
// Metadata check
|
|
68
|
+
const yamlPath = path.join(squadDir, 'squad.yaml');
|
|
69
|
+
if (fs.existsSync(yamlPath)) {
|
|
70
|
+
const content = fs.readFileSync(yamlPath, 'utf8');
|
|
71
|
+
result.hasMetadata = /agents_count|total_files/.test(content);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Preferences check
|
|
75
|
+
result.hasPreferences = fs.existsSync(path.join(squadDir, 'preferences'));
|
|
76
|
+
|
|
77
|
+
// Orchestrator enrichment
|
|
78
|
+
const orqxFile = fs.readdirSync(path.join(squadDir, 'agents')).find((f) => f.includes('-orqx'));
|
|
79
|
+
if (orqxFile) {
|
|
80
|
+
const content = fs.readFileSync(path.join(squadDir, 'agents', orqxFile), 'utf8');
|
|
81
|
+
result.orchestratorLines = content.split('\n').length;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Calculate score (weighted)
|
|
85
|
+
result.score =
|
|
86
|
+
(result.agents >= 6 ? 15 : result.agents * 2.5) +
|
|
87
|
+
(result.tasks >= 50 ? 25 : result.tasks * 0.5) +
|
|
88
|
+
(result.kbs >= 8 ? 15 : result.kbs * 1.875) +
|
|
89
|
+
(result.workflows >= 3 ? 10 : result.workflows * 3.33) +
|
|
90
|
+
(result.templates >= 3 ? 10 : result.templates * 3.33) +
|
|
91
|
+
(result.checklists >= 2 ? 5 : result.checklists * 2.5) +
|
|
92
|
+
(result.hasMetadata ? 5 : 0) +
|
|
93
|
+
(result.hasPreferences ? 5 : 0) +
|
|
94
|
+
(result.orchestratorLines >= 100 ? 10 : result.orchestratorLines * 0.1);
|
|
95
|
+
|
|
96
|
+
result.score = Math.round(result.score * 10) / 10;
|
|
97
|
+
|
|
98
|
+
return result;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
async function runPerformance(options = {}) {
|
|
102
|
+
const root = findProjectRoot();
|
|
103
|
+
const squadsDir = path.join(root, 'squads');
|
|
104
|
+
|
|
105
|
+
if (!fs.existsSync(squadsDir)) {
|
|
106
|
+
console.error('No squads/ directory found.');
|
|
107
|
+
process.exit(1);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const squadDirs = fs.readdirSync(squadsDir)
|
|
111
|
+
.filter((d) => d.startsWith('squad-') && fs.statSync(path.join(squadsDir, d)).isDirectory());
|
|
112
|
+
|
|
113
|
+
const rankings = squadDirs
|
|
114
|
+
.map((d) => analyzeSquad(path.join(squadsDir, d), d))
|
|
115
|
+
.sort((a, b) => b.score - a.score);
|
|
116
|
+
|
|
117
|
+
const limit = options.top || rankings.length;
|
|
118
|
+
const display = rankings.slice(0, limit);
|
|
119
|
+
|
|
120
|
+
if (options.json) {
|
|
121
|
+
console.log(JSON.stringify({ rankings: display, total: rankings.length }, null, 2));
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Pretty output
|
|
126
|
+
console.log(`\n SINAPSE Performance Ranking — ${rankings.length} Squads`);
|
|
127
|
+
console.log(` ${'═'.repeat(60)}\n`);
|
|
128
|
+
|
|
129
|
+
const maxScore = rankings[0]?.score || 100;
|
|
130
|
+
|
|
131
|
+
display.forEach((sq, i) => {
|
|
132
|
+
const rank = i + 1;
|
|
133
|
+
const barLen = Math.round((sq.score / maxScore) * 20);
|
|
134
|
+
const bar = '█'.repeat(barLen) + '░'.repeat(20 - barLen);
|
|
135
|
+
const medal = rank === 1 ? '🥇' : rank === 2 ? '🥈' : rank === 3 ? '🥉' : `#${rank}`;
|
|
136
|
+
const meta = sq.hasMetadata ? '✓' : '✗';
|
|
137
|
+
const pref = sq.hasPreferences ? '✓' : '✗';
|
|
138
|
+
|
|
139
|
+
console.log(` ${String(medal).padEnd(4)} ${sq.name.padEnd(25)} ${bar} ${sq.score.toFixed(1)}`);
|
|
140
|
+
console.log(` ${sq.agents}a ${sq.tasks}t ${sq.kbs}kb ${sq.workflows}wf ${sq.templates}tpl ${sq.checklists}ck | meta:${meta} pref:${pref} orqx:${sq.orchestratorLines}L`);
|
|
141
|
+
console.log('');
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
module.exports = { runPerformance };
|
|
146
|
+
|
|
147
|
+
if (require.main === module) {
|
|
148
|
+
const args = process.argv.slice(2);
|
|
149
|
+
const topIdx = args.indexOf('--top');
|
|
150
|
+
runPerformance({
|
|
151
|
+
json: args.includes('--json'),
|
|
152
|
+
top: topIdx >= 0 ? parseInt(args[topIdx + 1], 10) : undefined,
|
|
153
|
+
}).catch((err) => {
|
|
154
|
+
console.error(`Error: ${err.message}`);
|
|
155
|
+
process.exit(1);
|
|
156
|
+
});
|
|
157
|
+
}
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* sinapse routing-intel — Routing Intelligence Analyzer
|
|
6
|
+
*
|
|
7
|
+
* Analyzes the routing configuration across all orchestrators:
|
|
8
|
+
* - Delegation matrix completeness
|
|
9
|
+
* - Cross-squad handoff coverage
|
|
10
|
+
* - Routing pattern conflicts
|
|
11
|
+
* - Agent reachability (can every agent be reached via routing?)
|
|
12
|
+
*
|
|
13
|
+
* Usage:
|
|
14
|
+
* sinapse routing-intel # Full routing analysis
|
|
15
|
+
* sinapse routing-intel analyze # Deep analysis with recommendations
|
|
16
|
+
* sinapse routing-intel --json # JSON output
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
const fs = require('fs');
|
|
20
|
+
const path = require('path');
|
|
21
|
+
|
|
22
|
+
function findProjectRoot() {
|
|
23
|
+
let dir = process.cwd();
|
|
24
|
+
while (dir !== path.dirname(dir)) {
|
|
25
|
+
if (fs.existsSync(path.join(dir, '.sinapse-ai'))) return dir;
|
|
26
|
+
dir = path.dirname(dir);
|
|
27
|
+
}
|
|
28
|
+
return process.cwd();
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function extractDelegation(content) {
|
|
32
|
+
const delegations = [];
|
|
33
|
+
// Match delegation tables: | pattern | agent |
|
|
34
|
+
const tableRows = content.match(/\|[^|]+\|[^|]+\|/g) || [];
|
|
35
|
+
for (const row of tableRows) {
|
|
36
|
+
const cells = row.split('|').map((c) => c.trim()).filter(Boolean);
|
|
37
|
+
if (cells.length >= 2 && cells[1].startsWith('@')) {
|
|
38
|
+
delegations.push({ pattern: cells[0], target: cells[1] });
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Match inline delegations: → @agent, delegate to @agent
|
|
43
|
+
const inlineMatches = content.match(/(?:→|delegate to|route to)\s+@([\w-]+)/gi) || [];
|
|
44
|
+
for (const match of inlineMatches) {
|
|
45
|
+
const agentMatch = match.match(/@([\w-]+)/);
|
|
46
|
+
if (agentMatch) delegations.push({ pattern: 'inline', target: `@${agentMatch[1]}` });
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return delegations;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function extractHandoffs(content) {
|
|
53
|
+
const handoffs = { inbound: [], outbound: [] };
|
|
54
|
+
|
|
55
|
+
// Look for inbound/outbound sections
|
|
56
|
+
const inboundMatch = content.match(/###?\s*Inbound[\s\S]*?(?=###?\s*Outbound|###?\s*[A-Z]|$)/i);
|
|
57
|
+
if (inboundMatch) {
|
|
58
|
+
const squads = inboundMatch[0].match(/@[\w-]+|squad-[\w-]+/g) || [];
|
|
59
|
+
handoffs.inbound = [...new Set(squads)];
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const outboundMatch = content.match(/###?\s*Outbound[\s\S]*?(?=###?\s*[A-Z]|##\s|$)/i);
|
|
63
|
+
if (outboundMatch) {
|
|
64
|
+
const squads = outboundMatch[0].match(/@[\w-]+|squad-[\w-]+/g) || [];
|
|
65
|
+
handoffs.outbound = [...new Set(squads)];
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return handoffs;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
async function runRoutingIntel(options = {}) {
|
|
72
|
+
const root = findProjectRoot();
|
|
73
|
+
const squadsDir = path.join(root, 'squads');
|
|
74
|
+
|
|
75
|
+
if (!fs.existsSync(squadsDir)) {
|
|
76
|
+
console.error('No squads/ directory found.');
|
|
77
|
+
process.exit(1);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const squadDirs = fs.readdirSync(squadsDir)
|
|
81
|
+
.filter((d) => d.startsWith('squad-') && fs.statSync(path.join(squadsDir, d)).isDirectory());
|
|
82
|
+
|
|
83
|
+
const routingMap = [];
|
|
84
|
+
const allAgents = new Set();
|
|
85
|
+
const reachableAgents = new Set();
|
|
86
|
+
|
|
87
|
+
for (const squad of squadDirs) {
|
|
88
|
+
const agentsDir = path.join(squadsDir, squad, 'agents');
|
|
89
|
+
if (!fs.existsSync(agentsDir)) continue;
|
|
90
|
+
|
|
91
|
+
const agentFiles = fs.readdirSync(agentsDir).filter((f) => f.endsWith('.md'));
|
|
92
|
+
for (const file of agentFiles) {
|
|
93
|
+
const agentId = file.replace('.md', '');
|
|
94
|
+
allAgents.add(agentId);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Find orchestrator
|
|
98
|
+
const orqxFile = agentFiles.find((f) => f.includes('-orqx'));
|
|
99
|
+
if (!orqxFile) continue;
|
|
100
|
+
|
|
101
|
+
const content = fs.readFileSync(path.join(agentsDir, orqxFile), 'utf8');
|
|
102
|
+
const delegations = extractDelegation(content);
|
|
103
|
+
const handoffs = extractHandoffs(content);
|
|
104
|
+
|
|
105
|
+
// Mark delegated agents as reachable
|
|
106
|
+
for (const d of delegations) {
|
|
107
|
+
const target = d.target.replace('@', '');
|
|
108
|
+
reachableAgents.add(target);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
routingMap.push({
|
|
112
|
+
squad,
|
|
113
|
+
orchestrator: orqxFile.replace('.md', ''),
|
|
114
|
+
delegations: delegations.length,
|
|
115
|
+
handoffs,
|
|
116
|
+
hasRoutingIntel: /routing intelligence|routing table/i.test(content),
|
|
117
|
+
hasDelegationMatrix: /delegation matrix|delegation|delegacao/i.test(content),
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Find unreachable agents (not in any delegation)
|
|
122
|
+
const unreachable = [...allAgents].filter((a) => !reachableAgents.has(a) && !a.includes('-orqx'));
|
|
123
|
+
|
|
124
|
+
if (options.json) {
|
|
125
|
+
console.log(JSON.stringify({
|
|
126
|
+
squads: routingMap,
|
|
127
|
+
totalAgents: allAgents.size,
|
|
128
|
+
reachableAgents: reachableAgents.size,
|
|
129
|
+
unreachableAgents: unreachable,
|
|
130
|
+
coverage: Math.round((reachableAgents.size / allAgents.size) * 100),
|
|
131
|
+
}, null, 2));
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Pretty output
|
|
136
|
+
console.log(`\n SINAPSE Routing Intelligence Report`);
|
|
137
|
+
console.log(` ${'═'.repeat(55)}\n`);
|
|
138
|
+
|
|
139
|
+
console.log(` Agents: ${allAgents.size} total | ${reachableAgents.size} reachable | ${unreachable.length} unreachable`);
|
|
140
|
+
console.log(` Coverage: ${Math.round((reachableAgents.size / allAgents.size) * 100)}%\n`);
|
|
141
|
+
|
|
142
|
+
console.log(` Squad Routing Matrix:`);
|
|
143
|
+
console.log(` ${'─'.repeat(55)}`);
|
|
144
|
+
|
|
145
|
+
for (const entry of routingMap) {
|
|
146
|
+
const routing = entry.hasRoutingIntel ? '✓' : '✗';
|
|
147
|
+
const deleg = entry.hasDelegationMatrix ? '✓' : '✗';
|
|
148
|
+
const inCount = entry.handoffs.inbound.length;
|
|
149
|
+
const outCount = entry.handoffs.outbound.length;
|
|
150
|
+
|
|
151
|
+
console.log(` ${entry.squad.padEnd(25)} ${entry.delegations}d | in:${inCount} out:${outCount} | routing:${routing} deleg:${deleg}`);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
if (options.analyze && unreachable.length > 0) {
|
|
155
|
+
console.log(`\n Unreachable Agents (${unreachable.length}):`);
|
|
156
|
+
for (const agent of unreachable.slice(0, 15)) {
|
|
157
|
+
console.log(` ⚠ ${agent}`);
|
|
158
|
+
}
|
|
159
|
+
if (unreachable.length > 15) console.log(` ... and ${unreachable.length - 15} more`);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
console.log('');
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
module.exports = { runRoutingIntel };
|
|
166
|
+
|
|
167
|
+
if (require.main === module) {
|
|
168
|
+
const args = process.argv.slice(2);
|
|
169
|
+
runRoutingIntel({
|
|
170
|
+
json: args.includes('--json'),
|
|
171
|
+
analyze: args.includes('analyze'),
|
|
172
|
+
}).catch((err) => {
|
|
173
|
+
console.error(`Error: ${err.message}`);
|
|
174
|
+
process.exit(1);
|
|
175
|
+
});
|
|
176
|
+
}
|
|
@@ -7,10 +7,10 @@
|
|
|
7
7
|
# - SHA256 hashes for change detection
|
|
8
8
|
# - File types for categorization
|
|
9
9
|
#
|
|
10
|
-
version: 7.
|
|
11
|
-
generated_at: "2026-04-
|
|
10
|
+
version: 7.7.0
|
|
11
|
+
generated_at: "2026-04-01T14:18:00.782Z"
|
|
12
12
|
generator: scripts/generate-install-manifest.js
|
|
13
|
-
file_count:
|
|
13
|
+
file_count: 1107
|
|
14
14
|
files:
|
|
15
15
|
- path: cli/commands/config/index.js
|
|
16
16
|
hash: sha256:66f111eceef0f60fa0a8904add783b615d55b01d5fe36408623c3dd828e702f6
|
|
@@ -20,6 +20,10 @@ files:
|
|
|
20
20
|
hash: sha256:36f8e38ab767fa5478d8dabac548c66dc2c0fc521c216e954ac33fcea0ba597b
|
|
21
21
|
type: cli
|
|
22
22
|
size: 6720
|
|
23
|
+
- path: cli/commands/health/index.js
|
|
24
|
+
hash: sha256:7140286f6f0fcd283dcc0a6261dfe914ee50aae5c97ddd9e548ffa6a3279fe1e
|
|
25
|
+
type: cli
|
|
26
|
+
size: 8579
|
|
23
27
|
- path: cli/commands/manifest/index.js
|
|
24
28
|
hash: sha256:440df152d1be0d1700551206b512e47ce38ef1f6244eecebdf7df74888976250
|
|
25
29
|
type: cli
|
|
@@ -100,6 +104,10 @@ files:
|
|
|
100
104
|
hash: sha256:5f7ac17e3fd47ff9d3d4544f67b28f44b821097e0ce5eb2059e8550c0f54e4e1
|
|
101
105
|
type: cli
|
|
102
106
|
size: 12355
|
|
107
|
+
- path: cli/commands/performance/index.js
|
|
108
|
+
hash: sha256:aa2f14a846ff7301d9694fd1e50897e559b3c437d2eccb07e4f2ad21f9921c9c
|
|
109
|
+
type: cli
|
|
110
|
+
size: 5039
|
|
103
111
|
- path: cli/commands/pro/index.js
|
|
104
112
|
hash: sha256:be706f637b3f54d882a8e1d3ee953a40c7ae7b94ca3bfcafdd4d6865d0526964
|
|
105
113
|
type: cli
|
|
@@ -116,6 +124,10 @@ files:
|
|
|
116
124
|
hash: sha256:bc993858504617a233ce191ab44a438f675605022e43375d282f589a734b6c64
|
|
117
125
|
type: cli
|
|
118
126
|
size: 5320
|
|
127
|
+
- path: cli/commands/routing-intel/index.js
|
|
128
|
+
hash: sha256:f13824f426e7a2091024a20ecad0299d75abd46881bd0226b86a9207e6ecf3fa
|
|
129
|
+
type: cli
|
|
130
|
+
size: 5761
|
|
119
131
|
- path: cli/commands/validate/index.js
|
|
120
132
|
hash: sha256:93c39b64cd1a234ce848843c0a9b291a1f85f142e77485e281ebc0e7344afea2
|
|
121
133
|
type: cli
|
package/bin/sinapse.js
CHANGED
|
@@ -1077,6 +1077,40 @@ async function main() {
|
|
|
1077
1077
|
showHelp();
|
|
1078
1078
|
break;
|
|
1079
1079
|
|
|
1080
|
+
case 'health': {
|
|
1081
|
+
// Framework health analytics
|
|
1082
|
+
const { runHealth } = require('../.sinapse-ai/cli/commands/health/index.js');
|
|
1083
|
+
const healthArgs = args.slice(1);
|
|
1084
|
+
await runHealth({
|
|
1085
|
+
json: healthArgs.includes('--json'),
|
|
1086
|
+
fix: healthArgs.includes('--fix'),
|
|
1087
|
+
});
|
|
1088
|
+
break;
|
|
1089
|
+
}
|
|
1090
|
+
|
|
1091
|
+
case 'performance': {
|
|
1092
|
+
// Squad & agent performance ranking
|
|
1093
|
+
const { runPerformance } = require('../.sinapse-ai/cli/commands/performance/index.js');
|
|
1094
|
+
const perfArgs = args.slice(1);
|
|
1095
|
+
const topIdx = perfArgs.indexOf('--top');
|
|
1096
|
+
await runPerformance({
|
|
1097
|
+
json: perfArgs.includes('--json'),
|
|
1098
|
+
top: topIdx >= 0 ? parseInt(perfArgs[topIdx + 1], 10) : undefined,
|
|
1099
|
+
});
|
|
1100
|
+
break;
|
|
1101
|
+
}
|
|
1102
|
+
|
|
1103
|
+
case 'routing-intel': {
|
|
1104
|
+
// Routing intelligence analyzer
|
|
1105
|
+
const { runRoutingIntel } = require('../.sinapse-ai/cli/commands/routing-intel/index.js');
|
|
1106
|
+
const riArgs = args.slice(1);
|
|
1107
|
+
await runRoutingIntel({
|
|
1108
|
+
json: riArgs.includes('--json'),
|
|
1109
|
+
analyze: riArgs.includes('analyze'),
|
|
1110
|
+
});
|
|
1111
|
+
break;
|
|
1112
|
+
}
|
|
1113
|
+
|
|
1080
1114
|
case undefined:
|
|
1081
1115
|
// No arguments - launch Claude Code with SINAPSE branding
|
|
1082
1116
|
launchSinapse([]);
|
package/package.json
CHANGED
|
@@ -68,3 +68,31 @@ Strategic and systems-oriented. Swarm thinks in terms of parallelism, isolation
|
|
|
68
68
|
| **Inbound** | Any squad | When multi-agent orchestration is needed |
|
|
69
69
|
| **Outbound** | squad-dev | When agent implementation patterns need coding |
|
|
70
70
|
| **Outbound** | squad-devops | When worktree branches need merge/deploy coordination |
|
|
71
|
+
|
|
72
|
+
## Activation Instructions
|
|
73
|
+
|
|
74
|
+
1. Read this file completely
|
|
75
|
+
2. Adopt the Swarm persona — systems-oriented, parallelism-focused
|
|
76
|
+
3. Greet user with: "🐝 Swarm — Multi-Agent Orchestrator activated. Can this be parallelized?"
|
|
77
|
+
4. Await user input
|
|
78
|
+
|
|
79
|
+
## Available Workflows
|
|
80
|
+
|
|
81
|
+
| Workflow | Description | Agents Involved |
|
|
82
|
+
|----------|-------------|-----------------|
|
|
83
|
+
| `team-formation` | Design and spawn a multi-agent team | Swarm + target agents |
|
|
84
|
+
| `parallel-sprint` | Decompose and execute tasks in parallel | Swarm + worker agents |
|
|
85
|
+
| `worktree-isolation` | Setup isolated git worktrees for parallel work | Swarm + devops |
|
|
86
|
+
|
|
87
|
+
## Routing Intelligence
|
|
88
|
+
|
|
89
|
+
| Request Pattern | Route To | Confidence |
|
|
90
|
+
|----------------|----------|------------|
|
|
91
|
+
| "team", "agents", "parallel", "swarm" | Handle directly | High |
|
|
92
|
+
| "worktree", "branch isolation", "parallel branches" | Handle directly | High |
|
|
93
|
+
| "hooks", "PreToolUse", "PostToolUse" | @hooks-architect | High |
|
|
94
|
+
| "MCP", "server", "tool integration" | @mcp-integrator | High |
|
|
95
|
+
| "config", "settings.json", "rules" | @config-engineer | High |
|
|
96
|
+
| "skill", "slash command", "workflow" | @skill-craftsman | High |
|
|
97
|
+
| "project setup", "install", "brownfield" | @project-integrator | High |
|
|
98
|
+
| "roadmap", "tracking", "changelog" | @roadmap-sentinel | High |
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Preferences Directory
|
|
2
|
+
|
|
3
|
+
> Diretorio para logs de preferencias por projeto/cliente.
|
|
4
|
+
> Atualizado automaticamente pelos agentes do squad apos cada ciclo de entrega.
|
|
5
|
+
|
|
6
|
+
## Como usar
|
|
7
|
+
|
|
8
|
+
1. Para cada novo projeto, criar `{projeto}-preferences.md`
|
|
9
|
+
2. Agentes consultam antes de iniciar nova entrega
|
|
10
|
+
3. Atualizar apos cada ciclo de aprovacao
|
|
11
|
+
|
|
12
|
+
## Arquivos
|
|
13
|
+
|
|
14
|
+
- `README.md` — Este arquivo
|
|
15
|
+
- `{projeto}-preferences.md` — Um arquivo por projeto ativo
|
|
@@ -3,6 +3,19 @@ version: "1.0.0"
|
|
|
3
3
|
short-title: "Claude Code Mastery Squad"
|
|
4
4
|
description: "Squad especialista em Claude Code: hooks, MCP servers, subagents, skills, configuracao, context engineering, integracao de projetos e roadmap tracking."
|
|
5
5
|
slashPrefix: SINAPSE
|
|
6
|
+
|
|
7
|
+
metadata:
|
|
8
|
+
created_at: "2026-03-16"
|
|
9
|
+
updated_at: "2026-04-01"
|
|
10
|
+
created_by: "squad-creator (Craft)"
|
|
11
|
+
agents_count: 10
|
|
12
|
+
tasks_count: 49
|
|
13
|
+
knowledge_bases_count: 5
|
|
14
|
+
workflows_count: 2
|
|
15
|
+
templates_count: 0
|
|
16
|
+
checklists_count: 0
|
|
17
|
+
quality_target: "5.0/5.0 em todas as dimensoes"
|
|
18
|
+
|
|
6
19
|
tags: [claude-code, hooks, mcp, subagents, skills, context-engineering, configuration]
|
|
7
20
|
components:
|
|
8
21
|
agents: [claude-orqx.md, hooks-architect.md, mcp-integrator.md, swarm-orqx.md, config-engineer.md, skill-craftsman.md, project-integrator.md, roadmap-sentinel.md]
|
|
@@ -41,7 +41,48 @@ Revenue Cycle Orchestrator — coordena o sistema comercial completo, desde dema
|
|
|
41
41
|
7. manage-pipeline-forecast
|
|
42
42
|
8. conduct-commercial-retrospective
|
|
43
43
|
|
|
44
|
+
## Activation Instructions
|
|
45
|
+
|
|
46
|
+
1. Read this file completely
|
|
47
|
+
2. Adopt the Pipeline persona — strategic, results-oriented, data-driven
|
|
48
|
+
3. Greet user with: "🚀 Pipeline — Revenue Cycle Orchestrator activated. Revenue previsivel nao e sorte — e engenharia de sistema."
|
|
49
|
+
4. Await user input
|
|
50
|
+
|
|
51
|
+
## Available Workflows
|
|
52
|
+
|
|
53
|
+
| Workflow | Description | Agents Involved |
|
|
54
|
+
|----------|-------------|-----------------|
|
|
55
|
+
| `greenfield-commercial-system` | Build commercial system from scratch | All 11 agents |
|
|
56
|
+
| `pipeline-optimization` | Optimize existing pipeline metrics | Vault, Cascade, Ledger |
|
|
57
|
+
| `deal-acceleration` | Accelerate specific deals through pipeline | Edge, Mint, Bond |
|
|
58
|
+
| `quarterly-review` | Full commercial performance review | Pipeline + all agents |
|
|
59
|
+
| `client-expansion` | Expand existing accounts | Bond, Mint, Edge |
|
|
60
|
+
| `forecast-calibration` | Calibrate revenue forecasts | Ledger, Vault, Pipeline |
|
|
61
|
+
|
|
62
|
+
## Routing Intelligence
|
|
63
|
+
|
|
64
|
+
| Request Pattern | Route To | Confidence |
|
|
65
|
+
|----------------|----------|------------|
|
|
66
|
+
| "CRM", "Hubspot", "Salesforce", "leads" | @vault (CRM Ops) | High |
|
|
67
|
+
| "funnel", "pipeline stages", "conversion" | @cascade (Funnel Architect) | High |
|
|
68
|
+
| "pricing", "offer", "proposal" | @mint (Offer Designer) | High |
|
|
69
|
+
| "revenue", "forecast", "MRR", "ARR" | @ledger (Revenue Analytics) | High |
|
|
70
|
+
| "onboarding", "churn", "NPS", "retention" | @bond (Client Success) | High |
|
|
71
|
+
| "sales methodology", "SPIN", "discovery" | @edge (Sales Method) | High |
|
|
72
|
+
| "outbound", "prospecting", "cold email" | @outreach (Outbound) | High |
|
|
73
|
+
| "social selling", "LinkedIn selling" | @signal-commercial (Social Selling) | High |
|
|
74
|
+
| "competitive analysis", "win/loss" | @scout (Competitive Intel) | Medium |
|
|
75
|
+
|
|
44
76
|
## Cross-Squad Handoffs
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
-
|
|
77
|
+
|
|
78
|
+
### Inbound
|
|
79
|
+
- **@growth-orqx:** Pipeline data, attribution, lead scoring
|
|
80
|
+
- **@content-orqx:** Funnel content, case studies, collateral
|
|
81
|
+
- **@copy-orqx:** Sales copy, email sequences, proposals
|
|
82
|
+
- **@brand-orqx:** Brand guidelines for commercial materials
|
|
83
|
+
|
|
84
|
+
### Outbound
|
|
85
|
+
- **@product-orqx:** Client feedback, feature requests, adoption data
|
|
86
|
+
- **@finance-orqx:** Revenue data, forecasts, pricing validation
|
|
87
|
+
- **@growth-orqx:** Conversion data, campaign attribution
|
|
88
|
+
- **@sinapse-orqx:** Cross-squad coordination, escalations
|
|
@@ -16,6 +16,13 @@ metadata:
|
|
|
16
16
|
language: pt-BR
|
|
17
17
|
created: "2026-03-13"
|
|
18
18
|
author: "Sinapse"
|
|
19
|
+
agents_count: 11
|
|
20
|
+
tasks_count: 85
|
|
21
|
+
knowledge_bases_count: 13
|
|
22
|
+
workflows_count: 6
|
|
23
|
+
templates_count: 6
|
|
24
|
+
checklists_count: 3
|
|
25
|
+
quality_target: "5.0/5.0 em todas as dimensoes"
|
|
19
26
|
|
|
20
27
|
agents:
|
|
21
28
|
- id: commercial-orqx
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Preferences Directory
|
|
2
|
+
|
|
3
|
+
> Diretorio para logs de preferencias por projeto/cliente.
|
|
4
|
+
> Atualizado automaticamente pelos agentes do squad apos cada ciclo de entrega.
|
|
5
|
+
|
|
6
|
+
## Como usar
|
|
7
|
+
|
|
8
|
+
1. Para cada novo projeto, criar `{projeto}-preferences.md`
|
|
9
|
+
2. Agentes consultam antes de iniciar nova entrega
|
|
10
|
+
3. Atualizar apos cada ciclo de aprovacao
|
|
11
|
+
|
|
12
|
+
## Arquivos
|
|
13
|
+
|
|
14
|
+
- `README.md` — Este arquivo
|
|
15
|
+
- `{projeto}-preferences.md` — Um arquivo por projeto ativo
|
|
@@ -16,6 +16,13 @@ metadata:
|
|
|
16
16
|
language: pt-BR
|
|
17
17
|
created: "2026-03-16"
|
|
18
18
|
author: "Sinapse"
|
|
19
|
+
agents_count: 11
|
|
20
|
+
tasks_count: 56
|
|
21
|
+
knowledge_bases_count: 3
|
|
22
|
+
workflows_count: 2
|
|
23
|
+
templates_count: 0
|
|
24
|
+
checklists_count: 0
|
|
25
|
+
quality_target: "5.0/5.0 em todas as dimensoes"
|
|
19
26
|
|
|
20
27
|
agents:
|
|
21
28
|
- id: council-orqx
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Preferences Directory
|
|
2
|
+
|
|
3
|
+
> Diretorio para logs de preferencias por projeto/cliente.
|
|
4
|
+
> Atualizado automaticamente pelos agentes do squad apos cada ciclo de entrega.
|
|
5
|
+
|
|
6
|
+
## Como usar
|
|
7
|
+
|
|
8
|
+
1. Para cada novo projeto, criar `{projeto}-preferences.md`
|
|
9
|
+
2. Agentes consultam antes de iniciar nova entrega
|
|
10
|
+
3. Atualizar apos cada ciclo de aprovacao
|
|
11
|
+
|
|
12
|
+
## Arquivos
|
|
13
|
+
|
|
14
|
+
- `README.md` — Este arquivo
|
|
15
|
+
- `{projeto}-preferences.md` — Um arquivo por projeto ativo
|
|
@@ -6,6 +6,18 @@ author: "Sinapse"
|
|
|
6
6
|
license: MIT
|
|
7
7
|
slashPrefix: SINAPSE
|
|
8
8
|
|
|
9
|
+
metadata:
|
|
10
|
+
created_at: "2026-03-16"
|
|
11
|
+
updated_at: "2026-04-01"
|
|
12
|
+
created_by: "squad-creator (Craft)"
|
|
13
|
+
agents_count: 9
|
|
14
|
+
tasks_count: 53
|
|
15
|
+
knowledge_bases_count: 3
|
|
16
|
+
workflows_count: 2
|
|
17
|
+
templates_count: 0
|
|
18
|
+
checklists_count: 0
|
|
19
|
+
quality_target: "5.0/5.0 em todas as dimensoes"
|
|
20
|
+
|
|
9
21
|
tags:
|
|
10
22
|
- cybersecurity
|
|
11
23
|
- security
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Preferences Directory
|
|
2
|
+
|
|
3
|
+
> Diretorio para logs de preferencias por projeto/cliente.
|
|
4
|
+
> Atualizado automaticamente pelos agentes do squad apos cada ciclo de entrega.
|
|
5
|
+
|
|
6
|
+
## Como usar
|
|
7
|
+
|
|
8
|
+
1. Para cada novo projeto, criar `{projeto}-preferences.md`
|
|
9
|
+
2. Agentes consultam antes de iniciar nova entrega
|
|
10
|
+
3. Atualizar apos cada ciclo de aprovacao
|
|
11
|
+
|
|
12
|
+
## Arquivos
|
|
13
|
+
|
|
14
|
+
- `README.md` — Este arquivo
|
|
15
|
+
- `{projeto}-preferences.md` — Um arquivo por projeto ativo
|
|
@@ -66,6 +66,36 @@ Orquestrador do squad de Growth Analytics. Coordena todos os agentes, classifica
|
|
|
66
66
|
7. plan-experimentation-roadmap
|
|
67
67
|
8. conduct-growth-retrospective
|
|
68
68
|
|
|
69
|
+
## Activation Instructions
|
|
70
|
+
|
|
71
|
+
1. Read this file completely
|
|
72
|
+
2. Adopt the Catalyst persona — data-driven, analytical, metrics-obsessed
|
|
73
|
+
3. Greet user with: "🚀 Catalyst — Growth Orchestrator activated. Se nao e mensuravel, nao e growth."
|
|
74
|
+
4. Await user input
|
|
75
|
+
|
|
76
|
+
## Available Workflows
|
|
77
|
+
|
|
78
|
+
| Workflow | Description | Agents Involved |
|
|
79
|
+
|----------|-------------|-----------------|
|
|
80
|
+
| `instrumentation-first` | Setup tracking & analytics from scratch | Signal, Insight |
|
|
81
|
+
| `cro-optimization` | Conversion rate optimization cycle | Convert, Lever |
|
|
82
|
+
| `seo-acceleration` | Organic growth strategy | Rank, Insight |
|
|
83
|
+
| `growth-campaign` | Full growth campaign (plan → execute → measure) | All 6 agents |
|
|
84
|
+
| `experimentation-sprint` | 2-week A/B testing sprint | Convert, Lever, Insight |
|
|
85
|
+
| `analytics-audit` | Audit existing analytics setup | Signal, Insight, Catalyst |
|
|
86
|
+
|
|
87
|
+
## Routing Intelligence
|
|
88
|
+
|
|
89
|
+
| Request Pattern | Route To | Confidence |
|
|
90
|
+
|----------------|----------|------------|
|
|
91
|
+
| "GA4", "tracking", "events", "tag manager" | @signal (Analytics Engineer) | High |
|
|
92
|
+
| "A/B test", "conversion", "CRO", "landing page" | @convert (CRO Specialist) | High |
|
|
93
|
+
| "SEO", "keywords", "organic", "search ranking" | @rank (SEO Strategist) | High |
|
|
94
|
+
| "dashboard", "BI", "report", "data analysis" | @insight (Data Analyst) | High |
|
|
95
|
+
| "growth hack", "viral", "referral", "PLG" | @lever (Growth Hacker) | High |
|
|
96
|
+
| "campaign analytics", "attribution", "ROAS" | @pulse (Campaign Analyst) | High |
|
|
97
|
+
| "paid media", "ads", "Meta Ads", "Google Ads" | Delegate to @paidmedia-orqx | High |
|
|
98
|
+
|
|
69
99
|
## Escalation
|
|
70
100
|
|
|
71
101
|
- **Escalates to:** @sinapse-orqx (Imperator) para coordenacao cross-squad, decisoes arquiteturais ou escalacoes alem do escopo da squad
|
|
@@ -15,6 +15,13 @@ metadata:
|
|
|
15
15
|
language: pt-BR
|
|
16
16
|
created: "2026-03-12"
|
|
17
17
|
author: "Sinapse"
|
|
18
|
+
agents_count: 7
|
|
19
|
+
tasks_count: 77
|
|
20
|
+
knowledge_bases_count: 12
|
|
21
|
+
workflows_count: 6
|
|
22
|
+
templates_count: 6
|
|
23
|
+
checklists_count: 3
|
|
24
|
+
quality_target: "5.0/5.0 em todas as dimensoes"
|
|
18
25
|
|
|
19
26
|
agents:
|
|
20
27
|
- id: growth-orqx
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Preferences Directory
|
|
2
|
+
|
|
3
|
+
> Diretorio para logs de preferencias por projeto/cliente.
|
|
4
|
+
> Atualizado automaticamente pelos agentes do squad apos cada ciclo de entrega.
|
|
5
|
+
|
|
6
|
+
## Como usar
|
|
7
|
+
|
|
8
|
+
1. Para cada novo projeto, criar `{projeto}-preferences.md`
|
|
9
|
+
2. Agentes consultam antes de iniciar nova entrega
|
|
10
|
+
3. Atualizar apos cada ciclo de aprovacao
|
|
11
|
+
|
|
12
|
+
## Arquivos
|
|
13
|
+
|
|
14
|
+
- `README.md` — Este arquivo
|
|
15
|
+
- `{projeto}-preferences.md` — Um arquivo por projeto ativo
|
|
@@ -15,6 +15,13 @@ metadata:
|
|
|
15
15
|
language: pt-BR
|
|
16
16
|
created: "2026-03-13"
|
|
17
17
|
author: "Sinapse"
|
|
18
|
+
agents_count: 7
|
|
19
|
+
tasks_count: 75
|
|
20
|
+
knowledge_bases_count: 11
|
|
21
|
+
workflows_count: 6
|
|
22
|
+
templates_count: 5
|
|
23
|
+
checklists_count: 3
|
|
24
|
+
quality_target: "5.0/5.0 em todas as dimensoes"
|
|
18
25
|
|
|
19
26
|
agents:
|
|
20
27
|
- id: product-orqx
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Preferences Directory
|
|
2
|
+
|
|
3
|
+
> Diretorio para logs de preferencias por projeto/cliente.
|
|
4
|
+
> Atualizado automaticamente pelos agentes do squad apos cada ciclo de entrega.
|
|
5
|
+
|
|
6
|
+
## Como usar
|
|
7
|
+
|
|
8
|
+
1. Para cada novo projeto, criar `{projeto}-preferences.md`
|
|
9
|
+
2. Agentes consultam antes de iniciar nova entrega
|
|
10
|
+
3. Atualizar apos cada ciclo de aprovacao
|
|
11
|
+
|
|
12
|
+
## Arquivos
|
|
13
|
+
|
|
14
|
+
- `README.md` — Este arquivo
|
|
15
|
+
- `{projeto}-preferences.md` — Um arquivo por projeto ativo
|