progmune-runtime 2.0.4 → 2.1.1

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 (110) 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/README.md +108 -54
  7. package/demo-project/auth.ts +55 -0
  8. package/demo-project/tsconfig.json +8 -0
  9. package/dist/ab-stats.js +11 -0
  10. package/dist/acl-breakdown.js +13 -0
  11. package/dist/action-runtime.js +1 -0
  12. package/dist/all-sessions.js +11 -0
  13. package/dist/antibody-stats.js +11 -0
  14. package/dist/audit.js +222 -0
  15. package/dist/benchmark-count.js +7 -0
  16. package/dist/benchmark-full.js +17 -0
  17. package/dist/benchmark-pass-rate.js +54 -0
  18. package/dist/benchmark-report.js +67 -0
  19. package/dist/benchmark-save.js +62 -0
  20. package/dist/benchmark-status.js +15 -0
  21. package/dist/branch-ledger.js +393 -0
  22. package/dist/branch-tree-count.js +14 -0
  23. package/dist/check.js +506 -0
  24. package/dist/common-fixpath.js +12 -0
  25. package/dist/constraint-types.js +12 -0
  26. package/dist/deterministic-replay.js +283 -0
  27. package/dist/emitter.js +143 -12
  28. package/dist/exec-metrics.js +11 -0
  29. package/dist/execute.js +251 -0
  30. package/dist/extract-ir.js +592 -5
  31. package/dist/failure-collector.js +163 -0
  32. package/dist/failure-corpus.js +507 -35
  33. package/dist/failure-report.js +11 -0
  34. package/dist/failures.js +11 -0
  35. package/dist/fast-path-hits.js +13 -0
  36. package/dist/feedback.js +10 -3
  37. package/dist/file-lock.js +82 -0
  38. package/dist/find-session.js +10 -0
  39. package/dist/fingerprint-list.js +15 -0
  40. package/dist/gen-history-log.js +13 -0
  41. package/dist/generate.js +2 -1
  42. package/dist/generate_500.js +4 -2
  43. package/dist/genome.js +11 -0
  44. package/dist/heatmap-data.js +11 -0
  45. package/dist/heatmap.js +11 -0
  46. package/dist/immune-reporter.js +34 -22
  47. package/dist/ir-utils.js +18 -0
  48. package/dist/learned.js +11 -0
  49. package/dist/ledger-registry.js +252 -0
  50. package/dist/llm.js +46 -2
  51. package/dist/load-benchmarks.js +47 -0
  52. package/dist/main.js +2 -1
  53. package/dist/mcp-server.mjs +445 -43
  54. package/dist/memory-layer.js +54 -13
  55. package/dist/metrics.js +11 -0
  56. package/dist/obs-web.js +561 -0
  57. package/dist/p0_ssg_demo.js +255 -40
  58. package/dist/planner.js +996 -80
  59. package/dist/protocol-registry.js +112 -0
  60. package/dist/recent-session.js +12 -0
  61. package/dist/repair-proposal.js +363 -0
  62. package/dist/runtime-invariants.js +170 -0
  63. package/dist/runtime-types.js +117 -0
  64. package/dist/runtime.js +1 -0
  65. package/dist/search-planner.js +39 -9
  66. package/dist/semantic-snapshot.js +157 -0
  67. package/dist/semantic-trace.js +1497 -0
  68. package/dist/semantic-validator.js +3 -2
  69. package/dist/semantic_guard_test.js +2 -1
  70. package/dist/session-utils.js +19 -0
  71. package/dist/sessions.js +11 -0
  72. package/dist/ssg-validator.js +666 -20
  73. package/dist/svl-distribution.js +11 -0
  74. package/dist/terminal-status.js +11 -0
  75. package/dist/test_failure_corpus.js +3 -1
  76. package/dist/token-savings.js +11 -0
  77. package/dist/total-repairs.js +12 -0
  78. package/dist/unresolved-count.js +12 -0
  79. package/dist/utils.js +2 -0
  80. package/dist/valid-fingerprints.js +13 -0
  81. package/dist/validator.js +118 -60
  82. package/dist/verify-fps.js +11 -0
  83. package/dist/verify-ledgers.js +11 -0
  84. package/docs/whitepaper-style.css +77 -0
  85. package/docs/whitepaper-v2.1.md +609 -0
  86. package/docs/whitepaper-v2.2.md +1064 -0
  87. package/docs/whitepaper-v2.2.pdf +0 -0
  88. package/fly.toml +1 -1
  89. package/package.json +13 -4
  90. package/protocols.json +131 -11
  91. package/public/dashboard.html +119 -0
  92. package/server/hub.js +84 -12
  93. package/test/replay-golden/sess_1780063202050_mgeld.json +9 -0
  94. package/test/replay-golden/sess_1780064032560_gocld.json +354 -0
  95. package/test/replay-golden/sess_1780064413331_s2709.json +606 -0
  96. package/test/replay-golden/sess_1780064792710_y3avo.json +614 -0
  97. package/test/replay-golden.ts +84 -0
  98. package/test_benchmark.js +165 -0
  99. package/test_comprehensive.mjs +638 -0
  100. package/test_concurrency.js +129 -0
  101. package/test_ir_robustness.js +85 -0
  102. package/test_semantic_contracts.js +269 -0
  103. package/test_ssg_stress.js +156 -0
  104. package/test_svl3.js +58 -0
  105. package/tsconfig.json +1 -1
  106. package/.env.example +0 -3
  107. package/.progmune_memory/episodic.json +0 -186
  108. package/.progmune_memory/fingerprints.json +0 -7
  109. package/.progmune_memory/opt_in.json +0 -4
  110. package/immune_hub_data/2026-05-14.json +0 -50
@@ -0,0 +1,251 @@
1
+ "use strict";
2
+ /**
3
+ * Phase 5: Semantic Execution Kernel
4
+ *
5
+ * Single entry point: intent → validated code → file written → audit verified.
6
+ * Wires together: IR extraction → Planner → EmitCode → Fingerprint.
7
+ *
8
+ * This is what progmune_execute MCP tool calls internally.
9
+ */
10
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
11
+ if (k2 === undefined) k2 = k;
12
+ var desc = Object.getOwnPropertyDescriptor(m, k);
13
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
14
+ desc = { enumerable: true, get: function() { return m[k]; } };
15
+ }
16
+ Object.defineProperty(o, k2, desc);
17
+ }) : (function(o, m, k, k2) {
18
+ if (k2 === undefined) k2 = k;
19
+ o[k2] = m[k];
20
+ }));
21
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
22
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
23
+ }) : function(o, v) {
24
+ o["default"] = v;
25
+ });
26
+ var __importStar = (this && this.__importStar) || (function () {
27
+ var ownKeys = function(o) {
28
+ ownKeys = Object.getOwnPropertyNames || function (o) {
29
+ var ar = [];
30
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
31
+ return ar;
32
+ };
33
+ return ownKeys(o);
34
+ };
35
+ return function (mod) {
36
+ if (mod && mod.__esModule) return mod;
37
+ var result = {};
38
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
39
+ __setModuleDefault(result, mod);
40
+ return result;
41
+ };
42
+ })();
43
+ Object.defineProperty(exports, "__esModule", { value: true });
44
+ exports.recordGeneration = recordGeneration;
45
+ exports.getExecutionMetrics = getExecutionMetrics;
46
+ exports.execute = execute;
47
+ exports.verifyCompiles = verifyCompiles;
48
+ exports.verifyFileMarker = verifyFileMarker;
49
+ const fs = __importStar(require("fs"));
50
+ const path = __importStar(require("path"));
51
+ const planner_1 = require("./planner");
52
+ const extract_ir_1 = require("./extract-ir");
53
+ const failure_collector_1 = require("./failure-collector");
54
+ const emitter_1 = require("./emitter");
55
+ const METRICS_FILE = ".progmune_corpus/metrics.json";
56
+ function loadMetrics() {
57
+ try {
58
+ if (fs.existsSync(METRICS_FILE)) {
59
+ return JSON.parse(fs.readFileSync(METRICS_FILE, "utf-8"));
60
+ }
61
+ }
62
+ catch { }
63
+ return { generated: 0, repaired: 0, lastGeneration: null, history: [] };
64
+ }
65
+ function saveMetrics(m) {
66
+ const dir = ".progmune_corpus";
67
+ if (!fs.existsSync(dir))
68
+ fs.mkdirSync(dir, { recursive: true });
69
+ fs.writeFileSync(METRICS_FILE, JSON.stringify(m, null, 2), "utf-8");
70
+ }
71
+ /** Record a generation event. Called automatically by execute(). */
72
+ /** @requires GENERATION_EVENT @produces METRICS_DATA */
73
+ function recordGeneration(record) {
74
+ const m = loadMetrics();
75
+ m.generated++;
76
+ if (record.repaired)
77
+ m.repaired++;
78
+ m.lastGeneration = record.filePath;
79
+ m.history.push(record);
80
+ // Keep last 100 entries
81
+ if (m.history.length > 100)
82
+ m.history = m.history.slice(-100);
83
+ saveMetrics(m);
84
+ }
85
+ /** Get current execution metrics. */
86
+ /** @requires METRICS_DATA @produces EXECUTION_METRICS */
87
+ /** @requires METRICS_DATA @produces EXECUTION_METRICS */
88
+ function getExecutionMetrics() {
89
+ return loadMetrics();
90
+ }
91
+ /**
92
+ * Execute the full Progmune pipeline: intent → validated code → file.
93
+ *
94
+ * @param intent - Natural language programming intent
95
+ * @param projectPath - Absolute path to project root
96
+ * @param filePath - Optional: write generated code to this file
97
+ */
98
+ /** @requires INTENT @produces CODE */
99
+ /** @requires INTENT @produces CODE */
100
+ async function execute(intent, projectPath, filePath) {
101
+ // 1. IR extraction
102
+ let ir;
103
+ try {
104
+ ir = (0, extract_ir_1.extractIR)(projectPath);
105
+ }
106
+ catch (e) {
107
+ return { success: false, code: "", sessionId: "", hash: "", ruleHash: "", irFunctionCount: 0, protocolRuleCount: 0, violations: 0, repairApplied: false, repairCount: 0, repairBranchIds: [], branchWinner: undefined, error: `IR extraction failed: ${e.message}` };
108
+ }
109
+ // 2. Protocol rule count
110
+ let protocolRuleCount = 0;
111
+ try {
112
+ const protoPath = path.resolve(projectPath, "protocols.json");
113
+ if (fs.existsSync(protoPath)) {
114
+ protocolRuleCount = Object.keys(JSON.parse(fs.readFileSync(protoPath, "utf-8")).rules || {}).length;
115
+ }
116
+ }
117
+ catch { }
118
+ // 3. Plan (LLM + immune constraints)
119
+ let planResult;
120
+ try {
121
+ planResult = await (0, planner_1.plan)(intent);
122
+ }
123
+ catch (e) {
124
+ (0, failure_collector_1.recordFailure)({
125
+ intent,
126
+ stage: "plan",
127
+ plan: [],
128
+ compileErrors: [e.message],
129
+ rootCause: (0, failure_collector_1.classifyPlanError)(e.message),
130
+ sessionId: undefined,
131
+ });
132
+ return { success: false, code: "", sessionId: "", hash: "", ruleHash: "", irFunctionCount: ir.length, protocolRuleCount, violations: 0, repairApplied: false, repairCount: 0, repairBranchIds: [], branchWinner: undefined, error: `Planning failed: ${e.message}` };
133
+ }
134
+ const actions = planResult.actions || [];
135
+ if (actions.length === 0) {
136
+ return { success: false, code: "", sessionId: planResult.sessionId, hash: "", ruleHash: planResult.ruleHash || "", irFunctionCount: ir.length, protocolRuleCount, violations: 0, repairApplied: false, repairCount: 0, repairBranchIds: [], branchWinner: undefined, error: "Planner returned empty action sequence" };
137
+ }
138
+ // 4. Emit code with generation marker
139
+ const code = (0, emitter_1.emitCode)(actions, {
140
+ sessionId: planResult.sessionId,
141
+ ruleHash: planResult.ruleHash,
142
+ irFunctionCount: ir.length,
143
+ protocolRuleCount,
144
+ });
145
+ // 5. Write to file if requested
146
+ if (filePath) {
147
+ const resolvedPath = path.isAbsolute(filePath) ? filePath : path.resolve(projectPath, filePath);
148
+ const dir = path.dirname(resolvedPath);
149
+ if (!fs.existsSync(dir)) {
150
+ fs.mkdirSync(dir, { recursive: true });
151
+ }
152
+ fs.writeFileSync(resolvedPath, code, "utf-8");
153
+ }
154
+ // 6. Compute hash (from code content)
155
+ const crypto = require("crypto");
156
+ const hash = crypto.createHash("sha256").update(code).digest("hex").slice(0, 16);
157
+ const ruleHash = planResult.ruleHash || "";
158
+ // Phase 7: Record execution metrics
159
+ if (filePath) {
160
+ recordGeneration({
161
+ sessionId: planResult.sessionId,
162
+ timestamp: Date.now(),
163
+ filePath: filePath,
164
+ repaired: planResult.repairApplied,
165
+ repairCount: planResult.repairCount,
166
+ irFunctionCount: ir.length,
167
+ });
168
+ }
169
+ // Fingerprint registration is NOT done here.
170
+ // plan() internally calls recordSession() which writes real transitions to
171
+ // .progmune_corpus/sessions/. The fingerprint is registered later by
172
+ // `npm run check` → registerAllMissingFingerprints() which reads the
173
+ // actual session file with real StateTransition[].
174
+ return {
175
+ success: true,
176
+ code,
177
+ sessionId: planResult.sessionId,
178
+ filePath: filePath || undefined,
179
+ hash,
180
+ ruleHash,
181
+ irFunctionCount: ir.length,
182
+ protocolRuleCount,
183
+ violations: 0,
184
+ repairApplied: planResult.repairApplied,
185
+ repairCount: planResult.repairCount,
186
+ repairBranchIds: planResult.repairBranchIds,
187
+ branchWinner: planResult.repairApplied && planResult.repairBranchIds.length >= 2
188
+ ? (() => {
189
+ try {
190
+ // Load branches from the session file to evaluate
191
+ const sessionFile = `.progmune_corpus/sessions/${planResult.sessionId}.json`;
192
+ if (fs.existsSync(sessionFile)) {
193
+ const session = JSON.parse(fs.readFileSync(sessionFile, "utf-8"));
194
+ if (session.branchTree && session.branchTree.length > 0) {
195
+ const { evaluateBranches } = require("./branch-ledger");
196
+ const { getNsInit } = require("./protocol-registry");
197
+ const evalResult = evaluateBranches(session.branchTree, getNsInit());
198
+ if (evalResult.winner) {
199
+ return {
200
+ id: evalResult.winner.branchId.slice(0, 12),
201
+ score: evalResult.winner.score,
202
+ recommendation: evalResult.winner.recommendation,
203
+ };
204
+ }
205
+ }
206
+ }
207
+ }
208
+ catch { }
209
+ return undefined;
210
+ })()
211
+ : undefined,
212
+ };
213
+ }
214
+ /** Verify a file compiles without errors. Returns {pass, errors[]}.
215
+ * Uses tsc directly — no grep tricks, no pipefail ambiguity. */
216
+ /** @requires FILE_PATH @produces COMPILE_RESULT */
217
+ /** @requires FILE_PATH @produces COMPILE_RESULT */
218
+ /** @requires FILE_PATH @produces COMPILE_RESULT */
219
+ function verifyCompiles(filePath) {
220
+ try {
221
+ const { execSync } = require("child_process");
222
+ const result = execSync(`npx tsc --noEmit --project tsconfig.json --pretty false 2>&1`, {
223
+ timeout: 30000,
224
+ encoding: "utf-8",
225
+ stdio: "pipe",
226
+ });
227
+ // tsc exits 0, check if our file is mentioned in output anyway (unlikely but safe)
228
+ const lines = result.split("\n").filter((l) => l.includes(filePath));
229
+ return { pass: lines.length === 0, errors: lines };
230
+ }
231
+ catch (e) {
232
+ // tsc exits non-zero — parse stderr/stdout for our file's errors
233
+ const output = (e.stdout || "") + (e.stderr || "");
234
+ const lines = output.split("\n").filter((l) => l.includes(filePath));
235
+ return { pass: lines.length === 0, errors: lines };
236
+ }
237
+ }
238
+ /** Quick audit: check whether a file has the @progmune-generated marker. */
239
+ /** @requires FILE_PATH @produces MARKER_STATUS */
240
+ function verifyFileMarker(filePath) {
241
+ try {
242
+ const content = fs.readFileSync(filePath, "utf-8");
243
+ const head = content.split("\n").slice(0, 5).join("\n");
244
+ const match = head.match(/@progmune-generated\s+session=(\S+)(?:\s+timestamp=(\S+))?/);
245
+ if (match) {
246
+ return { marked: true, sessionId: match[1], timestamp: match[2] };
247
+ }
248
+ }
249
+ catch { }
250
+ return { marked: false };
251
+ }