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.
Files changed (70) hide show
  1. package/.sinapse-ai/core/atlas/render-html.js +10 -8
  2. package/.sinapse-ai/core/registry/service-registry.json +2 -32
  3. package/.sinapse-ai/data/entity-registry.yaml +440 -195
  4. package/.sinapse-ai/development/agents/analyst.md +18 -34
  5. package/.sinapse-ai/development/agents/architect.md +18 -34
  6. package/.sinapse-ai/development/agents/data-engineer.md +15 -28
  7. package/.sinapse-ai/development/agents/developer.md +0 -6
  8. package/.sinapse-ai/development/agents/devops.md +15 -28
  9. package/.sinapse-ai/development/agents/product-lead.md +18 -34
  10. package/.sinapse-ai/development/agents/project-lead.md +18 -34
  11. package/.sinapse-ai/development/agents/quality-gate.md +18 -34
  12. package/.sinapse-ai/development/agents/squad-creator.md +15 -27
  13. package/.sinapse-ai/development/agents/ux-design-expert.md +15 -27
  14. package/.sinapse-ai/development/scripts/populate-entity-registry.js +3 -0
  15. package/.sinapse-ai/development/tasks/execute-epic-plan.md +0 -4
  16. package/.sinapse-ai/development/workflows/epic-orchestration.yaml +0 -1
  17. package/.sinapse-ai/git-hooks/lib/staged-secret-scan.js +3 -1
  18. package/.sinapse-ai/install-manifest.yaml +40 -72
  19. package/.sinapse-ai/product/templates/personalized-agent-template.md +3 -5
  20. package/.sinapse-ai/workflow-intelligence/index.js +3 -21
  21. package/AGENTS.md +2 -2
  22. package/CHANGELOG.md +38 -19
  23. package/bin/commands/install.js +5 -4
  24. package/bin/lib/command-generator.js +4 -4
  25. package/bin/lib/fs-utils.js +18 -0
  26. package/bin/lib/setup-statusline.js +3 -1
  27. package/bin/modules/chrome-brain-installer.js +5 -3
  28. package/bin/modules/mcp-installer.js +3 -6
  29. package/bin/postinstall.js +2 -1
  30. package/bin/sinapse-init.js +8 -9
  31. package/bin/sinapse.js +3 -1
  32. package/bin/utils/staged-secret-scan.js +3 -1
  33. package/docs/framework/atlas/OPERATING-ATLAS.md +1 -1
  34. package/docs/framework/atlas/atlas-data.json +22 -22
  35. package/docs/framework/atlas/atlas.html +12 -10
  36. package/docs/framework/source-tree.md +1 -2
  37. package/package.json +1 -1
  38. package/packages/installer/src/config/configure-environment.js +8 -6
  39. package/packages/installer/src/installer/brownfield-upgrader.js +5 -3
  40. package/packages/installer/src/installer/file-hasher.js +29 -21
  41. package/packages/installer/src/installer/manifest-signature.js +61 -49
  42. package/packages/installer/src/installer/post-install-validator.js +24 -17
  43. package/packages/installer/src/merger/parsers/markdown-section-parser.js +3 -2
  44. package/packages/installer/src/updater/index.js +7 -1
  45. package/packages/installer/src/utils/atomic-write.js +35 -0
  46. package/packages/installer/src/wizard/index.js +5 -3
  47. package/packages/sinapse-install/src/capabilities/chrome-brain.js +5 -3
  48. package/packages/sinapse-install/src/installer.js +3 -1
  49. package/packages/sinapse-install/src/utils/atomic-write.js +67 -0
  50. package/scripts/apply-persona-disclaimer.js +2 -1
  51. package/scripts/sinapse-patch.js +2 -1
  52. package/scripts/sync-squad-yaml-components.js +2 -1
  53. package/scripts/validate-agents-md.js +2 -1
  54. package/scripts/validate-article-xi.js +10 -8
  55. package/scripts/validate-no-external-refs.js +14 -8
  56. package/squads/claude-code-mastery/agents/claude-mastery-chief.md +3 -8
  57. package/squads/claude-code-mastery/agents/config-engineer.md +5 -12
  58. package/squads/claude-code-mastery/agents/hooks-architect.md +5 -11
  59. package/squads/claude-code-mastery/agents/mcp-integrator.md +5 -12
  60. package/squads/claude-code-mastery/agents/project-integrator.md +5 -12
  61. package/squads/claude-code-mastery/agents/roadmap-sentinel.md +5 -12
  62. package/squads/claude-code-mastery/agents/skill-craftsman.md +5 -11
  63. package/squads/claude-code-mastery/agents/swarm-orqx.md +15 -28
  64. package/.sinapse-ai/core/execution/context-injector.js +0 -539
  65. package/.sinapse-ai/core/execution/parallel-executor.js +0 -301
  66. package/.sinapse-ai/core/execution/parallel-monitor.js +0 -432
  67. package/.sinapse-ai/core/execution/semantic-merge-engine.js +0 -1750
  68. package/.sinapse-ai/core/execution/wave-executor.js +0 -403
  69. package/.sinapse-ai/development/tasks/waves.md +0 -205
  70. package/.sinapse-ai/workflow-intelligence/engine/wave-analyzer.js +0 -692
package/CHANGELOG.md CHANGED
@@ -1,31 +1,22 @@
1
- ## [1.20.0](https://github.com/caioimori/sinapse-ai/compare/v1.19.2...1.20.0) (2026-07-03)
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
- * **cli:** binário canônico honestoagents/ideate, uninstall hooksPath, PlanTracker, simulate stub ([#321](https://github.com/caioimori/sinapse-ai/issues/321)) ([19b4dd7](https://github.com/caioimori/sinapse-ai/commit/19b4dd7d6aab9a4abf5b1fde754646491ba04362))
12
- * **context:** dual-trigger de compactação + statusline re-significado pra era 1M ([#329](https://github.com/caioimori/sinapse-ai/issues/329)) ([18f8582](https://github.com/caioimori/sinapse-ai/commit/18f85821693c90792d7d1ffb74e4023319fdcbed))
13
- * **models:** registry na era Fable 5 + token-economy sem pin de versão ([#322](https://github.com/caioimori/sinapse-ai/issues/322)) ([b1d120c](https://github.com/caioimori/sinapse-ai/commit/b1d120cacf30f7fa9e45bc556d15a663f7c2e869))
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:** executa DEC-02/DEC-05 + triagem de segurança na mesa de decisões ([#335](https://github.com/caioimori/sinapse-ai/issues/335)) ([108e6e2](https://github.com/caioimori/sinapse-ai/commit/108e6e2ff987190edf3dd214c2dd06c8748bf5ed))
19
- * **decisions:** mesa de decisões da Onda 2 5 pareceres de arquitetura + medições armadas ([#333](https://github.com/caioimori/sinapse-ai/issues/333)) ([d2d50c3](https://github.com/caioimori/sinapse-ai/commit/d2d50c3d78d23d5884ea00579d78e502c27bc2d6))
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:** piloto de ativação enxuta + 24 colisões de codinome resolvidas (27 renames) ([#332](https://github.com/caioimori/sinapse-ai/issues/332)) ([702a146](https://github.com/caioimori/sinapse-ai/commit/702a146d762f6a54644f6dd7b573d7c777c9dd41))
27
- * installer bilíngue (troubleshooting i18n) + init sem TTY não crasha ([#331](https://github.com/caioimori/sinapse-ai/issues/331)) ([d4434af](https://github.com/caioimori/sinapse-ai/commit/d4434afded0ee892625f80395989763e5dd393d4))
28
- * **install:** template CLAUDE.md fiel e enxuto + guard de codinome sem blind spot ([#324](https://github.com/caioimori/sinapse-ai/issues/324)) ([64b5868](https://github.com/caioimori/sinapse-ai/commit/64b586881589cd4dd814fc8c0112029ca7607f2c))
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.
@@ -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
- fs.writeFileSync(claudeSettingsPath, JSON.stringify(settings, null, 2) + '\n');
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
- fs.writeFileSync(path.join(SINAPSE_HOME, 'metadata.json'), JSON.stringify(meta, null, 2));
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
- fs.writeFileSync(bashPath, bashLauncher);
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
- fs.writeFileSync(path.join(BIN_DIR, 'sinapse.cmd'), cmdLauncher);
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
- fs.writeFileSync(path.join(commandsDir, `${agentId}.md`), cmdContent);
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
- fs.writeFileSync(path.join(commandsDir, `${agentId}.md`), cmdContent);
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
- fs.writeFileSync(path.join(commandsDir, `${id}.md`), stub);
277
+ atomicWriteFileSync(path.join(commandsDir, `${id}.md`), stub);
278
278
  writtenAgents.add(`${id}.md`);
279
279
  }
280
280
  }
@@ -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
- await fse.writeFile(globalSettingsPath, JSON.stringify(settings, null, 2), 'utf8');
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
- fs.writeFileSync(filePath, JSON.stringify(data, null, 2) + '\n', 'utf8');
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
- fs.writeFileSync(kbPath, [
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
- fs.writeFileSync(cicKbPath, [
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
- await fse.writeFile(
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
  /**
@@ -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
- fs.writeFileSync(flag, `${new Date().toISOString()}\n`, 'utf8');
165
+ atomicWriteFileSync(flag, `${new Date().toISOString()}\n`, 'utf8');
165
166
  }
166
167
  return true;
167
168
  } catch {
@@ -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 { execSync, exec, spawn } = require('child_process');
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
- // INS-2 Performance: Use async write instead of sync
176
- await fse.writeFile(packageJsonPath, JSON.stringify(defaultPackage, null, 2));
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
- await fse.writeFile(targetRules, mergeResult.content, 'utf8');
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
- // INS-2 Performance: Use async write
976
- await fse.writeFile(gitignorePath, gitignore);
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
- fs.writeFileSync(gitignorePath, newLines.join('\n'));
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
- const TEST_FILE_PATTERN = /(^|\/)(tests?|__tests__)\/|\.(test|spec)\.[cm]?[jt]s$/i;
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-02T21:47:12.575Z
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-02T21:47:12.575Z",
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), Vault (CRM),…",
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 (Vault), unit economics (Ledger), e expansion (Bon…",
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": "Lens",
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": "Flux",
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": "Convert",
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": "Beacon",
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": "Stratum",
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": "Kinetic",
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": "Apex",
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": "Canvas",
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": "Compass",
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": "Vertex",
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": "Horizon",
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": "Mint",
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": "Pulse",
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": "Convert",
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": "Signal",
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": "Lens",
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": "Pulse",
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": "Loom",
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": "Scope",
2392
+ "persona": "Sonar",
2393
2393
  "title": "Market Analysis Strategist",
2394
2394
  "role": "Market Analysis Strategist",
2395
2395
  "squad": "squad-research",