@ismaelsoilet/synapsejs 1.4.0 → 1.9.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 (53) hide show
  1. package/README.md +108 -10
  2. package/bin/synapse.ts +263 -218
  3. package/package.json +1 -1
  4. package/src/client/components.tsx +26 -9
  5. package/src/client/outlet.tsx +40 -0
  6. package/src/client/sub-slice.tsx +45 -0
  7. package/src/client/use-websocket.ts +146 -0
  8. package/src/client.ts +12 -0
  9. package/src/compiler/client-bundler.ts +17 -7
  10. package/src/compiler/context-bench.ts +7 -1
  11. package/src/compiler/contract.ts +31 -4
  12. package/src/compiler/db-schema-generator.ts +39 -8
  13. package/src/compiler/fields-parser.ts +28 -1
  14. package/src/compiler/impact-analyzer.ts +31 -1
  15. package/src/compiler/migration-runner.ts +144 -11
  16. package/src/compiler/optional-coverage.ts +137 -0
  17. package/src/compiler/oracle-runner.ts +8 -3
  18. package/src/compiler/scaffolder.ts +174 -3
  19. package/src/compiler/schema-dag.ts +6 -3
  20. package/src/compiler/slice-discovery.ts +8 -1
  21. package/src/compiler/slice-splitter.ts +67 -6
  22. package/src/compiler/slice-templates.ts +10 -0
  23. package/src/compiler/standalone-builder.ts +16 -2
  24. package/src/core/action-context.ts +101 -8
  25. package/src/core/cache.ts +139 -0
  26. package/src/core/config.ts +124 -10
  27. package/src/core/database-client.ts +68 -6
  28. package/src/core/index.ts +5 -0
  29. package/src/core/path-guard.ts +105 -0
  30. package/src/core/postgres-client.ts +6 -0
  31. package/src/core/postgres-queue.ts +45 -7
  32. package/src/core/query-builder.ts +75 -60
  33. package/src/core/session-context.ts +1 -1
  34. package/src/core/session-token.ts +115 -8
  35. package/src/core/sqlite-client.ts +26 -1
  36. package/src/core/storage.ts +61 -24
  37. package/src/core/topics.ts +84 -0
  38. package/src/core/webhook-signature.ts +151 -0
  39. package/src/core/websocket.ts +30 -0
  40. package/src/index.ts +10 -2
  41. package/src/mcp/server.ts +78 -173
  42. package/src/mcp/tools.ts +238 -0
  43. package/src/project-status.ts +330 -0
  44. package/src/runtime/discovery-rules.ts +20 -1
  45. package/src/runtime/event-hub.ts +6 -1
  46. package/src/runtime/network-guard.ts +182 -0
  47. package/src/runtime/queue-engine.ts +102 -21
  48. package/src/runtime/rate-limiter.ts +24 -0
  49. package/src/runtime/server.ts +1380 -251
  50. package/src/runtime/uploads.ts +199 -19
  51. package/src/version.ts +11 -0
  52. package/templates/starter/.jev.json +1 -1
  53. package/templates/starter/tsconfig.json +1 -0
package/src/mcp/server.ts CHANGED
@@ -8,9 +8,13 @@
8
8
 
9
9
  import {
10
10
  type AbortGateResult,
11
+ type ModelRouteResult,
11
12
  modulateReasoningEffort,
13
+ type NudgeGateResult,
12
14
  type ReasoningEffortResult,
15
+ routeModelTier,
13
16
  shouldAbortTrajectory,
17
+ shouldNudgeContinuation,
14
18
  type TestTriageResult,
15
19
  triageTestFailure,
16
20
  type VerificationResult,
@@ -28,6 +32,33 @@ import { type SliceTemplate, scaffoldCrud, scaffoldSlice } from '../compiler/sca
28
32
  import { checkSchemaDrift } from '../compiler/schema-drift';
29
33
  import { findSliceFiles, resolveSlicesDir } from '../compiler/slice-discovery';
30
34
  import { artifactDirectory, splitSlice, verifySplit, writeSplitArtifacts } from '../compiler/slice-splitter';
35
+ import { SYNAPSE_VERSION } from '../version';
36
+ import { MCP_TOOLS } from './tools';
37
+
38
+ /**
39
+ * Caps a tool payload so a broken workspace cannot flood the caller's context, and
40
+ * makes every path relative to the project root so a tool result carries no absolute
41
+ * filesystem location.
42
+ */
43
+ const MCP_MAX_ITEMS = 100;
44
+
45
+ export function capItems<T>(items: T[]): { items: T[]; truncated: boolean; total: number } {
46
+ return {
47
+ items: items.slice(0, MCP_MAX_ITEMS),
48
+ truncated: items.length > MCP_MAX_ITEMS,
49
+ total: items.length
50
+ };
51
+ }
52
+
53
+ export function toRelativePath(root: string, value: unknown): unknown {
54
+ if (typeof value !== 'string' || !path.isAbsolute(value)) {
55
+ return value;
56
+ }
57
+
58
+ const relative = path.relative(root, value);
59
+
60
+ return relative.startsWith('..') ? path.basename(value) : relative;
61
+ }
31
62
 
32
63
  interface JsonRpcRequest {
33
64
  jsonrpc: string;
@@ -90,7 +121,7 @@ export class SynapseMcpServer {
90
121
  },
91
122
  serverInfo: {
92
123
  name: 'synapse-mcp',
93
- version: '1.2.0'
124
+ version: SYNAPSE_VERSION
94
125
  }
95
126
  }
96
127
  };
@@ -105,175 +136,7 @@ export class SynapseMcpServer {
105
136
  jsonrpc: '2.0',
106
137
  id,
107
138
  result: {
108
- tools: [
109
- {
110
- name: 'synapse_get_repo_map',
111
- description:
112
- 'Get compressed codebase skeleton map (.codebase/repo-map.d.ts) for AI context (<3000 tokens)',
113
- inputSchema: { type: 'object', properties: {} }
114
- },
115
- {
116
- name: 'synapse_get_db_schema',
117
- description:
118
- 'Get the centralized database schema catalog (.codebase/db-schema.d.ts) for AI context and type-safe relational queries',
119
- inputSchema: { type: 'object', properties: {} }
120
- },
121
- {
122
- name: 'synapse_check',
123
- description:
124
- 'Run machine-centric compiler diagnostics, returning exact JSON coordinates (file, line, col, message)',
125
- inputSchema: {
126
- type: 'object',
127
- properties: {
128
- targetFile: { type: 'string', description: 'Optional specific file to check' }
129
- }
130
- }
131
- },
132
- {
133
- name: 'synapse_split',
134
- description:
135
- 'Run slice splitter and leak verification gates to enforce server/client isolation and zero leakage',
136
- inputSchema: {
137
- type: 'object',
138
- properties: {
139
- targetSlice: { type: 'string', description: 'Optional specific slice name to split' }
140
- }
141
- }
142
- },
143
- {
144
- name: 'synapse_run_pbt',
145
- description: 'Execute Fast-Check Property-Based Testing (PBT) invariant test suite across all slices',
146
- inputSchema: { type: 'object', properties: {} }
147
- },
148
- {
149
- name: 'synapse_scaffold_slice',
150
- description:
151
- 'Scaffold a new fullstack atomic vertical slice with TypeBox, Result, Action, React UI, and PBT oracles',
152
- inputSchema: {
153
- type: 'object',
154
- required: ['domain', 'name'],
155
- properties: {
156
- domain: { type: 'string', description: 'Domain name (e.g. billing, customers, orders)' },
157
- name: { type: 'string', description: 'Slice name in kebab-case (e.g. cancel-subscription)' },
158
- template: {
159
- type: 'string',
160
- enum: ['create', 'list', 'update', 'delete', 'login', 'oauth-github', 'crud'],
161
- description: 'Optional slice template shape (default: create)'
162
- },
163
- fields: {
164
- type: 'string',
165
- description:
166
- 'Optional fields grammar, e.g. "name:string,email:string,status:enum(ACTIVE|INACTIVE),price:number"'
167
- }
168
- }
169
- }
170
- },
171
- {
172
- name: 'synapse_contract',
173
- description:
174
- 'Return the machine contract: slice exports and suffixes, Result and HTTP semantics, session rules, addressing, SSR behavior and the gates to run',
175
- inputSchema: { type: 'object', properties: {} }
176
- },
177
- {
178
- name: 'synapse_migrate',
179
- description:
180
- 'Auto-discover and apply sliceSchema DDL declarations across slices into the active database',
181
- inputSchema: { type: 'object', properties: {} }
182
- },
183
- {
184
- name: 'synapse_check_db_drift',
185
- description:
186
- 'Inspects live database catalog against sliceSchema DDL contracts, identifying missing tables, missing columns, and orphan tables',
187
- inputSchema: { type: 'object', properties: {} }
188
- },
189
- {
190
- name: 'synapse_diff_impact',
191
- description:
192
- 'Analyzes cross-slice dependencies (Foreign Keys, shared module imports, and table references) to report all slices impacted by a file or table change',
193
- inputSchema: {
194
- type: 'object',
195
- required: ['target'],
196
- properties: {
197
- target: {
198
- type: 'string',
199
- description: 'Slice file path, slice name, shared module path, or table name'
200
- }
201
- }
202
- }
203
- },
204
- {
205
- name: 'synapse_rollback',
206
- description: 'Roll back applied sliceSchema migrations by executing their -- down: statements',
207
- inputSchema: {
208
- type: 'object',
209
- properties: {
210
- targetSlice: { type: 'string', description: 'Optional target slice to rollback' },
211
- steps: { type: 'number', description: 'Number of recent migrations to rollback (default: 1)' }
212
- }
213
- }
214
- },
215
- {
216
- name: 'synapse_test_gate',
217
- description:
218
- 'Execute Fast-Check PBT oracles and immediately triage failures with Jev System One semantic test-gate to prevent LLM token waste',
219
- inputSchema: {
220
- type: 'object',
221
- properties: {}
222
- }
223
- },
224
- {
225
- name: 'synapse_abort_check',
226
- description:
227
- 'Evaluate plan and error history with Jev System One to detect doomed trajectories, circular loops, or high-risk refactor dead ends',
228
- inputSchema: {
229
- type: 'object',
230
- required: ['plan', 'history'],
231
- properties: {
232
- plan: { type: 'string', description: 'Proposed implementation plan or architectural change' },
233
- history: { type: 'string', description: 'Recent attempt history, error logs, or failure reasons' }
234
- }
235
- }
236
- },
237
- {
238
- name: 'synapse_verify_completion',
239
- description:
240
- 'Verify slice implementation and test outputs against acceptance criteria using Jev System One before committing work',
241
- inputSchema: {
242
- type: 'object',
243
- required: ['criteria', 'output'],
244
- properties: {
245
- criteria: { type: 'string', description: 'Acceptance criteria or requirement specifications' },
246
- output: {
247
- type: 'string',
248
- description: 'Actual implementation summary, test output, or slice behavior'
249
- }
250
- }
251
- }
252
- },
253
- {
254
- name: 'synapse_reasoning_effort',
255
- description:
256
- 'Dynamically modulate agent reasoning effort (Astra-Jev) to low/medium/high based on step context (lowering effort for mechanical commands like split/migrate/skeleton)',
257
- inputSchema: {
258
- type: 'object',
259
- required: ['context'],
260
- properties: {
261
- context: {
262
- type: 'string',
263
- description: 'Immediate command or task context, e.g. "synapse split", "git commit"'
264
- },
265
- provider: {
266
- type: 'string',
267
- description: 'Target LLM provider, e.g. "deepseek", "anthropic", "openai"'
268
- },
269
- sessionContextTokens: {
270
- type: 'number',
271
- description: 'Estimated session context token count to protect prompt cache'
272
- }
273
- }
274
- }
275
- }
276
- ]
139
+ tools: MCP_TOOLS
277
140
  }
278
141
  };
279
142
  }
@@ -355,7 +218,22 @@ export class SynapseMcpServer {
355
218
  );
356
219
  } else if (toolName === 'synapse_check') {
357
220
  const report = runMachineVerifications(this.root, args.targetFile);
358
- contentText = JSON.stringify(report, null, 2);
221
+ const issues = capItems(report.issues).items.map((issue) => ({
222
+ ...issue,
223
+ file: toRelativePath(this.root, issue.file)
224
+ }));
225
+
226
+ contentText = JSON.stringify(
227
+ {
228
+ ...report,
229
+ issues,
230
+ issuesTruncated: report.issues.length > MCP_MAX_ITEMS,
231
+ reportedIssues: issues.length,
232
+ totalIssues: report.issues.length
233
+ },
234
+ null,
235
+ 2
236
+ );
359
237
  } else if (toolName === 'synapse_split') {
360
238
  const resolution = resolveSlicesDir(this.root);
361
239
  if (!resolution.ok) {
@@ -425,13 +303,15 @@ export class SynapseMcpServer {
425
303
  }
426
304
 
427
305
  const splitStatus = failed || slices.length === 0 ? 'FAIL' : 'PASS';
306
+ const boundedSlices = capItems(slices);
428
307
  contentText = JSON.stringify(
429
308
  {
430
309
  status: splitStatus,
431
310
  operation: 'SLICE_SPLIT',
432
311
  slicesDir: path.relative(this.root, resolution.value.slicesDir),
433
312
  totalProcessed: slices.length,
434
- slices
313
+ slicesTruncated: boundedSlices.truncated,
314
+ slices: boundedSlices.items
435
315
  },
436
316
  null,
437
317
  2
@@ -567,7 +447,20 @@ export class SynapseMcpServer {
567
447
  };
568
448
  }
569
449
  const report = analyzeImpact(args.target, this.root);
570
- contentText = JSON.stringify(report, null, 2);
450
+ const bounded = capItems(report.impactedSlices);
451
+ contentText = JSON.stringify(
452
+ {
453
+ ...report,
454
+ impactedSlices: bounded.items.map((slice) => ({
455
+ ...slice,
456
+ filePath: toRelativePath(this.root, slice.filePath)
457
+ })),
458
+ impactedTruncated: bounded.truncated,
459
+ totalImpacted: report.totalImpacted
460
+ },
461
+ null,
462
+ 2
463
+ );
571
464
  } else if (toolName === 'synapse_rollback') {
572
465
  const report = await rollbackSliceMigrations(this.root, undefined, {
573
466
  targetSlice: args.targetSlice,
@@ -597,6 +490,18 @@ export class SynapseMcpServer {
597
490
  sessionContextTokens
598
491
  });
599
492
  contentText = JSON.stringify(result, null, 2);
493
+ } else if (toolName === 'synapse_triage_error') {
494
+ const failureLog = String(args.failureLog || '');
495
+ const result: TestTriageResult = await triageTestFailure(failureLog);
496
+ contentText = JSON.stringify(result, null, 2);
497
+ } else if (toolName === 'synapse_route_task') {
498
+ const task = String(args.task || '');
499
+ const result: ModelRouteResult = await routeModelTier(task);
500
+ contentText = JSON.stringify(result, null, 2);
501
+ } else if (toolName === 'synapse_evaluate_nudge') {
502
+ const transcriptTail = String(args.transcriptTail || '');
503
+ const result: NudgeGateResult = await shouldNudgeContinuation(transcriptTail);
504
+ contentText = JSON.stringify(result, null, 2);
600
505
  } else {
601
506
  return {
602
507
  jsonrpc: '2.0',
@@ -0,0 +1,238 @@
1
+ /**
2
+ * SynapseJS - Model Context Protocol Tool Inventory
3
+ *
4
+ * The declarative list of tools the MCP server registers: names, descriptions and
5
+ * input schemas, with no runtime dependency. Keeping it here means the count the
6
+ * documentation quotes is derived from the registered list rather than maintained by
7
+ * hand, and `synapse info` can report it without loading the JSON-RPC server.
8
+ */
9
+
10
+ import { PATH_SEGMENT_PATTERN } from '../core/path-guard';
11
+
12
+ export interface McpToolDefinition {
13
+ name: string;
14
+ description: string;
15
+ inputSchema: Record<string, unknown>;
16
+ }
17
+
18
+ export const MCP_TOOLS: McpToolDefinition[] = [
19
+ {
20
+ name: 'synapse_get_repo_map',
21
+ description: 'Get compressed codebase skeleton map (.codebase/repo-map.d.ts) for AI context (<3000 tokens)',
22
+ inputSchema: { type: 'object', properties: {} }
23
+ },
24
+ {
25
+ name: 'synapse_get_db_schema',
26
+ description:
27
+ 'Get the centralized database schema catalog (.codebase/db-schema.d.ts) for AI context and type-safe relational queries',
28
+ inputSchema: { type: 'object', properties: {} }
29
+ },
30
+ {
31
+ name: 'synapse_check',
32
+ description:
33
+ 'Run machine-centric compiler diagnostics, returning exact JSON coordinates (file, line, col, message)',
34
+ inputSchema: {
35
+ type: 'object',
36
+ properties: {
37
+ targetFile: { type: 'string', description: 'Optional specific file to check' }
38
+ }
39
+ }
40
+ },
41
+ {
42
+ name: 'synapse_split',
43
+ description: 'Run slice splitter and leak verification gates to enforce server/client isolation and zero leakage',
44
+ inputSchema: {
45
+ type: 'object',
46
+ properties: {
47
+ targetSlice: { type: 'string', description: 'Optional specific slice name to split' }
48
+ }
49
+ }
50
+ },
51
+ {
52
+ name: 'synapse_run_pbt',
53
+ description: 'Execute Fast-Check Property-Based Testing (PBT) invariant test suite across all slices',
54
+ inputSchema: { type: 'object', properties: {} }
55
+ },
56
+ {
57
+ name: 'synapse_scaffold_slice',
58
+ description:
59
+ 'Scaffold a new fullstack atomic vertical slice with TypeBox, Result, Action, React UI, and PBT oracles',
60
+ inputSchema: {
61
+ type: 'object',
62
+ required: ['domain', 'name'],
63
+ properties: {
64
+ domain: {
65
+ type: 'string',
66
+ pattern: PATH_SEGMENT_PATTERN,
67
+ description: 'Domain name (e.g. billing, customers, orders)'
68
+ },
69
+ name: {
70
+ type: 'string',
71
+ pattern: PATH_SEGMENT_PATTERN,
72
+ description: 'Slice name in kebab-case (e.g. cancel-subscription)'
73
+ },
74
+ template: {
75
+ type: 'string',
76
+ enum: ['create', 'list', 'update', 'delete', 'login', 'oauth-github', 'crud'],
77
+ description: 'Optional slice template shape (default: create)'
78
+ },
79
+ fields: {
80
+ type: 'string',
81
+ description:
82
+ 'Optional fields grammar, e.g. "name:string,email:string,status:enum(ACTIVE|INACTIVE),price:number"'
83
+ }
84
+ }
85
+ }
86
+ },
87
+ {
88
+ name: 'synapse_contract',
89
+ description:
90
+ 'Return the machine contract: slice exports and suffixes, Result and HTTP semantics, session rules, addressing, SSR behavior and the gates to run',
91
+ inputSchema: { type: 'object', properties: {} }
92
+ },
93
+ {
94
+ name: 'synapse_migrate',
95
+ description: 'Auto-discover and apply sliceSchema DDL declarations across slices into the active database',
96
+ inputSchema: { type: 'object', properties: {} }
97
+ },
98
+ {
99
+ name: 'synapse_check_db_drift',
100
+ description:
101
+ 'Inspects live database catalog against sliceSchema DDL contracts, identifying missing tables, missing columns, and orphan tables',
102
+ inputSchema: { type: 'object', properties: {} }
103
+ },
104
+ {
105
+ name: 'synapse_diff_impact',
106
+ description:
107
+ 'Analyzes cross-slice dependencies (Foreign Keys, shared module imports, and table references) to report all slices impacted by a file or table change',
108
+ inputSchema: {
109
+ type: 'object',
110
+ required: ['target'],
111
+ properties: {
112
+ target: {
113
+ type: 'string',
114
+ description: 'Slice file path, slice name, shared module path, or table name'
115
+ }
116
+ }
117
+ }
118
+ },
119
+ {
120
+ name: 'synapse_rollback',
121
+ description: 'Roll back applied sliceSchema migrations by executing their -- down: statements',
122
+ inputSchema: {
123
+ type: 'object',
124
+ properties: {
125
+ targetSlice: { type: 'string', description: 'Optional target slice to rollback' },
126
+ steps: { type: 'number', description: 'Number of recent migrations to rollback (default: 1)' }
127
+ }
128
+ }
129
+ },
130
+ {
131
+ name: 'synapse_test_gate',
132
+ description:
133
+ 'Execute Fast-Check PBT oracles and immediately triage failures with Jev System One semantic test-gate to prevent LLM token waste',
134
+ inputSchema: {
135
+ type: 'object',
136
+ properties: {}
137
+ }
138
+ },
139
+ {
140
+ name: 'synapse_abort_check',
141
+ description:
142
+ 'Evaluate plan and error history with Jev System One to detect doomed trajectories, circular loops, or high-risk refactor dead ends',
143
+ inputSchema: {
144
+ type: 'object',
145
+ required: ['plan', 'history'],
146
+ properties: {
147
+ plan: { type: 'string', description: 'Proposed implementation plan or architectural change' },
148
+ history: { type: 'string', description: 'Recent attempt history, error logs, or failure reasons' }
149
+ }
150
+ }
151
+ },
152
+ {
153
+ name: 'synapse_verify_completion',
154
+ description:
155
+ 'Verify slice implementation and test outputs against acceptance criteria using Jev System One before committing work',
156
+ inputSchema: {
157
+ type: 'object',
158
+ required: ['criteria', 'output'],
159
+ properties: {
160
+ criteria: { type: 'string', description: 'Acceptance criteria or requirement specifications' },
161
+ output: {
162
+ type: 'string',
163
+ description: 'Actual implementation summary, test output, or slice behavior'
164
+ }
165
+ }
166
+ }
167
+ },
168
+ {
169
+ name: 'synapse_reasoning_effort',
170
+ description:
171
+ 'Dynamically modulate agent reasoning effort (Astra-Jev) to low/medium/high based on step context (lowering effort for mechanical commands like split/migrate/skeleton)',
172
+ inputSchema: {
173
+ type: 'object',
174
+ required: ['context'],
175
+ properties: {
176
+ context: {
177
+ type: 'string',
178
+ description: 'Immediate command or task context, e.g. "synapse split", "git commit"'
179
+ },
180
+ provider: {
181
+ type: 'string',
182
+ description: 'Target LLM provider, e.g. "deepseek", "anthropic", "openai"'
183
+ },
184
+ sessionContextTokens: {
185
+ type: 'number',
186
+ description: 'Estimated session context token count to protect prompt cache'
187
+ }
188
+ }
189
+ }
190
+ },
191
+ {
192
+ name: 'synapse_triage_error',
193
+ description:
194
+ 'Triage an arbitrary test failure or execution error log using Jev System One to classify root causes (env_missing vs flaky_transient vs deep_logic) and avoid token waste',
195
+ inputSchema: {
196
+ type: 'object',
197
+ required: ['failureLog'],
198
+ properties: {
199
+ failureLog: {
200
+ type: 'string',
201
+ description: 'Error log, stack trace or terminal output to triage'
202
+ }
203
+ }
204
+ }
205
+ },
206
+ {
207
+ name: 'synapse_route_task',
208
+ description: 'Semantically route a development task to the optimal model/reasoning tier via Jev System One',
209
+ inputSchema: {
210
+ type: 'object',
211
+ required: ['task'],
212
+ properties: {
213
+ task: {
214
+ type: 'string',
215
+ description: 'Description of the coding, refactoring, or diagnostic task'
216
+ }
217
+ }
218
+ }
219
+ },
220
+ {
221
+ name: 'synapse_evaluate_nudge',
222
+ description:
223
+ 'Evaluate whether an agent is prematurely stopping or needs a proactive nudge to continue verification',
224
+ inputSchema: {
225
+ type: 'object',
226
+ required: ['transcriptTail'],
227
+ properties: {
228
+ transcriptTail: {
229
+ type: 'string',
230
+ description: 'Recent transcript steps or conversation history tail'
231
+ }
232
+ }
233
+ }
234
+ }
235
+ ];
236
+
237
+ /** The registered tool names, in registration order. */
238
+ export const MCP_TOOL_NAMES: string[] = MCP_TOOLS.map((tool) => tool.name);