sinapse-ai 1.20.0 → 1.20.1
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/.sinapse-ai/core/atlas/render-html.js +10 -8
- package/.sinapse-ai/core/registry/service-registry.json +2 -32
- package/.sinapse-ai/data/entity-registry.yaml +440 -195
- package/.sinapse-ai/development/agents/analyst.md +18 -34
- package/.sinapse-ai/development/agents/architect.md +18 -34
- package/.sinapse-ai/development/agents/data-engineer.md +15 -28
- package/.sinapse-ai/development/agents/developer.md +0 -6
- package/.sinapse-ai/development/agents/devops.md +15 -28
- package/.sinapse-ai/development/agents/product-lead.md +18 -34
- package/.sinapse-ai/development/agents/project-lead.md +18 -34
- package/.sinapse-ai/development/agents/quality-gate.md +18 -34
- package/.sinapse-ai/development/agents/squad-creator.md +15 -27
- package/.sinapse-ai/development/agents/ux-design-expert.md +15 -27
- package/.sinapse-ai/development/scripts/populate-entity-registry.js +3 -0
- package/.sinapse-ai/development/tasks/execute-epic-plan.md +0 -4
- package/.sinapse-ai/development/workflows/epic-orchestration.yaml +0 -1
- package/.sinapse-ai/git-hooks/lib/staged-secret-scan.js +3 -1
- package/.sinapse-ai/install-manifest.yaml +40 -72
- package/.sinapse-ai/product/templates/personalized-agent-template.md +3 -5
- package/.sinapse-ai/workflow-intelligence/index.js +3 -21
- package/AGENTS.md +2 -2
- package/CHANGELOG.md +38 -19
- package/bin/commands/install.js +5 -4
- package/bin/lib/command-generator.js +4 -4
- package/bin/lib/fs-utils.js +18 -0
- package/bin/lib/setup-statusline.js +3 -1
- package/bin/modules/chrome-brain-installer.js +5 -3
- package/bin/modules/mcp-installer.js +3 -6
- package/bin/postinstall.js +2 -1
- package/bin/sinapse-init.js +8 -9
- package/bin/sinapse.js +3 -1
- package/bin/utils/staged-secret-scan.js +3 -1
- package/docs/framework/atlas/OPERATING-ATLAS.md +1 -1
- package/docs/framework/atlas/atlas-data.json +22 -22
- package/docs/framework/atlas/atlas.html +12 -10
- package/docs/framework/source-tree.md +1 -2
- package/package.json +1 -1
- package/packages/installer/src/config/configure-environment.js +8 -6
- package/packages/installer/src/installer/brownfield-upgrader.js +5 -3
- package/packages/installer/src/installer/file-hasher.js +29 -21
- package/packages/installer/src/installer/manifest-signature.js +61 -49
- package/packages/installer/src/installer/post-install-validator.js +24 -17
- package/packages/installer/src/merger/parsers/markdown-section-parser.js +3 -2
- package/packages/installer/src/updater/index.js +7 -1
- package/packages/installer/src/utils/atomic-write.js +35 -0
- package/packages/installer/src/wizard/index.js +5 -3
- package/packages/sinapse-install/src/capabilities/chrome-brain.js +5 -3
- package/packages/sinapse-install/src/installer.js +3 -1
- package/packages/sinapse-install/src/utils/atomic-write.js +67 -0
- package/scripts/apply-persona-disclaimer.js +2 -1
- package/scripts/sinapse-patch.js +2 -1
- package/scripts/sync-squad-yaml-components.js +2 -1
- package/scripts/validate-agents-md.js +2 -1
- package/scripts/validate-article-xi.js +10 -8
- package/scripts/validate-no-external-refs.js +14 -8
- package/squads/claude-code-mastery/agents/claude-mastery-chief.md +3 -8
- package/squads/claude-code-mastery/agents/config-engineer.md +5 -12
- package/squads/claude-code-mastery/agents/hooks-architect.md +5 -11
- package/squads/claude-code-mastery/agents/mcp-integrator.md +5 -12
- package/squads/claude-code-mastery/agents/project-integrator.md +5 -12
- package/squads/claude-code-mastery/agents/roadmap-sentinel.md +5 -12
- package/squads/claude-code-mastery/agents/skill-craftsman.md +5 -11
- package/squads/claude-code-mastery/agents/swarm-orqx.md +15 -28
- package/.sinapse-ai/core/execution/context-injector.js +0 -539
- package/.sinapse-ai/core/execution/parallel-executor.js +0 -301
- package/.sinapse-ai/core/execution/parallel-monitor.js +0 -432
- package/.sinapse-ai/core/execution/semantic-merge-engine.js +0 -1750
- package/.sinapse-ai/core/execution/wave-executor.js +0 -403
- package/.sinapse-ai/development/tasks/waves.md +0 -205
- package/.sinapse-ai/workflow-intelligence/engine/wave-analyzer.js +0 -692
package/CHANGELOG.md
CHANGED
|
@@ -1,31 +1,22 @@
|
|
|
1
|
-
## [1.20.
|
|
2
|
-
|
|
3
|
-
### Features
|
|
4
|
-
|
|
5
|
-
* **cli:** spec/plan de 1ª classe + orchestrate no binário canônico + QA honesto no Windows ([#328](https://github.com/caioimori/sinapse-ai/issues/328)) ([6e55337](https://github.com/caioimori/sinapse-ai/commit/6e553373815c75e766fc4c1f002dcd8ae63b5fb6)), closes [S1/#321](https://github.com/S1/sinapse-ai/issues/321)
|
|
6
|
-
* **installer:** motor de contexto ativo pós-install — .synapse/ no caminho canônico + models no template ([#334](https://github.com/caioimori/sinapse-ai/issues/334)) ([6dbe799](https://github.com/caioimori/sinapse-ai/commit/6dbe799fb0a9724bd53b07f0183d5f627c1cd14a))
|
|
7
|
-
* **synapse:** dieta de contexto — Constitution completa só no 1º prompt + budgets honestos ([#323](https://github.com/caioimori/sinapse-ai/issues/323)) ([39b78e2](https://github.com/caioimori/sinapse-ai/commit/39b78e2c0e30746d433670764ec57e34c0691989))
|
|
1
|
+
## [1.20.1](https://github.com/caioimori/sinapse-ai/compare/1.20.0...1.20.1) (2026-07-03)
|
|
8
2
|
|
|
9
3
|
### Bug Fixes
|
|
10
4
|
|
|
11
|
-
* **
|
|
12
|
-
* **
|
|
13
|
-
* **
|
|
14
|
-
* **models:** varredura final de era — atlas sincronizado + squad mastery sem pins ([#326](https://github.com/caioimori/sinapse-ai/issues/326)) ([bbf4b9b](https://github.com/caioimori/sinapse-ai/commit/bbf4b9b29aac8bd06eb79cc45f7bbd94a198f4b8))
|
|
5
|
+
* **security:** Onda A da triagem AF-20260703 — 4 fixes cirúrgicos ([#337](https://github.com/caioimori/sinapse-ai/issues/337)) ([39f3338](https://github.com/caioimori/sinapse-ai/commit/39f33384aea83df4f609c91eec1ef25acce30d29)), closes [#1](https://github.com/caioimori/sinapse-ai/issues/1) [524-#528](https://github.com/caioimori/524-/issues/528) [#332](https://github.com/caioimori/sinapse-ai/issues/332) [#511](https://github.com/caioimori/sinapse-ai/issues/511) [#32](https://github.com/caioimori/sinapse-ai/issues/32)
|
|
6
|
+
* **security:** Onda B1 — TOCTOU na cadeia de confiança do instalador + git sem shell ([#340](https://github.com/caioimori/sinapse-ai/issues/340)) ([6f0a72b](https://github.com/caioimori/sinapse-ai/commit/6f0a72b89f8a72df741d5e7c94e89c2d3bd7bfd8)), closes [19/#20](https://github.com/19/sinapse-ai/issues/20) [15-#18](https://github.com/caioimori/15-/issues/18) [#22](https://github.com/caioimori/sinapse-ai/issues/22) [#507](https://github.com/caioimori/sinapse-ai/issues/507)
|
|
7
|
+
* **security:** Onda B2 — escrita atômica em todo o caminho de instalação ([#341](https://github.com/caioimori/sinapse-ai/issues/341)) ([0c90216](https://github.com/caioimori/sinapse-ai/commit/0c9021628526ff7cf5ef3dcf41efae3dc629e20a))
|
|
15
8
|
|
|
16
9
|
### Documentation
|
|
17
10
|
|
|
18
|
-
* **decisions:**
|
|
19
|
-
* **decisions:**
|
|
20
|
-
* **honestidade:** Art. VIII escopado ao caminho real + status executável dos workflows ([#330](https://github.com/caioimori/sinapse-ai/issues/330)) ([c277ff8](https://github.com/caioimori/sinapse-ai/commit/c277ff81438330edf56b68975b081fe776d82419)), closes [agent-exit-hooks.js#onCommandComplete](https://github.com/caioimori/agent-exit-hooks.js/issues/onCommandComplete)
|
|
21
|
-
* vitrine imediata honesta — CHANGELOG, user-guide revisado, limitação 1-story visível, ids por família ([#325](https://github.com/caioimori/sinapse-ai/issues/325)) ([ccd2f8b](https://github.com/caioimori/sinapse-ai/commit/ccd2f8b686fd16cc520838b3cb800ff44195b747)), closes [#318](https://github.com/caioimori/sinapse-ai/issues/318)
|
|
22
|
-
* vitrine profunda honesta — guides no veredito híbrido + README com motor visível + relatório da auditoria ([#327](https://github.com/caioimori/sinapse-ai/issues/327)) ([67889e8](https://github.com/caioimori/sinapse-ai/commit/67889e8ddeed672da91a7612ea0171f9773dcb37))
|
|
11
|
+
* **decisions:** registra Onda A de segurança executada (PR [#337](https://github.com/caioimori/sinapse-ai/issues/337)) ([#338](https://github.com/caioimori/sinapse-ai/issues/338)) ([c2dbe72](https://github.com/caioimori/sinapse-ai/commit/c2dbe72e2c686a9f2db01a85f4e02e444d4eea24))
|
|
12
|
+
* **decisions:** registra Ondas B/C de segurança + rollout da ativação enxuta executados ([#343](https://github.com/caioimori/sinapse-ai/issues/343)) ([0500b56](https://github.com/caioimori/sinapse-ai/commit/0500b56411e44f25cb1729126a3de828ef3f251d))
|
|
23
13
|
|
|
24
14
|
### Maintenance
|
|
25
15
|
|
|
26
|
-
* **agents:**
|
|
27
|
-
*
|
|
28
|
-
* **
|
|
16
|
+
* **agents:** rollout da ativação enxuta — pós-piloto aprovado por avaliação ([#342](https://github.com/caioimori/sinapse-ai/issues/342)) ([6815e51](https://github.com/caioimori/sinapse-ai/commit/6815e511e13fb1fa146f0a866d054073075c9212)), closes [#332](https://github.com/caioimori/sinapse-ai/issues/332)
|
|
17
|
+
* **cleanup:** DEC-03 — remove cluster multi-story órfão + split DEC-02 ([#344](https://github.com/caioimori/sinapse-ai/issues/344)) ([359b2fa](https://github.com/caioimori/sinapse-ai/commit/359b2fa2e905eee9be30ea5cac2d7a8bb305a0bd))
|
|
18
|
+
* **release:** sync da main pós-release v1.20.0 ([#336](https://github.com/caioimori/sinapse-ai/issues/336)) ([b3973f0](https://github.com/caioimori/sinapse-ai/commit/b3973f0223173ce570b9ae49878f2d278dc257f8)), closes [#277](https://github.com/caioimori/sinapse-ai/issues/277)
|
|
19
|
+
* **security:** Onda C — higiene do code scanning + 5 fixes de qualidade em produção ([#339](https://github.com/caioimori/sinapse-ai/issues/339)) ([13ae8dd](https://github.com/caioimori/sinapse-ai/commit/13ae8ddd314d2ab923ab019b4e0994be4e1627a1)), closes [#515](https://github.com/caioimori/sinapse-ai/issues/515) [#2](https://github.com/caioimori/sinapse-ai/issues/2) [#409](https://github.com/caioimori/sinapse-ai/issues/409) [#226](https://github.com/caioimori/sinapse-ai/issues/226) [401/#402](https://github.com/401/sinapse-ai/issues/402) [#228](https://github.com/caioimori/sinapse-ai/issues/228)
|
|
29
20
|
|
|
30
21
|
# Changelog
|
|
31
22
|
|
|
@@ -36,6 +27,34 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
36
27
|
|
|
37
28
|
## [Unreleased]
|
|
38
29
|
|
|
30
|
+
## [1.20.0] — 2026-07-03 — 🧠 Ciclo Fable 5: dieta de contexto, spec/plan de 1ª classe, era de modelo sincronizada
|
|
31
|
+
|
|
32
|
+
> Minor. Atualização segura via `npx sinapse-ai update`. Consolida o ciclo de upgrade Fable 5 (auditoria AF-20260702 → Onda 1 → Onda 2 → mesa de decisões): 15 PRs (#321–#335).
|
|
33
|
+
|
|
34
|
+
### Features
|
|
35
|
+
|
|
36
|
+
- **cli** — `sinapse spec` e `sinapse plan` como comandos de 1ª classe + `orchestrate` no binário canônico + QA honesto no Windows (`PASS_QA_SKIPPED`, exit 0) (#328)
|
|
37
|
+
- **installer** — motor de contexto ativo pós-install: `.synapse/` criado no caminho canônico + models no template; 2º prompt em diante entrega ~−88% de contexto injetado (#334)
|
|
38
|
+
- **synapse** — dieta de contexto: Constitution completa só no 1º prompt (−90,5%/turno) + budgets honestos (#323)
|
|
39
|
+
|
|
40
|
+
### Bug Fixes
|
|
41
|
+
|
|
42
|
+
- **cli** — binário canônico honesto: `agents`/`ideate` reais, uninstall de hooksPath, PlanTracker, simulate stub (#321)
|
|
43
|
+
- **context** — dual-trigger de compactação (60% OU 165K) + statusline re-significado pra era 1M (#329)
|
|
44
|
+
- **models** — registry na era Fable 5 (`active: claude-fable-5`) + token-economy sem pin de versão (#322); varredura final de era — atlas sincronizado + squad mastery sem pins (#326)
|
|
45
|
+
|
|
46
|
+
### Documentation
|
|
47
|
+
|
|
48
|
+
- **honestidade** — Art. VIII escopado ao caminho real + `docs/framework/workflow-engine-status.md` com status executável dos workflows (#330)
|
|
49
|
+
- **vitrine** — guides públicos no veredito híbrido do motor + README com motor real (#327); docs de vitrine imediata da Onda 1 (#325)
|
|
50
|
+
- **decisions** — mesa de decisões da Onda 2 (5 pareceres) (#333); execução DEC-02/DEC-05 + triagem de segurança (429 alertas, zero crítico-real) (#335)
|
|
51
|
+
|
|
52
|
+
### Maintenance
|
|
53
|
+
|
|
54
|
+
- **agents** — piloto de ativação enxuta + 24 colisões de codinome resolvidas (27 renames, reversíveis) (#332)
|
|
55
|
+
- **installer** — bilíngue (troubleshooting i18n) + init sem TTY não crasha (#331)
|
|
56
|
+
- **template** — CLAUDE.md enxuto + guard de codinomes (Nexus→Relay/Bulletin) (#324)
|
|
57
|
+
|
|
39
58
|
## [1.19.2] — 2026-07-01 — 🔒 Honestidade do gate (build vazio não passa) + aposta medida
|
|
40
59
|
|
|
41
60
|
> Patch. Atualização segura via `npx sinapse-ai update`. Fecha o último furo de honestidade do motor achado ao medir a aposta de orquestração multi-story.
|
package/bin/commands/install.js
CHANGED
|
@@ -27,6 +27,7 @@ const {
|
|
|
27
27
|
copyDirSync,
|
|
28
28
|
rmDirSync,
|
|
29
29
|
syncDirSync,
|
|
30
|
+
atomicWriteFileSync,
|
|
30
31
|
toForwardSlash,
|
|
31
32
|
} = require('../lib/fs-utils');
|
|
32
33
|
const {
|
|
@@ -112,7 +113,7 @@ async function cmdInstallGlobal(opts = {}) {
|
|
|
112
113
|
}
|
|
113
114
|
if (!parseFailed) {
|
|
114
115
|
settings.language = language === 'pt' ? 'portuguese' : 'english';
|
|
115
|
-
|
|
116
|
+
atomicWriteFileSync(claudeSettingsPath, JSON.stringify(settings, null, 2) + '\n');
|
|
116
117
|
}
|
|
117
118
|
} catch { /* non-critical */ }
|
|
118
119
|
|
|
@@ -587,7 +588,7 @@ function installFatalPhases({ squads, squadsDir, isUpsert, llmChoice, existing,
|
|
|
587
588
|
if (isUpsert) {
|
|
588
589
|
meta.updatedAt = nowIso;
|
|
589
590
|
}
|
|
590
|
-
|
|
591
|
+
atomicWriteFileSync(path.join(SINAPSE_HOME, 'metadata.json'), JSON.stringify(meta, null, 2));
|
|
591
592
|
|
|
592
593
|
return { writtenAgents, totalAgents, totalDelta, squadsRefreshed, squadsAdded, meta };
|
|
593
594
|
}
|
|
@@ -735,14 +736,14 @@ function createLauncher() {
|
|
|
735
736
|
exec claude --add-dir "${sinapsePathForBash}" --agent sinapse-orqx "$@"
|
|
736
737
|
`;
|
|
737
738
|
const bashPath = path.join(BIN_DIR, 'sinapse');
|
|
738
|
-
|
|
739
|
+
atomicWriteFileSync(bashPath, bashLauncher);
|
|
739
740
|
try { fs.chmodSync(bashPath, 0o755); } catch { /* chmod is best-effort (no-op on non-POSIX) */ }
|
|
740
741
|
logger.always(` ${GREEN}OK${NC} ~/bin/sinapse`);
|
|
741
742
|
|
|
742
743
|
// Windows CMD launcher
|
|
743
744
|
if (IS_WIN) {
|
|
744
745
|
const cmdLauncher = '@echo off\r\nclaude --add-dir "%USERPROFILE%\\.sinapse" --agent sinapse-orqx %*\r\n';
|
|
745
|
-
|
|
746
|
+
atomicWriteFileSync(path.join(BIN_DIR, 'sinapse.cmd'), cmdLauncher);
|
|
746
747
|
logger.always(` ${GREEN}OK${NC} ~/bin/sinapse.cmd`);
|
|
747
748
|
}
|
|
748
749
|
}
|
|
@@ -11,7 +11,7 @@ const path = require('path');
|
|
|
11
11
|
|
|
12
12
|
const { SINAPSE_HOME, CLAUDE_COMMANDS_DIR, ROOT } = require('./constants');
|
|
13
13
|
const { extractAgentMeta } = require('./squads');
|
|
14
|
-
const { toForwardSlash } = require('./fs-utils');
|
|
14
|
+
const { toForwardSlash, atomicWriteFileSync } = require('./fs-utils');
|
|
15
15
|
|
|
16
16
|
// Framework "core" agents (developer, architect, quality-gate, devops, …) live
|
|
17
17
|
// OUTSIDE the squads/ tree, under .sinapse-ai/development/agents/*.md. `scripts/
|
|
@@ -239,7 +239,7 @@ function regenerateAgentCommands(deps = {}) {
|
|
|
239
239
|
const agentId = file.replace('.md', '');
|
|
240
240
|
const meta = extractAgentMeta(path.join(agentsDir, file));
|
|
241
241
|
const cmdContent = generateCommandMd(agentId, meta.name, meta.icon, squad.name, squadPath, file);
|
|
242
|
-
|
|
242
|
+
atomicWriteFileSync(path.join(commandsDir, `${agentId}.md`), cmdContent);
|
|
243
243
|
writtenAgents.add(file);
|
|
244
244
|
}
|
|
245
245
|
}
|
|
@@ -254,7 +254,7 @@ function regenerateAgentCommands(deps = {}) {
|
|
|
254
254
|
const meta = extractAgentMeta(path.join(masterAgentsDir, file));
|
|
255
255
|
const squadPath = `${sinapseBase}/sinapse`;
|
|
256
256
|
const cmdContent = generateCommandMd(agentId, meta.name, meta.icon, 'sinapse', squadPath, file);
|
|
257
|
-
|
|
257
|
+
atomicWriteFileSync(path.join(commandsDir, `${agentId}.md`), cmdContent);
|
|
258
258
|
writtenAgents.add(file);
|
|
259
259
|
}
|
|
260
260
|
}
|
|
@@ -274,7 +274,7 @@ function regenerateAgentCommands(deps = {}) {
|
|
|
274
274
|
for (const [id, personaFile] of masterEntryPoints) {
|
|
275
275
|
const personaPath = `${masterSquadPath}/agents/${personaFile}`;
|
|
276
276
|
const stub = generateMasterStub(id, personaPath, masterSquadPath, squads);
|
|
277
|
-
|
|
277
|
+
atomicWriteFileSync(path.join(commandsDir, `${id}.md`), stub);
|
|
278
278
|
writtenAgents.add(`${id}.md`);
|
|
279
279
|
}
|
|
280
280
|
}
|
package/bin/lib/fs-utils.js
CHANGED
|
@@ -97,6 +97,23 @@ function syncDirSync(src, dest, delta = { added: 0, updated: 0, unchanged: 0, re
|
|
|
97
97
|
return delta;
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
+
// atomicWriteFileSync — Onda B2 (AF-20260703): tmp+rename via the canonical
|
|
101
|
+
// core util so a crash or concurrent reader never sees a torn config file.
|
|
102
|
+
// Fail-open: if the util can't be loaded, fall back to a plain write (the
|
|
103
|
+
// pre-hardening behavior) rather than breaking the installer.
|
|
104
|
+
let _atomicWriteSync = null;
|
|
105
|
+
try {
|
|
106
|
+
_atomicWriteSync = require('../../.sinapse-ai/core/synapse/utils/atomic-write').atomicWriteSync;
|
|
107
|
+
} catch { /* fallback below */ }
|
|
108
|
+
|
|
109
|
+
function atomicWriteFileSync(filePath, data, encoding = 'utf8') {
|
|
110
|
+
if (_atomicWriteSync) {
|
|
111
|
+
_atomicWriteSync(filePath, data, encoding);
|
|
112
|
+
} else {
|
|
113
|
+
fs.writeFileSync(filePath, data, encoding);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
100
117
|
function toForwardSlash(p) {
|
|
101
118
|
return p.replace(/\\/g, '/');
|
|
102
119
|
}
|
|
@@ -112,6 +129,7 @@ module.exports = {
|
|
|
112
129
|
copyDirSync,
|
|
113
130
|
rmDirSync,
|
|
114
131
|
syncDirSync,
|
|
132
|
+
atomicWriteFileSync,
|
|
115
133
|
toForwardSlash,
|
|
116
134
|
toPosixPath,
|
|
117
135
|
};
|
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
const os = require('os');
|
|
31
31
|
const path = require('path');
|
|
32
32
|
const fse = require('fs-extra');
|
|
33
|
+
const { atomicWriteFileSync } = require('./fs-utils');
|
|
33
34
|
|
|
34
35
|
/**
|
|
35
36
|
* Resolve the canonical source paths for the statusline templates.
|
|
@@ -182,7 +183,8 @@ async function setupStatusline(opts = {}) {
|
|
|
182
183
|
}
|
|
183
184
|
|
|
184
185
|
await fse.ensureDir(path.dirname(globalSettingsPath));
|
|
185
|
-
|
|
186
|
+
// Atomic (tmp+rename): a crash mid-write must never leave a torn settings.json
|
|
187
|
+
atomicWriteFileSync(globalSettingsPath, JSON.stringify(settings, null, 2), 'utf8');
|
|
186
188
|
|
|
187
189
|
result.installed = true;
|
|
188
190
|
return result;
|
|
@@ -12,6 +12,7 @@ const path = require('path');
|
|
|
12
12
|
const fs = require('fs');
|
|
13
13
|
const os = require('os');
|
|
14
14
|
const { execSync } = require('child_process');
|
|
15
|
+
const { atomicWriteFileSync } = require('../lib/fs-utils');
|
|
15
16
|
|
|
16
17
|
// ============================================================================
|
|
17
18
|
// Constants
|
|
@@ -134,7 +135,8 @@ function readJson(filePath) {
|
|
|
134
135
|
function writeJson(filePath, data) {
|
|
135
136
|
const dir = path.dirname(filePath);
|
|
136
137
|
fs.mkdirSync(dir, { recursive: true });
|
|
137
|
-
|
|
138
|
+
// Atomic (tmp+rename): these are user config files (settings.json, .mcp.json)
|
|
139
|
+
atomicWriteFileSync(filePath, JSON.stringify(data, null, 2) + '\n', 'utf8');
|
|
138
140
|
}
|
|
139
141
|
|
|
140
142
|
function mergeHooks(settingsPath, hookDefs) {
|
|
@@ -432,7 +434,7 @@ function createMinimalKB() {
|
|
|
432
434
|
fs.mkdirSync(kbDir, { recursive: true });
|
|
433
435
|
const kbPath = path.join(kbDir, 'chrome-brain.md');
|
|
434
436
|
if (!fs.existsSync(kbPath)) {
|
|
435
|
-
|
|
437
|
+
atomicWriteFileSync(kbPath, [
|
|
436
438
|
'# Chrome Brain — Browser Automation Capability',
|
|
437
439
|
'',
|
|
438
440
|
'> Cross-squad capability for browser automation.',
|
|
@@ -462,7 +464,7 @@ function createMinimalKB() {
|
|
|
462
464
|
// Create claude-in-chrome.md KB (Story 7.4.2)
|
|
463
465
|
const cicKbPath = path.join(kbDir, 'claude-in-chrome.md');
|
|
464
466
|
if (!fs.existsSync(cicKbPath)) {
|
|
465
|
-
|
|
467
|
+
atomicWriteFileSync(cicKbPath, [
|
|
466
468
|
'# claude-in-chrome — Chrome Extension for Visual Browser Interaction',
|
|
467
469
|
'',
|
|
468
470
|
'> Manual install required. This extension cannot be auto-installed via CLI.',
|
|
@@ -18,6 +18,7 @@ const path = require('path');
|
|
|
18
18
|
const { exec } = require('child_process');
|
|
19
19
|
const { promisify } = require('util');
|
|
20
20
|
const chalk = require('chalk');
|
|
21
|
+
const { atomicWriteFileSync } = require('../lib/fs-utils');
|
|
21
22
|
|
|
22
23
|
const execAsync = promisify(exec);
|
|
23
24
|
|
|
@@ -322,12 +323,8 @@ async function addMCPToConfig(mcpId, config, configPath) {
|
|
|
322
323
|
// Add new MCP config
|
|
323
324
|
mcpConfig.mcpServers[mcpId] = config;
|
|
324
325
|
|
|
325
|
-
// Write updated config
|
|
326
|
-
|
|
327
|
-
configPath,
|
|
328
|
-
JSON.stringify(mcpConfig, null, 2) + '\n',
|
|
329
|
-
'utf8',
|
|
330
|
-
);
|
|
326
|
+
// Write updated config — atomic (tmp+rename): .mcp.json must never be torn
|
|
327
|
+
atomicWriteFileSync(configPath, JSON.stringify(mcpConfig, null, 2) + '\n', 'utf8');
|
|
331
328
|
}
|
|
332
329
|
|
|
333
330
|
/**
|
package/bin/postinstall.js
CHANGED
|
@@ -45,6 +45,7 @@ const fs = require('fs');
|
|
|
45
45
|
const os = require('os');
|
|
46
46
|
const path = require('path');
|
|
47
47
|
const { spawnSync } = require('child_process');
|
|
48
|
+
const { atomicWriteFileSync } = require('./lib/fs-utils');
|
|
48
49
|
|
|
49
50
|
const PROJECT_ROOT = path.resolve(__dirname, '..');
|
|
50
51
|
|
|
@@ -161,7 +162,7 @@ function markFirstRunDone() {
|
|
|
161
162
|
}
|
|
162
163
|
const flag = firstRunFlag();
|
|
163
164
|
if (!fs.existsSync(flag)) {
|
|
164
|
-
|
|
165
|
+
atomicWriteFileSync(flag, `${new Date().toISOString()}\n`, 'utf8');
|
|
165
166
|
}
|
|
166
167
|
return true;
|
|
167
168
|
} catch {
|
package/bin/sinapse-init.js
CHANGED
|
@@ -24,7 +24,8 @@ const path = require('path');
|
|
|
24
24
|
const fs = require('fs');
|
|
25
25
|
const fse = require('fs-extra');
|
|
26
26
|
const yaml = require('js-yaml');
|
|
27
|
-
const {
|
|
27
|
+
const { exec, spawn } = require('child_process');
|
|
28
|
+
const { atomicWriteFileSync } = require('./lib/fs-utils');
|
|
28
29
|
const { promisify } = require('util');
|
|
29
30
|
const inquirer = require('inquirer');
|
|
30
31
|
const chalk = require('chalk');
|
|
@@ -172,8 +173,8 @@ async function main() {
|
|
|
172
173
|
author: '',
|
|
173
174
|
license: 'ISC',
|
|
174
175
|
};
|
|
175
|
-
//
|
|
176
|
-
|
|
176
|
+
// Atomic (tmp+rename): never leave a torn package.json
|
|
177
|
+
atomicWriteFileSync(packageJsonPath, JSON.stringify(defaultPackage, null, 2));
|
|
177
178
|
console.log(chalk.green('✓') + ' package.json created');
|
|
178
179
|
}
|
|
179
180
|
|
|
@@ -582,7 +583,8 @@ async function main() {
|
|
|
582
583
|
const existing = await fse.readFile(targetRules, 'utf8');
|
|
583
584
|
const incoming = await fse.readFile(sourceRules, 'utf8');
|
|
584
585
|
const mergeResult = await markdownMerger.merge(existing, incoming);
|
|
585
|
-
|
|
586
|
+
// Atomic (tmp+rename): merged user rules must never be half-written
|
|
587
|
+
atomicWriteFileSync(targetRules, mergeResult.content, 'utf8');
|
|
586
588
|
console.log(
|
|
587
589
|
chalk.green('✓') +
|
|
588
590
|
` ${ide.charAt(0).toUpperCase() + ide.slice(1)} rules merged (existing content preserved)`
|
|
@@ -830,7 +832,6 @@ See .sinapse-ai/user-guide.md for complete documentation.
|
|
|
830
832
|
// INS-2 Performance: Add spinner for validation (AC9)
|
|
831
833
|
const validationSpinner = ora('Validating installation integrity...').start();
|
|
832
834
|
|
|
833
|
-
let validationPassed = true;
|
|
834
835
|
try {
|
|
835
836
|
const { PostInstallValidator } = require('../packages/installer/src/installer/post-install-validator');
|
|
836
837
|
const validator = new PostInstallValidator(context.projectRoot, context.frameworkLocation, {
|
|
@@ -851,7 +852,6 @@ See .sinapse-ai/user-guide.md for complete documentation.
|
|
|
851
852
|
report.stats.missingFiles > 0 ||
|
|
852
853
|
report.stats.corruptedFiles > 0
|
|
853
854
|
) {
|
|
854
|
-
validationPassed = false;
|
|
855
855
|
validationSpinner.warn('Installation validation found issues:');
|
|
856
856
|
console.log(chalk.dim(` - Missing files: ${report.stats.missingFiles}`));
|
|
857
857
|
console.log(chalk.dim(` - Corrupted files: ${report.stats.corruptedFiles}`));
|
|
@@ -868,7 +868,6 @@ See .sinapse-ai/user-guide.md for complete documentation.
|
|
|
868
868
|
// Log validation errors but don't fail installation
|
|
869
869
|
// This allows installation to proceed even if validator module has issues
|
|
870
870
|
// However, users should investigate validation errors manually
|
|
871
|
-
validationPassed = false;
|
|
872
871
|
validationSpinner.warn('Post-installation validation encountered an error');
|
|
873
872
|
console.log(chalk.dim(` Error: ${validationError.message}`));
|
|
874
873
|
if (process.env.DEBUG || process.env.SINAPSE_DEBUG) {
|
|
@@ -972,8 +971,8 @@ async function updateGitIgnore(mode, projectRoot) {
|
|
|
972
971
|
|
|
973
972
|
if (!hasFrameworkSection) {
|
|
974
973
|
gitignore += frameworkRules.join('\n');
|
|
975
|
-
//
|
|
976
|
-
|
|
974
|
+
// Atomic (tmp+rename): appended .gitignore must never be half-written
|
|
975
|
+
atomicWriteFileSync(gitignorePath, gitignore);
|
|
977
976
|
}
|
|
978
977
|
}
|
|
979
978
|
}
|
package/bin/sinapse.js
CHANGED
|
@@ -14,6 +14,7 @@ const { emitDeprecationWarning } = require('./utils/deprecation-warning');
|
|
|
14
14
|
// Story onda2-p6 — shared, TTY-detection used by `init` to fall back to the
|
|
15
15
|
// wizard's quiet/default path in non-interactive shells (see shouldRunInitQuiet below).
|
|
16
16
|
const { detectInteractiveMode } = require('./lib/detection');
|
|
17
|
+
const { atomicWriteFileSync } = require('./lib/fs-utils');
|
|
17
18
|
|
|
18
19
|
// Story A.2 — unified logger. Levels: error/warn/info/debug.
|
|
19
20
|
// Flags: --verbose, --debug, --quiet, --json. Default level: warn.
|
|
@@ -506,7 +507,8 @@ function cleanGitignore(gitignorePath) {
|
|
|
506
507
|
}
|
|
507
508
|
|
|
508
509
|
if (removedLines > 0) {
|
|
509
|
-
|
|
510
|
+
// Atomic (tmp+rename): never leave a half-written .gitignore
|
|
511
|
+
atomicWriteFileSync(gitignorePath, newLines.join('\n'));
|
|
510
512
|
return { removed: true, lines: removedLines };
|
|
511
513
|
}
|
|
512
514
|
return { removed: false };
|
|
@@ -50,7 +50,9 @@ const SCANNER_SELF_FILES = new Set([
|
|
|
50
50
|
'bin/utils/staged-secret-scan.js',
|
|
51
51
|
'.claude/hooks/secret-scanning.cjs',
|
|
52
52
|
]);
|
|
53
|
-
|
|
53
|
+
// Each alternative carries its own anchors (grouped explicitly) so neither
|
|
54
|
+
// branch can accidentally match a substring of the other's context.
|
|
55
|
+
const TEST_FILE_PATTERN = /((^|\/)(tests?|__tests__)\/)|(\.(test|spec)\.[cm]?[jt]s$)/i;
|
|
54
56
|
|
|
55
57
|
function isScanExemptPath(filePath) {
|
|
56
58
|
const norm = String(filePath).replace(/\\/g, '/');
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
> Single, generated map of how the SINAPSE framework works: routing, models,
|
|
4
4
|
> constitution, workflows, agents, squads. Regenerate with `sinapse atlas`.
|
|
5
5
|
> Counts are read from disk (Article VII — always exact).
|
|
6
|
-
> Generated: 2026-07-
|
|
6
|
+
> Generated: 2026-07-03T03:44:39.813Z
|
|
7
7
|
|
|
8
8
|
**At a glance:** 17 squads · 172 agents
|
|
9
9
|
(12 framework + 160 squad) ·
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"generatedAt": "2026-07-
|
|
2
|
+
"generatedAt": "2026-07-03T03:44:39.813Z",
|
|
3
3
|
"counts": {
|
|
4
4
|
"squads": 17,
|
|
5
5
|
"agentsTotal": 172,
|
|
@@ -417,7 +417,7 @@
|
|
|
417
417
|
{
|
|
418
418
|
"id": "new-offer-launch",
|
|
419
419
|
"name": "new-offer-launch",
|
|
420
|
-
"description": "Workflow completo para lançamento de nova oferta — do design à ativação comercial. Integra Mint (design), Edge (enablement), Cascade (demand gen),
|
|
420
|
+
"description": "Workflow completo para lançamento de nova oferta — do design à ativação comercial. Integra Mint (design), Edge (enablement), Cascade (demand gen), Rolodex (CRM…",
|
|
421
421
|
"type": "",
|
|
422
422
|
"source": "squad:squad-commercial",
|
|
423
423
|
"file": "squads/squad-commercial/workflows/new-offer-launch.yaml",
|
|
@@ -435,7 +435,7 @@
|
|
|
435
435
|
{
|
|
436
436
|
"id": "revenue-forecasting-cycle",
|
|
437
437
|
"name": "revenue-forecasting-cycle",
|
|
438
|
-
"description": "Ciclo mensal de forecasting de receita — coleta, análise, projeção e apresentação. Combina dados de pipeline (
|
|
438
|
+
"description": "Ciclo mensal de forecasting de receita — coleta, análise, projeção e apresentação. Combina dados de pipeline (Rolodex), unit economics (Turbine), e expansion (…",
|
|
439
439
|
"type": "",
|
|
440
440
|
"source": "squad:squad-commercial",
|
|
441
441
|
"file": "squads/squad-commercial/workflows/revenue-forecasting-cycle.yaml",
|
|
@@ -1138,7 +1138,7 @@
|
|
|
1138
1138
|
},
|
|
1139
1139
|
{
|
|
1140
1140
|
"id": "animation-interpreter",
|
|
1141
|
-
"persona": "
|
|
1141
|
+
"persona": "Decoder",
|
|
1142
1142
|
"title": "Animation Intent Interpreter",
|
|
1143
1143
|
"role": "Animation Intent Interpreter",
|
|
1144
1144
|
"squad": "squad-animations",
|
|
@@ -1291,7 +1291,7 @@
|
|
|
1291
1291
|
},
|
|
1292
1292
|
{
|
|
1293
1293
|
"id": "squad-brand",
|
|
1294
|
-
"persona": "
|
|
1294
|
+
"persona": "Ripple",
|
|
1295
1295
|
"title": "Motion & VFX Designer",
|
|
1296
1296
|
"role": "Motion & VFX Designer — linguagem de movimento, animacoes, video graphics e animation library",
|
|
1297
1297
|
"squad": "squad-brand",
|
|
@@ -1948,7 +1948,7 @@
|
|
|
1948
1948
|
},
|
|
1949
1949
|
{
|
|
1950
1950
|
"id": "cro-persuasion",
|
|
1951
|
-
"persona": "
|
|
1951
|
+
"persona": "Sway",
|
|
1952
1952
|
"title": "CRO & Persuasion Specialist",
|
|
1953
1953
|
"role": "CRO & Persuasion Specialist",
|
|
1954
1954
|
"squad": "squad-design",
|
|
@@ -1975,7 +1975,7 @@
|
|
|
1975
1975
|
},
|
|
1976
1976
|
{
|
|
1977
1977
|
"id": "dx-accessibility-specialist",
|
|
1978
|
-
"persona": "
|
|
1978
|
+
"persona": "Aperture",
|
|
1979
1979
|
"title": "Accessibility & Inclusive Design Expert",
|
|
1980
1980
|
"role": "Accessibility & Inclusive Design Expert",
|
|
1981
1981
|
"squad": "squad-design",
|
|
@@ -1984,7 +1984,7 @@
|
|
|
1984
1984
|
},
|
|
1985
1985
|
{
|
|
1986
1986
|
"id": "dx-design-system-architect",
|
|
1987
|
-
"persona": "
|
|
1987
|
+
"persona": "Lattice",
|
|
1988
1988
|
"title": "Design System & Token Architecture Specialist",
|
|
1989
1989
|
"role": "Design System & Token Architecture Specialist",
|
|
1990
1990
|
"squad": "squad-design",
|
|
@@ -2002,7 +2002,7 @@
|
|
|
2002
2002
|
},
|
|
2003
2003
|
{
|
|
2004
2004
|
"id": "dx-interaction-designer",
|
|
2005
|
-
"persona": "
|
|
2005
|
+
"persona": "Gesture",
|
|
2006
2006
|
"title": "Interaction Design & Motion Systems Specialist",
|
|
2007
2007
|
"role": "Interaction Design & Motion Systems Specialist",
|
|
2008
2008
|
"squad": "squad-design",
|
|
@@ -2011,7 +2011,7 @@
|
|
|
2011
2011
|
},
|
|
2012
2012
|
{
|
|
2013
2013
|
"id": "dx-performance-engineer",
|
|
2014
|
-
"persona": "
|
|
2014
|
+
"persona": "Velocity",
|
|
2015
2015
|
"title": "Web Performance Optimization Specialist",
|
|
2016
2016
|
"role": "Web Performance Optimization Specialist",
|
|
2017
2017
|
"squad": "squad-design",
|
|
@@ -2020,7 +2020,7 @@
|
|
|
2020
2020
|
},
|
|
2021
2021
|
{
|
|
2022
2022
|
"id": "dx-ui-designer",
|
|
2023
|
-
"persona": "
|
|
2023
|
+
"persona": "Palette",
|
|
2024
2024
|
"title": "UI Design & Visual Systems Specialist",
|
|
2025
2025
|
"role": "UI Design & Visual Systems Specialist",
|
|
2026
2026
|
"squad": "squad-design",
|
|
@@ -2029,7 +2029,7 @@
|
|
|
2029
2029
|
},
|
|
2030
2030
|
{
|
|
2031
2031
|
"id": "dx-ux-strategist",
|
|
2032
|
-
"persona": "
|
|
2032
|
+
"persona": "Vantage",
|
|
2033
2033
|
"title": "UX Strategy & Research Lead",
|
|
2034
2034
|
"role": "UX Strategy & Research Lead",
|
|
2035
2035
|
"squad": "squad-design",
|
|
@@ -2038,7 +2038,7 @@
|
|
|
2038
2038
|
},
|
|
2039
2039
|
{
|
|
2040
2040
|
"id": "platform-aesthetic-director",
|
|
2041
|
-
"persona": "
|
|
2041
|
+
"persona": "Hue",
|
|
2042
2042
|
"title": "Platform Aesthetic Director",
|
|
2043
2043
|
"role": "Platform Aesthetic Director",
|
|
2044
2044
|
"squad": "squad-design",
|
|
@@ -2110,7 +2110,7 @@
|
|
|
2110
2110
|
},
|
|
2111
2111
|
{
|
|
2112
2112
|
"id": "forecast-strategist",
|
|
2113
|
-
"persona": "
|
|
2113
|
+
"persona": "Runway",
|
|
2114
2114
|
"title": "Forecast Strategist",
|
|
2115
2115
|
"role": "Forecast Strategist",
|
|
2116
2116
|
"squad": "squad-finance",
|
|
@@ -2119,7 +2119,7 @@
|
|
|
2119
2119
|
},
|
|
2120
2120
|
{
|
|
2121
2121
|
"id": "pricing-strategist",
|
|
2122
|
-
"persona": "
|
|
2122
|
+
"persona": "Markup",
|
|
2123
2123
|
"title": "Pricing Strategist",
|
|
2124
2124
|
"role": "Pricing Strategist",
|
|
2125
2125
|
"squad": "squad-finance",
|
|
@@ -2209,7 +2209,7 @@
|
|
|
2209
2209
|
},
|
|
2210
2210
|
{
|
|
2211
2211
|
"id": "campaign-analyst",
|
|
2212
|
-
"persona": "
|
|
2212
|
+
"persona": "Cadence",
|
|
2213
2213
|
"title": "Campaign Analyst",
|
|
2214
2214
|
"role": "Campaign Analyst",
|
|
2215
2215
|
"squad": "squad-paidmedia",
|
|
@@ -2227,7 +2227,7 @@
|
|
|
2227
2227
|
},
|
|
2228
2228
|
{
|
|
2229
2229
|
"id": "cro-specialist",
|
|
2230
|
-
"persona": "
|
|
2230
|
+
"persona": "Uplift",
|
|
2231
2231
|
"title": "CRO Specialist",
|
|
2232
2232
|
"role": "CRO Specialist",
|
|
2233
2233
|
"squad": "squad-paidmedia",
|
|
@@ -2245,7 +2245,7 @@
|
|
|
2245
2245
|
},
|
|
2246
2246
|
{
|
|
2247
2247
|
"id": "meta-ads-specialist",
|
|
2248
|
-
"persona": "
|
|
2248
|
+
"persona": "Reach",
|
|
2249
2249
|
"title": "Meta Ads Specialist",
|
|
2250
2250
|
"role": "Meta Ads Specialist",
|
|
2251
2251
|
"squad": "squad-paidmedia",
|
|
@@ -2272,7 +2272,7 @@
|
|
|
2272
2272
|
},
|
|
2273
2273
|
{
|
|
2274
2274
|
"id": "pm-creative-performance-analyst",
|
|
2275
|
-
"persona": "
|
|
2275
|
+
"persona": "Focal",
|
|
2276
2276
|
"title": "Creative Performance Analyst",
|
|
2277
2277
|
"role": "Creative Performance Analyst",
|
|
2278
2278
|
"squad": "squad-paidmedia",
|
|
@@ -2353,7 +2353,7 @@
|
|
|
2353
2353
|
},
|
|
2354
2354
|
{
|
|
2355
2355
|
"id": "audience-intelligence",
|
|
2356
|
-
"persona": "
|
|
2356
|
+
"persona": "Empath",
|
|
2357
2357
|
"title": "Audience Intelligence Empath",
|
|
2358
2358
|
"role": "Audience Intelligence Empath",
|
|
2359
2359
|
"squad": "squad-research",
|
|
@@ -2371,7 +2371,7 @@
|
|
|
2371
2371
|
},
|
|
2372
2372
|
{
|
|
2373
2373
|
"id": "data-synthesizer",
|
|
2374
|
-
"persona": "
|
|
2374
|
+
"persona": "Braid",
|
|
2375
2375
|
"title": "Data Synthesis Weaver",
|
|
2376
2376
|
"role": "Data Synthesis Weaver",
|
|
2377
2377
|
"squad": "squad-research",
|
|
@@ -2389,7 +2389,7 @@
|
|
|
2389
2389
|
},
|
|
2390
2390
|
{
|
|
2391
2391
|
"id": "market-analyst",
|
|
2392
|
-
"persona": "
|
|
2392
|
+
"persona": "Sonar",
|
|
2393
2393
|
"title": "Market Analysis Strategist",
|
|
2394
2394
|
"role": "Market Analysis Strategist",
|
|
2395
2395
|
"squad": "squad-research",
|