sinapse-ai 1.11.3 → 1.12.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/enforce-architecture-first.cjs +2 -2
- package/.claude/hooks/enforce-delegation.cjs +2 -2
- package/.claude/hooks/enforce-permission-mode.cjs +12 -12
- package/.claude/hooks/enforce-story-gate.cjs +5 -5
- package/.claude/hooks/precompact-session-digest.cjs +2 -2
- package/.claude/hooks/secret-scanning.cjs +6 -6
- package/.claude/hooks/telemetry-post-tool.cjs +0 -1
- package/.claude/hooks/write-path-validation.cjs +2 -2
- package/.sinapse-ai/core/code-intel/helpers/dev-helper.js +1 -1
- package/.sinapse-ai/core/code-intel/helpers/devops-helper.js +0 -1
- package/.sinapse-ai/core/code-intel/helpers/planning-helper.js +1 -1
- package/.sinapse-ai/core/code-intel/helpers/qa-helper.js +2 -2
- package/.sinapse-ai/core/config/template-overrides.js +1 -1
- package/.sinapse-ai/core/doctor/checks/git-hooks.js +6 -3
- package/.sinapse-ai/core/doctor/checks/npm-packages.js +1 -1
- package/.sinapse-ai/core/doctor/checks/rules-files.js +0 -1
- package/.sinapse-ai/core/doctor/index.js +0 -1
- package/.sinapse-ai/core/graph-dashboard/cli.js +1 -1
- package/.sinapse-ai/core/graph-dashboard/data-sources/code-intel-source.js +1 -1
- package/.sinapse-ai/core/health-check/checks/project/constitution-consistency.js +0 -1
- package/.sinapse-ai/core/ideation/ideation-engine.js +0 -2
- package/.sinapse-ai/core/ids/layer-classifier.js +1 -1
- package/.sinapse-ai/core/registry/build-registry.js +12 -2
- package/.sinapse-ai/core/registry/service-registry.json +178 -55
- package/.sinapse-ai/core/registry/squad-agent-resolver.js +6 -0
- package/.sinapse-ai/core/synapse/layers/layer-processor.js +1 -1
- package/.sinapse-ai/data/capability-detection.js +15 -15
- package/.sinapse-ai/data/tok3-token-comparison.js +0 -3
- package/.sinapse-ai/data/tool-search-validation.js +1 -1
- package/.sinapse-ai/development/agents/snps-orqx.md +109 -0
- package/.sinapse-ai/development/scripts/agent-config-loader.js +8 -2
- package/.sinapse-ai/development/templates/sinapse-doc-template.md +6 -6
- package/.sinapse-ai/git-hooks/lib/framework-guard.js +1 -0
- package/.sinapse-ai/git-hooks/lib/staged-protected-files-guard.js +63 -0
- package/.sinapse-ai/git-hooks/pre-commit +3 -1
- package/.sinapse-ai/index.d.ts +19 -0
- package/.sinapse-ai/install-manifest.yaml +59 -55
- package/.sinapse-ai/package.json +0 -1
- package/.sinapse-ai/utils/filters/index.js +2 -1
- package/CHANGELOG.md +31 -2
- package/bin/commands/doctor.js +1 -1
- package/bin/commands/help.js +3 -4
- package/bin/commands/install.js +7 -7
- package/bin/commands/status.js +3 -3
- package/bin/modules/chrome-brain-installer.js +3 -3
- package/bin/postinstall.js +1 -1
- package/bin/sinapse-init.js +11 -9
- package/bin/sinapse.js +1 -1
- package/bin/utils/framework-guard.js +1 -0
- package/bin/utils/staged-protected-files-guard.js +63 -0
- package/package.json +19 -2
- package/packages/installer/src/index.js +1 -1
- package/packages/installer/src/installer/brownfield-upgrader.js +1 -1
- package/packages/installer/src/installer/git-hooks-installer.js +10 -3
- package/packages/installer/src/pro/pro-scaffolder.js +3 -3
- package/packages/installer/src/wizard/ide-config-generator.js +1 -1
- package/packages/installer/src/wizard/index.js +4 -41
- package/scripts/audit-tasks.cjs +1 -1
- package/scripts/package-synapse.js +1 -1
- package/scripts/sinapse-patch.js +31 -31
- package/scripts/sync-squad-yaml-components.js +3 -3
- package/scripts/validate-agents-md.js +1 -1
- package/scripts/validate-no-personal-leaks.js +1 -1
- package/scripts/validate-orqx-discipline.js +0 -2
- package/scripts/validate-package-completeness.js +7 -7
- package/scripts/validate-squad-yaml.js +6 -6
- package/sinapse/agents/sinapse-orqx.md +1 -1
- package/sinapse/agents/snps-orqx.md +110 -1
- package/squads/claude-code-mastery/agents/swarm-orqx.md +12 -11
- package/squads/claude-code-mastery/scripts/validate-setup.js +2 -2
- package/squads/squad-brand/agents/brand-orqx.md +16 -1
- package/squads/squad-cloning/agents/cloning-orqx.md +2 -0
- package/squads/squad-commercial/agents/commercial-orqx.md +7 -4
- package/squads/squad-council/squad.yaml +67 -11
- package/squads/squad-design/agents/design-orqx.md +20 -0
- package/squads/squad-finance/agents/finance-orqx.md +6 -0
- package/squads/squad-paidmedia/agents/paidmedia-orqx.md +3 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,8 +1,37 @@
|
|
|
1
|
-
## [1.
|
|
1
|
+
## [1.12.0](https://github.com/caioimori/sinapse-ai/compare/1.11.3...1.12.0) (2026-06-20)
|
|
2
|
+
|
|
3
|
+
### Features
|
|
4
|
+
|
|
5
|
+
* **git-hooks:** protected-files guard recusa deleção/untrack de arquivos críticos [Story feat-protected-files-commit-guard] ([#257](https://github.com/caioimori/sinapse-ai/issues/257)) ([ee50168](https://github.com/caioimori/sinapse-ai/commit/ee501688d945591e0759c0f84963c6d44ff34f0e))
|
|
2
6
|
|
|
3
7
|
### Bug Fixes
|
|
4
8
|
|
|
5
|
-
* **
|
|
9
|
+
* **activation:** resolve alias de agent id pro arquivo canonico (greeting degradado em 6/12) [Story fix-agent-activation-alias-resolution] ([#256](https://github.com/caioimori/sinapse-ai/issues/256)) ([dffae0c](https://github.com/caioimori/sinapse-ai/commit/dffae0c1680b7ded166a44185a02be1fbb3bedcc))
|
|
10
|
+
* **doctor:** git-hooks usa WARN p/ hook system proprio (era FAIL) ([#240](https://github.com/caioimori/sinapse-ai/issues/240)) ([d112326](https://github.com/caioimori/sinapse-ai/commit/d1123269cbbe12d14fbedd116a1d92f9c2a86925))
|
|
11
|
+
* **ide-sync:** resync mirror .claude + conserta YAML do swarm-orqx ([#244](https://github.com/caioimori/sinapse-ai/issues/244)) ([bdc93b6](https://github.com/caioimori/sinapse-ai/commit/bdc93b6118389a979289505d37a8eec9752d51b1))
|
|
12
|
+
* **registry:** dedup robusto de IDs + ressync service-registry stale [Story fix-registry-dedup-stale] ([#251](https://github.com/caioimori/sinapse-ai/issues/251)) ([e53eac3](https://github.com/caioimori/sinapse-ai/commit/e53eac3e70a53efdda9102399c90c68bb0c6b425))
|
|
13
|
+
* **squad-commercial:** religa roteamento do orqx aos 9 especialistas reais ([#238](https://github.com/caioimori/sinapse-ai/issues/238)) ([6469883](https://github.com/caioimori/sinapse-ai/commit/64698839ad08ee0a045f90257a1b2fafbc2a5ade))
|
|
14
|
+
* **squad-council:** enumera as 56 tasks no squad.yaml (eram nao-descobriveis) ([#242](https://github.com/caioimori/sinapse-ai/issues/242)) ([20320fd](https://github.com/caioimori/sinapse-ai/commit/20320fd2b21312f64de7faa91a8f3a6e7c54d988))
|
|
15
|
+
* **squads:** religa 16 especialistas orfaos nos orqx de 5 squads ([#241](https://github.com/caioimori/sinapse-ai/issues/241)) ([ac7283b](https://github.com/caioimori/sinapse-ai/commit/ac7283bc03a672fbb9568918b80734cd50ca62f0))
|
|
16
|
+
* **test:** corrige semantica do coverageThreshold + sobe piso real do core/ [Story test-coverage-threshold-semantics] ([#255](https://github.com/caioimori/sinapse-ai/issues/255)) ([e9f80ee](https://github.com/caioimori/sinapse-ai/commit/e9f80eeb57758fdb3f5c408e6459ba8b89f59407)), closes [#254](https://github.com/caioimori/sinapse-ai/issues/254) [#254](https://github.com/caioimori/sinapse-ai/issues/254)
|
|
17
|
+
|
|
18
|
+
### Maintenance
|
|
19
|
+
|
|
20
|
+
* **ci:** renomeia workflow 'Test' -> 'Post-Merge Smoke & Build Checks' ([#249](https://github.com/caioimori/sinapse-ai/issues/249)) ([a40b0c7](https://github.com/caioimori/sinapse-ai/commit/a40b0c7ca9355a715424858813c02f416e4e87de))
|
|
21
|
+
* **conformance:** assisted-mode default + rebrand instalador legado + remove residuo ES [Story chore-sinapse-conformance] ([#258](https://github.com/caioimori/sinapse-ai/issues/258)) ([3fb88a3](https://github.com/caioimori/sinapse-ai/commit/3fb88a3712d0e44fa53fdc3e984a8c0cf30d265f))
|
|
22
|
+
* **deps:** bump undici dev (6.27.0/7.28.0) p/ corrigir HIGH dev-only ([#243](https://github.com/caioimori/sinapse-ai/issues/243)) ([9940576](https://github.com/caioimori/sinapse-ai/commit/99405767012b5cd06d942a1ed47148e4b9fd93c0))
|
|
23
|
+
* ignora colaborator/ (pasta local de referencia, fora do git e do npm) ([34bc1bc](https://github.com/caioimori/sinapse-ai/commit/34bc1bc07fa9f44df9c8259ace099f5f5a5aedf0))
|
|
24
|
+
* **lint:** autofix triviais (392->44 warns, 0 errors) + ignora colaborator/ ([#245](https://github.com/caioimori/sinapse-ai/issues/245)) ([70c54ae](https://github.com/caioimori/sinapse-ai/commit/70c54ae01403825724f3987e72ce70978c41b074))
|
|
25
|
+
* **lint:** zera os 33 warnings remanescentes (0 errors, 0 warnings) ([#250](https://github.com/caioimori/sinapse-ai/issues/250)) ([0ac779a](https://github.com/caioimori/sinapse-ai/commit/0ac779a7855166e3ab6cae7b74f163a9f2fa5efc))
|
|
26
|
+
* **packaging:** corta node_modules do tarball + higiene de deps runtime ([#239](https://github.com/caioimori/sinapse-ai/issues/239)) ([d36afb0](https://github.com/caioimori/sinapse-ai/commit/d36afb09da96c946ab9f06743306513ff6aa55ce))
|
|
27
|
+
* **pkg:** expoe API programatica (main/module/types/exports) + index.d.ts honesto ([#253](https://github.com/caioimori/sinapse-ai/issues/253)) ([4971413](https://github.com/caioimori/sinapse-ai/commit/4971413b419fe41000c0fbfffe668eaec39cc013))
|
|
28
|
+
* **test:** deleta 22 testes mortos do tools-system (codigo removido v4.31->v2.1) ([#252](https://github.com/caioimori/sinapse-ai/issues/252)) ([8ed5bd6](https://github.com/caioimori/sinapse-ai/commit/8ed5bd61c150e4c25f04fef70d8d60dc9325aeb1))
|
|
29
|
+
* **test:** exclui colaborator/ do jest (local test passa a espelhar CI) ([#248](https://github.com/caioimori/sinapse-ai/issues/248)) ([3eae775](https://github.com/caioimori/sinapse-ai/commit/3eae775298d2686f679fcadbb80994044d974874)), closes [#245](https://github.com/caioimori/sinapse-ai/issues/245)
|
|
30
|
+
|
|
31
|
+
### Refactoring
|
|
32
|
+
|
|
33
|
+
* **identity:** SINAPSE canonico — remove dir SNPS/ stale + corrige help ([#246](https://github.com/caioimori/sinapse-ai/issues/246)) ([3a805fa](https://github.com/caioimori/sinapse-ai/commit/3a805fa5366dce9881125521a41e90d6eb4a0e80))
|
|
34
|
+
* **identity:** unifica conteudo do Imperator (snps-orqx desatualizado) ([#247](https://github.com/caioimori/sinapse-ai/issues/247)) ([f52376d](https://github.com/caioimori/sinapse-ai/commit/f52376d040fdfc2c3f3c4f95789249d5cae6f8ef))
|
|
6
35
|
|
|
7
36
|
# Changelog
|
|
8
37
|
|
package/bin/commands/doctor.js
CHANGED
|
@@ -33,7 +33,7 @@ Exit codes (Story A.3):
|
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
const doctorModulePath = path.join(__dirname, '..', '..', '.sinapse-ai', 'core', 'doctor');
|
|
36
|
-
|
|
36
|
+
|
|
37
37
|
const { runDoctorChecks, resolveExitCode } = require(doctorModulePath);
|
|
38
38
|
const result = await runDoctorChecks({
|
|
39
39
|
fix: Boolean(opts.fix),
|
package/bin/commands/help.js
CHANGED
|
@@ -31,10 +31,9 @@ function cmdHelp() {
|
|
|
31
31
|
logger.always(` ${CYAN}sinapse --continue${NC} Continua última sessão`);
|
|
32
32
|
logger.always('');
|
|
33
33
|
logger.always(`${BOLD}Agents:${NC}\n`);
|
|
34
|
-
logger.always(` Invocação canônica: ${CYAN}/
|
|
35
|
-
logger.always(` Exemplo: ${CYAN}/
|
|
36
|
-
logger.always(` Master orchestrator: ${CYAN}@
|
|
37
|
-
logger.always(` ${DIM}Alias /SINAPSE:agents:* preservado até v1.3.0 (deprecação suave).${NC}`);
|
|
34
|
+
logger.always(` Invocação canônica: ${CYAN}/SINAPSE:agents:{agent-id}${NC}`);
|
|
35
|
+
logger.always(` Exemplo: ${CYAN}/SINAPSE:agents:brand-orqx${NC}`);
|
|
36
|
+
logger.always(` Master orchestrator: ${CYAN}@sinapse-orqx${NC} (alias: ${DIM}@snps-orqx${NC})`);
|
|
38
37
|
logger.always('');
|
|
39
38
|
logger.always(`${BOLD}Ajuda extra:${NC}\n`);
|
|
40
39
|
logger.always(` Erros comuns + remediação: ${CYAN}docs/guides/cli-errors.md${NC}`);
|
package/bin/commands/install.js
CHANGED
|
@@ -155,7 +155,7 @@ async function cmdInstallGlobal(opts = {}) {
|
|
|
155
155
|
if (squads.length === 0) {
|
|
156
156
|
logger.error(`${RED}Erro: nenhum diretório de squad encontrado no pacote.${NC}`);
|
|
157
157
|
logger.error(`Tente reinstalar: ${CYAN}npm install -g sinapse-ai${NC}`);
|
|
158
|
-
logger.error(
|
|
158
|
+
logger.error('Se persistir, abra um issue: https://github.com/caioimori/sinapse-ai/issues');
|
|
159
159
|
process.exit(1);
|
|
160
160
|
}
|
|
161
161
|
|
|
@@ -275,7 +275,7 @@ async function cmdInstallGlobal(opts = {}) {
|
|
|
275
275
|
for (const f of fs.readdirSync(CLAUDE_COMMANDS_DIR)) {
|
|
276
276
|
fs.unlinkSync(path.join(CLAUDE_COMMANDS_DIR, f));
|
|
277
277
|
}
|
|
278
|
-
} catch {}
|
|
278
|
+
} catch { /* dir may not exist on a fresh install */ }
|
|
279
279
|
|
|
280
280
|
const sinapseBase = toForwardSlash(SINAPSE_HOME);
|
|
281
281
|
const writtenAgents = new Set();
|
|
@@ -622,13 +622,13 @@ function generateCommandMd(agentId, agentName, agentIcon, squadName, squadPath,
|
|
|
622
622
|
? `4. Briefing-on-activation check (this agent is an ORCHESTRATOR):
|
|
623
623
|
- If user provided briefing/context with the activation → proceed IMMEDIATELY: absorb → diagnose → plan with phases + agents + handoffs → execute (YOLO). NEVER ask "do you want me to plan?".
|
|
624
624
|
- If bare activation only → await briefing. On receipt, apply same flow automatically.`
|
|
625
|
-
:
|
|
625
|
+
: '4. HALT and await user input';
|
|
626
626
|
|
|
627
627
|
const step6 = isOrchestrator
|
|
628
628
|
? `6. Briefing-on-activation check (ORCHESTRATOR):
|
|
629
629
|
- If user provided briefing → proceed IMMEDIATELY: absorb → diagnose → plan → execute
|
|
630
630
|
- If bare activation → await briefing, then plan automatically. NEVER ask "do you want me to plan?".`
|
|
631
|
-
:
|
|
631
|
+
: '6. HALT and await user input';
|
|
632
632
|
|
|
633
633
|
// Frontmatter (name + description) is REQUIRED so the file resolves as a Claude Code
|
|
634
634
|
// subagent (@id) — without it, @id matches nothing. The same file doubles as a slash
|
|
@@ -754,7 +754,7 @@ See \`.claude/rules/squad-awareness.md\` for the full delegation map.
|
|
|
754
754
|
try {
|
|
755
755
|
const orqxFile = fs.readdirSync(sAgentsDir).find(f => f.endsWith('-orqx.md'));
|
|
756
756
|
if (orqxFile) orqxName = orqxFile.replace('.md', '');
|
|
757
|
-
} catch {}
|
|
757
|
+
} catch { /* fall back to the derived orqx name */ }
|
|
758
758
|
return `| ${s.name} | @${orqxName} | ${s.agents} agents, ${s.tasks} tasks |`;
|
|
759
759
|
}).join('\n');
|
|
760
760
|
|
|
@@ -828,12 +828,12 @@ exec claude --add-dir "${sinapsePathForBash}" --agent sinapse-orqx "$@"
|
|
|
828
828
|
`;
|
|
829
829
|
const bashPath = path.join(BIN_DIR, 'sinapse');
|
|
830
830
|
fs.writeFileSync(bashPath, bashLauncher);
|
|
831
|
-
try { fs.chmodSync(bashPath, 0o755); } catch {}
|
|
831
|
+
try { fs.chmodSync(bashPath, 0o755); } catch { /* chmod is best-effort (no-op on non-POSIX) */ }
|
|
832
832
|
logger.always(` ${GREEN}OK${NC} ~/bin/sinapse`);
|
|
833
833
|
|
|
834
834
|
// Windows CMD launcher
|
|
835
835
|
if (IS_WIN) {
|
|
836
|
-
const cmdLauncher =
|
|
836
|
+
const cmdLauncher = '@echo off\r\nclaude --add-dir "%USERPROFILE%\\.sinapse" --agent sinapse-orqx %*\r\n';
|
|
837
837
|
fs.writeFileSync(path.join(BIN_DIR, 'sinapse.cmd'), cmdLauncher);
|
|
838
838
|
logger.always(` ${GREEN}OK${NC} ~/bin/sinapse.cmd`);
|
|
839
839
|
}
|
package/bin/commands/status.js
CHANGED
|
@@ -23,9 +23,9 @@ function verifyInstall() {
|
|
|
23
23
|
const logger = getLogger();
|
|
24
24
|
const checks = [
|
|
25
25
|
[fs.existsSync(SINAPSE_HOME), `${getSquads(SINAPSE_HOME).length} squads in ~/.sinapse/`],
|
|
26
|
-
[fs.existsSync(CLAUDE_COMMANDS_DIR),
|
|
27
|
-
[fs.existsSync(path.join(BIN_DIR, 'sinapse')),
|
|
28
|
-
[fs.existsSync(path.join(SINAPSE_HOME, '.claude', 'rules', 'squad-awareness.md')),
|
|
26
|
+
[fs.existsSync(CLAUDE_COMMANDS_DIR), 'Commands in ~/.claude/commands/SINAPSE/agents/'],
|
|
27
|
+
[fs.existsSync(path.join(BIN_DIR, 'sinapse')), 'Launcher at ~/bin/sinapse'],
|
|
28
|
+
[fs.existsSync(path.join(SINAPSE_HOME, '.claude', 'rules', 'squad-awareness.md')), 'squad-awareness.md'],
|
|
29
29
|
];
|
|
30
30
|
|
|
31
31
|
for (const [ok, msg] of checks) {
|
|
@@ -183,7 +183,7 @@ function removeHooks(settingsPath, matchers) {
|
|
|
183
183
|
function sanitizeChromePath(chromePath) {
|
|
184
184
|
// Validate Chrome path contains only safe characters to prevent shell injection
|
|
185
185
|
const sanitized = chromePath.replace(/\\/g, '/');
|
|
186
|
-
if (!/^[a-zA-Z0-9\s/\-_.:()
|
|
186
|
+
if (!/^[a-zA-Z0-9\s/\-_.:()[\]]+$/.test(sanitized)) {
|
|
187
187
|
throw new Error(`Unsafe Chrome path detected: ${chromePath}`);
|
|
188
188
|
}
|
|
189
189
|
return sanitized;
|
|
@@ -201,7 +201,7 @@ if command -v taskkill &>/dev/null; then
|
|
|
201
201
|
elif command -v pgrep &>/dev/null; then
|
|
202
202
|
pgrep -f "user-data-dir=$CHROME_DEBUG_PROFILE" 2>/dev/null | xargs kill 2>/dev/null || true
|
|
203
203
|
fi`
|
|
204
|
-
:
|
|
204
|
+
: 'pgrep -f "user-data-dir=$CHROME_DEBUG_PROFILE" 2>/dev/null | xargs kill 2>/dev/null || true';
|
|
205
205
|
|
|
206
206
|
return `#!/bin/bash
|
|
207
207
|
# Chrome Brain — chrome-ensure (auto-launch)
|
|
@@ -253,7 +253,7 @@ if command -v taskkill &>/dev/null; then
|
|
|
253
253
|
elif command -v pgrep &>/dev/null; then
|
|
254
254
|
pgrep -f "user-data-dir=$CHROME_DEBUG_PROFILE" 2>/dev/null | xargs kill 2>/dev/null || true
|
|
255
255
|
fi`
|
|
256
|
-
:
|
|
256
|
+
: 'pgrep -f "user-data-dir=$CHROME_DEBUG_PROFILE" 2>/dev/null | xargs kill 2>/dev/null || true';
|
|
257
257
|
|
|
258
258
|
return `#!/bin/bash
|
|
259
259
|
# Chrome Brain — chrome-debug (manual launch)
|
package/bin/postinstall.js
CHANGED
|
@@ -485,7 +485,7 @@ function renderFinalSummary(opts = {}) {
|
|
|
485
485
|
}
|
|
486
486
|
lines.push('');
|
|
487
487
|
if (isGlobal) {
|
|
488
|
-
lines.push(
|
|
488
|
+
lines.push('Próximo passo:');
|
|
489
489
|
lines.push(` cd ${c.cyan}seu-projeto${c.reset}`);
|
|
490
490
|
lines.push(` ${c.cyan}sinapse install${c.reset}`);
|
|
491
491
|
} else {
|
package/bin/sinapse-init.js
CHANGED
|
@@ -55,17 +55,19 @@ function spawnAsync(command, options = {}) {
|
|
|
55
55
|
});
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
// ASCII Art Banner
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
58
|
+
// ASCII Art Banner — canonical SNPS AI wordmark in white (matches bin/lib/header.js).
|
|
59
|
+
// Kept in sync with the live banner so the legacy fallback installer never shows
|
|
60
|
+
// off-brand art (this banner predated the SINAPSE rebrand).
|
|
61
|
+
const BANNER = chalk.white.bold(`
|
|
62
|
+
███████╗███╗ ██╗██████╗ ███████╗ █████╗ ██╗
|
|
63
|
+
██╔════╝████╗ ██║██╔══██╗██╔════╝ ██╔══██╗██║
|
|
64
|
+
███████╗██╔██╗ ██║██████╔╝███████╗ ███████║██║
|
|
65
|
+
╚════██║██║╚██╗██║██╔═══╝ ╚════██║ ██╔══██║██║
|
|
66
|
+
███████║██║ ╚████║██║ ███████║ ██║ ██║██║
|
|
67
|
+
╚══════╝╚═╝ ╚═══╝╚═╝ ╚══════╝ ╚═╝ ╚═╝╚═╝
|
|
66
68
|
`);
|
|
67
69
|
|
|
68
|
-
const SUBTITLE = chalk.
|
|
70
|
+
const SUBTITLE = chalk.dim('Seu copiloto de inteligencia artificial');
|
|
69
71
|
// Read version from package.json dynamically
|
|
70
72
|
const packageJsonVersion = require(path.join(__dirname, '..', 'package.json')).version;
|
|
71
73
|
const VERSION = chalk.yellow(`Installer v${packageJsonVersion}`);
|
package/bin/sinapse.js
CHANGED
|
@@ -548,7 +548,7 @@ function findClaudeCliPath() {
|
|
|
548
548
|
try {
|
|
549
549
|
const npmRoot = execSync('npm root -g', { encoding: 'utf8' }).trim();
|
|
550
550
|
candidates.unshift(path.join(npmRoot, '@anthropic-ai/claude-code/cli.js'));
|
|
551
|
-
} catch {}
|
|
551
|
+
} catch { /* npm root -g may be unavailable; fall through to other candidates */ }
|
|
552
552
|
for (const p of candidates) {
|
|
553
553
|
if (fs.existsSync(p)) return p;
|
|
554
554
|
}
|
|
@@ -54,6 +54,7 @@ function globToRegex(glob) {
|
|
|
54
54
|
pattern = pattern.replace(/\*/g, '[^/]+');
|
|
55
55
|
|
|
56
56
|
// 4. Restore ** placeholder to any-depth matcher
|
|
57
|
+
// eslint-disable-next-line no-control-regex -- internal placeholder char (set above), never user input
|
|
57
58
|
pattern = pattern.replace(/\u0000/g, '.+');
|
|
58
59
|
|
|
59
60
|
// If pattern ends with .+ (was **), match prefix
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* staged-protected-files-guard — blocks a commit that DELETES (or untracks) a
|
|
6
|
+
* protected, committed-but-critical framework file.
|
|
7
|
+
*
|
|
8
|
+
* Why: on 2026-06-20 a "snapshot migracao notebook" sweep (`git add -A`) untracked
|
|
9
|
+
* `.sinapse-ai/core/registry/service-registry.json` (the committed registry drift
|
|
10
|
+
* detector, ~12k lines), bundled it with unrelated work, and pushed it. The
|
|
11
|
+
* framework-boundary guard is a no-op in contributor mode
|
|
12
|
+
* (boundary.frameworkProtection=false), so nothing stopped the deletion. This guard
|
|
13
|
+
* is ALWAYS on and narrowly targets that class of damage — it never touches normal
|
|
14
|
+
* edits, only the removal of a curated set of protected paths.
|
|
15
|
+
*
|
|
16
|
+
* Intentional removal (done in a story) bypasses with: git commit --no-verify
|
|
17
|
+
*
|
|
18
|
+
* Self-contained: Node built-ins + `git` only (matches the other lib guards so it
|
|
19
|
+
* bundles into <hooksDir>/lib/ with no extra deps).
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
const { spawnSync } = require('child_process');
|
|
23
|
+
|
|
24
|
+
// Curated, high-signal list. Keep small to guarantee zero false positives on
|
|
25
|
+
// normal work. These files are committed on purpose and must never be removed by
|
|
26
|
+
// an automated sweep without an explicit story.
|
|
27
|
+
const PROTECTED = ['.sinapse-ai/core/registry/service-registry.json'];
|
|
28
|
+
|
|
29
|
+
function stagedDeletions() {
|
|
30
|
+
// --no-renames forces a rename-away of a protected file to surface as a real
|
|
31
|
+
// deletion (D) of the old path, so moving the file out also trips the guard.
|
|
32
|
+
const res = spawnSync('git', ['diff', '--cached', '--name-status', '--no-renames'], {
|
|
33
|
+
encoding: 'utf8',
|
|
34
|
+
});
|
|
35
|
+
if (!res || res.status !== 0 || typeof res.stdout !== 'string') return [];
|
|
36
|
+
const deleted = [];
|
|
37
|
+
for (const line of res.stdout.split('\n')) {
|
|
38
|
+
if (!line) continue;
|
|
39
|
+
const parts = line.split('\t');
|
|
40
|
+
const status = parts[0];
|
|
41
|
+
const file = (parts[parts.length - 1] || '').replace(/\\/g, '/');
|
|
42
|
+
if (status === 'D') deleted.push(file);
|
|
43
|
+
}
|
|
44
|
+
return deleted;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const offenders = stagedDeletions().filter((f) => PROTECTED.includes(f));
|
|
48
|
+
|
|
49
|
+
if (offenders.length > 0) {
|
|
50
|
+
process.stderr.write(
|
|
51
|
+
'SINAPSE Protected Files: blocking commit — it deletes/untracks a protected file:\n',
|
|
52
|
+
);
|
|
53
|
+
for (const f of offenders) process.stderr.write(' - ' + f + '\n');
|
|
54
|
+
process.stderr.write(
|
|
55
|
+
'\nThese files are committed on purpose (e.g. service-registry.json is the registry\n' +
|
|
56
|
+
'drift detector). They must not be removed by an automated sweep (git add -A) or a\n' +
|
|
57
|
+
'machine-migration snapshot. If this removal is intentional, do it in a story and\n' +
|
|
58
|
+
'bypass once with: git commit --no-verify\n',
|
|
59
|
+
);
|
|
60
|
+
process.exit(1);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
process.exit(0);
|
package/package.json
CHANGED
|
@@ -1,12 +1,23 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sinapse-ai",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.12.0",
|
|
4
4
|
"description": "SINAPSE AI: Framework de orquestracao de IA — 17 squads, 172 agentes especializados",
|
|
5
5
|
"bin": {
|
|
6
6
|
"sinapse": "bin/sinapse.js",
|
|
7
7
|
"sinapse-ai": "bin/cli.js",
|
|
8
8
|
"sinapse-delegate": "bin/sinapse-delegate.js"
|
|
9
9
|
},
|
|
10
|
+
"main": ".sinapse-ai/index.js",
|
|
11
|
+
"module": ".sinapse-ai/index.esm.js",
|
|
12
|
+
"types": ".sinapse-ai/index.d.ts",
|
|
13
|
+
"exports": {
|
|
14
|
+
".": {
|
|
15
|
+
"types": "./.sinapse-ai/index.d.ts",
|
|
16
|
+
"default": "./.sinapse-ai/index.js"
|
|
17
|
+
},
|
|
18
|
+
"./package.json": "./package.json",
|
|
19
|
+
"./*": "./*"
|
|
20
|
+
},
|
|
10
21
|
"preferGlobal": false,
|
|
11
22
|
"workspaces": [
|
|
12
23
|
"packages/*"
|
|
@@ -16,6 +27,8 @@
|
|
|
16
27
|
"scripts/",
|
|
17
28
|
"packages/",
|
|
18
29
|
".sinapse-ai/",
|
|
30
|
+
"!.sinapse-ai/node_modules",
|
|
31
|
+
"!**/node_modules/**",
|
|
19
32
|
".claude/CLAUDE.md",
|
|
20
33
|
".claude/rules/",
|
|
21
34
|
".claude/hooks/",
|
|
@@ -139,6 +152,7 @@
|
|
|
139
152
|
"cli-progress": "^3.12.0",
|
|
140
153
|
"commander": "^12.1.0",
|
|
141
154
|
"cross-spawn": "^7.0.6",
|
|
155
|
+
"diff": "^5.2.0",
|
|
142
156
|
"execa": "^5.1.1",
|
|
143
157
|
"fast-glob": "^3.3.3",
|
|
144
158
|
"fs-extra": "^11.3.2",
|
|
@@ -178,6 +192,9 @@
|
|
|
178
192
|
"url": "https://github.com/caioimori/sinapse-ai/issues"
|
|
179
193
|
},
|
|
180
194
|
"homepage": "https://github.com/caioimori/sinapse-ai#readme",
|
|
195
|
+
"publishConfig": {
|
|
196
|
+
"access": "public"
|
|
197
|
+
},
|
|
181
198
|
"engines": {
|
|
182
199
|
"node": ">=18.0.0",
|
|
183
200
|
"npm": ">=9.0.0"
|
|
@@ -216,7 +233,7 @@
|
|
|
216
233
|
]
|
|
217
234
|
},
|
|
218
235
|
"overrides": {
|
|
219
|
-
"diff": "^
|
|
236
|
+
"diff": "^5.2.0",
|
|
220
237
|
"serialize-javascript": "^7.0.5",
|
|
221
238
|
"picomatch": "^4.0.4",
|
|
222
239
|
"brace-expansion": "^5.0.6",
|
|
@@ -19,7 +19,7 @@ if (require.main === module) {
|
|
|
19
19
|
Promise.resolve()
|
|
20
20
|
.then(() => wizard.runWizard())
|
|
21
21
|
.catch((error) => {
|
|
22
|
-
|
|
22
|
+
|
|
23
23
|
console.error('Installer failed:', error && error.message ? error.message : error);
|
|
24
24
|
process.exit(1);
|
|
25
25
|
});
|
|
@@ -287,7 +287,7 @@ async function applyUpgrade(report, sourceDir, targetDir, options = {}) {
|
|
|
287
287
|
result.mergeWarnings = result.mergeWarnings || [];
|
|
288
288
|
for (const conflict of conflicts) {
|
|
289
289
|
result.mergeWarnings.push(
|
|
290
|
-
`core-config.yaml: ${conflict.identifier} — ${conflict.reason}
|
|
290
|
+
`core-config.yaml: ${conflict.identifier} — ${conflict.reason}`,
|
|
291
291
|
);
|
|
292
292
|
}
|
|
293
293
|
}
|
|
@@ -67,6 +67,9 @@ const SCANNER_SOURCES = [
|
|
|
67
67
|
{ from: path.join(BIN_UTILS, 'staged-sql-guard.js'), to: 'staged-sql-guard.js' },
|
|
68
68
|
// --- framework boundary guard (FASE C; respects boundary.frameworkProtection) ---
|
|
69
69
|
{ from: path.join(BIN_UTILS, 'framework-guard.js'), to: 'framework-guard.js' },
|
|
70
|
+
// --- protected-files guard (always-on; blocks deletion/untrack of committed
|
|
71
|
+
// critical files like service-registry.json — anti git-add-A-sweep) ---
|
|
72
|
+
{ from: path.join(BIN_UTILS, 'staged-protected-files-guard.js'), to: 'staged-protected-files-guard.js' },
|
|
70
73
|
];
|
|
71
74
|
|
|
72
75
|
/**
|
|
@@ -173,13 +176,15 @@ function copyScannerLib(hooksDir) {
|
|
|
173
176
|
/**
|
|
174
177
|
* Build the content of the managed `pre-commit` Node hook.
|
|
175
178
|
*
|
|
176
|
-
* The hook runs
|
|
179
|
+
* The hook runs FOUR bundled guards in sequence (each a standalone module
|
|
177
180
|
* under ./lib that exits non-zero on a finding), then chains to a pre-existing
|
|
178
181
|
* husky hook:
|
|
179
182
|
* 1. staged-secret-scan.js — secret/.env/private-key/entropy leak (fail-CLOSED)
|
|
180
183
|
* 2. staged-sql-guard.js — destructive DDL/DML (DROP/TRUNCATE/DELETE-no-WHERE)
|
|
181
184
|
* 3. framework-guard.js — L1/L2 boundary (no-op unless boundary
|
|
182
185
|
* .frameworkProtection is true in core-config.yaml)
|
|
186
|
+
* 4. staged-protected-files-guard.js — always-on; blocks deletion/untrack of
|
|
187
|
+
* committed critical files (e.g. service-registry.json)
|
|
183
188
|
*
|
|
184
189
|
* Each guard is spawned as a child Node process (cwd = project root, where git
|
|
185
190
|
* already runs hooks) so it gets the same staged index and reuses its own
|
|
@@ -209,13 +214,15 @@ const { spawnSync } = require('child_process');
|
|
|
209
214
|
const projectRoot = process.cwd();
|
|
210
215
|
const libDir = path.join(__dirname, 'lib');
|
|
211
216
|
|
|
212
|
-
// --- 1-
|
|
213
|
-
// Order: secret scan,
|
|
217
|
+
// --- 1-4. SINAPSE staged guards (each fail-CLOSED) ---------------------------
|
|
218
|
+
// Order: secret scan, destructive-SQL guard, framework-boundary guard, then
|
|
219
|
+
// protected-files guard (always-on anti-sweep; does NOT respect frameworkProtection).
|
|
214
220
|
// framework-guard self-disables when boundary.frameworkProtection is false.
|
|
215
221
|
const GUARDS = [
|
|
216
222
|
{ file: 'staged-secret-scan.js', label: 'Secret Scan' },
|
|
217
223
|
{ file: 'staged-sql-guard.js', label: 'SQL Guard' },
|
|
218
224
|
{ file: 'framework-guard.js', label: 'Framework Boundary' },
|
|
225
|
+
{ file: 'staged-protected-files-guard.js', label: 'Protected Files' },
|
|
219
226
|
];
|
|
220
227
|
|
|
221
228
|
for (const guard of GUARDS) {
|
|
@@ -80,7 +80,7 @@ async function scaffoldProContent(targetDir, proSourceDir, options = {}) {
|
|
|
80
80
|
// Validate pro source exists
|
|
81
81
|
if (!await fs.pathExists(proSourceDir)) {
|
|
82
82
|
result.errors.push(
|
|
83
|
-
`Pro package not found at ${proSourceDir}. Run "npm install @sinapse-fullstack/pro" first
|
|
83
|
+
`Pro package not found at ${proSourceDir}. Run "npm install @sinapse-fullstack/pro" first.`,
|
|
84
84
|
);
|
|
85
85
|
return result;
|
|
86
86
|
}
|
|
@@ -160,7 +160,7 @@ async function scaffoldProContent(targetDir, proSourceDir, options = {}) {
|
|
|
160
160
|
result.errors.push(`Rollback errors: ${rollbackResult.errors.join(', ')}`);
|
|
161
161
|
}
|
|
162
162
|
result.warnings.push(
|
|
163
|
-
`Scaffolding failed: ${error.message}. ${rollbackResult.removed} files cleaned up
|
|
163
|
+
`Scaffolding failed: ${error.message}. ${rollbackResult.removed} files cleaned up.`,
|
|
164
164
|
);
|
|
165
165
|
}
|
|
166
166
|
|
|
@@ -425,7 +425,7 @@ async function installSquadCommands(targetDir) {
|
|
|
425
425
|
for (const agentFile of agentFiles) {
|
|
426
426
|
await fs.copy(
|
|
427
427
|
path.join(agentsDir, agentFile),
|
|
428
|
-
path.join(destDir, agentFile)
|
|
428
|
+
path.join(destDir, agentFile),
|
|
429
429
|
);
|
|
430
430
|
files.push(path.relative(targetDir, path.join(destDir, agentFile)).replace(/\\/g, '/'));
|
|
431
431
|
}
|
|
@@ -182,7 +182,7 @@ function generateTemplateVariables(wizardState) {
|
|
|
182
182
|
* @param {Object} ideConfig - IDE configuration object (optional, for special handling)
|
|
183
183
|
* @returns {Promise<string[]>} List of copied files
|
|
184
184
|
*/
|
|
185
|
-
async function copyAgentFiles(projectRoot, agentFolder,
|
|
185
|
+
async function copyAgentFiles(projectRoot, agentFolder, _ideConfig = null) {
|
|
186
186
|
// v4: Agents are in development/agents/ (not root agents/)
|
|
187
187
|
const sourceDir = path.join(__dirname, '..', '..', '..', '..', '.sinapse-ai', 'development', 'agents');
|
|
188
188
|
const targetDir = path.join(projectRoot, agentFolder);
|
|
@@ -15,14 +15,9 @@ const { execSync } = require('child_process');
|
|
|
15
15
|
const { colors } = require('../utils/sinapse-colors');
|
|
16
16
|
const {
|
|
17
17
|
getLanguageQuestion,
|
|
18
|
-
getUserProfileQuestion,
|
|
19
18
|
getLLMQuestion,
|
|
20
|
-
getProjectTypeQuestion,
|
|
21
|
-
getIDEQuestions,
|
|
22
|
-
getTechPresetQuestion,
|
|
23
19
|
} = require('./questions');
|
|
24
|
-
const { setLanguage, t
|
|
25
|
-
const yaml = require('js-yaml');
|
|
20
|
+
const { setLanguage, t } = require('./i18n');
|
|
26
21
|
const { detectProjectTypeExtended } = require('../detection/detect-project-type');
|
|
27
22
|
const { showWelcome, showCompletion, showCancellation } = require('./feedback');
|
|
28
23
|
const { generateIDEConfigs, showSuccessSummary, copySkillFiles, copyExtraCommandFiles } = require('./ide-config-generator');
|
|
@@ -47,38 +42,6 @@ const {
|
|
|
47
42
|
isLLMRoutingInstalled,
|
|
48
43
|
} = require('../../../../.sinapse-ai/infrastructure/scripts/llm-routing/install-llm-routing');
|
|
49
44
|
|
|
50
|
-
/**
|
|
51
|
-
* Check for existing user_profile in core-config.yaml (Story 10.2 - Idempotency)
|
|
52
|
-
* Returns the existing profile if found, null otherwise
|
|
53
|
-
*
|
|
54
|
-
* @param {string} targetDir - Target directory to check
|
|
55
|
-
* @returns {Promise<string|null>} Existing user profile or null
|
|
56
|
-
*/
|
|
57
|
-
async function getExistingUserProfile(targetDir = process.cwd()) {
|
|
58
|
-
const coreConfigPath = path.join(targetDir, '.sinapse-ai', 'core-config.yaml');
|
|
59
|
-
|
|
60
|
-
try {
|
|
61
|
-
if (await fse.pathExists(coreConfigPath)) {
|
|
62
|
-
const content = await fse.readFile(coreConfigPath, 'utf8');
|
|
63
|
-
const config = yaml.load(content);
|
|
64
|
-
|
|
65
|
-
if (config && config.user_profile) {
|
|
66
|
-
// Validate the value
|
|
67
|
-
const validProfiles = ['bob', 'advanced'];
|
|
68
|
-
const normalizedProfile = String(config.user_profile).toLowerCase().trim();
|
|
69
|
-
|
|
70
|
-
if (validProfiles.includes(normalizedProfile)) {
|
|
71
|
-
return normalizedProfile;
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
} catch {
|
|
76
|
-
// Config doesn't exist or is invalid - will ask for profile
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
return null;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
45
|
/**
|
|
83
46
|
* Map wizard language code to Claude Code settings.json language name (Story ACT-12)
|
|
84
47
|
* Claude Code uses full language names, not ISO codes.
|
|
@@ -369,7 +332,7 @@ function buildAgentTemplate(agentId, squadName, homedir) {
|
|
|
369
332
|
'ACTIVATION-NOTICE: This command activates an agent from sinapse.',
|
|
370
333
|
'',
|
|
371
334
|
`CRITICAL: Read the agent definition file at \`${agentDefPath}\` to understand your full operating parameters. Then:`,
|
|
372
|
-
|
|
335
|
+
'1. Adopt the persona defined in that file',
|
|
373
336
|
`2. Load the squad manifest at \`${squadManifestPath}\` for context`,
|
|
374
337
|
'3. Display a greeting showing your agent name, role, and available commands',
|
|
375
338
|
'4. Briefing-on-activation check (this agent is an ORCHESTRATOR):',
|
|
@@ -781,7 +744,7 @@ async function runWizard(options = {}) {
|
|
|
781
744
|
try {
|
|
782
745
|
await commandValidate({ quiet: true });
|
|
783
746
|
answers.ideSyncValidation = 'pass';
|
|
784
|
-
} catch
|
|
747
|
+
} catch {
|
|
785
748
|
answers.ideSyncValidation = 'drift';
|
|
786
749
|
} finally {
|
|
787
750
|
console.log = _origLog;
|
|
@@ -879,7 +842,7 @@ async function runWizard(options = {}) {
|
|
|
879
842
|
projectType: answers.projectType || 'greenfield',
|
|
880
843
|
selectedIDEs: answers.selectedIDEs || [],
|
|
881
844
|
mcpServers: answers.mcpServers || [],
|
|
882
|
-
userProfile: answers.userProfile || '
|
|
845
|
+
userProfile: answers.userProfile || 'bob', // Assisted-by-default (open-source p/ leigos); advanced é toggle opt-in pós-install
|
|
883
846
|
skipPrompts: options.quiet || false, // Skip prompts in quiet mode
|
|
884
847
|
forceMerge: options.forceMerge, // Story 9.4: Smart Merge support
|
|
885
848
|
noMerge: options.noMerge, // Story 9.4: Smart Merge support
|
package/scripts/audit-tasks.cjs
CHANGED
|
@@ -223,7 +223,7 @@ Add to \`.claude/settings.local.json\`:
|
|
|
223
223
|
"UserPromptSubmit": [
|
|
224
224
|
{
|
|
225
225
|
"type": "command",
|
|
226
|
-
"command": "node
|
|
226
|
+
"command": "node \\"$CLAUDE_PROJECT_DIR/.claude/hooks/synapse-engine.cjs\\"",
|
|
227
227
|
"timeout": 10
|
|
228
228
|
}
|
|
229
229
|
]
|