progmune-runtime 2.1.5 → 3.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.
Files changed (356) hide show
  1. package/README.md +108 -468
  2. package/dist/ablation-study.js +144 -0
  3. package/dist/ablation-study.test.js +18 -0
  4. package/dist/action-runtime.js +3 -1
  5. package/dist/active-learning.js +211 -0
  6. package/dist/analytics.js +139 -0
  7. package/dist/asset-factory.js +309 -0
  8. package/dist/asset-growth.js +244 -0
  9. package/dist/asset-promotion.js +382 -0
  10. package/dist/asset-quality.js +550 -0
  11. package/dist/audit/business-translator.js +285 -0
  12. package/dist/audit/cli.js +66 -0
  13. package/dist/audit/formatters/html.js +379 -0
  14. package/dist/audit/formatters/json.js +11 -0
  15. package/dist/audit/formatters/markdown.js +192 -0
  16. package/dist/audit/formatters/terminal.js +189 -0
  17. package/dist/audit/index.js +25 -0
  18. package/dist/audit/report-builder.js +318 -0
  19. package/dist/audit/types.js +8 -0
  20. package/dist/audit.js +3 -3
  21. package/dist/auto-benchmark-generator.js +137 -0
  22. package/dist/auto-benchmark-generator.test.js +45 -0
  23. package/dist/auto-protocol-synthesizer.js +362 -0
  24. package/dist/auto-protocol-synthesizer.test.js +82 -0
  25. package/dist/autonomous-patch.js +175 -0
  26. package/dist/autonomous-patch.test.js +128 -0
  27. package/dist/badge/badge-server.js +98 -0
  28. package/dist/behavior-miner.js +442 -0
  29. package/dist/belief-layer.js +475 -0
  30. package/dist/benchmark-count.js +5 -0
  31. package/dist/benchmark-generator.js +211 -0
  32. package/dist/benchmark-harness.js +201 -0
  33. package/dist/benchmark-pass-rate.js +7 -0
  34. package/dist/benchmark-report.js +8 -3
  35. package/dist/benchmark-save.js +14 -1
  36. package/dist/bootstrap-validation.js +197 -0
  37. package/dist/bootstrap-validation.test.js +51 -0
  38. package/dist/branch-ledger.js +1 -1
  39. package/dist/capability-gap.js +130 -0
  40. package/dist/certify-html.js +351 -0
  41. package/dist/certify.js +326 -0
  42. package/dist/check.js +4 -4
  43. package/dist/compliance-miner.js +447 -0
  44. package/dist/continuous-benchmark.js +194 -0
  45. package/dist/continuous-benchmark.test.js +116 -0
  46. package/dist/corpus-stats.js +173 -0
  47. package/dist/counterfactual-engine.js +288 -0
  48. package/dist/coverage-dashboard.js +109 -0
  49. package/dist/coverage-system.test.js +205 -0
  50. package/dist/cross-repo-precision.js +352 -0
  51. package/dist/cve-benchmark.js +180 -0
  52. package/dist/cve-benchmark.test.js +28 -0
  53. package/dist/cve-collector.js +73 -0
  54. package/dist/data-quality.js +141 -0
  55. package/dist/decision-engine.js +388 -0
  56. package/dist/derive-metadata.js +250 -0
  57. package/dist/difficulty-active.test.js +198 -0
  58. package/dist/difficulty-map.js +244 -0
  59. package/dist/discovery-analytics.js +125 -0
  60. package/dist/discovery-model.js +149 -0
  61. package/dist/discovery-optimize.test.js +199 -0
  62. package/dist/discovery-trace.js +276 -0
  63. package/dist/discovery-trace.test.js +97 -0
  64. package/dist/emitter.js +83 -1
  65. package/dist/enterprise-dashboard.js +405 -0
  66. package/dist/eval-hardening.js +297 -0
  67. package/dist/eval-hardening.test.js +85 -0
  68. package/dist/evaluation-campaign.js +359 -0
  69. package/dist/evaluation-campaign.test.js +181 -0
  70. package/dist/evidence-growth.js +143 -0
  71. package/dist/evidence-repository.js +209 -0
  72. package/dist/evidence-system.js +441 -0
  73. package/dist/execute.js +15 -7
  74. package/dist/experimental/software-physics.js +291 -0
  75. package/dist/experimental/state-inference.js +516 -0
  76. package/dist/experimental/unsupervised-physics.js +230 -0
  77. package/dist/extract-ir-python.js +54 -7
  78. package/dist/extract-ir.js +376 -12
  79. package/dist/failure-collector.js +2 -2
  80. package/dist/failure-corpus.js +322 -9
  81. package/dist/feedback.js +16 -5
  82. package/dist/feedback.test.js +49 -0
  83. package/dist/file-lock.js +1 -1
  84. package/dist/flywheel-batch.js +292 -0
  85. package/dist/frameworks/express-cli.js +237 -0
  86. package/dist/frameworks/express-detector.js +445 -0
  87. package/dist/frameworks/express-detector.test.js +206 -0
  88. package/dist/frameworks/index.js +30 -0
  89. package/dist/frameworks/nestjs-detector.js +302 -0
  90. package/dist/frameworks/trpc-detector.js +161 -0
  91. package/dist/frameworks/version-awareness.js +179 -0
  92. package/dist/function-synonyms.js +164 -0
  93. package/dist/function-synonyms.test.js +68 -0
  94. package/dist/generalization.test.js +352 -0
  95. package/dist/goal-annotator.js +113 -0
  96. package/dist/goal-planner.js +563 -0
  97. package/dist/gold-cve.js +164 -0
  98. package/dist/gold-cve.test.js +104 -0
  99. package/dist/gold-quality.js +206 -0
  100. package/dist/gold-tiers.js +241 -0
  101. package/dist/governance-dashboard.js +327 -0
  102. package/dist/graph-viz.js +240 -0
  103. package/dist/guided-frontier.js +195 -0
  104. package/dist/hierarchical-planner.js +148 -0
  105. package/dist/identifier-parser.js +260 -0
  106. package/dist/immune-metrics.js +93 -0
  107. package/dist/immune-receiver.js +158 -0
  108. package/dist/immune-reporter.js +1 -1
  109. package/dist/improvement-orchestrator.js +206 -0
  110. package/dist/inject-p0-vocabulary.js +300 -0
  111. package/dist/intent-parser.js +218 -0
  112. package/dist/invariant-algebra.js +476 -0
  113. package/dist/invariant-calculus.js +533 -0
  114. package/dist/ir-utils.js +70 -0
  115. package/dist/ir-utils.test.js +50 -0
  116. package/dist/knowledge-api.js +312 -0
  117. package/dist/knowledge-evolution.js +452 -0
  118. package/dist/knowledge-explorer.js +506 -0
  119. package/dist/knowledge-flywheel.js +274 -0
  120. package/dist/knowledge-governance.js +338 -0
  121. package/dist/knowledge-governance.test.js +150 -0
  122. package/dist/knowledge-graph.js +181 -0
  123. package/dist/knowledge-guided-synth.js +246 -0
  124. package/dist/knowledge-loop.test.js +77 -0
  125. package/dist/knowledge-object.js +316 -0
  126. package/dist/knowledge-package.js +98 -0
  127. package/dist/kpi-dashboard.js +561 -0
  128. package/dist/l3-cross-function.js +280 -0
  129. package/dist/learning-ranker.js +148 -0
  130. package/dist/learning-ranker.test.js +291 -0
  131. package/dist/ledger/accountability.js +322 -0
  132. package/dist/ledger/chain-builder.js +185 -0
  133. package/dist/ledger/cli.js +222 -0
  134. package/dist/ledger/index.js +13 -0
  135. package/dist/ledger/signatures.js +193 -0
  136. package/dist/ledger/types.js +9 -0
  137. package/dist/llm.js +74 -3
  138. package/dist/load-benchmarks.js +8 -3
  139. package/dist/logger.js +66 -0
  140. package/dist/logger.test.js +37 -0
  141. package/dist/logistic-reward.js +339 -0
  142. package/dist/logistic-reward.test.js +180 -0
  143. package/dist/macro-graph.js +193 -0
  144. package/dist/macro-repair.js +183 -0
  145. package/dist/mcp-server.mjs +1202 -483
  146. package/dist/memory-layer.js +42 -5
  147. package/dist/multi-repo-precision.js +422 -0
  148. package/dist/name-free-protocol.js +425 -0
  149. package/dist/name-free-protocol.test.js +170 -0
  150. package/dist/name-scrambling.js +138 -0
  151. package/dist/name-scrambling.test.js +16 -0
  152. package/dist/p3-observability.test.js +281 -0
  153. package/dist/p5-orchestrator.test.js +225 -0
  154. package/dist/pairwise-preference.js +294 -0
  155. package/dist/pairwise-preference.test.js +140 -0
  156. package/dist/planner-constraints.js +104 -0
  157. package/dist/planner-prompts.js +155 -0
  158. package/dist/planner-telemetry.js +415 -0
  159. package/dist/planner-trace.js +214 -0
  160. package/dist/planner.js +162 -167
  161. package/dist/plsb/artifact.js +116 -0
  162. package/dist/plsb/cli.js +71 -0
  163. package/dist/plsb/index.js +19 -0
  164. package/dist/plsb/leaderboard.js +249 -0
  165. package/dist/plsb/report-md.js +156 -0
  166. package/dist/plsb/schema.js +179 -0
  167. package/dist/plsb-benchmark.js +284 -0
  168. package/dist/plsb-benchmark.test.js +119 -0
  169. package/dist/policy/cli.js +134 -0
  170. package/dist/policy/engine.js +333 -0
  171. package/dist/policy/index.js +12 -0
  172. package/dist/policy/types.js +59 -0
  173. package/dist/policy-miner.js +505 -0
  174. package/dist/precision-analyze.js +229 -0
  175. package/dist/precision-benchmark.js +147 -0
  176. package/dist/precision-label-c.js +134 -0
  177. package/dist/precision-label.js +193 -0
  178. package/dist/precision-report-c.js +149 -0
  179. package/dist/precision-report.js +246 -0
  180. package/dist/progmune-status.js +108 -0
  181. package/dist/proof-engine.js +479 -0
  182. package/dist/proof-provenance.js +315 -0
  183. package/dist/protocol-coverage.js +294 -0
  184. package/dist/protocol-detector.js +1189 -0
  185. package/dist/protocol-embedding-expanded.js +297 -0
  186. package/dist/protocol-embedding-expanded.test.js +97 -0
  187. package/dist/protocol-embedding.js +195 -0
  188. package/dist/protocol-embedding.test.js +82 -0
  189. package/dist/protocol-extractor-v2.js +354 -0
  190. package/dist/protocol-extractor-v2.test.js +140 -0
  191. package/dist/protocol-extractor.js +310 -0
  192. package/dist/protocol-extractor.test.js +113 -0
  193. package/dist/protocol-foundation.js +322 -0
  194. package/dist/protocol-foundation.test.js +163 -0
  195. package/dist/protocol-frontier.js +243 -0
  196. package/dist/protocol-frontier.test.js +92 -0
  197. package/dist/protocol-gap-analyzer.js +228 -0
  198. package/dist/protocol-gap-analyzer.test.js +49 -0
  199. package/dist/protocol-invariants.js +276 -0
  200. package/dist/protocol-invariants.test.js +111 -0
  201. package/dist/protocol-knowledge.js +464 -0
  202. package/dist/protocol-miner.js +343 -0
  203. package/dist/protocol-mining.js +207 -0
  204. package/dist/protocol-mining.test.js +37 -0
  205. package/dist/protocol-registry.js +1 -1
  206. package/dist/protocol-security-benchmark.js +222 -0
  207. package/dist/protocol-vulnerability.js +257 -0
  208. package/dist/protocol-vulnerability.test.js +60 -0
  209. package/dist/python-benchmark.js +120 -0
  210. package/dist/python-emitter.js +163 -45
  211. package/dist/python-protocol-extractor.js +187 -0
  212. package/dist/python-protocol-extractor.test.js +116 -0
  213. package/dist/realworld-benchmark.js +646 -0
  214. package/dist/realworld-benchmark.test.js +36 -0
  215. package/dist/repair-arch.test.js +411 -0
  216. package/dist/repair-evolution.test.js +454 -0
  217. package/dist/repair-executor.js +719 -0
  218. package/dist/repair-proposal.js +4 -4
  219. package/dist/repair-ranker.js +141 -0
  220. package/dist/repair-strategies.js +419 -0
  221. package/dist/repair-taxonomy.js +234 -0
  222. package/dist/repair-types.js +12 -0
  223. package/dist/repo-evaluator.js +250 -0
  224. package/dist/repo-evaluator.test.js +128 -0
  225. package/dist/resource-abstraction.js +242 -0
  226. package/dist/resource-detector.js +211 -0
  227. package/dist/result.test.js +43 -0
  228. package/dist/reward-system.js +411 -0
  229. package/dist/reward-system.test.js +175 -0
  230. package/dist/risk-model.js +215 -0
  231. package/dist/rule-miner.js +234 -7
  232. package/dist/rule-specificity.js +254 -0
  233. package/dist/runtime-types.js +27 -0
  234. package/dist/scaffold.js +208 -0
  235. package/dist/scale-collector.test.js +101 -0
  236. package/dist/scale-trajectory-collector.js +128 -0
  237. package/dist/sdk.js +250 -0
  238. package/dist/search-planner.js +4 -41
  239. package/dist/semantic-snapshot.js +1 -1
  240. package/dist/semantic-topology.js +121 -0
  241. package/dist/semantic-trace.js +310 -317
  242. package/dist/sequence-extractor.js +343 -0
  243. package/dist/skill-library.js +245 -0
  244. package/dist/skill-planner.test.js +189 -0
  245. package/dist/software-physics.js +291 -0
  246. package/dist/software-physics.test.js +81 -0
  247. package/dist/ssg-precision.js +478 -0
  248. package/dist/ssg-validator.js +71 -21
  249. package/dist/state-inference-doubleblind.test.js +160 -0
  250. package/dist/state-inference.js +516 -0
  251. package/dist/state-inference.test.js +115 -0
  252. package/dist/state-machine-fingerprint.js +345 -0
  253. package/dist/state-machine-fingerprint.test.js +120 -0
  254. package/dist/state-miner.js +386 -0
  255. package/dist/state-name-inference.js +213 -0
  256. package/dist/state-name-inference.test.js +69 -0
  257. package/dist/strategy-planner.js +326 -59
  258. package/dist/strategy-planner.test.js +135 -0
  259. package/dist/telemetry-analytics.test.js +402 -0
  260. package/dist/terminal-format.js +68 -0
  261. package/dist/terminal-format.test.js +83 -0
  262. package/dist/topology-factory.js +196 -0
  263. package/dist/topology-representation.js +242 -0
  264. package/dist/topology-representation.test.js +27 -0
  265. package/dist/trajectory-augmentation.js +254 -0
  266. package/dist/trajectory-augmentation.test.js +63 -0
  267. package/dist/trajectory-corpus.js +440 -0
  268. package/dist/trajectory-corpus.test.js +32 -0
  269. package/dist/trajectory-feedback.test.js +116 -0
  270. package/dist/transition-synthesizer.js +286 -0
  271. package/dist/transition-synthesizer.test.js +123 -0
  272. package/dist/trust/api-semantic-mapper.js +809 -0
  273. package/dist/trust/call-graph-propagator.js +225 -0
  274. package/dist/trust/cli.js +122 -0
  275. package/dist/trust/compliance-scorer.js +283 -0
  276. package/dist/trust/confidence-calculator.js +261 -0
  277. package/dist/trust/engine.js +1145 -0
  278. package/dist/trust/explainability.js +85 -0
  279. package/dist/trust/formatters/ci.js +42 -0
  280. package/dist/trust/formatters/json.js +11 -0
  281. package/dist/trust/formatters/terminal.js +152 -0
  282. package/dist/trust/index.js +39 -0
  283. package/dist/trust/phase1-verify.js +171 -0
  284. package/dist/trust/protocol-domain-validator.js +697 -0
  285. package/dist/trust/score-calculator.js +282 -0
  286. package/dist/trust/ssg-bridge.js +641 -0
  287. package/dist/trust/ssg-bridge.test.js +269 -0
  288. package/dist/trust/types.js +67 -0
  289. package/dist/trust/violation-trace.js +335 -0
  290. package/dist/trust-api.js +179 -0
  291. package/dist/trust-calibration.js +279 -0
  292. package/dist/unknown-protocol-discovery.js +339 -0
  293. package/dist/unknown-protocol-discovery.test.js +102 -0
  294. package/dist/unsupervised-physics.js +230 -0
  295. package/dist/unsupervised-physics.test.js +95 -0
  296. package/dist/utils.test.js +37 -0
  297. package/dist/validator.js +187 -10
  298. package/dist/verification-intelligence.js +475 -0
  299. package/dist/verify-api.js +432 -0
  300. package/dist/vi-impact-report.js +293 -0
  301. package/dist/wl-fingerprint.js +162 -0
  302. package/dist/wl-fingerprint.test.js +130 -0
  303. package/dist/zeroshot-strategy.js +139 -0
  304. package/docs/Progmune_/346/212/225/350/265/204/344/272/272/347/231/275/347/232/256/344/271/246_v2.0.html +576 -0
  305. package/docs/Progmune_/351/241/271/347/233/256/345/205/250/350/247/243.html +710 -0
  306. package/package.json +74 -7
  307. package/protocols.json +1956 -50
  308. package/.dockerignore +0 -14
  309. package/.mcp.json +0 -11
  310. package/.progmune_allowlist +0 -50
  311. package/.test_report/test_report.md +0 -87
  312. package/Dockerfile +0 -9
  313. package/FAQ.md +0 -167
  314. package/WHITEPAPER.md +0 -540
  315. package/demo-project/auth.ts +0 -55
  316. package/demo-project/tsconfig.json +0 -8
  317. package/dist/acl-breakdown.js +0 -13
  318. package/dist/all-sessions.js +0 -11
  319. package/dist/antibody-stats.js +0 -11
  320. package/dist/branch-tree-count.js +0 -14
  321. package/dist/common-fixpath.js +0 -12
  322. package/dist/constraint-types.js +0 -12
  323. package/dist/exec-metrics.js +0 -11
  324. package/dist/failure-report.js +0 -11
  325. package/dist/fast-path-hits.js +0 -13
  326. package/dist/fingerprint-list.js +0 -15
  327. package/dist/gen-history-log.js +0 -13
  328. package/dist/heatmap-data.js +0 -11
  329. package/dist/recent-session.js +0 -12
  330. package/dist/svl-distribution.js +0 -11
  331. package/dist/terminal-status.js +0 -11
  332. package/dist/token-savings.js +0 -11
  333. package/dist/total-repairs.js +0 -12
  334. package/dist/unresolved-count.js +0 -12
  335. package/dist/valid-fingerprints.js +0 -13
  336. package/dist/verify-ledgers.js +0 -11
  337. package/docs/whitepaper-style.css +0 -77
  338. package/docs/whitepaper-v2.1.md +0 -609
  339. package/docs/whitepaper-v2.2.md +0 -1064
  340. package/docs/whitepaper-v2.2.pdf +0 -0
  341. package/fly.toml +0 -31
  342. package/public/dashboard.html +0 -119
  343. package/server/hub.js +0 -116
  344. package/test/replay-golden/sess_1780063202050_mgeld.json +0 -9
  345. package/test/replay-golden/sess_1780064032560_gocld.json +0 -354
  346. package/test/replay-golden/sess_1780064413331_s2709.json +0 -606
  347. package/test/replay-golden/sess_1780064792710_y3avo.json +0 -614
  348. package/test/replay-golden.ts +0 -84
  349. package/test_benchmark.js +0 -165
  350. package/test_comprehensive.mjs +0 -638
  351. package/test_concurrency.js +0 -129
  352. package/test_ir_robustness.js +0 -85
  353. package/test_semantic_contracts.js +0 -269
  354. package/test_ssg_stress.js +0 -156
  355. package/test_svl3.js +0 -58
  356. package/tsconfig.json +0 -17
@@ -0,0 +1,478 @@
1
+ "use strict";
2
+ /**
3
+ * P9.2p-SSG: Precision benchmark using REAL SSG state machine validation.
4
+ *
5
+ * Key difference from precision-benchmark.ts:
6
+ * precision-benchmark.ts: structural comparison (state count diff)
7
+ * ssg-precision.ts: SSG validation (pre_state → fn → post_state)
8
+ *
9
+ * Pipeline:
10
+ * 1. Extract call sequences from repo
11
+ * 2. Auto-discover protocol rules (auto-protocol-synthesizer)
12
+ * 3. Feed rules into SSG validator (ssg-validator)
13
+ * 4. Validate each sequence against discovered rules
14
+ * 5. Measure precision against labeled ground truth
15
+ */
16
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
17
+ if (k2 === undefined) k2 = k;
18
+ var desc = Object.getOwnPropertyDescriptor(m, k);
19
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
20
+ desc = { enumerable: true, get: function() { return m[k]; } };
21
+ }
22
+ Object.defineProperty(o, k2, desc);
23
+ }) : (function(o, m, k, k2) {
24
+ if (k2 === undefined) k2 = k;
25
+ o[k2] = m[k];
26
+ }));
27
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
28
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
29
+ }) : function(o, v) {
30
+ o["default"] = v;
31
+ });
32
+ var __importStar = (this && this.__importStar) || (function () {
33
+ var ownKeys = function(o) {
34
+ ownKeys = Object.getOwnPropertyNames || function (o) {
35
+ var ar = [];
36
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
37
+ return ar;
38
+ };
39
+ return ownKeys(o);
40
+ };
41
+ return function (mod) {
42
+ if (mod && mod.__esModule) return mod;
43
+ var result = {};
44
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
45
+ __setModuleDefault(result, mod);
46
+ return result;
47
+ };
48
+ })();
49
+ Object.defineProperty(exports, "__esModule", { value: true });
50
+ exports.validateSequenceWithSSG = validateSequenceWithSSG;
51
+ exports.loadHandWrittenRules = loadHandWrittenRules;
52
+ exports.discoverRulesFromSequences = discoverRulesFromSequences;
53
+ exports.runSSGPrecisionBenchmark = runSSGPrecisionBenchmark;
54
+ exports.runHandWrittenPrecisionBenchmark = runHandWrittenPrecisionBenchmark;
55
+ const fs = __importStar(require("fs"));
56
+ const auto_protocol_synthesizer_1 = require("./auto-protocol-synthesizer");
57
+ const ssg_validator_1 = require("./ssg-validator");
58
+ // ═══════════════════════════════════════════════════════════════
59
+ // SSG Validation Engine
60
+ // ═══════════════════════════════════════════════════════════════
61
+ /**
62
+ * Validate a single call sequence against SSG protocol rules.
63
+ *
64
+ * Unlike detectStructuralViolations (which compares SM topology),
65
+ * this does proper state-machine validation:
66
+ * 1. Start with initial states (namespace defaults)
67
+ * 2. For each function call, check if pre_states are satisfied
68
+ * 3. Apply state changes (invalidate old, add new)
69
+ * 4. A sequence is "clean" if ALL function calls pass pre_state checks
70
+ * 5. A sequence is "violation" if ANY function call fails pre_state checks
71
+ *
72
+ * @returns true if ALL calls pass validation, false if any call fails
73
+ */
74
+ function validateSequenceWithSSG(sequence, rules, nsInit = new Map([["_global", "INIT"]]), trainingSeqs) {
75
+ // Initialize per-namespace state sets
76
+ const nsStates = new Map();
77
+ for (const [ns, initState] of nsInit) {
78
+ nsStates.set(ns, new Set([initState]));
79
+ }
80
+ for (let i = 0; i < sequence.length; i++) {
81
+ const fn = sequence[i];
82
+ const rule = rules.get(fn);
83
+ // No rule for this function → no constraint → skip (not a violation)
84
+ if (!rule)
85
+ continue;
86
+ const ns = rule.namespace || "_global";
87
+ const states = nsStates.get(ns) || new Set(["INIT"]);
88
+ // Check preconditions
89
+ if (rule.pre_states.length > 0) {
90
+ const preMet = rule.pre_states.every(s => states.has(s));
91
+ if (!preMet) {
92
+ const missing = rule.pre_states.filter(s => !states.has(s));
93
+ return {
94
+ valid: false,
95
+ failingStep: i,
96
+ failingFunction: fn,
97
+ reason: `${fn} requires [${missing.join(",")}] but state has [${[...states].join(",")}] (namespace: ${ns})`,
98
+ };
99
+ }
100
+ }
101
+ // Apply state changes
102
+ if (rule.invalidate)
103
+ rule.invalidate.forEach(s => states.delete(s));
104
+ for (const s of rule.post_states)
105
+ states.add(s);
106
+ }
107
+ // P9.2p: Check for incomplete lifecycle.
108
+ // Only flag if ALL of these conditions are met:
109
+ // 1. The state was PRODUCED by a function in this sequence (not inherited from INIT)
110
+ // 2. A closer function EXISTS in the rule set that can invalidate this state
111
+ // 3. That closer function appears in the CLEAN training data as a frequent terminal call
112
+ // This prevents false positives on sequences that naturally end without a closer.
113
+ const lingering = [];
114
+ for (const [ns, st] of nsStates) {
115
+ if (ns === "_global")
116
+ continue;
117
+ for (const s of st) {
118
+ if (s === "INIT" || s === "IDLE")
119
+ continue;
120
+ // Condition 1: Was this state produced during this sequence?
121
+ let producedInSequence = false;
122
+ for (const fn of sequence) {
123
+ const r = rules.get(fn);
124
+ if (r && r.post_states.includes(s)) {
125
+ producedInSequence = true;
126
+ break;
127
+ }
128
+ }
129
+ if (!producedInSequence)
130
+ continue;
131
+ // Condition 2: Does a closer function exist that can invalidate this state?
132
+ let closerFn = "";
133
+ for (const [fn, rule] of rules) {
134
+ if (rule.invalidate && rule.invalidate.includes(s)) {
135
+ closerFn = fn;
136
+ break;
137
+ }
138
+ }
139
+ if (!closerFn)
140
+ continue;
141
+ // Condition 3: Has this closer been called in this sequence?
142
+ if (sequence.includes(closerFn))
143
+ continue; // already called — no violation
144
+ // Condition 4: Is this closer a frequent terminal call?
145
+ // Only flag if ≥50% of sequences containing the state's producer
146
+ // also call the closer as the last step.
147
+ if (trainingSeqs && !isFrequentTerminal(closerFn, s, trainingSeqs, rules))
148
+ continue;
149
+ lingering.push(`${ns}:${s}→${closerFn}`);
150
+ }
151
+ }
152
+ if (lingering.length > 0) {
153
+ return {
154
+ valid: false,
155
+ failingStep: sequence.length - 1,
156
+ failingFunction: sequence[sequence.length - 1] || "",
157
+ reason: `Incomplete lifecycle: acquired states [${lingering.join(",")}] not released — missing closer call`,
158
+ };
159
+ }
160
+ // P9.2p: Check for reordering violations.
161
+ // If function A always precedes function B in the clean training data,
162
+ // but B precedes A in this test sequence, that's a potential violation.
163
+ const orderViolations = checkOrderViolations(sequence, rules, nsInit);
164
+ if (orderViolations.length > 0) {
165
+ return {
166
+ valid: false,
167
+ failingStep: orderViolations[0].pos,
168
+ failingFunction: orderViolations[0].fn,
169
+ reason: `Order violation: ${orderViolations[0].reason}`,
170
+ };
171
+ }
172
+ return { valid: true, failingStep: -1, failingFunction: "", reason: "" };
173
+ }
174
+ /**
175
+ * Check if any functions appear in the wrong order compared to
176
+ * the discovered protocol rules' state machine graph.
177
+ *
178
+ * Builds a partial order from the state machine topology:
179
+ * if fnA's post_states include S, and fnB's pre_states include S,
180
+ * then fnA must precede fnB. If fnB appears before fnA, it's a violation.
181
+ */
182
+ function checkOrderViolations(sequence, rules, nsInit) {
183
+ const violations = [];
184
+ // Build must-precede graph from rules
185
+ for (const [fnA, ruleA] of rules) {
186
+ if (ruleA.post_states.length === 0)
187
+ continue;
188
+ for (const [fnB, ruleB] of rules) {
189
+ if (fnA === fnB)
190
+ continue;
191
+ // fnA produces a state that fnB requires → fnA must precede fnB
192
+ const shared = ruleA.post_states.filter(s => ruleB.pre_states.includes(s));
193
+ if (shared.length === 0)
194
+ continue;
195
+ // Check if fnB appears before fnA in the sequence
196
+ const posA = sequence.indexOf(fnA);
197
+ const posB = sequence.indexOf(fnB);
198
+ if (posB >= 0 && posA >= 0 && posB < posA) {
199
+ violations.push({
200
+ pos: posB,
201
+ fn: fnB,
202
+ reason: `${fnB} should come AFTER ${fnA} (state [${shared[0]}] must be produced first)`,
203
+ });
204
+ }
205
+ }
206
+ }
207
+ return violations;
208
+ }
209
+ // ═══════════════════════════════════════════════════════════════
210
+ // Auto-discover protocol rules from sequences
211
+ // ═══════════════════════════════════════════════════════════════
212
+ /**
213
+ * Load hand-written protocol rules from a JSON file (like protocols.json format).
214
+ */
215
+ function loadHandWrittenRules(protoPath) {
216
+ const protoDef = JSON.parse(fs.readFileSync(protoPath, "utf-8"));
217
+ const fns = (0, ssg_validator_1.parseProtocolsFromJSON)(protoDef);
218
+ const rules = new Map();
219
+ for (const p of fns)
220
+ rules.set(p.function, p.protocol);
221
+ const nsInit = new Map();
222
+ nsInit.set("_global", "INIT");
223
+ if (protoDef.namespaceInitialStates) {
224
+ for (const [ns, init] of Object.entries(protoDef.namespaceInitialStates)) {
225
+ nsInit.set(ns, init);
226
+ }
227
+ }
228
+ return { rules, nsInit };
229
+ }
230
+ /**
231
+ * Build ordering constraints from clean sequences.
232
+ * If fnA appears before fnB in ≥80% of sequences where both appear,
233
+ * then fnA must precede fnB.
234
+ */
235
+ function buildOrderConstraints(sequences) {
236
+ const pairs = new Map();
237
+ for (const seq of sequences) {
238
+ for (let i = 0; i < seq.length; i++) {
239
+ for (let j = i + 1; j < seq.length; j++) {
240
+ const a = seq[i], b = seq[j];
241
+ if (a === b)
242
+ continue;
243
+ if (!pairs.has(a))
244
+ pairs.set(a, new Map());
245
+ if (!pairs.get(a).has(b))
246
+ pairs.get(a).set(b, { aBeforeB: 0, bBeforeA: 0 });
247
+ pairs.get(a).get(b).aBeforeB++;
248
+ }
249
+ }
250
+ }
251
+ const constraints = new Map();
252
+ for (const [fnA, pbs] of pairs) {
253
+ for (const [fnB, counts] of pbs) {
254
+ const total = counts.aBeforeB + counts.bBeforeA;
255
+ // Require ≥2 co-occurrences AND ≥80% ordering confidence.
256
+ // Lower threshold catches more violations; higher precision trades off recall.
257
+ if (total >= 2 && counts.aBeforeB / total >= 0.8) {
258
+ if (!constraints.has(fnA))
259
+ constraints.set(fnA, new Set());
260
+ constraints.get(fnA).add(fnB);
261
+ }
262
+ }
263
+ }
264
+ return constraints;
265
+ }
266
+ /**
267
+ * Check if a closer function is a frequent terminal call for sequences
268
+ * that produce a given state. Prevents flagging sequences that naturally
269
+ * end without a closer.
270
+ */
271
+ function isFrequentTerminal(closerFn, targetState, sequences, rules) {
272
+ let producesState = 0;
273
+ let closerAsLast = 0;
274
+ for (const seq of sequences) {
275
+ let hasProducer = false;
276
+ for (const fn of seq) {
277
+ const r = rules.get(fn);
278
+ if (r && r.post_states.includes(targetState)) {
279
+ hasProducer = true;
280
+ break;
281
+ }
282
+ }
283
+ if (!hasProducer)
284
+ continue;
285
+ producesState++;
286
+ if (seq.length > 0 && seq[seq.length - 1] === closerFn)
287
+ closerAsLast++;
288
+ }
289
+ // Closer must appear as last call in ≥50% of sequences that produce this state
290
+ return producesState >= 2 && closerAsLast / producesState >= 0.5;
291
+ }
292
+ /** Validate a sequence against ordering constraints + SSG rules. */
293
+ function validateWithOrdering(sequence, rules, nsInit, orderConstraints, trainingSeqs) {
294
+ // First: SSG validation
295
+ const ssgResult = validateSequenceWithSSG(sequence, rules, nsInit, trainingSeqs);
296
+ if (!ssgResult.valid)
297
+ return ssgResult;
298
+ // Second: ordering constraint check
299
+ for (let i = 0; i < sequence.length; i++) {
300
+ const fnA = sequence[i];
301
+ const mustFollow = orderConstraints.get(fnA);
302
+ if (!mustFollow)
303
+ continue;
304
+ // Check if any required follower is BEFORE fnA in this sequence
305
+ for (let j = 0; j < i; j++) {
306
+ const fnB = sequence[j];
307
+ if (mustFollow.has(fnB)) {
308
+ return {
309
+ valid: false, failingStep: j, failingFunction: fnB,
310
+ reason: `Order violation: ${fnB} should come AFTER ${fnA} (appears before in ${Math.round(sequence.length / 2)} of clean sequences)`,
311
+ };
312
+ }
313
+ }
314
+ }
315
+ return { valid: true, failingStep: -1, failingFunction: "", reason: "" };
316
+ }
317
+ /**
318
+ * Discover protocol rules from call sequences using the auto-protocol-synthesizer.
319
+ * Returns SSG-compatible StateAnnotation rules ready for validation.
320
+ */
321
+ function discoverRulesFromSequences(sequences) {
322
+ const synthesized = (0, auto_protocol_synthesizer_1.synthesizeProtocols)(sequences);
323
+ const rules = new Map();
324
+ const namespaces = new Set();
325
+ for (const proto of synthesized) {
326
+ for (const r of proto.rules) {
327
+ // Infer namespace from prototype pattern
328
+ const ns = proto.inferredPattern || "discovered";
329
+ namespaces.add(ns);
330
+ rules.set(r.function, {
331
+ pre_states: r.pre_states,
332
+ post_states: r.post_states,
333
+ invalidate: r.invalidate,
334
+ namespace: ns,
335
+ });
336
+ }
337
+ }
338
+ // Build namespace initial states
339
+ const nsInit = new Map();
340
+ nsInit.set("_global", "INIT");
341
+ for (const ns of namespaces) {
342
+ nsInit.set(ns, "INIT");
343
+ }
344
+ return { rules, nsInit };
345
+ }
346
+ /**
347
+ * Run precision benchmark using SSG validation with auto-discovered rules.
348
+ *
349
+ * @param sequences Labeled call sequences
350
+ * @param labels Index → 'clean' | 'violation'
351
+ * @returns SSGPrecisionResult with TP/FP/TN/FN breakdown
352
+ */
353
+ function runSSGPrecisionBenchmark(sequences, labels) {
354
+ // 1. Build rule set from clean-labeled sequences
355
+ const cleanSeqs = sequences
356
+ .filter(s => labels[s.index] === "clean" && s.calls.length >= 2)
357
+ .map(s => s.calls);
358
+ if (cleanSeqs.length === 0) {
359
+ return { total: 0, truePositive: 0, falsePositive: 0, trueNegative: 0, falseNegative: 0, precision: 0, recall: 0, f1: 0, discoveredRules: 0, mismatches: [] };
360
+ }
361
+ // 2. Auto-discover protocol rules
362
+ const { rules, nsInit } = discoverRulesFromSequences(cleanSeqs);
363
+ // 2b. Build ordering constraints from clean data
364
+ const orderConstraints = buildOrderConstraints(cleanSeqs);
365
+ // 3. Validate each sequence
366
+ let tp = 0, fp = 0, tn = 0, fn = 0;
367
+ const mismatches = [];
368
+ for (const seq of sequences) {
369
+ const expected = labels[seq.index];
370
+ if (!expected)
371
+ continue;
372
+ const result = validateWithOrdering(seq.calls, rules, nsInit, orderConstraints, cleanSeqs);
373
+ const detected = result.valid ? "clean" : "violation";
374
+ if (expected === "clean" && detected === "clean") {
375
+ tn++;
376
+ }
377
+ else if (expected === "violation" && detected === "violation") {
378
+ tp++;
379
+ }
380
+ else if (expected === "clean" && detected === "violation") {
381
+ fp++;
382
+ mismatches.push({ index: seq.index, functionName: seq.functionName, expected, detected, reason: result.reason });
383
+ }
384
+ else if (expected === "violation" && detected === "clean") {
385
+ fn++;
386
+ mismatches.push({ index: seq.index, functionName: seq.functionName, expected, detected, reason: "SSG passed — no pre_state violation detected" });
387
+ }
388
+ }
389
+ const total = tp + fp + tn + fn;
390
+ const precision = total > 0 ? tp / (tp + fp) : 0;
391
+ const recall = total > 0 ? tp / (tp + fn) : 0;
392
+ const f1 = precision + recall > 0 ? 2 * precision * recall / (precision + recall) : 0;
393
+ return { total, truePositive: tp, falsePositive: fp, trueNegative: tn, falseNegative: fn, precision, recall, f1, discoveredRules: rules.size, mismatches };
394
+ }
395
+ // ═══════════════════════════════════════════════════════════════
396
+ // Hand-written rule precision benchmark
397
+ // ═══════════════════════════════════════════════════════════════
398
+ /**
399
+ * Run precision benchmark using HAND-WRITTEN protocol rules instead of auto-discovered ones.
400
+ * This measures the UPPER BOUND of what the SSG validator can achieve.
401
+ */
402
+ function runHandWrittenPrecisionBenchmark(sequences, labels, protoPath) {
403
+ const { rules, nsInit } = loadHandWrittenRules(protoPath);
404
+ let tp = 0, fp = 0, tn = 0, fn = 0;
405
+ const mismatches = [];
406
+ for (const seq of sequences) {
407
+ const expected = labels[seq.index];
408
+ if (!expected)
409
+ continue;
410
+ const result = validateSequenceWithSSG(seq.calls, rules, nsInit);
411
+ const detected = result.valid ? "clean" : "violation";
412
+ if (expected === "clean" && detected === "clean") {
413
+ tn++;
414
+ }
415
+ else if (expected === "violation" && detected === "violation") {
416
+ tp++;
417
+ }
418
+ else if (expected === "clean" && detected === "violation") {
419
+ fp++;
420
+ mismatches.push({ index: seq.index, functionName: seq.functionName, expected, detected, reason: result.reason });
421
+ }
422
+ else if (expected === "violation" && detected === "clean") {
423
+ fn++;
424
+ mismatches.push({ index: seq.index, functionName: seq.functionName, expected, detected, reason: "SSG passed — no violation detected" });
425
+ }
426
+ }
427
+ const total = tp + fp + tn + fn;
428
+ const precision = total > 0 ? tp / (tp + fp) : 0;
429
+ const recall = total > 0 ? tp / (tp + fn) : 0;
430
+ const f1 = precision + recall > 0 ? 2 * precision * recall / (precision + recall) : 0;
431
+ return { total, truePositive: tp, falsePositive: fp, trueNegative: tn, falseNegative: fn, precision, recall, f1, discoveredRules: rules.size, mismatches };
432
+ }
433
+ // ═══════════════════════════════════════════════════════════════
434
+ // CLI — only runs when executed directly (not required from tests)
435
+ // ═══════════════════════════════════════════════════════════════
436
+ if (require.main === module) {
437
+ const args = process.argv.slice(2);
438
+ const seqFile = args[0];
439
+ const labelFile = args[1];
440
+ if (!seqFile || !labelFile) {
441
+ console.error("Usage: npx tsx src/ssg-precision.ts <sequences.json> <labels.json>");
442
+ process.exit(1);
443
+ }
444
+ const seqData = JSON.parse(fs.readFileSync(seqFile, "utf-8"));
445
+ const rawSeqs = seqData.sequences || seqData;
446
+ // Add index to each sequence if missing
447
+ const sequences = rawSeqs.map((s, i) => ({
448
+ index: s.index ?? i,
449
+ functionName: s.functionName || s.functionName || (`seq_${i}`),
450
+ calls: s.calls || [],
451
+ expected: 'clean',
452
+ }));
453
+ const labels = JSON.parse(fs.readFileSync(labelFile, "utf-8"));
454
+ console.log("Running SSG precision benchmark...");
455
+ const result = runSSGPrecisionBenchmark(sequences, labels);
456
+ console.log("\n=== SSG Precision Benchmark Results ===");
457
+ console.log(`Discovered rules: ${result.discoveredRules}`);
458
+ console.log(`Sequences evaluated: ${result.total}`);
459
+ console.log(`True Positives: ${result.truePositive}`);
460
+ console.log(`False Positives: ${result.falsePositive}`);
461
+ console.log(`True Negatives: ${result.trueNegative}`);
462
+ console.log(`False Negatives: ${result.falseNegative}`);
463
+ console.log(`\nPrecision: ${(result.precision * 100).toFixed(1)}%`);
464
+ console.log(`Recall: ${(result.recall * 100).toFixed(1)}%`);
465
+ console.log(`F1 Score: ${(result.f1 * 100).toFixed(1)}%`);
466
+ if (result.mismatches.length > 0) {
467
+ console.log(`\n--- Mismatches (${result.mismatches.length}) ---`);
468
+ for (const m of result.mismatches.slice(0, 20)) {
469
+ console.log(` [${m.index}] ${m.functionName}: expected=${m.expected} detected=${m.detected}`);
470
+ console.log(` ${m.reason}`);
471
+ }
472
+ if (result.mismatches.length > 20) {
473
+ console.log(` ... and ${result.mismatches.length - 20} more`);
474
+ }
475
+ }
476
+ fs.writeFileSync("benchmarks/ssg-precision-report.json", JSON.stringify({ timestamp: new Date().toISOString(), result }, null, 2));
477
+ console.log("\nReport saved to benchmarks/ssg-precision-report.json");
478
+ } // end if (require.main === module)
@@ -260,32 +260,34 @@ function validateTransition(ctx, candidateFunctionName, actionIndex, rules, name
260
260
  valid: true,
261
261
  ruleHash,
262
262
  };
263
- // Invariant-1: delta consistency
264
- const deltaMap = fromSnapshot(currentState);
265
- applyTransitionDelta(deltaMap, transition);
266
- const computedAfter = toSnapshot(deltaMap);
267
- if (!deepEqualSnapshots(computedAfter, statesAfter)) {
268
- const detail = `[Invariant-1] Delta consistency violation in validateTransition for "${candidateFunctionName}":\n` +
269
- ` acquired: [${acquired.join(", ")}] invalidated: [${invalidated.join(", ")}]\n` +
270
- ` expected after: ${JSON.stringify(computedAfter)}\n` +
271
- ` actual after: ${JSON.stringify(statesAfter)}`;
272
- // P0 Strict Mode: fail fast on kernel corruption
273
- if (process.env.PROGMUNE_STRICT !== "false") {
274
- throw new InvariantViolationError(detail, {
275
- invariant: "delta-consistency",
276
- namespace: ns,
277
- function: candidateFunctionName,
278
- expected: computedAfter,
279
- actual: statesAfter,
280
- });
263
+ // Invariant-1: delta consistency (skip in fast mode for performance)
264
+ if (process.env.PROGMUNE_FAST_VALIDATE !== "true") {
265
+ const deltaMap = fromSnapshot(currentState);
266
+ applyTransitionDelta(deltaMap, transition);
267
+ const computedAfter = toSnapshot(deltaMap);
268
+ if (!deepEqualSnapshots(computedAfter, statesAfter)) {
269
+ const detail = `[Invariant-1] Delta consistency violation in validateTransition for "${candidateFunctionName}":\n` +
270
+ ` acquired: [${acquired.join(", ")}] invalidated: [${invalidated.join(", ")}]\n` +
271
+ ` expected after: ${JSON.stringify(computedAfter)}\n` +
272
+ ` actual after: ${JSON.stringify(statesAfter)}`;
273
+ // P0 Strict Mode: fail fast on kernel corruption
274
+ if (process.env.PROGMUNE_STRICT !== "false") {
275
+ throw new InvariantViolationError(detail, {
276
+ invariant: "delta-consistency",
277
+ namespace: ns,
278
+ function: candidateFunctionName,
279
+ expected: computedAfter,
280
+ actual: statesAfter,
281
+ });
282
+ }
283
+ console.error(detail);
281
284
  }
282
- console.error(detail);
283
- }
285
+ } // PROGMUNE_FAST_VALIDATE guard
284
286
  return { valid: true, transition };
285
287
  }
286
288
  // ── checkLedgerConsistency: Invariant-0 + Invariant-1 over full ledger ──
287
289
  /** @requires LEDGER_DATA @produces CONSISTENCY_RESULT */
288
- function checkLedgerConsistency(ledger, namespaceInitialStates = new Map([["_global", "INIT"]])) {
290
+ function checkLedgerConsistency(ledger, namespaceInitialStates = new Map([["_global", "INIT"]]), protocolRules) {
289
291
  const violations = [];
290
292
  const running = fromSnapshot({});
291
293
  // Pre-scan: collect all namespaces referenced in any transition
@@ -344,6 +346,53 @@ function checkLedgerConsistency(ledger, namespaceInitialStates = new Map([["_glo
344
346
  });
345
347
  }
346
348
  }
349
+ // Invariant-2: delta legality — acquired/invalidated must match protocol rules
350
+ if (t.valid && protocolRules && protocolRules.size > 0) {
351
+ const rule = protocolRules.get(t.function);
352
+ if (rule) {
353
+ // Check acquired states are in the function's post_states
354
+ const beforeStates = t.statesBefore[t.namespace] || [];
355
+ for (const a of (t.acquired || [])) {
356
+ if (!rule.post_states.includes(a)) {
357
+ violations.push({
358
+ index: i,
359
+ invariant: "delta-legality",
360
+ detail: `Transition[${i}] "${t.function}": acquired state "${a}" is not in protocol post_states [${rule.post_states.join(", ")}]`,
361
+ });
362
+ }
363
+ // Reject acquiring a state that already exists in statesBefore
364
+ if (beforeStates.includes(a)) {
365
+ violations.push({
366
+ index: i,
367
+ invariant: "delta-legality",
368
+ detail: `Transition[${i}] "${t.function}": acquired state "${a}" already exists in statesBefore [${beforeStates.join(", ")}]`,
369
+ });
370
+ }
371
+ }
372
+ // Check invalidated states are in the function's invalidate list
373
+ for (const inv of (t.invalidated || [])) {
374
+ if (!(rule.invalidate || []).includes(inv)) {
375
+ violations.push({
376
+ index: i,
377
+ invariant: "delta-legality",
378
+ detail: `Transition[${i}] "${t.function}": invalidated state "${inv}" is not in protocol invalidate [${(rule.invalidate || []).join(", ")}]`,
379
+ });
380
+ }
381
+ }
382
+ // Check no missing expected invalidations (unless the function has no invalidate rule)
383
+ if (rule.invalidate && rule.invalidate.length > 0) {
384
+ for (const expectedInv of rule.invalidate) {
385
+ if (!(t.invalidated || []).includes(expectedInv)) {
386
+ violations.push({
387
+ index: i,
388
+ invariant: "delta-legality",
389
+ detail: `Transition[${i}] "${t.function}": expected invalidation of "${expectedInv}" per protocol, but not present in transition`,
390
+ });
391
+ }
392
+ }
393
+ }
394
+ }
395
+ }
347
396
  // Advance running state
348
397
  if (t.valid) {
349
398
  applyTransitionDelta(running, t);
@@ -671,6 +720,7 @@ function parseProtocolsFromJSON(protocolDef) {
671
720
  post_states: rule.post_states,
672
721
  invalidate: rule.invalidate,
673
722
  namespace: rule.namespace,
723
+ aliases: rule.aliases,
674
724
  },
675
725
  });
676
726
  }