aios-core 4.0.4 → 4.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.aios-core/cli/commands/migrate/analyze.js +6 -6
- package/.aios-core/cli/commands/migrate/backup.js +2 -2
- package/.aios-core/cli/commands/migrate/execute.js +4 -4
- package/.aios-core/cli/commands/migrate/index.js +5 -5
- package/.aios-core/cli/commands/migrate/rollback.js +6 -6
- package/.aios-core/cli/commands/migrate/update-imports.js +2 -2
- package/.aios-core/cli/commands/migrate/validate.js +2 -2
- package/.aios-core/cli/commands/pro/index.js +52 -0
- package/.aios-core/cli/index.js +1 -1
- package/.aios-core/core/ids/registry-updater.js +29 -3
- package/.aios-core/core/migration/migration-config.yaml +2 -2
- package/.aios-core/core/migration/module-mapping.yaml +2 -2
- package/.aios-core/core/registry/README.md +2 -2
- package/.aios-core/core/synapse/context/context-builder.js +34 -0
- package/.aios-core/core/synapse/diagnostics/collectors/consistency-collector.js +168 -0
- package/.aios-core/core/synapse/diagnostics/collectors/hook-collector.js +129 -0
- package/.aios-core/core/synapse/diagnostics/collectors/manifest-collector.js +82 -0
- package/.aios-core/core/synapse/diagnostics/collectors/output-analyzer.js +134 -0
- package/.aios-core/core/synapse/diagnostics/collectors/pipeline-collector.js +75 -0
- package/.aios-core/core/synapse/diagnostics/collectors/quality-collector.js +252 -0
- package/.aios-core/core/synapse/diagnostics/collectors/relevance-matrix.js +174 -0
- package/.aios-core/core/synapse/diagnostics/collectors/safe-read-json.js +31 -0
- package/.aios-core/core/synapse/diagnostics/collectors/session-collector.js +102 -0
- package/.aios-core/core/synapse/diagnostics/collectors/timing-collector.js +126 -0
- package/.aios-core/core/synapse/diagnostics/collectors/uap-collector.js +83 -0
- package/.aios-core/core/synapse/diagnostics/report-formatter.js +484 -0
- package/.aios-core/core/synapse/diagnostics/synapse-diagnostics.js +95 -0
- package/.aios-core/core/synapse/engine.js +73 -20
- package/.aios-core/core/synapse/runtime/hook-runtime.js +60 -0
- package/.aios-core/core-config.yaml +6 -0
- package/.aios-core/data/agent-config-requirements.yaml +2 -2
- package/.aios-core/data/aios-kb.md +4 -4
- package/.aios-core/data/entity-registry.yaml +210 -10
- package/.aios-core/data/registry-update-log.jsonl +52 -0
- package/.aios-core/development/agents/architect.md +10 -10
- package/.aios-core/development/agents/devops.md +93 -50
- package/.aios-core/development/agents/qa.md +94 -40
- package/.aios-core/development/agents/ux-design-expert.md +25 -25
- package/.aios-core/development/scripts/activation-runtime.js +63 -0
- package/.aios-core/development/scripts/generate-greeting.js +9 -8
- package/.aios-core/development/scripts/unified-activation-pipeline.js +102 -2
- package/.aios-core/development/tasks/{db-expansion-pack-integration.md → db-squad-integration.md} +5 -5
- package/.aios-core/development/tasks/{integrate-expansion-pack.md → integrate-squad.md} +2 -2
- package/.aios-core/development/tasks/next.md +3 -3
- package/.aios-core/development/tasks/pr-automation.md +2 -2
- package/.aios-core/development/tasks/publish-npm.md +257 -0
- package/.aios-core/development/tasks/release-management.md +4 -4
- package/.aios-core/development/tasks/setup-github.md +1 -1
- package/.aios-core/development/tasks/squad-creator-migrate.md +1 -1
- package/.aios-core/development/tasks/squad-creator-sync-ide-command.md +14 -14
- package/.aios-core/development/tasks/update-aios.md +1 -1
- package/.aios-core/development/tasks/validate-next-story.md +99 -2
- package/.aios-core/docs/standards/AIOS-COLOR-PALETTE-QUICK-REFERENCE.md +1 -1
- package/.aios-core/docs/standards/AIOS-COLOR-PALETTE-V2.1.md +5 -5
- package/.aios-core/docs/standards/AIOS-LIVRO-DE-OURO-V2.1-COMPLETE.md +21 -21
- package/.aios-core/docs/standards/AIOS-LIVRO-DE-OURO-V2.2-SUMMARY.md +25 -25
- package/.aios-core/docs/standards/OPEN-SOURCE-VS-SERVICE-DIFFERENCES.md +4 -4
- package/.aios-core/docs/standards/QUALITY-GATES-SPECIFICATION.md +3 -3
- package/.aios-core/docs/standards/STANDARDS-INDEX.md +13 -13
- package/.aios-core/docs/standards/STORY-TEMPLATE-V2-SPECIFICATION.md +1 -1
- package/.aios-core/framework-config.yaml +4 -0
- package/.aios-core/infrastructure/scripts/codex-skills-sync/index.js +182 -0
- package/.aios-core/infrastructure/scripts/codex-skills-sync/validate.js +172 -0
- package/.aios-core/infrastructure/scripts/ide-sync/README.md +14 -0
- package/.aios-core/infrastructure/scripts/ide-sync/index.js +6 -0
- package/.aios-core/infrastructure/scripts/tool-resolver.js +4 -4
- package/.aios-core/infrastructure/scripts/validate-paths.js +142 -0
- package/.aios-core/infrastructure/templates/aios-sync.yaml.template +11 -11
- package/.aios-core/infrastructure/templates/github-workflows/README.md +1 -1
- package/.aios-core/install-manifest.yaml +193 -109
- package/.aios-core/local-config.yaml.template +2 -0
- package/.aios-core/manifests/agents.csv +29 -1
- package/.aios-core/manifests/tasks.csv +80 -3
- package/.aios-core/product/README.md +2 -2
- package/.aios-core/product/data/integration-patterns.md +1 -1
- package/.aios-core/product/templates/ide-rules/cline-rules.md +1 -1
- package/.aios-core/product/templates/ide-rules/codex-rules.md +65 -0
- package/.aios-core/product/templates/ide-rules/copilot-rules.md +1 -1
- package/.aios-core/product/templates/ide-rules/roo-rules.md +1 -1
- package/.aios-core/user-guide.md +15 -14
- package/.aios-core/workflow-intelligence/engine/output-formatter.js +1 -1
- package/.claude/hooks/synapse-engine.js +9 -20
- package/README.md +14 -7
- package/bin/aios-init.js +255 -184
- package/bin/aios-minimal.js +2 -2
- package/bin/aios.js +4 -4
- package/package.json +6 -1
- package/packages/aios-pro-cli/bin/aios-pro.js +75 -2
- package/packages/aios-pro-cli/package.json +5 -1
- package/packages/aios-pro-cli/src/recover.js +100 -0
- package/packages/installer/src/__tests__/performance-benchmark.js +382 -0
- package/packages/installer/src/config/ide-configs.js +12 -1
- package/packages/installer/src/config/templates/core-config-template.js +2 -2
- package/packages/installer/src/installer/aios-core-installer.js +2 -2
- package/packages/installer/src/installer/file-hasher.js +97 -0
- package/packages/installer/src/installer/post-install-validator.js +41 -1
- package/packages/installer/src/pro/pro-scaffolder.js +335 -0
- package/packages/installer/src/utils/aios-colors.js +2 -2
- package/packages/installer/src/wizard/feedback.js +1 -1
- package/packages/installer/src/wizard/ide-config-generator.js +2 -2
- package/packages/installer/src/wizard/index.js +58 -19
- package/packages/installer/src/wizard/pro-setup.js +931 -0
- package/packages/installer/src/wizard/questions.js +20 -14
- package/packages/installer/src/wizard/validators.js +1 -1
- package/scripts/code-intel-health-check.js +343 -0
- package/scripts/package-synapse.js +323 -0
- package/scripts/validate-package-completeness.js +317 -0
|
@@ -0,0 +1,484 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Report Formatter — Generates structured markdown diagnostic report.
|
|
3
|
+
*
|
|
4
|
+
* Takes collector results and produces a human-readable report
|
|
5
|
+
* with sections for each diagnostic area.
|
|
6
|
+
*
|
|
7
|
+
* @module core/synapse/diagnostics/report-formatter
|
|
8
|
+
* @version 1.0.0
|
|
9
|
+
* @created Story SYN-13
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
'use strict';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Format a complete diagnostic report from collector results.
|
|
16
|
+
*
|
|
17
|
+
* @param {object} data - Collected diagnostic data
|
|
18
|
+
* @param {object} data.hook - Hook collector results
|
|
19
|
+
* @param {object} data.session - Session collector results
|
|
20
|
+
* @param {object} data.manifest - Manifest collector results
|
|
21
|
+
* @param {object} data.pipeline - Pipeline collector results
|
|
22
|
+
* @param {object} data.uap - UAP collector results
|
|
23
|
+
* @returns {string} Formatted markdown report
|
|
24
|
+
*/
|
|
25
|
+
function formatReport(data) {
|
|
26
|
+
if (!data || typeof data !== 'object') {
|
|
27
|
+
return '# SYNAPSE Diagnostic Report\n**Error:** No diagnostic data provided.\n';
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const lines = [];
|
|
31
|
+
const timestamp = new Date().toISOString();
|
|
32
|
+
|
|
33
|
+
// Header
|
|
34
|
+
lines.push('# SYNAPSE Diagnostic Report');
|
|
35
|
+
lines.push(`**Timestamp:** ${timestamp}`);
|
|
36
|
+
|
|
37
|
+
if (data.pipeline) {
|
|
38
|
+
const bracket = data.pipeline.bracket || 'UNKNOWN';
|
|
39
|
+
const contextPercent = typeof data.pipeline.contextPercent === 'number'
|
|
40
|
+
? data.pipeline.contextPercent.toFixed(1)
|
|
41
|
+
: '?';
|
|
42
|
+
lines.push(`**Bracket:** ${bracket} (${contextPercent}% context remaining)`);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const agentId = _extractAgentId(data);
|
|
46
|
+
if (agentId) {
|
|
47
|
+
const quality = data.session?.raw?.bridgeData?.activation_quality || 'unknown';
|
|
48
|
+
lines.push(`**Agent:** @${agentId} (activation_quality: ${quality})`);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
lines.push('');
|
|
52
|
+
|
|
53
|
+
// Section 1: Hook Status
|
|
54
|
+
lines.push('## 1. Hook Status');
|
|
55
|
+
if (data.hook && data.hook.checks) {
|
|
56
|
+
lines.push('| Check | Status | Detail |');
|
|
57
|
+
lines.push('|-------|--------|--------|');
|
|
58
|
+
for (const check of data.hook.checks) {
|
|
59
|
+
lines.push(`| ${check.name} | ${check.status} | ${check.detail} |`);
|
|
60
|
+
}
|
|
61
|
+
} else {
|
|
62
|
+
lines.push('*No hook data collected*');
|
|
63
|
+
}
|
|
64
|
+
lines.push('');
|
|
65
|
+
|
|
66
|
+
// Section 2: Session Status
|
|
67
|
+
lines.push('## 2. Session Status');
|
|
68
|
+
if (data.session && data.session.fields) {
|
|
69
|
+
lines.push('| Field | Expected | Actual | Status |');
|
|
70
|
+
lines.push('|-------|----------|--------|--------|');
|
|
71
|
+
for (const field of data.session.fields) {
|
|
72
|
+
lines.push(`| ${field.field} | ${field.expected} | ${field.actual} | ${field.status} |`);
|
|
73
|
+
}
|
|
74
|
+
} else {
|
|
75
|
+
lines.push('*No session data collected*');
|
|
76
|
+
}
|
|
77
|
+
lines.push('');
|
|
78
|
+
|
|
79
|
+
// Section 3: Manifest Integrity
|
|
80
|
+
lines.push('## 3. Manifest Integrity');
|
|
81
|
+
if (data.manifest && data.manifest.entries) {
|
|
82
|
+
lines.push('| Domain | In Manifest | File Exists | Status |');
|
|
83
|
+
lines.push('|--------|-------------|-------------|--------|');
|
|
84
|
+
for (const entry of data.manifest.entries) {
|
|
85
|
+
lines.push(`| ${entry.domain} | ${entry.inManifest} | ${entry.fileExists ? 'yes' : 'no'} | ${entry.status} |`);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (data.manifest.orphanedFiles && data.manifest.orphanedFiles.length > 0) {
|
|
89
|
+
lines.push('');
|
|
90
|
+
lines.push(`**Orphaned files** (in .synapse/ but not in manifest): ${data.manifest.orphanedFiles.join(', ')}`);
|
|
91
|
+
}
|
|
92
|
+
} else {
|
|
93
|
+
lines.push('*No manifest data collected*');
|
|
94
|
+
}
|
|
95
|
+
lines.push('');
|
|
96
|
+
|
|
97
|
+
// Section 4: Pipeline Simulation
|
|
98
|
+
lines.push(`## 4. Pipeline Simulation (${data.pipeline?.bracket || 'UNKNOWN'} bracket)`);
|
|
99
|
+
if (data.pipeline && data.pipeline.layers) {
|
|
100
|
+
lines.push('| Layer | Expected | Status |');
|
|
101
|
+
lines.push('|-------|----------|--------|');
|
|
102
|
+
for (const layer of data.pipeline.layers) {
|
|
103
|
+
lines.push(`| ${layer.layer} | ${layer.expected} | ${layer.status} |`);
|
|
104
|
+
}
|
|
105
|
+
} else {
|
|
106
|
+
lines.push('*No pipeline data collected*');
|
|
107
|
+
}
|
|
108
|
+
lines.push('');
|
|
109
|
+
|
|
110
|
+
// Section 5: UAP Bridge
|
|
111
|
+
lines.push('## 5. UAP Bridge');
|
|
112
|
+
if (data.uap && data.uap.checks) {
|
|
113
|
+
lines.push('| Check | Status | Detail |');
|
|
114
|
+
lines.push('|-------|--------|--------|');
|
|
115
|
+
for (const check of data.uap.checks) {
|
|
116
|
+
lines.push(`| ${check.name} | ${check.status} | ${check.detail} |`);
|
|
117
|
+
}
|
|
118
|
+
} else {
|
|
119
|
+
lines.push('*No UAP bridge data collected*');
|
|
120
|
+
}
|
|
121
|
+
lines.push('');
|
|
122
|
+
|
|
123
|
+
// Section 6: Memory Bridge
|
|
124
|
+
lines.push('## 6. Memory Bridge');
|
|
125
|
+
lines.push('| Check | Status | Detail |');
|
|
126
|
+
lines.push('|-------|--------|--------|');
|
|
127
|
+
|
|
128
|
+
// Memory bridge is Pro-only, so always report current state
|
|
129
|
+
lines.push('| Pro available | INFO | Check `pro/` submodule |');
|
|
130
|
+
lines.push(`| Bracket requires hints | ${_bracketNeedsMemory(data.pipeline?.bracket) ? 'YES' : 'NO'} | ${data.pipeline?.bracket || 'UNKNOWN'} bracket |`);
|
|
131
|
+
lines.push('');
|
|
132
|
+
|
|
133
|
+
// Section 7: Gaps & Recommendations
|
|
134
|
+
lines.push('## 7. Gaps & Recommendations');
|
|
135
|
+
const gaps = _collectGaps(data);
|
|
136
|
+
|
|
137
|
+
if (gaps.length === 0) {
|
|
138
|
+
lines.push('| # | Severity | Gap | Recommendation |');
|
|
139
|
+
lines.push('|---|----------|-----|----------------|');
|
|
140
|
+
lines.push('| - | - | None found | Pipeline operating correctly |');
|
|
141
|
+
} else {
|
|
142
|
+
lines.push('| # | Severity | Gap | Recommendation |');
|
|
143
|
+
lines.push('|---|----------|-----|----------------|');
|
|
144
|
+
for (let i = 0; i < gaps.length; i++) {
|
|
145
|
+
lines.push(`| ${i + 1} | ${gaps[i].severity} | ${gaps[i].gap} | ${gaps[i].recommendation} |`);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
lines.push('');
|
|
149
|
+
|
|
150
|
+
// Section 8: Timing Analysis (SYN-14)
|
|
151
|
+
_formatTimingSection(lines, data.timing);
|
|
152
|
+
|
|
153
|
+
// Section 9: Context Quality Analysis (SYN-14)
|
|
154
|
+
_formatQualitySection(lines, data.quality);
|
|
155
|
+
|
|
156
|
+
// Section 10: Consistency Checks (SYN-14)
|
|
157
|
+
_formatConsistencySection(lines, data.consistency);
|
|
158
|
+
|
|
159
|
+
// Section 11: Output Quality (SYN-14)
|
|
160
|
+
_formatOutputSection(lines, data.outputAnalysis);
|
|
161
|
+
|
|
162
|
+
// Section 12: Relevance Matrix (SYN-14)
|
|
163
|
+
_formatRelevanceSection(lines, data.relevance);
|
|
164
|
+
|
|
165
|
+
return lines.join('\n');
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Extract agent ID from collected data.
|
|
170
|
+
* @param {object} data
|
|
171
|
+
* @returns {string|null}
|
|
172
|
+
*/
|
|
173
|
+
function _extractAgentId(data) {
|
|
174
|
+
if (data.session?.raw?.bridgeData?.id) return data.session.raw.bridgeData.id;
|
|
175
|
+
if (data.session?.raw?.session?.active_agent?.id) return data.session.raw.session.active_agent.id;
|
|
176
|
+
return null;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Check if a bracket requires memory hints.
|
|
181
|
+
* @param {string} bracket
|
|
182
|
+
* @returns {boolean}
|
|
183
|
+
*/
|
|
184
|
+
function _bracketNeedsMemory(bracket) {
|
|
185
|
+
return bracket === 'DEPLETED' || bracket === 'CRITICAL';
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Collect gaps from all collector results.
|
|
190
|
+
* @param {object} data
|
|
191
|
+
* @returns {Array<{ severity: string, gap: string, recommendation: string }>}
|
|
192
|
+
*/
|
|
193
|
+
function _collectGaps(data) {
|
|
194
|
+
const gaps = [];
|
|
195
|
+
|
|
196
|
+
// Check hook failures
|
|
197
|
+
const hookChecks = data.hook?.checks || [];
|
|
198
|
+
for (const check of hookChecks) {
|
|
199
|
+
if (check.status === 'FAIL') {
|
|
200
|
+
gaps.push({
|
|
201
|
+
severity: 'HIGH',
|
|
202
|
+
gap: `Hook: ${check.name} — ${check.detail}`,
|
|
203
|
+
recommendation: 'Run `npx aios-core install` to reinstall hooks',
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// Check session issues
|
|
209
|
+
const sessionFields = data.session?.fields || [];
|
|
210
|
+
for (const field of sessionFields) {
|
|
211
|
+
if (field.status === 'FAIL') {
|
|
212
|
+
gaps.push({
|
|
213
|
+
severity: 'HIGH',
|
|
214
|
+
gap: `Session: ${field.field} — ${field.actual}`,
|
|
215
|
+
recommendation: 'Activate an agent with @agent to create session',
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// Check manifest failures
|
|
221
|
+
const manifestEntries = data.manifest?.entries || [];
|
|
222
|
+
for (const entry of manifestEntries) {
|
|
223
|
+
if (entry.status === 'FAIL') {
|
|
224
|
+
gaps.push({
|
|
225
|
+
severity: 'MEDIUM',
|
|
226
|
+
gap: `Manifest: domain "${entry.domain}" file missing`,
|
|
227
|
+
recommendation: `Create .synapse/${entry.domain} domain file`,
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// Check UAP bridge failures
|
|
233
|
+
const uapChecks = data.uap?.checks || [];
|
|
234
|
+
for (const check of uapChecks) {
|
|
235
|
+
if (check.status === 'FAIL') {
|
|
236
|
+
gaps.push({
|
|
237
|
+
severity: 'HIGH',
|
|
238
|
+
gap: `UAP Bridge: ${check.name} — ${check.detail}`,
|
|
239
|
+
recommendation: 'Activate an agent to trigger UAP bridge write',
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// SYN-14 fix: Include gaps from new collectors (consistency, quality, relevance)
|
|
245
|
+
|
|
246
|
+
// Consistency check failures
|
|
247
|
+
const consistencyChecks = data.consistency?.checks || [];
|
|
248
|
+
for (const check of consistencyChecks) {
|
|
249
|
+
if (check.status === 'FAIL') {
|
|
250
|
+
gaps.push({
|
|
251
|
+
severity: 'MEDIUM',
|
|
252
|
+
gap: `Consistency: ${check.name} — ${check.detail}`,
|
|
253
|
+
recommendation: 'Re-activate agent to refresh metrics alignment',
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// Quality grade below threshold
|
|
259
|
+
if (data.quality?.overall?.grade === 'F') {
|
|
260
|
+
gaps.push({
|
|
261
|
+
severity: 'HIGH',
|
|
262
|
+
gap: `Context quality: ${data.quality.overall.score}/100 (${data.quality.overall.grade})`,
|
|
263
|
+
recommendation: 'Re-activate agent to refresh UAP metrics',
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// Relevance critical gaps
|
|
268
|
+
const relevanceGaps = data.relevance?.gaps || [];
|
|
269
|
+
for (const g of relevanceGaps) {
|
|
270
|
+
if (g.importance === 'critical') {
|
|
271
|
+
gaps.push({
|
|
272
|
+
severity: 'HIGH',
|
|
273
|
+
gap: `Relevance: ${g.component} (${g.importance}) missing`,
|
|
274
|
+
recommendation: 'Ensure critical context component is available for active agent',
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// Sort by severity (HIGH first)
|
|
280
|
+
const severityOrder = { HIGH: 0, MEDIUM: 1, LOW: 2 };
|
|
281
|
+
gaps.sort((a, b) => {
|
|
282
|
+
const orderA = severityOrder[a.severity] !== undefined ? severityOrder[a.severity] : 3;
|
|
283
|
+
const orderB = severityOrder[b.severity] !== undefined ? severityOrder[b.severity] : 3;
|
|
284
|
+
return orderA - orderB;
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
return gaps;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* Section 8: Timing Analysis.
|
|
292
|
+
* @param {string[]} lines
|
|
293
|
+
* @param {object} timing
|
|
294
|
+
*/
|
|
295
|
+
function _formatTimingSection(lines, timing) {
|
|
296
|
+
lines.push('## 8. Timing Analysis');
|
|
297
|
+
if (!timing || timing.error) {
|
|
298
|
+
lines.push('*No timing data available*');
|
|
299
|
+
lines.push('');
|
|
300
|
+
return;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
// UAP Timing
|
|
304
|
+
if (timing.uap && timing.uap.available) {
|
|
305
|
+
const staleTag = timing.uap.stale ? ' **[STALE]**' : '';
|
|
306
|
+
lines.push(`### UAP Activation Pipeline (${timing.uap.totalDuration}ms total, quality: ${timing.uap.quality})${staleTag}`);
|
|
307
|
+
lines.push('| Loader | Duration | Status | Tier |');
|
|
308
|
+
lines.push('|--------|----------|--------|------|');
|
|
309
|
+
for (const loader of timing.uap.loaders) {
|
|
310
|
+
lines.push(`| ${loader.name} | ${loader.duration}ms | ${loader.status} | ${loader.tier} |`);
|
|
311
|
+
}
|
|
312
|
+
lines.push(`| **Total** | **${timing.uap.totalDuration}ms** | | |`);
|
|
313
|
+
} else {
|
|
314
|
+
lines.push('### UAP Activation Pipeline');
|
|
315
|
+
lines.push('*No UAP timing data — activate an agent first*');
|
|
316
|
+
}
|
|
317
|
+
lines.push('');
|
|
318
|
+
|
|
319
|
+
// Hook Timing
|
|
320
|
+
if (timing.hook && timing.hook.available) {
|
|
321
|
+
const staleTag = timing.hook.stale ? ' **[STALE]**' : '';
|
|
322
|
+
const bootInfo = timing.hook.hookBootMs ? ` boot: ${Math.round(timing.hook.hookBootMs)}ms,` : '';
|
|
323
|
+
lines.push(`### SYNAPSE Hook Pipeline (${timing.hook.totalDuration}ms total,${bootInfo} ${timing.hook.bracket} bracket)${staleTag}`);
|
|
324
|
+
lines.push('| Layer | Duration | Status | Rules |');
|
|
325
|
+
lines.push('|-------|----------|--------|-------|');
|
|
326
|
+
for (const layer of timing.hook.layers) {
|
|
327
|
+
lines.push(`| ${layer.name} | ${layer.duration}ms | ${layer.status} | ${layer.rules} |`);
|
|
328
|
+
}
|
|
329
|
+
const totalRules = timing.hook.layers.reduce((sum, l) => sum + (l.rules || 0), 0);
|
|
330
|
+
lines.push(`| **Total** | **${timing.hook.totalDuration}ms** | | **${totalRules}** |`);
|
|
331
|
+
} else {
|
|
332
|
+
lines.push('### SYNAPSE Hook Pipeline');
|
|
333
|
+
lines.push('*No Hook timing data — send a prompt first*');
|
|
334
|
+
}
|
|
335
|
+
lines.push('');
|
|
336
|
+
|
|
337
|
+
// Combined
|
|
338
|
+
lines.push(`**Combined pipeline time:** ${timing.combined ? timing.combined.totalMs : 0}ms`);
|
|
339
|
+
lines.push('');
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* Section 9: Context Quality Analysis.
|
|
344
|
+
* @param {string[]} lines
|
|
345
|
+
* @param {object} quality
|
|
346
|
+
*/
|
|
347
|
+
function _formatQualitySection(lines, quality) {
|
|
348
|
+
lines.push('## 9. Context Quality Analysis');
|
|
349
|
+
if (!quality || quality.error) {
|
|
350
|
+
lines.push('*No quality data available*');
|
|
351
|
+
lines.push('');
|
|
352
|
+
return;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
const overall = quality.overall || { score: 0, grade: 'F', label: 'UNKNOWN' };
|
|
356
|
+
lines.push(`**Overall: ${overall.score}/100 (${overall.grade} — ${overall.label})**`);
|
|
357
|
+
|
|
358
|
+
const uapScore = quality.uap ? quality.uap.score : 0;
|
|
359
|
+
const hookScore = quality.hook ? quality.hook.score : 0;
|
|
360
|
+
const uapStale = quality.uap && quality.uap.stale ? ' [STALE]' : '';
|
|
361
|
+
const hookStale = quality.hook && quality.hook.stale ? ' [STALE]' : '';
|
|
362
|
+
lines.push(`UAP: ${uapScore}/100${uapStale} | Hook: ${hookScore}/100${hookStale}`);
|
|
363
|
+
lines.push('');
|
|
364
|
+
|
|
365
|
+
// UAP Loaders
|
|
366
|
+
if (quality.uap && quality.uap.loaders && quality.uap.loaders.length > 0) {
|
|
367
|
+
lines.push('### UAP Loaders');
|
|
368
|
+
lines.push('| Loader | Score | Criticality | Impact |');
|
|
369
|
+
lines.push('|--------|-------|-------------|--------|');
|
|
370
|
+
for (const loader of quality.uap.loaders) {
|
|
371
|
+
lines.push(`| ${loader.name} | ${loader.score}/${loader.maxScore} | ${loader.criticality} | ${loader.impact} |`);
|
|
372
|
+
}
|
|
373
|
+
lines.push('');
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
// Hook Layers
|
|
377
|
+
if (quality.hook && quality.hook.layers && quality.hook.layers.length > 0) {
|
|
378
|
+
lines.push('### Hook Layers');
|
|
379
|
+
lines.push('| Layer | Score | Criticality | Rules | Impact |');
|
|
380
|
+
lines.push('|-------|-------|-------------|-------|--------|');
|
|
381
|
+
for (const layer of quality.hook.layers) {
|
|
382
|
+
lines.push(`| ${layer.name} | ${layer.score}/${layer.maxScore} | ${layer.criticality} | ${layer.rules || '-'} | ${layer.impact} |`);
|
|
383
|
+
}
|
|
384
|
+
lines.push('');
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
/**
|
|
389
|
+
* Section 10: Consistency Checks.
|
|
390
|
+
* @param {string[]} lines
|
|
391
|
+
* @param {object} consistency
|
|
392
|
+
*/
|
|
393
|
+
function _formatConsistencySection(lines, consistency) {
|
|
394
|
+
lines.push('## 10. Consistency Checks');
|
|
395
|
+
if (!consistency || consistency.error || !consistency.available) {
|
|
396
|
+
lines.push('*No consistency data available*');
|
|
397
|
+
lines.push('');
|
|
398
|
+
return;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
lines.push(`**Score:** ${consistency.score}/${consistency.maxScore}`);
|
|
402
|
+
lines.push('');
|
|
403
|
+
lines.push('| Check | Status | Detail |');
|
|
404
|
+
lines.push('|-------|--------|--------|');
|
|
405
|
+
for (const check of consistency.checks) {
|
|
406
|
+
lines.push(`| ${check.name} | ${check.status} | ${check.detail} |`);
|
|
407
|
+
}
|
|
408
|
+
lines.push('');
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
/**
|
|
412
|
+
* Section 11: Output Quality.
|
|
413
|
+
* @param {string[]} lines
|
|
414
|
+
* @param {object} outputAnalysis
|
|
415
|
+
*/
|
|
416
|
+
function _formatOutputSection(lines, outputAnalysis) {
|
|
417
|
+
lines.push('## 11. Output Quality');
|
|
418
|
+
if (!outputAnalysis || outputAnalysis.error || !outputAnalysis.available) {
|
|
419
|
+
lines.push('*No output analysis data available*');
|
|
420
|
+
lines.push('');
|
|
421
|
+
return;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
const s = outputAnalysis.summary;
|
|
425
|
+
lines.push(`**UAP:** ${s.uapHealthy}/${s.uapTotal} healthy | **Hook:** ${s.hookHealthy}/${s.hookTotal} healthy`);
|
|
426
|
+
lines.push('');
|
|
427
|
+
|
|
428
|
+
if (outputAnalysis.uapAnalysis && outputAnalysis.uapAnalysis.length > 0) {
|
|
429
|
+
lines.push('### UAP Loaders');
|
|
430
|
+
lines.push('| Loader | Status | Quality | Detail |');
|
|
431
|
+
lines.push('|--------|--------|---------|--------|');
|
|
432
|
+
for (const a of outputAnalysis.uapAnalysis) {
|
|
433
|
+
lines.push(`| ${a.name} | ${a.status} | ${a.quality} | ${a.detail} |`);
|
|
434
|
+
}
|
|
435
|
+
lines.push('');
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
if (outputAnalysis.hookAnalysis && outputAnalysis.hookAnalysis.length > 0) {
|
|
439
|
+
lines.push('### Hook Layers');
|
|
440
|
+
lines.push('| Layer | Status | Rules | Quality | Detail |');
|
|
441
|
+
lines.push('|-------|--------|-------|---------|--------|');
|
|
442
|
+
for (const a of outputAnalysis.hookAnalysis) {
|
|
443
|
+
lines.push(`| ${a.name} | ${a.status} | ${a.rules} | ${a.quality} | ${a.detail} |`);
|
|
444
|
+
}
|
|
445
|
+
lines.push('');
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
/**
|
|
450
|
+
* Section 12: Relevance Matrix.
|
|
451
|
+
* @param {string[]} lines
|
|
452
|
+
* @param {object} relevance
|
|
453
|
+
*/
|
|
454
|
+
function _formatRelevanceSection(lines, relevance) {
|
|
455
|
+
lines.push('## 12. Relevance Matrix');
|
|
456
|
+
if (!relevance || relevance.error || !relevance.available) {
|
|
457
|
+
lines.push('*No relevance data available*');
|
|
458
|
+
lines.push('');
|
|
459
|
+
return;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
lines.push(`**Agent:** @${relevance.agentId} | **Relevance Score:** ${relevance.score}/100`);
|
|
463
|
+
lines.push('');
|
|
464
|
+
|
|
465
|
+
if (relevance.matrix && relevance.matrix.length > 0) {
|
|
466
|
+
lines.push('| Component | Importance | Status | Gap |');
|
|
467
|
+
lines.push('|-----------|------------|--------|-----|');
|
|
468
|
+
for (const item of relevance.matrix) {
|
|
469
|
+
const gapFlag = item.gap ? 'YES' : '-';
|
|
470
|
+
lines.push(`| ${item.component} | ${item.importance} | ${item.status} | ${gapFlag} |`);
|
|
471
|
+
}
|
|
472
|
+
lines.push('');
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
if (relevance.gaps && relevance.gaps.length > 0) {
|
|
476
|
+
lines.push('### Critical Gaps');
|
|
477
|
+
for (const gap of relevance.gaps) {
|
|
478
|
+
lines.push(`- **${gap.component}** (${gap.importance}): missing or failed`);
|
|
479
|
+
}
|
|
480
|
+
lines.push('');
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
module.exports = { formatReport };
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SYNAPSE Diagnostics Orchestrator
|
|
3
|
+
*
|
|
4
|
+
* Coordinates all collectors and generates a comprehensive diagnostic report
|
|
5
|
+
* comparing expected vs. actual SYNAPSE pipeline state.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* const { runDiagnostics } = require('.../synapse-diagnostics');
|
|
9
|
+
* const report = runDiagnostics('/path/to/project');
|
|
10
|
+
*
|
|
11
|
+
* @module core/synapse/diagnostics/synapse-diagnostics
|
|
12
|
+
* @version 1.0.0
|
|
13
|
+
* @created Story SYN-13
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
'use strict';
|
|
17
|
+
|
|
18
|
+
const path = require('path');
|
|
19
|
+
const { collectHookStatus } = require('./collectors/hook-collector');
|
|
20
|
+
const { collectSessionStatus } = require('./collectors/session-collector');
|
|
21
|
+
const { collectManifestIntegrity } = require('./collectors/manifest-collector');
|
|
22
|
+
const { collectPipelineSimulation } = require('./collectors/pipeline-collector');
|
|
23
|
+
const { collectUapBridgeStatus } = require('./collectors/uap-collector');
|
|
24
|
+
const { formatReport } = require('./report-formatter');
|
|
25
|
+
const { parseManifest } = require('../domain/domain-loader');
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Safely execute a collector, returning an error object on failure.
|
|
29
|
+
* Diagnostics must be resilient — a broken collector should not crash the entire run.
|
|
30
|
+
* @param {string} name - Collector name for error reporting
|
|
31
|
+
* @param {Function} fn - Collector function to execute
|
|
32
|
+
* @returns {*} Collector result or { error: true, collector, message, checks, fields, entries }
|
|
33
|
+
*/
|
|
34
|
+
function _safeCollect(name, fn) {
|
|
35
|
+
try {
|
|
36
|
+
return fn();
|
|
37
|
+
} catch (error) {
|
|
38
|
+
return { error: true, collector: name, message: error.message, checks: [], fields: [], entries: [] };
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Run all collectors and return raw results.
|
|
44
|
+
* Shared orchestration logic used by both runDiagnostics and runDiagnosticsRaw.
|
|
45
|
+
* @param {string} projectRoot - Absolute path to project root
|
|
46
|
+
* @param {object} options - Diagnostic options
|
|
47
|
+
* @returns {{ hook, session, manifest, pipeline, uap }} Collector results
|
|
48
|
+
*/
|
|
49
|
+
function _collectAll(projectRoot, options) {
|
|
50
|
+
if (!projectRoot || typeof projectRoot !== 'string') {
|
|
51
|
+
throw new Error('projectRoot is required and must be a string');
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const synapsePath = path.join(projectRoot, '.synapse');
|
|
55
|
+
const manifestPath = path.join(synapsePath, 'manifest');
|
|
56
|
+
|
|
57
|
+
const hook = _safeCollect('hook', () => collectHookStatus(projectRoot));
|
|
58
|
+
const session = _safeCollect('session', () => collectSessionStatus(projectRoot, options.sessionId));
|
|
59
|
+
const manifest = _safeCollect('manifest', () => collectManifestIntegrity(projectRoot));
|
|
60
|
+
const parsedManifest = _safeCollect('parsedManifest', () => parseManifest(manifestPath));
|
|
61
|
+
|
|
62
|
+
const promptCount = session?.raw?.session?.prompt_count || 0;
|
|
63
|
+
const activeAgentId = session?.raw?.bridgeData?.id || session?.raw?.session?.active_agent?.id || null;
|
|
64
|
+
|
|
65
|
+
const pipeline = _safeCollect('pipeline', () => collectPipelineSimulation(promptCount, activeAgentId, parsedManifest));
|
|
66
|
+
const uap = _safeCollect('uap', () => collectUapBridgeStatus(projectRoot));
|
|
67
|
+
|
|
68
|
+
return { hook, session, manifest, pipeline, uap };
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Run full SYNAPSE diagnostics and return formatted markdown report.
|
|
73
|
+
*
|
|
74
|
+
* @param {string} projectRoot - Absolute path to project root
|
|
75
|
+
* @param {object} [options] - Diagnostic options
|
|
76
|
+
* @param {string} [options.sessionId] - Session UUID for session-specific checks
|
|
77
|
+
* @returns {string} Formatted markdown diagnostic report
|
|
78
|
+
*/
|
|
79
|
+
function runDiagnostics(projectRoot, options = {}) {
|
|
80
|
+
const data = _collectAll(projectRoot, options);
|
|
81
|
+
return formatReport(data);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Run diagnostics and return raw collector data (for programmatic use).
|
|
86
|
+
*
|
|
87
|
+
* @param {string} projectRoot - Absolute path to project root
|
|
88
|
+
* @param {object} [options] - Diagnostic options
|
|
89
|
+
* @returns {object} Raw collector results
|
|
90
|
+
*/
|
|
91
|
+
function runDiagnosticsRaw(projectRoot, options = {}) {
|
|
92
|
+
return _collectAll(projectRoot, options);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
module.exports = { runDiagnostics, runDiagnosticsRaw };
|