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
@@ -0,0 +1,117 @@
1
+ "use strict";
2
+ // Runtime Ontology — Progmune 执行语义的 formal type system
3
+ // 所有 runtime primitive 的单一定义源
4
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
5
+ if (k2 === undefined) k2 = k;
6
+ var desc = Object.getOwnPropertyDescriptor(m, k);
7
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
8
+ desc = { enumerable: true, get: function() { return m[k]; } };
9
+ }
10
+ Object.defineProperty(o, k2, desc);
11
+ }) : (function(o, m, k, k2) {
12
+ if (k2 === undefined) k2 = k;
13
+ o[k2] = m[k];
14
+ }));
15
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
16
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
17
+ }) : function(o, v) {
18
+ o["default"] = v;
19
+ });
20
+ var __importStar = (this && this.__importStar) || (function () {
21
+ var ownKeys = function(o) {
22
+ ownKeys = Object.getOwnPropertyNames || function (o) {
23
+ var ar = [];
24
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
25
+ return ar;
26
+ };
27
+ return ownKeys(o);
28
+ };
29
+ return function (mod) {
30
+ if (mod && mod.__esModule) return mod;
31
+ var result = {};
32
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
33
+ __setModuleDefault(result, mod);
34
+ return result;
35
+ };
36
+ })();
37
+ Object.defineProperty(exports, "__esModule", { value: true });
38
+ exports.replayLedger = exports.replaySession = exports.getMinimalFixSet = exports.generateRepairSummary = exports.validateProposal = exports.applyProposalAsBranch = exports.suggestInvariantRepair = exports.suggestProtocolRepair = exports.suggestRepairs = exports.describeBranchTree = exports.unwrapBranchTree = exports.wrapAsBranch = exports.findRootBranch = exports.buildBranchMap = exports.replayBranch = exports.getBranchPath = exports.flattenBranch = exports.mergeBranches = exports.forkBranch = exports.createBranch = exports.createRootBranch = exports.registerAllMissingFingerprints = exports.verifyAllFingerprints = exports.verifyFingerprint = exports.getFingerprintRegistry = exports.getFingerprint = exports.registerFingerprint = exports.assertLedgerInvariants = exports.assertTransitionOrder = exports.assertRuleHashMatch = exports.assertDeltaConsistency = exports.assertLedgerConsistency = exports.InvariantViolationError = exports.listAllStates = exports.findTransition = exports.findViolations = exports.findConsumer = exports.findProducer = exports.rejectionToJSON = exports.explainRejection = exports.diffLedgers = exports.hashLedger = exports.hashRules = exports.findFixPathStatic = exports.checkLedgerConsistency = exports.validateTransition = exports.applyTransitionDelta = exports.rebuildState = exports.parseProtocolsFromJSON = exports.StateMachineValidator = void 0;
39
+ exports.replayWithDetail = void 0;
40
+ exports.generateAttemptId = generateAttemptId;
41
+ exports.generateSessionId = generateSessionId;
42
+ exports.generatePlannerSeed = generatePlannerSeed;
43
+ const crypto = __importStar(require("crypto"));
44
+ var ssg_validator_1 = require("./ssg-validator");
45
+ Object.defineProperty(exports, "StateMachineValidator", { enumerable: true, get: function () { return ssg_validator_1.StateMachineValidator; } });
46
+ Object.defineProperty(exports, "parseProtocolsFromJSON", { enumerable: true, get: function () { return ssg_validator_1.parseProtocolsFromJSON; } });
47
+ // Phase 3: Semantic Ledger pure functions (re-exported from ssg-validator)
48
+ var ssg_validator_2 = require("./ssg-validator");
49
+ Object.defineProperty(exports, "rebuildState", { enumerable: true, get: function () { return ssg_validator_2.rebuildState; } });
50
+ Object.defineProperty(exports, "applyTransitionDelta", { enumerable: true, get: function () { return ssg_validator_2.applyTransitionDelta; } });
51
+ Object.defineProperty(exports, "validateTransition", { enumerable: true, get: function () { return ssg_validator_2.validateTransition; } });
52
+ Object.defineProperty(exports, "checkLedgerConsistency", { enumerable: true, get: function () { return ssg_validator_2.checkLedgerConsistency; } });
53
+ Object.defineProperty(exports, "findFixPathStatic", { enumerable: true, get: function () { return ssg_validator_2.findFixPathStatic; } });
54
+ Object.defineProperty(exports, "hashRules", { enumerable: true, get: function () { return ssg_validator_2.hashRules; } });
55
+ Object.defineProperty(exports, "hashLedger", { enumerable: true, get: function () { return ssg_validator_2.hashLedger; } });
56
+ Object.defineProperty(exports, "diffLedgers", { enumerable: true, get: function () { return ssg_validator_2.diffLedgers; } });
57
+ Object.defineProperty(exports, "explainRejection", { enumerable: true, get: function () { return ssg_validator_2.explainRejection; } });
58
+ Object.defineProperty(exports, "rejectionToJSON", { enumerable: true, get: function () { return ssg_validator_2.rejectionToJSON; } });
59
+ Object.defineProperty(exports, "findProducer", { enumerable: true, get: function () { return ssg_validator_2.findProducer; } });
60
+ Object.defineProperty(exports, "findConsumer", { enumerable: true, get: function () { return ssg_validator_2.findConsumer; } });
61
+ Object.defineProperty(exports, "findViolations", { enumerable: true, get: function () { return ssg_validator_2.findViolations; } });
62
+ Object.defineProperty(exports, "findTransition", { enumerable: true, get: function () { return ssg_validator_2.findTransition; } });
63
+ Object.defineProperty(exports, "listAllStates", { enumerable: true, get: function () { return ssg_validator_2.listAllStates; } });
64
+ // Phase 4: Invariant assertion layer
65
+ var runtime_invariants_1 = require("./runtime-invariants");
66
+ Object.defineProperty(exports, "InvariantViolationError", { enumerable: true, get: function () { return runtime_invariants_1.InvariantViolationError; } });
67
+ Object.defineProperty(exports, "assertLedgerConsistency", { enumerable: true, get: function () { return runtime_invariants_1.assertLedgerConsistency; } });
68
+ Object.defineProperty(exports, "assertDeltaConsistency", { enumerable: true, get: function () { return runtime_invariants_1.assertDeltaConsistency; } });
69
+ Object.defineProperty(exports, "assertRuleHashMatch", { enumerable: true, get: function () { return runtime_invariants_1.assertRuleHashMatch; } });
70
+ Object.defineProperty(exports, "assertTransitionOrder", { enumerable: true, get: function () { return runtime_invariants_1.assertTransitionOrder; } });
71
+ Object.defineProperty(exports, "assertLedgerInvariants", { enumerable: true, get: function () { return runtime_invariants_1.assertLedgerInvariants; } });
72
+ // Phase 4: Fingerprint Registry
73
+ var ledger_registry_1 = require("./ledger-registry");
74
+ Object.defineProperty(exports, "registerFingerprint", { enumerable: true, get: function () { return ledger_registry_1.registerFingerprint; } });
75
+ Object.defineProperty(exports, "getFingerprint", { enumerable: true, get: function () { return ledger_registry_1.getFingerprint; } });
76
+ Object.defineProperty(exports, "getFingerprintRegistry", { enumerable: true, get: function () { return ledger_registry_1.getFingerprintRegistry; } });
77
+ Object.defineProperty(exports, "verifyFingerprint", { enumerable: true, get: function () { return ledger_registry_1.verifyFingerprint; } });
78
+ Object.defineProperty(exports, "verifyAllFingerprints", { enumerable: true, get: function () { return ledger_registry_1.verifyAllFingerprints; } });
79
+ Object.defineProperty(exports, "registerAllMissingFingerprints", { enumerable: true, get: function () { return ledger_registry_1.registerAllMissingFingerprints; } });
80
+ // Phase 4: Branch Ledger
81
+ var branch_ledger_1 = require("./branch-ledger");
82
+ Object.defineProperty(exports, "createRootBranch", { enumerable: true, get: function () { return branch_ledger_1.createRootBranch; } });
83
+ Object.defineProperty(exports, "createBranch", { enumerable: true, get: function () { return branch_ledger_1.createBranch; } });
84
+ Object.defineProperty(exports, "forkBranch", { enumerable: true, get: function () { return branch_ledger_1.forkBranch; } });
85
+ Object.defineProperty(exports, "mergeBranches", { enumerable: true, get: function () { return branch_ledger_1.mergeBranches; } });
86
+ Object.defineProperty(exports, "flattenBranch", { enumerable: true, get: function () { return branch_ledger_1.flattenBranch; } });
87
+ Object.defineProperty(exports, "getBranchPath", { enumerable: true, get: function () { return branch_ledger_1.getBranchPath; } });
88
+ Object.defineProperty(exports, "replayBranch", { enumerable: true, get: function () { return branch_ledger_1.replayBranch; } });
89
+ Object.defineProperty(exports, "buildBranchMap", { enumerable: true, get: function () { return branch_ledger_1.buildBranchMap; } });
90
+ Object.defineProperty(exports, "findRootBranch", { enumerable: true, get: function () { return branch_ledger_1.findRootBranch; } });
91
+ Object.defineProperty(exports, "wrapAsBranch", { enumerable: true, get: function () { return branch_ledger_1.wrapAsBranch; } });
92
+ Object.defineProperty(exports, "unwrapBranchTree", { enumerable: true, get: function () { return branch_ledger_1.unwrapBranchTree; } });
93
+ Object.defineProperty(exports, "describeBranchTree", { enumerable: true, get: function () { return branch_ledger_1.describeBranchTree; } });
94
+ // Phase 4: Repair Proposal Engine
95
+ var repair_proposal_1 = require("./repair-proposal");
96
+ Object.defineProperty(exports, "suggestRepairs", { enumerable: true, get: function () { return repair_proposal_1.suggestRepairs; } });
97
+ Object.defineProperty(exports, "suggestProtocolRepair", { enumerable: true, get: function () { return repair_proposal_1.suggestProtocolRepair; } });
98
+ Object.defineProperty(exports, "suggestInvariantRepair", { enumerable: true, get: function () { return repair_proposal_1.suggestInvariantRepair; } });
99
+ Object.defineProperty(exports, "applyProposalAsBranch", { enumerable: true, get: function () { return repair_proposal_1.applyProposalAsBranch; } });
100
+ Object.defineProperty(exports, "validateProposal", { enumerable: true, get: function () { return repair_proposal_1.validateProposal; } });
101
+ Object.defineProperty(exports, "generateRepairSummary", { enumerable: true, get: function () { return repair_proposal_1.generateRepairSummary; } });
102
+ Object.defineProperty(exports, "getMinimalFixSet", { enumerable: true, get: function () { return repair_proposal_1.getMinimalFixSet; } });
103
+ // Phase 4: Deterministic Replay
104
+ var deterministic_replay_1 = require("./deterministic-replay");
105
+ Object.defineProperty(exports, "replaySession", { enumerable: true, get: function () { return deterministic_replay_1.replaySession; } });
106
+ Object.defineProperty(exports, "replayLedger", { enumerable: true, get: function () { return deterministic_replay_1.replayLedger; } });
107
+ Object.defineProperty(exports, "replayWithDetail", { enumerable: true, get: function () { return deterministic_replay_1.replayWithDetail; } });
108
+ // ── ID生成工具 ──
109
+ function generateAttemptId() {
110
+ return `att_${Date.now()}_${Math.random().toString(36).slice(2, 7)}`;
111
+ }
112
+ function generateSessionId() {
113
+ return `sess_${Date.now()}_${Math.random().toString(36).slice(2, 7)}`;
114
+ }
115
+ function generatePlannerSeed(prompt, model) {
116
+ return crypto.createHash("md5").update(`${prompt}|${model}|${Date.now()}`).digest("hex").slice(0, 8);
117
+ }
@@ -46,7 +46,8 @@ const WEIGHT_HISTORY = 0.4; // 反馈系统成功率的权重
46
46
  const WEIGHT_GOAL_COMPLETION = 0.5; // 目标完成奖励
47
47
  const STATIC_HIGH_THRESHOLD = 0.6; // 静态评分超过此值时,跳过LLM调用
48
48
  function loadIR() {
49
- return JSON.parse(fs.readFileSync("ir.json", "utf-8"));
49
+ const raw = JSON.parse(fs.readFileSync("ir.json", "utf-8"));
50
+ return Array.isArray(raw) ? raw : (raw.functions || []);
50
51
  }
51
52
  const staticScoreCache = new Map();
52
53
  function getStaticScore(funcName, goal) {
@@ -92,13 +93,39 @@ async function decomposeGoals(intent, functions) {
92
93
  catch { }
93
94
  return [intent];
94
95
  }
95
- async function functionMatchesGoal(funcName, goal, staticScore) {
96
- if (staticScore > STATIC_HIGH_THRESHOLD)
97
- return staticScore;
98
- const prompt = `函数 ${funcName} 对 "${goal}" 的贡献度(0-10整数),只返回数字:`;
99
- const resp = await (0, llm_1.generate)(prompt);
100
- const s = parseFloat(resp.trim());
101
- return isNaN(s) ? 0.3 : Math.min(1, s / 10);
96
+ /** 批量评分:将同一 goal 的所有候选函数打包为一次 LLM 调用 */
97
+ async function batchScoreFuncs(funcs, goal) {
98
+ const result = new Map();
99
+ const needsLLM = [];
100
+ for (const f of funcs) {
101
+ if (f.staticScore > STATIC_HIGH_THRESHOLD) {
102
+ result.set(f.name, f.staticScore);
103
+ }
104
+ else {
105
+ needsLLM.push(f);
106
+ }
107
+ }
108
+ if (needsLLM.length === 0)
109
+ return result;
110
+ const funcNames = needsLLM.map(f => f.name).join(", ");
111
+ const prompt = `评估以下每个函数对目标"${goal}"的贡献度(0-10整数)。只返回JSON对象,格式:{"函数名":整数}\n函数:${funcNames}`;
112
+ try {
113
+ const text = await (0, llm_1.generate)(prompt);
114
+ const match = text.match(/\{[\s\S]*\}/);
115
+ if (match) {
116
+ const scores = JSON.parse(match[0]);
117
+ for (const [name, score] of Object.entries(scores)) {
118
+ const n = typeof score === 'number' ? score : parseFloat(String(score));
119
+ result.set(name, isNaN(n) ? 0.3 : Math.min(1, n / 10));
120
+ }
121
+ }
122
+ }
123
+ catch { }
124
+ for (const f of needsLLM) {
125
+ if (!result.has(f.name))
126
+ result.set(f.name, 0.3);
127
+ }
128
+ return result;
102
129
  }
103
130
  async function searchPlan(intent, beamWidth = 2, maxDepth = 6) {
104
131
  (0, llm_1.resetCallCount)();
@@ -127,11 +154,13 @@ async function searchPlan(intent, beamWidth = 2, maxDepth = 6) {
127
154
  })).filter((f) => f.staticScore > 0.05)
128
155
  .sort((a, b) => b.staticScore - a.staticScore)
129
156
  .slice(0, 5);
157
+ // 批量评分:一次 LLM 调用评估所有候选函数
158
+ const scoreMap = await batchScoreFuncs(scoredFuncs.map(f => ({ name: f.name, staticScore: f.staticScore })), currentGoal);
130
159
  for (const func of scoredFuncs) {
131
160
  const alreadyUsed = cand.actions.some(a => a.kind === "call" && a.function === func.name && a._goalIndex === cand.currentGoalIndex);
132
161
  if (alreadyUsed)
133
162
  continue;
134
- const relevance = await functionMatchesGoal(func.name, currentGoal, func.staticScore);
163
+ const relevance = scoreMap.get(func.name) ?? 0.3;
135
164
  if (relevance < 0.2)
136
165
  continue;
137
166
  const args = func.params.map((p) => ({
@@ -0,0 +1,155 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.createSnapshot = createSnapshot;
37
+ exports.saveSnapshot = saveSnapshot;
38
+ exports.loadSnapshot = loadSnapshot;
39
+ exports.listSnapshots = listSnapshots;
40
+ exports.diffSnapshots = diffSnapshots;
41
+ exports.summarizeSnapshot = summarizeSnapshot;
42
+ exports.findSnapshotBySession = findSnapshotBySession;
43
+ const fs = __importStar(require("fs"));
44
+ const path = __importStar(require("path"));
45
+ const crypto = __importStar(require("crypto"));
46
+ const projectDir = process.env.PROGMUNE_PROJECT_DIR || process.cwd();
47
+ const SNAPSHOT_DIR = path.resolve(projectDir, ".progmune_corpus", "snapshots");
48
+ function ensureDir(dir) {
49
+ if (!fs.existsSync(dir))
50
+ fs.mkdirSync(dir, { recursive: true });
51
+ }
52
+ /** 从 IR 数据创建快照 */
53
+ function createSnapshot(ir, intent, sessionId) {
54
+ const functions = ir.map((f) => ({
55
+ name: f.name,
56
+ params: (f.params || []).map((p) => ({ name: p.name, type: p.type })),
57
+ returnType: f.returnType || "void",
58
+ }));
59
+ const hash = crypto.createHash("md5")
60
+ .update(JSON.stringify(functions))
61
+ .digest("hex")
62
+ .slice(0, 12);
63
+ return {
64
+ id: `snap_${Date.now()}_${hash}`,
65
+ timestamp: new Date().toISOString(),
66
+ intent,
67
+ sessionId,
68
+ functions,
69
+ };
70
+ }
71
+ /** 持久化快照 */
72
+ function saveSnapshot(snapshot) {
73
+ ensureDir(SNAPSHOT_DIR);
74
+ fs.writeFileSync(path.join(SNAPSHOT_DIR, `${snapshot.id}.json`), JSON.stringify(snapshot, null, 2));
75
+ return snapshot.id;
76
+ }
77
+ /** 加载快照 */
78
+ function loadSnapshot(snapshotId) {
79
+ try {
80
+ const raw = fs.readFileSync(path.join(SNAPSHOT_DIR, `${snapshotId}.json`), "utf-8");
81
+ return JSON.parse(raw);
82
+ }
83
+ catch {
84
+ return null;
85
+ }
86
+ }
87
+ /** 列出所有快照 */
88
+ function listSnapshots() {
89
+ const snapshots = [];
90
+ if (!fs.existsSync(SNAPSHOT_DIR))
91
+ return snapshots;
92
+ for (const file of fs.readdirSync(SNAPSHOT_DIR)) {
93
+ if (file.endsWith(".json")) {
94
+ try {
95
+ snapshots.push(JSON.parse(fs.readFileSync(path.join(SNAPSHOT_DIR, file), "utf-8")));
96
+ }
97
+ catch { }
98
+ }
99
+ }
100
+ snapshots.sort((a, b) => b.timestamp.localeCompare(a.timestamp));
101
+ return snapshots;
102
+ }
103
+ /** 计算两个快照之间的差异 */
104
+ function diffSnapshots(before, after) {
105
+ const beforeMap = new Map();
106
+ const afterMap = new Map();
107
+ for (const f of before.functions)
108
+ beforeMap.set(f.name, f);
109
+ for (const f of after.functions)
110
+ afterMap.set(f.name, f);
111
+ const added = [];
112
+ const removed = [];
113
+ const changed = [];
114
+ let unchanged = 0;
115
+ for (const [name, f] of afterMap) {
116
+ if (!beforeMap.has(name)) {
117
+ added.push(f);
118
+ }
119
+ else {
120
+ const bf = beforeMap.get(name);
121
+ const bSig = `${bf.returnType}:${bf.params.map(p => `${p.name}:${p.type}`).join(",")}`;
122
+ const aSig = `${f.returnType}:${f.params.map(p => `${p.name}:${p.type}`).join(",")}`;
123
+ if (bSig !== aSig) {
124
+ changed.push({ before: bf, after: f });
125
+ }
126
+ else {
127
+ unchanged++;
128
+ }
129
+ }
130
+ }
131
+ for (const [name, f] of beforeMap) {
132
+ if (!afterMap.has(name)) {
133
+ removed.push(f);
134
+ }
135
+ }
136
+ return { added, removed, changed, unchanged };
137
+ }
138
+ /** 生成快照摘要 */
139
+ function summarizeSnapshot(snapshot) {
140
+ const lines = [
141
+ `Snapshot: ${snapshot.id}`,
142
+ `Timestamp: ${snapshot.timestamp}`,
143
+ `Functions: ${snapshot.functions.length}`,
144
+ ];
145
+ if (snapshot.intent)
146
+ lines.push(`Intent: ${snapshot.intent}`);
147
+ if (snapshot.sessionId)
148
+ lines.push(`Session: ${snapshot.sessionId}`);
149
+ return lines.join("\n");
150
+ }
151
+ /** 按 sessionId 查找快照,返回最近的一个(或 undefined) */
152
+ function findSnapshotBySession(sessionId) {
153
+ const snapshots = listSnapshots();
154
+ return snapshots.find(s => s.sessionId === sessionId);
155
+ }