aios-core 4.0.2 → 4.1.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.
Files changed (111) hide show
  1. package/.aios-core/cli/commands/migrate/analyze.js +6 -6
  2. package/.aios-core/cli/commands/migrate/backup.js +2 -2
  3. package/.aios-core/cli/commands/migrate/execute.js +4 -4
  4. package/.aios-core/cli/commands/migrate/index.js +5 -5
  5. package/.aios-core/cli/commands/migrate/rollback.js +6 -6
  6. package/.aios-core/cli/commands/migrate/update-imports.js +2 -2
  7. package/.aios-core/cli/commands/migrate/validate.js +2 -2
  8. package/.aios-core/cli/commands/pro/index.js +52 -0
  9. package/.aios-core/cli/index.js +1 -1
  10. package/.aios-core/core/ids/registry-updater.js +29 -3
  11. package/.aios-core/core/migration/migration-config.yaml +2 -2
  12. package/.aios-core/core/migration/module-mapping.yaml +2 -2
  13. package/.aios-core/core/registry/README.md +2 -2
  14. package/.aios-core/core/synapse/context/context-builder.js +34 -0
  15. package/.aios-core/core/synapse/diagnostics/collectors/consistency-collector.js +168 -0
  16. package/.aios-core/core/synapse/diagnostics/collectors/hook-collector.js +129 -0
  17. package/.aios-core/core/synapse/diagnostics/collectors/manifest-collector.js +82 -0
  18. package/.aios-core/core/synapse/diagnostics/collectors/output-analyzer.js +134 -0
  19. package/.aios-core/core/synapse/diagnostics/collectors/pipeline-collector.js +75 -0
  20. package/.aios-core/core/synapse/diagnostics/collectors/quality-collector.js +252 -0
  21. package/.aios-core/core/synapse/diagnostics/collectors/relevance-matrix.js +174 -0
  22. package/.aios-core/core/synapse/diagnostics/collectors/safe-read-json.js +31 -0
  23. package/.aios-core/core/synapse/diagnostics/collectors/session-collector.js +102 -0
  24. package/.aios-core/core/synapse/diagnostics/collectors/timing-collector.js +126 -0
  25. package/.aios-core/core/synapse/diagnostics/collectors/uap-collector.js +83 -0
  26. package/.aios-core/core/synapse/diagnostics/report-formatter.js +484 -0
  27. package/.aios-core/core/synapse/diagnostics/synapse-diagnostics.js +95 -0
  28. package/.aios-core/core/synapse/engine.js +73 -20
  29. package/.aios-core/core/synapse/runtime/hook-runtime.js +60 -0
  30. package/.aios-core/core-config.yaml +6 -0
  31. package/.aios-core/data/agent-config-requirements.yaml +2 -2
  32. package/.aios-core/data/aios-kb.md +4 -4
  33. package/.aios-core/data/entity-registry.yaml +5 -5
  34. package/.aios-core/development/agents/architect.md +10 -10
  35. package/.aios-core/development/agents/devops.md +93 -50
  36. package/.aios-core/development/agents/qa.md +94 -40
  37. package/.aios-core/development/agents/ux-design-expert.md +25 -25
  38. package/.aios-core/development/scripts/activation-runtime.js +63 -0
  39. package/.aios-core/development/scripts/generate-greeting.js +9 -8
  40. package/.aios-core/development/scripts/unified-activation-pipeline.js +102 -2
  41. package/.aios-core/development/tasks/{db-expansion-pack-integration.md → db-squad-integration.md} +5 -5
  42. package/.aios-core/development/tasks/{integrate-expansion-pack.md → integrate-squad.md} +2 -2
  43. package/.aios-core/development/tasks/next.md +3 -3
  44. package/.aios-core/development/tasks/pr-automation.md +2 -2
  45. package/.aios-core/development/tasks/publish-npm.md +257 -0
  46. package/.aios-core/development/tasks/release-management.md +4 -4
  47. package/.aios-core/development/tasks/setup-github.md +1 -1
  48. package/.aios-core/development/tasks/squad-creator-migrate.md +1 -1
  49. package/.aios-core/development/tasks/squad-creator-sync-ide-command.md +14 -14
  50. package/.aios-core/development/tasks/update-aios.md +1 -1
  51. package/.aios-core/docs/standards/AIOS-COLOR-PALETTE-QUICK-REFERENCE.md +1 -1
  52. package/.aios-core/docs/standards/AIOS-COLOR-PALETTE-V2.1.md +5 -5
  53. package/.aios-core/docs/standards/AIOS-LIVRO-DE-OURO-V2.1-COMPLETE.md +21 -21
  54. package/.aios-core/docs/standards/AIOS-LIVRO-DE-OURO-V2.2-SUMMARY.md +25 -25
  55. package/.aios-core/docs/standards/OPEN-SOURCE-VS-SERVICE-DIFFERENCES.md +4 -4
  56. package/.aios-core/docs/standards/QUALITY-GATES-SPECIFICATION.md +3 -3
  57. package/.aios-core/docs/standards/STANDARDS-INDEX.md +13 -13
  58. package/.aios-core/docs/standards/STORY-TEMPLATE-V2-SPECIFICATION.md +1 -1
  59. package/.aios-core/framework-config.yaml +4 -0
  60. package/.aios-core/infrastructure/scripts/codex-skills-sync/index.js +182 -0
  61. package/.aios-core/infrastructure/scripts/codex-skills-sync/validate.js +172 -0
  62. package/.aios-core/infrastructure/scripts/ide-sync/README.md +14 -0
  63. package/.aios-core/infrastructure/scripts/ide-sync/index.js +6 -0
  64. package/.aios-core/infrastructure/scripts/tool-resolver.js +4 -4
  65. package/.aios-core/infrastructure/scripts/validate-paths.js +142 -0
  66. package/.aios-core/infrastructure/templates/aios-sync.yaml.template +11 -11
  67. package/.aios-core/infrastructure/templates/github-workflows/README.md +1 -1
  68. package/.aios-core/install-manifest.yaml +190 -106
  69. package/.aios-core/local-config.yaml.template +2 -0
  70. package/.aios-core/product/README.md +2 -2
  71. package/.aios-core/product/data/integration-patterns.md +1 -1
  72. package/.aios-core/product/templates/ide-rules/cline-rules.md +1 -1
  73. package/.aios-core/product/templates/ide-rules/codex-rules.md +65 -0
  74. package/.aios-core/product/templates/ide-rules/copilot-rules.md +1 -1
  75. package/.aios-core/product/templates/ide-rules/roo-rules.md +1 -1
  76. package/.aios-core/user-guide.md +15 -14
  77. package/.aios-core/workflow-intelligence/engine/output-formatter.js +1 -1
  78. package/.claude/hooks/enforce-architecture-first.py +196 -0
  79. package/.claude/hooks/install-hooks.sh +41 -0
  80. package/.claude/hooks/mind-clone-governance.py +192 -0
  81. package/.claude/hooks/pre-commit-mmos-guard.sh +99 -0
  82. package/.claude/hooks/pre-commit-version-check.sh +156 -0
  83. package/.claude/hooks/read-protection.py +151 -0
  84. package/.claude/hooks/slug-validation.py +176 -0
  85. package/.claude/hooks/sql-governance.py +182 -0
  86. package/.claude/hooks/synapse-engine.js +9 -20
  87. package/.claude/hooks/write-path-validation.py +194 -0
  88. package/README.md +44 -14
  89. package/bin/aios-init.js +255 -184
  90. package/bin/aios-minimal.js +2 -2
  91. package/bin/aios.js +19 -19
  92. package/package.json +7 -4
  93. package/packages/aios-pro-cli/bin/aios-pro.js +75 -2
  94. package/packages/aios-pro-cli/package.json +5 -1
  95. package/packages/aios-pro-cli/src/recover.js +100 -0
  96. package/packages/installer/src/__tests__/performance-benchmark.js +382 -0
  97. package/packages/installer/src/config/ide-configs.js +12 -1
  98. package/packages/installer/src/config/templates/core-config-template.js +2 -2
  99. package/packages/installer/src/installer/aios-core-installer.js +2 -2
  100. package/packages/installer/src/installer/file-hasher.js +97 -0
  101. package/packages/installer/src/installer/post-install-validator.js +41 -1
  102. package/packages/installer/src/pro/pro-scaffolder.js +335 -0
  103. package/packages/installer/src/utils/aios-colors.js +2 -2
  104. package/packages/installer/src/wizard/feedback.js +1 -1
  105. package/packages/installer/src/wizard/ide-config-generator.js +2 -2
  106. package/packages/installer/src/wizard/index.js +58 -19
  107. package/packages/installer/src/wizard/pro-setup.js +547 -0
  108. package/packages/installer/src/wizard/questions.js +20 -14
  109. package/packages/installer/src/wizard/validators.js +1 -1
  110. package/scripts/package-synapse.js +323 -0
  111. package/scripts/validate-package-completeness.js +317 -0
@@ -0,0 +1,323 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * SYNAPSE Package Builder — Creates a distributable ZIP for collaborators.
5
+ *
6
+ * Usage: node scripts/package-synapse.js
7
+ * Output: synapse-package.zip in project root
8
+ *
9
+ * The ZIP contains all SYNAPSE files organized by category with a
10
+ * README-INSTALL.md tutorial for setting up SYNAPSE in a new project.
11
+ */
12
+
13
+ 'use strict';
14
+
15
+ const fs = require('fs');
16
+ const path = require('path');
17
+ const { execSync } = require('child_process');
18
+
19
+ const ROOT = path.resolve(__dirname, '..');
20
+ const OUT_DIR = path.join(ROOT, '.synapse-package');
21
+ const ZIP_NAME = 'synapse-package.zip';
22
+
23
+ // ── File manifest ──────────────────────────────────────────────────────────
24
+
25
+ const FILES = {
26
+ // Core Engine
27
+ 'core/engine.js': '.aios-core/core/synapse/engine.js',
28
+ 'core/context/context-tracker.js': '.aios-core/core/synapse/context/context-tracker.js',
29
+ 'core/domain/domain-loader.js': '.aios-core/core/synapse/domain/domain-loader.js',
30
+ 'core/layers/layer-processor.js': '.aios-core/core/synapse/layers/layer-processor.js',
31
+ 'core/layers/l0-constitution.js': '.aios-core/core/synapse/layers/l0-constitution.js',
32
+ 'core/layers/l1-global.js': '.aios-core/core/synapse/layers/l1-global.js',
33
+ 'core/layers/l2-agent.js': '.aios-core/core/synapse/layers/l2-agent.js',
34
+ 'core/layers/l3-workflow.js': '.aios-core/core/synapse/layers/l3-workflow.js',
35
+ 'core/layers/l4-task.js': '.aios-core/core/synapse/layers/l4-task.js',
36
+ 'core/layers/l5-squad.js': '.aios-core/core/synapse/layers/l5-squad.js',
37
+ 'core/layers/l6-keyword.js': '.aios-core/core/synapse/layers/l6-keyword.js',
38
+ 'core/layers/l7-star-command.js': '.aios-core/core/synapse/layers/l7-star-command.js',
39
+ 'core/memory/memory-bridge.js': '.aios-core/core/synapse/memory/memory-bridge.js',
40
+ 'core/output/formatter.js': '.aios-core/core/synapse/output/formatter.js',
41
+ 'core/session/session-manager.js': '.aios-core/core/synapse/session/session-manager.js',
42
+ 'core/scripts/generate-constitution.js': '.aios-core/core/synapse/scripts/generate-constitution.js',
43
+ 'core/utils/paths.js': '.aios-core/core/synapse/utils/paths.js',
44
+ 'core/utils/tokens.js': '.aios-core/core/synapse/utils/tokens.js',
45
+
46
+ // Diagnostics
47
+ 'core/diagnostics/synapse-diagnostics.js': '.aios-core/core/synapse/diagnostics/synapse-diagnostics.js',
48
+ 'core/diagnostics/report-formatter.js': '.aios-core/core/synapse/diagnostics/report-formatter.js',
49
+ 'core/diagnostics/collectors/safe-read-json.js': '.aios-core/core/synapse/diagnostics/collectors/safe-read-json.js',
50
+ 'core/diagnostics/collectors/hook-collector.js': '.aios-core/core/synapse/diagnostics/collectors/hook-collector.js',
51
+ 'core/diagnostics/collectors/session-collector.js': '.aios-core/core/synapse/diagnostics/collectors/session-collector.js',
52
+ 'core/diagnostics/collectors/manifest-collector.js': '.aios-core/core/synapse/diagnostics/collectors/manifest-collector.js',
53
+ 'core/diagnostics/collectors/pipeline-collector.js': '.aios-core/core/synapse/diagnostics/collectors/pipeline-collector.js',
54
+ 'core/diagnostics/collectors/uap-collector.js': '.aios-core/core/synapse/diagnostics/collectors/uap-collector.js',
55
+ 'core/diagnostics/collectors/timing-collector.js': '.aios-core/core/synapse/diagnostics/collectors/timing-collector.js',
56
+ 'core/diagnostics/collectors/quality-collector.js': '.aios-core/core/synapse/diagnostics/collectors/quality-collector.js',
57
+ 'core/diagnostics/collectors/consistency-collector.js': '.aios-core/core/synapse/diagnostics/collectors/consistency-collector.js',
58
+ 'core/diagnostics/collectors/output-analyzer.js': '.aios-core/core/synapse/diagnostics/collectors/output-analyzer.js',
59
+ 'core/diagnostics/collectors/relevance-matrix.js': '.aios-core/core/synapse/diagnostics/collectors/relevance-matrix.js',
60
+
61
+ // Hook Entry Point
62
+ 'hook/synapse-engine.js': '.claude/hooks/synapse-engine.js',
63
+
64
+ // Commands
65
+ 'commands/manager.md': '.claude/commands/synapse/manager.md',
66
+ 'commands/tasks/add-rule.md': '.claude/commands/synapse/tasks/add-rule.md',
67
+ 'commands/tasks/create-command.md': '.claude/commands/synapse/tasks/create-command.md',
68
+ 'commands/tasks/create-domain.md': '.claude/commands/synapse/tasks/create-domain.md',
69
+ 'commands/tasks/diagnose-synapse.md': '.claude/commands/synapse/tasks/diagnose-synapse.md',
70
+ 'commands/tasks/edit-rule.md': '.claude/commands/synapse/tasks/edit-rule.md',
71
+ 'commands/tasks/suggest-domain.md': '.claude/commands/synapse/tasks/suggest-domain.md',
72
+ 'commands/tasks/toggle-domain.md': '.claude/commands/synapse/tasks/toggle-domain.md',
73
+ 'commands/templates/domain-template': '.claude/commands/synapse/templates/domain-template',
74
+ 'commands/templates/manifest-entry-template': '.claude/commands/synapse/templates/manifest-entry-template',
75
+ 'commands/utils/manifest-parser-reference.md': '.claude/commands/synapse/utils/manifest-parser-reference.md',
76
+
77
+ // Skills
78
+ 'skills/SKILL.md': '.claude/skills/synapse/SKILL.md',
79
+ 'skills/references/brackets.md': '.claude/skills/synapse/references/brackets.md',
80
+ 'skills/references/commands.md': '.claude/skills/synapse/references/commands.md',
81
+ 'skills/references/domains.md': '.claude/skills/synapse/references/domains.md',
82
+ 'skills/references/layers.md': '.claude/skills/synapse/references/layers.md',
83
+ 'skills/references/manifest.md': '.claude/skills/synapse/references/manifest.md',
84
+ 'skills/assets/README.md': '.claude/skills/synapse/assets/README.md',
85
+
86
+ // Documentation
87
+ 'docs/SYNAPSE-FLOWCHARTS.md': 'docs/architecture/SYNAPSE/SYNAPSE-FLOWCHARTS.md',
88
+ 'docs/DESIGN-SYNAPSE-ENGINE.md': 'docs/architecture/SYNAPSE/docs/DESIGN-SYNAPSE-ENGINE.md',
89
+ };
90
+
91
+ // Runtime domain files to copy from .synapse/
92
+ const RUNTIME_DOMAINS = [
93
+ 'manifest', 'constitution', 'global', 'context', 'commands',
94
+ 'agent-dev', 'agent-qa', 'agent-architect', 'agent-pm', 'agent-po',
95
+ 'agent-sm', 'agent-devops', 'agent-analyst', 'agent-data-engineer',
96
+ 'agent-ux', 'agent-aios-master', 'agent-squad-creator',
97
+ 'workflow-story-dev', 'workflow-epic-create', 'workflow-arch-review',
98
+ ];
99
+
100
+ // ── Build ──────────────────────────────────────────────────────────────────
101
+
102
+ function main() {
103
+ console.log('Building SYNAPSE package...\n');
104
+
105
+ // Clean
106
+ if (fs.existsSync(OUT_DIR)) fs.rmSync(OUT_DIR, { recursive: true });
107
+ fs.mkdirSync(OUT_DIR, { recursive: true });
108
+
109
+ // Copy files
110
+ let copied = 0;
111
+ let missing = 0;
112
+ for (const [dest, src] of Object.entries(FILES)) {
113
+ const srcPath = path.join(ROOT, src);
114
+ const destPath = path.join(OUT_DIR, dest);
115
+ if (!fs.existsSync(srcPath)) {
116
+ console.warn(` SKIP (missing): ${src}`);
117
+ missing++;
118
+ continue;
119
+ }
120
+ fs.mkdirSync(path.dirname(destPath), { recursive: true });
121
+ fs.copyFileSync(srcPath, destPath);
122
+ copied++;
123
+ }
124
+
125
+ // Copy runtime domains
126
+ const runtimeDir = path.join(OUT_DIR, 'runtime');
127
+ fs.mkdirSync(runtimeDir, { recursive: true });
128
+ for (const domain of RUNTIME_DOMAINS) {
129
+ const srcPath = path.join(ROOT, '.synapse', domain);
130
+ if (fs.existsSync(srcPath)) {
131
+ fs.copyFileSync(srcPath, path.join(runtimeDir, domain));
132
+ copied++;
133
+ } else {
134
+ console.warn(` SKIP (runtime): .synapse/${domain}`);
135
+ missing++;
136
+ }
137
+ }
138
+
139
+ // Copy tests
140
+ const testsDir = path.join(OUT_DIR, 'tests');
141
+ copyDirRecursive(path.join(ROOT, 'tests', 'synapse'), testsDir);
142
+
143
+ // Generate README-INSTALL.md
144
+ generateReadme(OUT_DIR);
145
+
146
+ console.log(`\nCopied: ${copied} files | Missing: ${missing} files`);
147
+
148
+ // Create ZIP
149
+ const zipPath = path.join(ROOT, ZIP_NAME);
150
+ if (fs.existsSync(zipPath)) fs.unlinkSync(zipPath);
151
+
152
+ try {
153
+ // Use PowerShell Compress-Archive on Windows
154
+ execSync(
155
+ `powershell -Command "Compress-Archive -Path '${OUT_DIR}\\*' -DestinationPath '${zipPath}' -Force"`,
156
+ { stdio: 'inherit' },
157
+ );
158
+ console.log(`\nZIP created: ${ZIP_NAME}`);
159
+ console.log(`Size: ${(fs.statSync(zipPath).size / 1024).toFixed(1)} KB`);
160
+ } catch (err) {
161
+ console.error('Failed to create ZIP:', err.message);
162
+ console.log(`Package directory still available at: ${OUT_DIR}`);
163
+ }
164
+
165
+ // Cleanup temp dir
166
+ if (fs.existsSync(zipPath) && fs.existsSync(OUT_DIR)) {
167
+ fs.rmSync(OUT_DIR, { recursive: true });
168
+ }
169
+ }
170
+
171
+ function copyDirRecursive(src, dest) {
172
+ if (!fs.existsSync(src)) return;
173
+ fs.mkdirSync(dest, { recursive: true });
174
+ for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
175
+ const srcPath = path.join(src, entry.name);
176
+ const destPath = path.join(dest, entry.name);
177
+ if (entry.isDirectory()) {
178
+ copyDirRecursive(srcPath, destPath);
179
+ } else {
180
+ fs.copyFileSync(srcPath, destPath);
181
+ }
182
+ }
183
+ }
184
+
185
+ function generateReadme(outDir) {
186
+ const content = `# SYNAPSE Context Engine — Installation Guide
187
+
188
+ ## What is SYNAPSE?
189
+
190
+ SYNAPSE (Synkra Adaptive Processing & State Engine) is the JIT context injection
191
+ engine for AIOS. On every user prompt, it injects \`<synapse-rules>\` with adaptive
192
+ contextual rules through an 8-layer pipeline.
193
+
194
+ ## Prerequisites
195
+
196
+ - **Node.js** 18+
197
+ - **Claude Code** CLI with hook support
198
+ - **AIOS Core** installed (\`npx aios-core install\`)
199
+
200
+ ## Quick Install
201
+
202
+ ### 1. Copy Core Engine
203
+
204
+ Copy the \`core/\` directory to your project:
205
+
206
+ \`\`\`
207
+ cp -r core/ <your-project>/.aios-core/core/synapse/
208
+ \`\`\`
209
+
210
+ ### 2. Copy Hook Entry Point
211
+
212
+ \`\`\`
213
+ cp hook/synapse-engine.js <your-project>/.claude/hooks/
214
+ \`\`\`
215
+
216
+ ### 3. Register the Hook
217
+
218
+ Add to \`.claude/settings.local.json\`:
219
+
220
+ \`\`\`json
221
+ {
222
+ "hooks": {
223
+ "UserPromptSubmit": [
224
+ {
225
+ "type": "command",
226
+ "command": "node .claude/hooks/synapse-engine.js"
227
+ }
228
+ ]
229
+ }
230
+ }
231
+ \`\`\`
232
+
233
+ ### 4. Copy Runtime Domains
234
+
235
+ \`\`\`
236
+ cp -r runtime/ <your-project>/.synapse/
237
+ mkdir -p <your-project>/.synapse/sessions
238
+ mkdir -p <your-project>/.synapse/metrics
239
+ mkdir -p <your-project>/.synapse/cache
240
+ \`\`\`
241
+
242
+ ### 5. Copy Commands & Skills (Optional)
243
+
244
+ \`\`\`
245
+ cp -r commands/ <your-project>/.claude/commands/synapse/
246
+ cp -r skills/ <your-project>/.claude/skills/synapse/
247
+ \`\`\`
248
+
249
+ ### 6. Update .gitignore
250
+
251
+ Add these lines:
252
+
253
+ \`\`\`
254
+ .synapse/sessions/
255
+ .synapse/metrics/
256
+ .synapse/cache/
257
+ !.claude/hooks/synapse-engine.js
258
+ \`\`\`
259
+
260
+ ## Verification
261
+
262
+ After installation, activate any agent and run:
263
+
264
+ \`\`\`
265
+ /synapse:tasks:diagnose-synapse
266
+ \`\`\`
267
+
268
+ Expected: All checks PASS, Context Quality grade B or higher.
269
+
270
+ ## Architecture
271
+
272
+ See \`docs/SYNAPSE-FLOWCHARTS.md\` for complete visual architecture including:
273
+ - 8-layer pipeline flow
274
+ - Context brackets (FRESH/MODERATE/DEPLETED/CRITICAL)
275
+ - Domain system
276
+ - Session management
277
+ - Diagnostics pipeline (10 collectors)
278
+ - Metrics persistence
279
+
280
+ ## Tests
281
+
282
+ Copy \`tests/\` to your project and run:
283
+
284
+ \`\`\`bash
285
+ npx jest synapse
286
+ \`\`\`
287
+
288
+ Expected: 749+ tests passing.
289
+
290
+ ## File Structure
291
+
292
+ \`\`\`
293
+ synapse-package/
294
+ ├── README-INSTALL.md # This file
295
+ ├── core/ # Engine source (.aios-core/core/synapse/)
296
+ │ ├── engine.js # Main orchestrator
297
+ │ ├── context/ # Bracket tracker
298
+ │ ├── domain/ # Manifest + domain loader
299
+ │ ├── layers/ # L0-L7 layer processors
300
+ │ ├── memory/ # MIS bridge (Pro)
301
+ │ ├── output/ # XML formatter
302
+ │ ├── session/ # Session manager
303
+ │ ├── diagnostics/ # Observability (10 collectors)
304
+ │ ├── scripts/ # Constitution generator
305
+ │ └── utils/ # Path + token helpers
306
+ ├── hook/ # .claude/hooks/synapse-engine.js
307
+ ├── commands/ # .claude/commands/synapse/
308
+ ├── skills/ # .claude/skills/synapse/
309
+ ├── runtime/ # .synapse/ domain files (manifest, domains)
310
+ ├── docs/ # Architecture documentation
311
+ └── tests/ # Full test suite (749+ tests)
312
+ \`\`\`
313
+
314
+ ---
315
+
316
+ *SYNAPSE Context Engine v2.0 — Synkra AIOS*
317
+ *Generated: ${new Date().toISOString().split('T')[0]}*
318
+ `;
319
+
320
+ fs.writeFileSync(path.join(outDir, 'README-INSTALL.md'), content, 'utf8');
321
+ }
322
+
323
+ main();
@@ -0,0 +1,317 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Validate Package Completeness for npm Publishing
4
+ *
5
+ * Ensures the npm tarball contains all critical files and excludes
6
+ * private content before publishing. Runs as prepublishOnly hook.
7
+ *
8
+ * @script scripts/validate-package-completeness.js
9
+ * @story INS-2 - Release Pipeline: Preview to Latest
10
+ *
11
+ * Usage:
12
+ * node scripts/validate-package-completeness.js
13
+ * node scripts/validate-package-completeness.js --verbose
14
+ *
15
+ * Exit codes:
16
+ * 0 - Package is complete and safe to publish
17
+ * 1 - Validation failed (missing files, leaked content, or config issues)
18
+ */
19
+
20
+ const { execSync } = require('child_process');
21
+ const fs = require('fs');
22
+ const path = require('path');
23
+
24
+ const ROOT = path.resolve(__dirname, '..');
25
+ const VERBOSE = process.argv.includes('--verbose') || process.env.VERBOSE === 'true';
26
+
27
+ // ─── Configuration ──────────────────────────────────────────────────────────
28
+
29
+ /**
30
+ * Files/directories that MUST be present in the tarball.
31
+ * Paths are relative to package root, checked as prefixes against tarball entries.
32
+ */
33
+ const REQUIRED_PATHS = [
34
+ // Hooks (critical - these were missing in v4.0.0)
35
+ '.claude/hooks/synapse-engine.js',
36
+ '.claude/hooks/precompact-session-digest.js',
37
+ // Rules
38
+ '.claude/rules/',
39
+ // CLI binaries
40
+ 'bin/aios.js',
41
+ 'bin/aios-minimal.js',
42
+ // Core framework
43
+ '.aios-core/core-config.yaml',
44
+ '.aios-core/constitution.md',
45
+ '.aios-core/development/agents/',
46
+ '.aios-core/development/tasks/',
47
+ ];
48
+
49
+ /**
50
+ * Paths that MUST NOT appear in the tarball (leak prevention).
51
+ */
52
+ const EXCLUDED_PATHS = [
53
+ 'pro/',
54
+ '.env',
55
+ '.git/',
56
+ 'node_modules/',
57
+ '.aios/',
58
+ 'tests/',
59
+ ];
60
+
61
+ /**
62
+ * Entries required in package.json "files" array.
63
+ */
64
+ const REQUIRED_FILES_ENTRIES = [
65
+ '.claude/hooks/',
66
+ '.claude/rules/',
67
+ '.aios-core/',
68
+ 'bin/',
69
+ ];
70
+
71
+ /**
72
+ * Bin entries that must point to existing files.
73
+ */
74
+ const REQUIRED_BIN_ENTRIES = ['aios', 'aios-core'];
75
+
76
+ /**
77
+ * Runtime dependencies that must be present.
78
+ */
79
+ const REQUIRED_DEPENDENCIES = ['js-yaml', 'execa', 'chalk', 'commander', 'fs-extra'];
80
+
81
+ // ─── Helpers ────────────────────────────────────────────────────────────────
82
+
83
+ let totalChecks = 0;
84
+ let passedChecks = 0;
85
+ let failedChecks = 0;
86
+ const failures = [];
87
+
88
+ function log(msg) {
89
+ console.log(msg);
90
+ }
91
+
92
+ function verbose(msg) {
93
+ if (VERBOSE) {
94
+ console.log(` [verbose] ${msg}`);
95
+ }
96
+ }
97
+
98
+ function check(description, passed, detail) {
99
+ totalChecks++;
100
+ if (passed) {
101
+ passedChecks++;
102
+ log(` PASS ${description}`);
103
+ } else {
104
+ failedChecks++;
105
+ const msg = detail ? `${description} -- ${detail}` : description;
106
+ failures.push(msg);
107
+ log(` FAIL ${description}`);
108
+ if (detail) {
109
+ log(` ${detail}`);
110
+ }
111
+ }
112
+ }
113
+
114
+ function getTarballContents() {
115
+ try {
116
+ const output = execSync('npm pack --dry-run --json 2>&1', {
117
+ cwd: ROOT,
118
+ encoding: 'utf8',
119
+ timeout: 30000,
120
+ });
121
+
122
+ // npm pack --json outputs a JSON array
123
+ const parsed = JSON.parse(output);
124
+ if (!Array.isArray(parsed) || parsed.length === 0) {
125
+ throw new Error('npm pack --json returned empty result');
126
+ }
127
+
128
+ const files = parsed[0].files || [];
129
+ return files.map((f) => f.path);
130
+ } catch (parseError) {
131
+ // Fallback: parse text output from npm pack --dry-run
132
+ verbose(`JSON parse failed, falling back to text output: ${parseError.message}`);
133
+ try {
134
+ const output = execSync('npm pack --dry-run 2>&1', {
135
+ cwd: ROOT,
136
+ encoding: 'utf8',
137
+ timeout: 30000,
138
+ });
139
+
140
+ // Text output has lines like "npm notice 1.2kB .claude/hooks/synapse-engine.js"
141
+ const lines = output.split('\n');
142
+ return lines
143
+ .filter((line) => line.includes('npm notice') && !line.includes('=== Tarball'))
144
+ .map((line) => {
145
+ // Extract file path (last token after size)
146
+ const match = line.match(/npm notice\s+[\d.]+[kMG]?B?\s+(.+)/);
147
+ return match ? match[1].trim() : null;
148
+ })
149
+ .filter(Boolean);
150
+ } catch (fallbackError) {
151
+ log(` FAIL Could not run npm pack: ${fallbackError.message}`);
152
+ return null;
153
+ }
154
+ }
155
+ }
156
+
157
+ function loadPackageJson() {
158
+ const pkgPath = path.join(ROOT, 'package.json');
159
+ return JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
160
+ }
161
+
162
+ // ─── Validation Phases ──────────────────────────────────────────────────────
163
+
164
+ function validateTarballContents(tarballFiles) {
165
+ log('\n--- Phase 1: Tarball Contents ---\n');
166
+
167
+ if (!tarballFiles) {
168
+ check('npm pack --dry-run executed', false, 'Failed to get tarball contents');
169
+ return;
170
+ }
171
+
172
+ verbose(`Tarball contains ${tarballFiles.length} files`);
173
+
174
+ // Check required paths exist
175
+ for (const required of REQUIRED_PATHS) {
176
+ const isDir = required.endsWith('/');
177
+ let found;
178
+
179
+ if (isDir) {
180
+ found = tarballFiles.some((f) => f.startsWith(required) || f.startsWith(`package/${required}`));
181
+ } else {
182
+ found = tarballFiles.some((f) => f === required || f === `package/${required}`);
183
+ }
184
+
185
+ check(
186
+ `Required: ${required}`,
187
+ found,
188
+ found ? undefined : `Not found in tarball (${tarballFiles.length} files scanned)`
189
+ );
190
+ }
191
+
192
+ // Check excluded paths do NOT exist
193
+ for (const excluded of EXCLUDED_PATHS) {
194
+ const leaked = tarballFiles.filter(
195
+ (f) => f.startsWith(excluded) || f.startsWith(`package/${excluded}`)
196
+ );
197
+
198
+ check(
199
+ `Excluded: ${excluded} not in tarball`,
200
+ leaked.length === 0,
201
+ leaked.length > 0 ? `LEAK DETECTED: ${leaked.slice(0, 3).join(', ')}` : undefined
202
+ );
203
+ }
204
+ }
205
+
206
+ function validatePackageJson(pkg) {
207
+ log('\n--- Phase 2: package.json Validation ---\n');
208
+
209
+ // Check "files" array includes required entries
210
+ const filesArray = pkg.files || [];
211
+
212
+ for (const entry of REQUIRED_FILES_ENTRIES) {
213
+ const found = filesArray.some((f) => f === entry || f.startsWith(entry));
214
+ check(
215
+ `files[] includes "${entry}"`,
216
+ found,
217
+ found ? undefined : `Add "${entry}" to package.json "files" array`
218
+ );
219
+ }
220
+
221
+ // Check bin entries point to existing files
222
+ const binEntries = pkg.bin || {};
223
+ for (const name of REQUIRED_BIN_ENTRIES) {
224
+ const binPath = binEntries[name];
225
+ if (!binPath) {
226
+ check(`bin.${name} defined`, false, `Missing bin entry for "${name}"`);
227
+ continue;
228
+ }
229
+
230
+ const fullPath = path.join(ROOT, binPath);
231
+ const exists = fs.existsSync(fullPath);
232
+ check(
233
+ `bin.${name} -> ${binPath} exists`,
234
+ exists,
235
+ exists ? undefined : `File not found: ${fullPath}`
236
+ );
237
+ }
238
+
239
+ // Check runtime dependencies
240
+ const deps = pkg.dependencies || {};
241
+ for (const dep of REQUIRED_DEPENDENCIES) {
242
+ check(
243
+ `dependency: ${dep}`,
244
+ dep in deps,
245
+ dep in deps ? undefined : `Missing runtime dependency "${dep}"`
246
+ );
247
+ }
248
+ }
249
+
250
+ function validateBinScripts() {
251
+ log('\n--- Phase 3: Bin Script Validation ---\n');
252
+
253
+ const pkg = loadPackageJson();
254
+ const binEntries = pkg.bin || {};
255
+
256
+ for (const [name, binPath] of Object.entries(binEntries)) {
257
+ const fullPath = path.join(ROOT, binPath);
258
+ if (!fs.existsSync(fullPath)) {
259
+ verbose(`Skipping shebang check for missing file: ${binPath}`);
260
+ continue;
261
+ }
262
+
263
+ const content = fs.readFileSync(fullPath, 'utf8');
264
+ const firstLine = content.split('\n')[0];
265
+ const hasShebang = firstLine.startsWith('#!/usr/bin/env node');
266
+
267
+ check(
268
+ `${name} (${binPath}) has correct shebang`,
269
+ hasShebang,
270
+ hasShebang ? undefined : `Expected "#!/usr/bin/env node", got "${firstLine.substring(0, 40)}"`
271
+ );
272
+ }
273
+ }
274
+
275
+ // ─── Main ───────────────────────────────────────────────────────────────────
276
+
277
+ function main() {
278
+ log('='.repeat(60));
279
+ log('AIOS-Core Package Completeness Validation');
280
+ log('='.repeat(60));
281
+
282
+ const pkg = loadPackageJson();
283
+ log(`\nPackage: ${pkg.name}@${pkg.version}`);
284
+
285
+ // Phase 1: Tarball contents
286
+ const tarballFiles = getTarballContents();
287
+ validateTarballContents(tarballFiles);
288
+
289
+ // Phase 2: package.json
290
+ validatePackageJson(pkg);
291
+
292
+ // Phase 3: Bin scripts
293
+ validateBinScripts();
294
+
295
+ // Summary
296
+ log('\n' + '='.repeat(60));
297
+ log(`Results: ${passedChecks}/${totalChecks} passed, ${failedChecks} failed`);
298
+
299
+ if (failures.length > 0) {
300
+ log('\nFailures:');
301
+ for (const f of failures) {
302
+ log(` - ${f}`);
303
+ }
304
+ log('\n' + '='.repeat(60));
305
+ log('BLOCKED: Package is NOT safe to publish.');
306
+ log('Fix the issues above before running npm publish.');
307
+ log('='.repeat(60));
308
+ process.exit(1);
309
+ }
310
+
311
+ log('\n' + '='.repeat(60));
312
+ log('PASSED: Package is complete and safe to publish.');
313
+ log('='.repeat(60));
314
+ process.exit(0);
315
+ }
316
+
317
+ main();