progmune-runtime 2.0.2 → 2.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 (107) hide show
  1. package/.mcp.json +11 -0
  2. package/.progmune_allowlist +50 -0
  3. package/.test_report/test_report.md +87 -0
  4. package/Dockerfile +2 -10
  5. package/FAQ.md +167 -0
  6. package/demo-project/auth.ts +55 -0
  7. package/demo-project/tsconfig.json +8 -0
  8. package/dist/ab-stats.js +11 -0
  9. package/dist/acl-breakdown.js +13 -0
  10. package/dist/all-sessions.js +11 -0
  11. package/dist/antibody-stats.js +11 -0
  12. package/dist/audit.js +218 -0
  13. package/dist/benchmark-count.js +7 -0
  14. package/dist/benchmark-full.js +17 -0
  15. package/dist/benchmark-pass-rate.js +54 -0
  16. package/dist/benchmark-report.js +67 -0
  17. package/dist/benchmark-save.js +62 -0
  18. package/dist/benchmark-status.js +15 -0
  19. package/dist/branch-ledger.js +365 -0
  20. package/dist/branch-tree-count.js +14 -0
  21. package/dist/check.js +506 -0
  22. package/dist/common-fixpath.js +12 -0
  23. package/dist/constraint-types.js +12 -0
  24. package/dist/deterministic-replay.js +277 -0
  25. package/dist/emitter.js +112 -12
  26. package/dist/exec-metrics.js +11 -0
  27. package/dist/execute.js +242 -0
  28. package/dist/extract-ir.js +550 -5
  29. package/dist/failure-collector.js +143 -0
  30. package/dist/failure-corpus.js +481 -35
  31. package/dist/failure-report.js +11 -0
  32. package/dist/failures.js +11 -0
  33. package/dist/fast-path-hits.js +13 -0
  34. package/dist/feedback.js +6 -3
  35. package/dist/file-lock.js +82 -0
  36. package/dist/find-session.js +10 -0
  37. package/dist/fingerprint-list.js +15 -0
  38. package/dist/gen-history-log.js +13 -0
  39. package/dist/generate.js +2 -1
  40. package/dist/generate_500.js +4 -2
  41. package/dist/genome.js +11 -0
  42. package/dist/heatmap-data.js +11 -0
  43. package/dist/heatmap.js +11 -0
  44. package/dist/immune-reporter.js +137 -0
  45. package/dist/learned.js +11 -0
  46. package/dist/ledger-registry.js +241 -0
  47. package/dist/llm.js +43 -2
  48. package/dist/load-benchmarks.js +47 -0
  49. package/dist/main.js +2 -1
  50. package/dist/mcp-server.mjs +446 -34
  51. package/dist/memory-layer.js +51 -13
  52. package/dist/metrics.js +11 -0
  53. package/dist/obs-web.js +561 -0
  54. package/dist/p0_ssg_demo.js +255 -40
  55. package/dist/planner.js +933 -65
  56. package/dist/protocol-registry.js +105 -0
  57. package/dist/recent-session.js +12 -0
  58. package/dist/repair-proposal.js +353 -0
  59. package/dist/report.js +32 -0
  60. package/dist/runtime-invariants.js +161 -0
  61. package/dist/runtime-types.js +117 -0
  62. package/dist/search-planner.js +38 -9
  63. package/dist/semantic-snapshot.js +155 -0
  64. package/dist/semantic-trace.js +1497 -0
  65. package/dist/semantic-validator.js +3 -2
  66. package/dist/semantic_guard_test.js +2 -1
  67. package/dist/sessions.js +11 -0
  68. package/dist/ssg-validator.js +658 -20
  69. package/dist/svl-distribution.js +11 -0
  70. package/dist/terminal-status.js +11 -0
  71. package/dist/test_failure_corpus.js +3 -1
  72. package/dist/token-savings.js +11 -0
  73. package/dist/total-repairs.js +12 -0
  74. package/dist/unresolved-count.js +12 -0
  75. package/dist/valid-fingerprints.js +13 -0
  76. package/dist/validator.js +116 -60
  77. package/dist/verify-fps.js +11 -0
  78. package/dist/verify-ledgers.js +11 -0
  79. package/docs/whitepaper-style.css +77 -0
  80. package/docs/whitepaper-v2.1.md +609 -0
  81. package/docs/whitepaper-v2.2.md +1064 -0
  82. package/docs/whitepaper-v2.2.pdf +0 -0
  83. package/fly.toml +1 -1
  84. package/package.json +13 -4
  85. package/protocols.json +136 -0
  86. package/public/dashboard.html +119 -0
  87. package/readme.md +829 -0
  88. package/server/hub.js +84 -12
  89. package/test/replay-golden/sess_1780063202050_mgeld.json +9 -0
  90. package/test/replay-golden/sess_1780064032560_gocld.json +354 -0
  91. package/test/replay-golden/sess_1780064413331_s2709.json +606 -0
  92. package/test/replay-golden/sess_1780064792710_y3avo.json +614 -0
  93. package/test/replay-golden.ts +84 -0
  94. package/test_benchmark.js +165 -0
  95. package/test_comprehensive.mjs +638 -0
  96. package/test_concurrency.js +129 -0
  97. package/test_ir_robustness.js +85 -0
  98. package/test_semantic_contracts.js +269 -0
  99. package/test_ssg_stress.js +156 -0
  100. package/test_svl3.js +58 -0
  101. package/tsconfig.json +1 -1
  102. package/.env.example +0 -3
  103. package/.progmune_memory/fingerprints.json +0 -7
  104. package/.progmune_memory/opt_in.json +0 -4
  105. package/README.md +0 -118
  106. package/dist/mcp-server.js +0 -55
  107. package/immune_hub_data/2026-05-14.json +0 -50
package/server/hub.js CHANGED
@@ -3,42 +3,114 @@ const fs = require('fs');
3
3
  const path = require('path');
4
4
 
5
5
  const DATA_DIR = path.resolve(__dirname, "../immune_hub_data");
6
+ const RULES_FILE = path.resolve(__dirname, "../global_antibodies.json");
6
7
  if (!fs.existsSync(DATA_DIR)) fs.mkdirSync(DATA_DIR, { recursive: true });
7
8
 
8
- const PORT = process.env.PORT || 3000;
9
+ const PORT = process.env.PORT || 8080;
10
+
11
+ // 工具函数:读取所有指纹数据
12
+ function getAllFingerprints() {
13
+ const all = [];
14
+ if (!fs.existsSync(DATA_DIR)) return all;
15
+ const files = fs.readdirSync(DATA_DIR).filter(f => f.endsWith('.json'));
16
+ for (const file of files) {
17
+ const records = JSON.parse(fs.readFileSync(path.join(DATA_DIR, file), 'utf-8'));
18
+ all.push(...records);
19
+ }
20
+ return all;
21
+ }
22
+
23
+ // 仪表板 API
24
+ function handleDashboard(req, res) {
25
+ const fingerprints = getAllFingerprints();
26
+ const now = new Date();
27
+ const today = now.toISOString().slice(0, 10);
28
+ const weekAgo = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000).toISOString().slice(0, 10);
29
+
30
+ // 今日/本周/总计
31
+ const todayCount = fingerprints.filter(f => f.timestamp.startsWith(today)).length;
32
+ const weekCount = fingerprints.filter(f => f.timestamp >= weekAgo).length;
33
+ const totalCount = fingerprints.length;
34
+
35
+ // 高频错误模式 (Top 10)
36
+ const patternMap = new Map();
37
+ fingerprints.forEach(f => {
38
+ const seq = Array.isArray(f.functionSequence) ? f.functionSequence.join(' → ') : f.functionSequence;
39
+ const key = `${f.violatedSVL} | ${f.constraintType} | ${seq || '(empty)'}`;
40
+ patternMap.set(key, (patternMap.get(key) || 0) + 1);
41
+ });
42
+ const topPatterns = [...patternMap.entries()]
43
+ .sort((a, b) => b[1] - a[1])
44
+ .slice(0, 10)
45
+ .map(([pattern, count]) => ({ pattern, count }));
46
+
47
+ // 最近10条时间线
48
+ const timeline = fingerprints
49
+ .sort((a, b) => (b.timestamp || '').localeCompare(a.timestamp || ''))
50
+ .slice(0, 10)
51
+ .map(f => ({
52
+ time: f.timestamp,
53
+ svl: f.violatedSVL,
54
+ pattern: Array.isArray(f.functionSequence) ? f.functionSequence.join(' → ') : f.functionSequence,
55
+ }));
56
+
57
+ res.writeHead(200, { 'Content-Type': 'application/json' });
58
+ res.end(JSON.stringify({ todayCount, weekCount, totalCount, topPatterns, timeline }));
59
+ }
60
+
61
+ // 静态页面
62
+ function handleDashboardPage(res) {
63
+ const htmlPath = path.resolve(__dirname, "../public/dashboard.html");
64
+ if (fs.existsSync(htmlPath)) {
65
+ res.writeHead(200, { 'Content-Type': 'text/html' });
66
+ res.end(fs.readFileSync(htmlPath, 'utf-8'));
67
+ } else {
68
+ res.writeHead(404);
69
+ res.end('Dashboard page not found');
70
+ }
71
+ }
9
72
 
10
73
  const server = http.createServer((req, res) => {
11
- if (req.method === "POST" && req.url === "/report") {
12
- let body = "";
13
- req.on("data", chunk => body += chunk);
14
- req.on("end", () => {
74
+ if (req.method === 'POST' && req.url === '/report') {
75
+ let body = '';
76
+ req.on('data', chunk => body += chunk);
77
+ req.on('end', () => {
15
78
  try {
16
79
  const { fingerprints } = JSON.parse(body);
17
80
  const date = new Date().toISOString().slice(0, 10);
18
81
  const filePath = path.join(DATA_DIR, `${date}.json`);
19
-
20
82
  let existing = [];
21
83
  if (fs.existsSync(filePath)) {
22
- existing = JSON.parse(fs.readFileSync(filePath, "utf-8"));
84
+ existing = JSON.parse(fs.readFileSync(filePath, 'utf-8'));
23
85
  }
24
86
  existing.push(...fingerprints);
25
87
  fs.writeFileSync(filePath, JSON.stringify(existing, null, 2));
26
-
27
88
  console.log(`[Hub] 收到 ${fingerprints.length} 条指纹,总计 ${existing.length} 条`);
28
- res.writeHead(200, { "Content-Type": "application/json" });
29
- res.end(JSON.stringify({ status: "ok", received: fingerprints.length, total: existing.length }));
89
+ res.writeHead(200, { 'Content-Type': 'application/json' });
90
+ res.end(JSON.stringify({ status: 'ok', received: fingerprints.length, total: existing.length }));
30
91
  } catch (e) {
31
92
  res.writeHead(400);
32
93
  res.end(JSON.stringify({ error: e.message }));
33
94
  }
34
95
  });
96
+ } else if (req.method === 'GET' && req.url === '/antibodies') {
97
+ if (fs.existsSync(RULES_FILE)) {
98
+ res.writeHead(200, { 'Content-Type': 'application/json' });
99
+ res.end(fs.readFileSync(RULES_FILE, 'utf-8'));
100
+ } else {
101
+ res.writeHead(200, { 'Content-Type': 'application/json' });
102
+ res.end('[]');
103
+ }
104
+ } else if (req.method === 'GET' && req.url === '/api/dashboard') {
105
+ handleDashboard(req, res);
106
+ } else if (req.method === 'GET' && (req.url === '/' || req.url === '/dashboard')) {
107
+ handleDashboardPage(res);
35
108
  } else {
36
109
  res.writeHead(404);
37
- res.end("Not Found");
110
+ res.end('Not Found');
38
111
  }
39
112
  });
40
113
 
41
- // 关键修复:显式绑定到 0.0.0.0
42
114
  server.listen(PORT, '0.0.0.0', () => {
43
115
  console.log(`[Hub] 免疫汇聚服务器已启动: 0.0.0.0:${PORT}`);
44
116
  });
@@ -0,0 +1,9 @@
1
+ {
2
+ "sessionId": "sess_1780063202050_mgeld",
3
+ "intent": "实现一个函数来提取 IR、校验动作、然后生成代码",
4
+ "attempts": [],
5
+ "resolved": false,
6
+ "startedAt": 1780063202050,
7
+ "snapshotId": "snap_1780063202052_5315551a7ee7",
8
+ "endedAt": 1780063203482
9
+ }
@@ -0,0 +1,354 @@
1
+ {
2
+ "sessionId": "sess_1780064032560_gocld",
3
+ "intent": "实现一个函数,先提取 IR,然后校验动作,最后生成代码并保存会话",
4
+ "attempts": [
5
+ {
6
+ "id": "att_1780064037502_vmsfo",
7
+ "sessionId": "sess_1780064032560_gocld",
8
+ "attemptNumber": 1,
9
+ "inputIntent": "实现一个函数,先提取 IR,然后校验动作,最后生成代码并保存会话",
10
+ "plannerSeed": "a525918c",
11
+ "constraintSnapshotId": "snap_1780064032562_82709ff22603",
12
+ "generatedActions": [
13
+ {
14
+ "kind": "call",
15
+ "function": "extractIRPython",
16
+ "args": [
17
+ {
18
+ "name": "projectRoot",
19
+ "type": "string",
20
+ "value": "{{projectRoot}}"
21
+ }
22
+ ],
23
+ "assignTo": "extractIRPython_result"
24
+ },
25
+ {
26
+ "kind": "call",
27
+ "function": "extractDirectCalls",
28
+ "args": [
29
+ {
30
+ "name": "func",
31
+ "type": "FunctionDeclaration | ArrowFunction",
32
+ "value": "{{func}}"
33
+ }
34
+ ],
35
+ "assignTo": "extractDirectCalls_result"
36
+ },
37
+ {
38
+ "kind": "call",
39
+ "function": "extractIR",
40
+ "args": [
41
+ {
42
+ "name": "projectRoot",
43
+ "type": "string",
44
+ "value": "{{projectRoot}}"
45
+ }
46
+ ],
47
+ "assignTo": "extractIR_result"
48
+ },
49
+ {
50
+ "kind": "call",
51
+ "function": "ensureDir",
52
+ "args": [
53
+ {
54
+ "name": "dir",
55
+ "type": "string",
56
+ "value": "{{dir}}"
57
+ }
58
+ ],
59
+ "assignTo": "ensureDir_result"
60
+ },
61
+ {
62
+ "kind": "call",
63
+ "function": "ensureLockDir",
64
+ "args": [],
65
+ "assignTo": "ensureLockDir_result"
66
+ },
67
+ {
68
+ "kind": "call",
69
+ "function": "loadProtocolsFromIR",
70
+ "args": [
71
+ {
72
+ "name": "ir",
73
+ "type": "any[]",
74
+ "value": "{{ir}}"
75
+ }
76
+ ],
77
+ "assignTo": "loadProtocolsFromIR_result"
78
+ },
79
+ {
80
+ "kind": "call",
81
+ "function": "attemptSSGRepair",
82
+ "args": [
83
+ {
84
+ "name": "actions",
85
+ "type": "Action[]",
86
+ "value": "{{actions}}"
87
+ },
88
+ {
89
+ "name": "rejection",
90
+ "type": "SSGRejection",
91
+ "value": "{{rejection}}"
92
+ },
93
+ {
94
+ "name": "ir",
95
+ "type": "any[]",
96
+ "value": "{{ir}}"
97
+ },
98
+ {
99
+ "name": "protocols",
100
+ "type": "FunctionProtocol[]",
101
+ "value": "{{protocols}}"
102
+ },
103
+ {
104
+ "name": "namespaceInitialStates",
105
+ "type": "Map<string, string>",
106
+ "value": "{{namespaceInitialStates}}"
107
+ }
108
+ ],
109
+ "assignTo": "attemptSSGRepair_result"
110
+ },
111
+ {
112
+ "kind": "call",
113
+ "function": "loadIR",
114
+ "args": [],
115
+ "assignTo": "loadIR_result"
116
+ },
117
+ {
118
+ "kind": "call",
119
+ "function": "mkdirSync",
120
+ "args": [
121
+ {
122
+ "name": "path",
123
+ "type": "string",
124
+ "value": "{{path}}"
125
+ },
126
+ {
127
+ "name": "options",
128
+ "type": "object",
129
+ "value": "{{options}}"
130
+ }
131
+ ]
132
+ },
133
+ {
134
+ "kind": "call",
135
+ "function": "readdirSync",
136
+ "args": [
137
+ {
138
+ "name": "path",
139
+ "type": "string",
140
+ "value": "{{path}}"
141
+ }
142
+ ],
143
+ "assignTo": "readdirSync_result"
144
+ },
145
+ {
146
+ "kind": "call",
147
+ "function": "rmdirSync",
148
+ "args": [],
149
+ "assignTo": "rmdirSync_result"
150
+ },
151
+ {
152
+ "kind": "call",
153
+ "function": "require",
154
+ "args": [],
155
+ "assignTo": "require_result"
156
+ },
157
+ {
158
+ "kind": "call",
159
+ "function": "dirname",
160
+ "args": [
161
+ {
162
+ "name": "path",
163
+ "type": "string",
164
+ "value": "{{path}}"
165
+ }
166
+ ],
167
+ "assignTo": "dirname_result"
168
+ }
169
+ ],
170
+ "transitions": [],
171
+ "violations": [],
172
+ "outcome": "success",
173
+ "timestamp": 1780064037502,
174
+ "llmCallCount": 0,
175
+ "durationMs": 0
176
+ }
177
+ ],
178
+ "resolved": true,
179
+ "startedAt": 1780064032560,
180
+ "successfulAttempt": {
181
+ "id": "att_1780064037502_vmsfo",
182
+ "sessionId": "sess_1780064032560_gocld",
183
+ "attemptNumber": 1,
184
+ "inputIntent": "实现一个函数,先提取 IR,然后校验动作,最后生成代码并保存会话",
185
+ "plannerSeed": "a525918c",
186
+ "constraintSnapshotId": "snap_1780064032562_82709ff22603",
187
+ "generatedActions": [
188
+ {
189
+ "kind": "call",
190
+ "function": "extractIRPython",
191
+ "args": [
192
+ {
193
+ "name": "projectRoot",
194
+ "type": "string",
195
+ "value": "{{projectRoot}}"
196
+ }
197
+ ],
198
+ "assignTo": "extractIRPython_result"
199
+ },
200
+ {
201
+ "kind": "call",
202
+ "function": "extractDirectCalls",
203
+ "args": [
204
+ {
205
+ "name": "func",
206
+ "type": "FunctionDeclaration | ArrowFunction",
207
+ "value": "{{func}}"
208
+ }
209
+ ],
210
+ "assignTo": "extractDirectCalls_result"
211
+ },
212
+ {
213
+ "kind": "call",
214
+ "function": "extractIR",
215
+ "args": [
216
+ {
217
+ "name": "projectRoot",
218
+ "type": "string",
219
+ "value": "{{projectRoot}}"
220
+ }
221
+ ],
222
+ "assignTo": "extractIR_result"
223
+ },
224
+ {
225
+ "kind": "call",
226
+ "function": "ensureDir",
227
+ "args": [
228
+ {
229
+ "name": "dir",
230
+ "type": "string",
231
+ "value": "{{dir}}"
232
+ }
233
+ ],
234
+ "assignTo": "ensureDir_result"
235
+ },
236
+ {
237
+ "kind": "call",
238
+ "function": "ensureLockDir",
239
+ "args": [],
240
+ "assignTo": "ensureLockDir_result"
241
+ },
242
+ {
243
+ "kind": "call",
244
+ "function": "loadProtocolsFromIR",
245
+ "args": [
246
+ {
247
+ "name": "ir",
248
+ "type": "any[]",
249
+ "value": "{{ir}}"
250
+ }
251
+ ],
252
+ "assignTo": "loadProtocolsFromIR_result"
253
+ },
254
+ {
255
+ "kind": "call",
256
+ "function": "attemptSSGRepair",
257
+ "args": [
258
+ {
259
+ "name": "actions",
260
+ "type": "Action[]",
261
+ "value": "{{actions}}"
262
+ },
263
+ {
264
+ "name": "rejection",
265
+ "type": "SSGRejection",
266
+ "value": "{{rejection}}"
267
+ },
268
+ {
269
+ "name": "ir",
270
+ "type": "any[]",
271
+ "value": "{{ir}}"
272
+ },
273
+ {
274
+ "name": "protocols",
275
+ "type": "FunctionProtocol[]",
276
+ "value": "{{protocols}}"
277
+ },
278
+ {
279
+ "name": "namespaceInitialStates",
280
+ "type": "Map<string, string>",
281
+ "value": "{{namespaceInitialStates}}"
282
+ }
283
+ ],
284
+ "assignTo": "attemptSSGRepair_result"
285
+ },
286
+ {
287
+ "kind": "call",
288
+ "function": "loadIR",
289
+ "args": [],
290
+ "assignTo": "loadIR_result"
291
+ },
292
+ {
293
+ "kind": "call",
294
+ "function": "mkdirSync",
295
+ "args": [
296
+ {
297
+ "name": "path",
298
+ "type": "string",
299
+ "value": "{{path}}"
300
+ },
301
+ {
302
+ "name": "options",
303
+ "type": "object",
304
+ "value": "{{options}}"
305
+ }
306
+ ]
307
+ },
308
+ {
309
+ "kind": "call",
310
+ "function": "readdirSync",
311
+ "args": [
312
+ {
313
+ "name": "path",
314
+ "type": "string",
315
+ "value": "{{path}}"
316
+ }
317
+ ],
318
+ "assignTo": "readdirSync_result"
319
+ },
320
+ {
321
+ "kind": "call",
322
+ "function": "rmdirSync",
323
+ "args": [],
324
+ "assignTo": "rmdirSync_result"
325
+ },
326
+ {
327
+ "kind": "call",
328
+ "function": "require",
329
+ "args": [],
330
+ "assignTo": "require_result"
331
+ },
332
+ {
333
+ "kind": "call",
334
+ "function": "dirname",
335
+ "args": [
336
+ {
337
+ "name": "path",
338
+ "type": "string",
339
+ "value": "{{path}}"
340
+ }
341
+ ],
342
+ "assignTo": "dirname_result"
343
+ }
344
+ ],
345
+ "transitions": [],
346
+ "violations": [],
347
+ "outcome": "success",
348
+ "timestamp": 1780064037502,
349
+ "llmCallCount": 0,
350
+ "durationMs": 0
351
+ },
352
+ "snapshotId": "snap_1780064032562_82709ff22603",
353
+ "endedAt": 1780064037502
354
+ }