progmune-runtime 2.1.6 → 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 +262 -96
  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,222 @@
1
+ "use strict";
2
+ /**
3
+ * P9.2b++: Protocol Security Benchmark — defining a new security category
4
+ *
5
+ * This is NOT just another CVE benchmark. It's the FIRST dataset
6
+ * specifically designed for protocol lifecycle vulnerabilities —
7
+ * missing states, missing edges, and illegal transitions that
8
+ * traditional SAST tools cannot see because they look at code
9
+ * patterns, not state machines.
10
+ *
11
+ * The benchmark measures one thing: can a system detect that a
12
+ * protocol lifecycle has been violated, regardless of how the
13
+ * code is written?
14
+ *
15
+ * Categories:
16
+ * RESOURCE_LEAK: Acquire→Use...no Release
17
+ * AUTH_BYPASS: Action without prior Authentication
18
+ * TRANSACTION_VIOLATION: Begin→...no Commit/Rollback
19
+ * USE_AFTER_FREE: Free→Use (illegal edge)
20
+ * SESSION_VIOLATION: Logout→Access (illegal edge)
21
+ * DOUBLE_FREE: Free→Free (illegal self-loop)
22
+ */
23
+ Object.defineProperty(exports, "__esModule", { value: true });
24
+ exports.buildProtocolSecurityBenchmark = buildProtocolSecurityBenchmark;
25
+ exports.runProtocolSecurityBenchmark = runProtocolSecurityBenchmark;
26
+ exports.printProtocolSecurityReport = printProtocolSecurityReport;
27
+ const gold_cve_1 = require("./gold-cve");
28
+ // ═══════════════════════════════════════════════════════════════
29
+ // Build the benchmark from all available verified cases
30
+ // ═══════════════════════════════════════════════════════════════
31
+ function buildProtocolSecurityBenchmark() {
32
+ const cases = [];
33
+ // Source 1: Curated 20 cases (manually verified against real CVE patterns)
34
+ const curated = (0, gold_cve_1.loadGoldDataset)().cases;
35
+ for (const c of curated) {
36
+ cases.push({
37
+ id: c.id,
38
+ category: c.category,
39
+ severity: c.severity,
40
+ broken: c.broken,
41
+ expected: c.expected,
42
+ source: "curated",
43
+ verified: true,
44
+ notes: c.notes,
45
+ });
46
+ }
47
+ // Source 2: Diff-based gold cases (from real git diffs)
48
+ try {
49
+ const fs = require("fs");
50
+ const path = require("path");
51
+ const seedPath = path.resolve(__dirname, "..", "benchmarks", "gold-seed.json");
52
+ if (fs.existsSync(seedPath)) {
53
+ const seed = JSON.parse(fs.readFileSync(seedPath, "utf-8"));
54
+ for (const c of seed) {
55
+ cases.push({
56
+ id: `GOLD-${c.cve}`,
57
+ category: c.category,
58
+ severity: c.severity || "high",
59
+ broken: c.before,
60
+ expected: c.after,
61
+ source: "git_diff",
62
+ verified: true,
63
+ notes: c.notes,
64
+ });
65
+ }
66
+ }
67
+ }
68
+ catch { }
69
+ // Source 3: Synthetic cases from topology factory (for stress testing)
70
+ // These are NOT verified — marked accordingly
71
+ const generateSyntheticCases = () => {
72
+ const { createProtocolForTopology, ALL_TOPOLOGIES } = require("./topology-factory");
73
+ const synthetic = [];
74
+ let id = 200;
75
+ for (const topo of ALL_TOPOLOGIES) {
76
+ const rules = createProtocolForTopology(topo);
77
+ if (rules.size < 2)
78
+ continue;
79
+ const entries = [...rules.entries()];
80
+ for (let v = 0; v < 3 && synthetic.length < 30; v++) {
81
+ const path = [];
82
+ const ss = new Set(["INIT", "IDLE"]);
83
+ const s = entries[Math.floor(Math.random() * entries.length)];
84
+ path.push(s[0]);
85
+ const r = s[1];
86
+ if (r.invalidate)
87
+ r.invalidate.forEach((x) => ss.delete(x));
88
+ for (const x of r.post_states)
89
+ ss.add(x);
90
+ for (let t = 0; t < 4; t++) {
91
+ const cands = entries.filter(([, rr]) => rr.pre_states.every((x) => ss.has(x)));
92
+ if (!cands.length)
93
+ break;
94
+ const [fn, nr] = cands[Math.floor(Math.random() * cands.length)];
95
+ path.push(fn);
96
+ if (nr.invalidate)
97
+ nr.invalidate.forEach((x) => ss.delete(x));
98
+ for (const x of nr.post_states)
99
+ ss.add(x);
100
+ }
101
+ if (path.length < 3)
102
+ continue;
103
+ synthetic.push({
104
+ id: `SYN-${id++}`,
105
+ category: "resource_leak",
106
+ severity: "medium",
107
+ broken: path.slice(0, -1),
108
+ expected: path,
109
+ source: "synthetic",
110
+ verified: false,
111
+ });
112
+ }
113
+ }
114
+ return synthetic;
115
+ };
116
+ try {
117
+ cases.push(...generateSyntheticCases());
118
+ }
119
+ catch { }
120
+ // Build metadata
121
+ const byCategory = {};
122
+ const bySource = {};
123
+ let verified = 0;
124
+ for (const c of cases) {
125
+ byCategory[c.category] = (byCategory[c.category] || 0) + 1;
126
+ bySource[c.source] = (bySource[c.source] || 0) + 1;
127
+ if (c.verified)
128
+ verified++;
129
+ }
130
+ return {
131
+ name: "Protocol Lifecycle Security Benchmark",
132
+ version: "1.0.0",
133
+ cases,
134
+ metadata: { total: cases.length, verified, byCategory, bySource },
135
+ };
136
+ }
137
+ function runProtocolSecurityBenchmark() {
138
+ const bench = buildProtocolSecurityBenchmark();
139
+ const { inferStateMachine } = require("./experimental/state-inference");
140
+ const { detectStructuralViolations } = require("./protocol-invariants");
141
+ const CWE_TO_VIOLATION = {
142
+ resource_leak: "missing_release",
143
+ auth_bypass: "missing_prerequisite",
144
+ data_corruption: "missing_commit",
145
+ use_after_free: "illegal_transition",
146
+ race_condition: "missing_prerequisite",
147
+ };
148
+ const byCat = {};
149
+ let totalDetected = 0, totalMatched = 0;
150
+ let verifiedDetected = 0, verifiedTotal = 0;
151
+ for (const c of bench.cases) {
152
+ if (!byCat[c.category])
153
+ byCat[c.category] = { total: 0, verified: 0, detected: 0, matched: 0 };
154
+ byCat[c.category].total++;
155
+ if (c.verified) {
156
+ byCat[c.category].verified++;
157
+ verifiedTotal++;
158
+ }
159
+ const templateSM = inferStateMachine([c.expected]);
160
+ const brokenSM = inferStateMachine([c.broken]);
161
+ const violations = detectStructuralViolations(brokenSM, templateSM);
162
+ const violationTypes = violations.map((v) => v.violationSubtype);
163
+ const detected = violations.length > 0;
164
+ const expectedV = CWE_TO_VIOLATION[c.category] || "";
165
+ const matched = expectedV ? violationTypes.includes(expectedV) : false;
166
+ if (detected) {
167
+ totalDetected++;
168
+ byCat[c.category].detected++;
169
+ if (c.verified)
170
+ verifiedDetected++;
171
+ }
172
+ if (matched) {
173
+ totalMatched++;
174
+ byCat[c.category].matched++;
175
+ }
176
+ }
177
+ const total = bench.cases.length;
178
+ const overallRecall = total > 0 ? totalDetected / total : 0;
179
+ const overallPrecision = totalDetected > 0 ? totalMatched / totalDetected : 0;
180
+ const verifiedRecall = verifiedTotal > 0 ? verifiedDetected / verifiedTotal : 0;
181
+ const verifiedPrecision = verifiedTotal > 0 ? totalMatched / Math.max(1, totalDetected) : 0;
182
+ const parserGap = verifiedRecall - overallRecall;
183
+ const categoryBreakdown = {};
184
+ for (const [cat, s] of Object.entries(byCat)) {
185
+ categoryBreakdown[cat] = {
186
+ total: s.total, verified: s.verified,
187
+ detected: s.detected, matched: s.matched,
188
+ recall: s.total > 0 ? s.detected / s.total : 0,
189
+ precision: s.detected > 0 ? s.matched / s.detected : 0,
190
+ };
191
+ }
192
+ return {
193
+ benchmark: bench.name,
194
+ totalCases: total,
195
+ verifiedCases: verifiedTotal,
196
+ overallRecall, overallPrecision,
197
+ byCategory: categoryBreakdown,
198
+ verifiedOnly: { total: verifiedTotal, detected: verifiedDetected, recall: verifiedRecall, precision: verifiedPrecision },
199
+ parserNoiseGap: parserGap,
200
+ verdict: verifiedRecall > 0.85
201
+ ? "✅ PROTOCOL LIFECYCLE SECURITY — verified performance exceeds 85%"
202
+ : verifiedRecall > 0.7
203
+ ? "⚠️ PROMISING — verified recall >70%, needs more cases"
204
+ : "❌ INSUFFICIENT — core detector performance below threshold",
205
+ };
206
+ }
207
+ function printProtocolSecurityReport(report) {
208
+ console.log(`\n╔════════════════════════════════════════════════════╗`);
209
+ console.log(`║ ${report.benchmark}`);
210
+ console.log(`║ ${report.totalCases} cases (${report.verifiedCases} manually verified)`);
211
+ console.log(`╚════════════════════════════════════════════════════╝\n`);
212
+ console.log(` Overall: recall ${(report.overallRecall * 100).toFixed(0)}% precision ${(report.overallPrecision * 100).toFixed(0)}%`);
213
+ console.log(` Verified: recall ${(report.verifiedOnly.recall * 100).toFixed(0)}% precision ${(report.verifiedOnly.precision * 100).toFixed(0)}%`);
214
+ console.log(` Parser gap: ${(report.parserNoiseGap * 100).toFixed(0)}% (noise in CVE→sequence conversion)`);
215
+ console.log();
216
+ console.log(` ── Per Category ──`);
217
+ for (const [cat, s] of Object.entries(report.byCategory)) {
218
+ const vMark = s.verified > 0 ? ` (${s.verified} verified)` : "";
219
+ console.log(` ${cat.padEnd(22)} ${String(s.total).padStart(3)} cases${vMark.padEnd(14)} recall ${(s.recall * 100).toFixed(0).padStart(3)}% precision ${(s.precision * 100).toFixed(0)}%`);
220
+ }
221
+ console.log(`\n Verdict: ${report.verdict}\n`);
222
+ }
@@ -0,0 +1,257 @@
1
+ "use strict";
2
+ /**
3
+ * P9.0: Protocol Structure → Vulnerability Prediction
4
+ *
5
+ * THE decisive question: does protocol TOPOLOGY carry enough information
6
+ * to predict defects WITHOUT seeing function names, code, or comments?
7
+ *
8
+ * If yes: protocol structure contains security information.
9
+ * If no: structure is real but semantically empty.
10
+ *
11
+ * Experiment design:
12
+ * 1. For each of 10 topologies, generate CLEAN (complete) and BROKEN
13
+ * (missing-step, wrong-order) sequences
14
+ * 2. Extract WL fingerprints from both
15
+ * 3. Train a simple nearest-centroid classifier on 7 topologies
16
+ * 4. Test zero-shot on 3 held-out topologies
17
+ * 5. Measure: precision, recall, F1 on held-out set
18
+ *
19
+ * Baseline: random guess = 50% (binary classification: clean/broken)
20
+ * Target: >70% F1 on held-out topologies
21
+ */
22
+ Object.defineProperty(exports, "__esModule", { value: true });
23
+ exports.buildWLDefectDataset = buildWLDefectDataset;
24
+ exports.runZeroShotDefectPrediction = runZeroShotDefectPrediction;
25
+ exports.printDefectReport = printDefectReport;
26
+ const topology_factory_1 = require("./topology-factory");
27
+ const state_inference_1 = require("./experimental/state-inference");
28
+ const wl_fingerprint_1 = require("./wl-fingerprint");
29
+ /**
30
+ * Generate clean sequences (valid random walks through the state machine).
31
+ */
32
+ function generateCleanSequences(rules, count) {
33
+ const entries = [...rules.entries()];
34
+ const sequences = [];
35
+ for (let i = 0; i < count; i++) {
36
+ const targetLen = 2 + Math.floor(Math.random() * 4); // 2-5 steps
37
+ const path = [];
38
+ const visited = new Set();
39
+ // Start from any rule
40
+ const startIdx = Math.floor(Math.random() * entries.length);
41
+ path.push(entries[startIdx][0]);
42
+ const stateSet = new Set(["INIT", "IDLE"]);
43
+ const rule = entries[startIdx][1];
44
+ if (rule.invalidate)
45
+ rule.invalidate.forEach((s) => stateSet.delete(s));
46
+ for (const s of rule.post_states)
47
+ stateSet.add(s);
48
+ let currentFn = path[0];
49
+ while (path.length < targetLen) {
50
+ const candidates = entries.filter(([fn, r]) => !visited.has(fn) && r.pre_states.every((s) => stateSet.has(s)));
51
+ if (candidates.length === 0)
52
+ break;
53
+ const [nextFn, nextRule] = candidates[Math.floor(Math.random() * candidates.length)];
54
+ path.push(nextFn);
55
+ visited.add(nextFn);
56
+ if (nextRule.invalidate)
57
+ nextRule.invalidate.forEach((s) => stateSet.delete(s));
58
+ for (const s of nextRule.post_states)
59
+ stateSet.add(s);
60
+ currentFn = nextFn;
61
+ }
62
+ if (path.length >= 2)
63
+ sequences.push(path);
64
+ }
65
+ return sequences;
66
+ }
67
+ /**
68
+ * Generate broken sequences by removing a step or inserting a wrong step.
69
+ *
70
+ * Broken variants:
71
+ * 1. REMOVE: drop the last step (incomplete lifecycle)
72
+ * 2. SKIP: skip a middle step (jump over a state)
73
+ */
74
+ function generateBrokenSequences(rules, count) {
75
+ const clean = generateCleanSequences(rules, Math.ceil(count * 1.5));
76
+ const broken = [];
77
+ for (const seq of clean) {
78
+ if (broken.length >= count)
79
+ break;
80
+ // REMOVE last step (resource leak / missing close / missing commit)
81
+ if (seq.length >= 3) {
82
+ broken.push(seq.slice(0, -1));
83
+ }
84
+ // SKIP: remove a middle step if long enough
85
+ if (seq.length >= 4 && broken.length < count) {
86
+ const mid = 1 + Math.floor(Math.random() * (seq.length - 2));
87
+ broken.push([...seq.slice(0, mid), ...seq.slice(mid + 1)]);
88
+ }
89
+ // WRONG ORDER: swap two adjacent steps
90
+ if (seq.length >= 3 && broken.length < count) {
91
+ const swapIdx = Math.floor(Math.random() * (seq.length - 1));
92
+ const swapped = [...seq];
93
+ [swapped[swapIdx], swapped[swapIdx + 1]] = [swapped[swapIdx + 1], swapped[swapIdx]];
94
+ broken.push(swapped);
95
+ }
96
+ }
97
+ return broken.slice(0, count);
98
+ }
99
+ // ═══════════════════════════════════════════════════════════════
100
+ // Dataset construction
101
+ // ═══════════════════════════════════════════════════════════════
102
+ /**
103
+ * Build a labeled dataset of WL fingerprints from protocol topologies.
104
+ *
105
+ * @param topologies Which topologies to include
106
+ * @param perClass Samples per class per topology
107
+ */
108
+ function buildWLDefectDataset(topologies, perClass = 10) {
109
+ const samples = [];
110
+ for (const topo of topologies) {
111
+ const rules = (0, topology_factory_1.createProtocolForTopology)(topo);
112
+ if (rules.size === 0)
113
+ continue;
114
+ const cleanSeqs = generateCleanSequences(rules, perClass);
115
+ const brokenSeqs = generateBrokenSequences(rules, perClass);
116
+ for (const seq of cleanSeqs) {
117
+ const sm = (0, state_inference_1.inferStateMachine)(seq.map(fn => [fn]));
118
+ const wl = (0, wl_fingerprint_1.extractWLFingerprint)(sm, 3);
119
+ samples.push({ topology: topo, label: "clean", wl });
120
+ }
121
+ for (const seq of brokenSeqs) {
122
+ const sm = (0, state_inference_1.inferStateMachine)(seq.map(fn => [fn]));
123
+ const wl = (0, wl_fingerprint_1.extractWLFingerprint)(sm, 3);
124
+ samples.push({ topology: topo, label: "broken", wl });
125
+ }
126
+ }
127
+ return samples;
128
+ }
129
+ // ═══════════════════════════════════════════════════════════════
130
+ // Nearest-centroid classifier (simplest possible, no overfitting risk)
131
+ // ═══════════════════════════════════════════════════════════════
132
+ function meanVector(vectors) {
133
+ const dims = vectors[0].length;
134
+ const mean = new Array(dims).fill(0);
135
+ for (const v of vectors) {
136
+ for (let i = 0; i < dims; i++)
137
+ mean[i] += v[i];
138
+ }
139
+ for (let i = 0; i < dims; i++)
140
+ mean[i] /= vectors.length;
141
+ return mean;
142
+ }
143
+ function cosineSim(a, b) {
144
+ let dot = 0, normA = 0, normB = 0;
145
+ for (let i = 0; i < a.length; i++) {
146
+ dot += a[i] * b[i];
147
+ normA += a[i] * a[i];
148
+ normB += b[i] * b[i];
149
+ }
150
+ if (normA === 0 && normB === 0)
151
+ return 1;
152
+ if (normA === 0 || normB === 0)
153
+ return 0;
154
+ return dot / (Math.sqrt(normA) * Math.sqrt(normB));
155
+ }
156
+ /**
157
+ * Train on some topologies, test zero-shot on held-out ones.
158
+ *
159
+ * Uses nearest-centroid: compute the mean WL vector for "clean" and
160
+ * "broken" classes from training topologies, then classify test
161
+ * samples by which centroid is closer.
162
+ */
163
+ function runZeroShotDefectPrediction(trainTopos, testTopos, samplesPerClass = 10) {
164
+ // Build training set
165
+ const trainSamples = buildWLDefectDataset(trainTopos, samplesPerClass);
166
+ const cleanVectors = trainSamples.filter(s => s.label === "clean").map(s => s.wl.vector);
167
+ const brokenVectors = trainSamples.filter(s => s.label === "broken").map(s => s.wl.vector);
168
+ if (cleanVectors.length === 0 || brokenVectors.length === 0) {
169
+ return {
170
+ trainTopos, testTopos, samples: samplesPerClass,
171
+ accuracy: 0, precision: 0, recall: 0, f1: 0,
172
+ perTopology: {}, confusion: { tp: 0, fp: 0, tn: 0, fn: 0 },
173
+ };
174
+ }
175
+ // Compute centroids
176
+ const cleanCentroid = meanVector(cleanVectors);
177
+ const brokenCentroid = meanVector(brokenVectors);
178
+ // Test on held-out topologies
179
+ const testSamples = buildWLDefectDataset(testTopos, samplesPerClass);
180
+ let tp = 0, fp = 0, tn = 0, fn = 0;
181
+ const perTopology = {};
182
+ for (const sample of testSamples) {
183
+ const distClean = 1 - cosineSim(sample.wl.vector, cleanCentroid);
184
+ const distBroken = 1 - cosineSim(sample.wl.vector, brokenCentroid);
185
+ const predicted = distClean < distBroken ? "clean" : "broken";
186
+ if (!perTopology[sample.topology]) {
187
+ perTopology[sample.topology] = { correct: 0, total: 0, tp: 0, fp: 0, tn: 0, fn: 0 };
188
+ }
189
+ perTopology[sample.topology].total++;
190
+ if (predicted === sample.label)
191
+ perTopology[sample.topology].correct++;
192
+ if (sample.label === "broken" && predicted === "broken") {
193
+ tp++;
194
+ perTopology[sample.topology].tp++;
195
+ }
196
+ else if (sample.label === "clean" && predicted === "broken") {
197
+ fp++;
198
+ perTopology[sample.topology].fp++;
199
+ }
200
+ else if (sample.label === "clean" && predicted === "clean") {
201
+ tn++;
202
+ perTopology[sample.topology].tn++;
203
+ }
204
+ else if (sample.label === "broken" && predicted === "clean") {
205
+ fn++;
206
+ perTopology[sample.topology].fn++;
207
+ }
208
+ }
209
+ const total = tp + fp + tn + fn;
210
+ const accuracy = total > 0 ? (tp + tn) / total : 0;
211
+ const precision = (tp + fp) > 0 ? tp / (tp + fp) : 0;
212
+ const recall = (tp + fn) > 0 ? tp / (tp + fn) : 0;
213
+ const f1 = (precision + recall) > 0 ? 2 * precision * recall / (precision + recall) : 0;
214
+ return {
215
+ trainTopos, testTopos, samples: samplesPerClass,
216
+ accuracy, precision, recall, f1,
217
+ perTopology: Object.fromEntries(Object.entries(perTopology).map(([k, v]) => [
218
+ k,
219
+ {
220
+ accuracy: v.total > 0 ? v.correct / v.total : 0,
221
+ f1: (v.tp + v.fp + v.fn) > 0
222
+ ? 2 * (v.tp / Math.max(1, v.tp + v.fp)) * (v.tp / Math.max(1, v.tp + v.fn))
223
+ / ((v.tp / Math.max(1, v.tp + v.fp)) + (v.tp / Math.max(1, v.tp + v.fn)))
224
+ : 0,
225
+ },
226
+ ])),
227
+ confusion: { tp, fp, tn, fn },
228
+ };
229
+ }
230
+ function printDefectReport(report) {
231
+ console.log("\n╔════════════════════════════════════════════════════╗");
232
+ console.log("║ P9.0 Protocol → Defect Prediction (Zero-Shot) ║");
233
+ console.log("╚════════════════════════════════════════════════════╝\n");
234
+ console.log(` Train: ${report.trainTopos.join(", ")}`);
235
+ console.log(` Test: ${report.testTopos.join(", ")}`);
236
+ console.log(` Samples per topology: ${report.samples}`);
237
+ console.log();
238
+ console.log(` Accuracy: ${(report.accuracy * 100).toFixed(0)}%`);
239
+ console.log(` Precision: ${(report.precision * 100).toFixed(0)}% (broken class)`);
240
+ console.log(` Recall: ${(report.recall * 100).toFixed(0)}% (broken class)`);
241
+ console.log(` F1: ${(report.f1 * 100).toFixed(0)}%`);
242
+ console.log();
243
+ console.log(` Confusion: TP=${report.confusion.tp} FP=${report.confusion.fp} TN=${report.confusion.tn} FN=${report.confusion.fn}`);
244
+ console.log();
245
+ console.log(` Per-topology:`);
246
+ for (const [topo, stats] of Object.entries(report.perTopology)) {
247
+ console.log(` ${topo.padEnd(18)} acc=${(stats.accuracy * 100).toFixed(0)}% f1=${(stats.f1 * 100).toFixed(0)}%`);
248
+ }
249
+ const baseline = 0.5; // random chance
250
+ const improvement = report.f1 - baseline;
251
+ const verdict = report.f1 > 0.7 ? "✅ PROTOCOL STRUCTURE PREDICTS DEFECTS"
252
+ : report.f1 > baseline + 0.1 ? "⚠️ WEAK SIGNAL — above random, below useful"
253
+ : "❌ No predictive power — structure alone insufficient";
254
+ console.log(`\n Baseline (random): 50%`);
255
+ console.log(` Improvement: ${improvement > 0 ? '+' : ''}${(improvement * 100).toFixed(0)}%`);
256
+ console.log(` Verdict: ${verdict}\n`);
257
+ }
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ /**
4
+ * P9.0: Protocol Structure → Defect Prediction Test
5
+ *
6
+ * THE decisive question: can WL fingerprints of protocol state machines
7
+ * predict whether a sequence has a defect (missing step, wrong order)
8
+ * WITHOUT seeing function names, code, or comments?
9
+ */
10
+ const vitest_1 = require("vitest");
11
+ const protocol_vulnerability_1 = require("./protocol-vulnerability");
12
+ const topology_factory_1 = require("./topology-factory");
13
+ (0, vitest_1.describe)("P9.0 Protocol → Vulnerability Prediction", () => {
14
+ (0, vitest_1.it)("builds WL defect dataset from protocol topologies", () => {
15
+ const samples = (0, protocol_vulnerability_1.buildWLDefectDataset)(["linear", "star", "loop"], 5);
16
+ (0, vitest_1.expect)(samples.length).toBeGreaterThanOrEqual(20);
17
+ const clean = samples.filter(s => s.label === "clean").length;
18
+ const broken = samples.filter(s => s.label === "broken").length;
19
+ (0, vitest_1.expect)(clean).toBeGreaterThan(0);
20
+ (0, vitest_1.expect)(broken).toBeGreaterThan(0);
21
+ // All samples should have valid WL fingerprints
22
+ for (const s of samples) {
23
+ (0, vitest_1.expect)(s.wl.vector.length).toBe(256);
24
+ (0, vitest_1.expect)(s.wl.uniqueLabels).toBeGreaterThan(0);
25
+ }
26
+ });
27
+ (0, vitest_1.it)("ZERO-SHOT: train on 7 topologies, test on 3 held-out", () => {
28
+ // Leave out 3 topologies for zero-shot testing
29
+ const trainTopos = topology_factory_1.ALL_TOPOLOGIES.slice(0, 7);
30
+ const testTopos = topology_factory_1.ALL_TOPOLOGIES.slice(7);
31
+ const report = (0, protocol_vulnerability_1.runZeroShotDefectPrediction)(trainTopos, testTopos, 10);
32
+ (0, protocol_vulnerability_1.printDefectReport)(report);
33
+ // Must be better than random (50%)
34
+ (0, vitest_1.expect)(report.accuracy).toBeGreaterThan(0.5);
35
+ });
36
+ (0, vitest_1.it)("FULL CROSS-VALIDATION: average over 3 random splits", () => {
37
+ const shuffled = [...topology_factory_1.ALL_TOPOLOGIES].sort(() => Math.random() - 0.5);
38
+ const splits = [
39
+ { train: shuffled.slice(0, 7), test: shuffled.slice(7) },
40
+ { train: shuffled.slice(3), test: shuffled.slice(0, 3) },
41
+ { train: [...shuffled.slice(0, 4), ...shuffled.slice(7)], test: shuffled.slice(4, 7) },
42
+ ];
43
+ let totalF1 = 0;
44
+ const results = [];
45
+ for (const { train, test } of splits) {
46
+ const report = (0, protocol_vulnerability_1.runZeroShotDefectPrediction)(train, test, 8);
47
+ totalF1 += report.f1;
48
+ results.push({ testTopos: test, accuracy: report.accuracy, f1: report.f1 });
49
+ }
50
+ const avgF1 = totalF1 / splits.length;
51
+ console.log(`\n ═══ 3-FOLD CROSS-VALIDATION ═══`);
52
+ for (const r of results) {
53
+ console.log(` Test: ${r.testTopos.join(",").padEnd(35)} acc=${(r.accuracy * 100).toFixed(0)}% f1=${(r.f1 * 100).toFixed(0)}%`);
54
+ }
55
+ console.log(` Average F1: ${(avgF1 * 100).toFixed(0)}%`);
56
+ console.log(` Baseline (random): 50%`);
57
+ // Average F1 should exceed random baseline
58
+ (0, vitest_1.expect)(avgF1).toBeGreaterThan(0.5);
59
+ });
60
+ });
@@ -0,0 +1,120 @@
1
+ "use strict";
2
+ /**
3
+ * Phase 2: Python Detection Benchmark Runner
4
+ *
5
+ * Runs protocol detection + safeguard detection on Python projects,
6
+ * compares against labeled data, reports Precision/Recall/F1.
7
+ *
8
+ * Usage: npx ts-node src/python-benchmark.ts [projectPath]
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.runPythonBenchmark = runPythonBenchmark;
45
+ exports.loadLabels = loadLabels;
46
+ const fs = __importStar(require("fs"));
47
+ const path = __importStar(require("path"));
48
+ const sequence_extractor_1 = require("./sequence-extractor");
49
+ const protocol_detector_1 = require("./protocol-detector");
50
+ const protocol_detector_2 = require("./protocol-detector");
51
+ const resource_detector_1 = require("./resource-detector");
52
+ function loadLabels(labelsPath) {
53
+ if (!fs.existsSync(labelsPath))
54
+ return [];
55
+ return JSON.parse(fs.readFileSync(labelsPath, "utf-8"));
56
+ }
57
+ function runPythonBenchmark(projectPath, labelsPath) {
58
+ const sequences = (0, sequence_extractor_1.extractSequences)(projectPath, { maxBodyLines: 200 });
59
+ const labels = loadLabels(labelsPath);
60
+ // Build label lookup
61
+ const labelMap = new Map();
62
+ for (const l of labels) {
63
+ labelMap.set(`${l.filePath}:${l.functionName}`, l);
64
+ }
65
+ let tp = 0, fp = 0, fn = 0, tn = 0;
66
+ for (const seq of sequences) {
67
+ const key = `${seq.filePath}:${seq.functionName}`;
68
+ const label = labelMap.get(key);
69
+ const hasLabelViolation = label?.hasViolation ?? false;
70
+ // Run detection
71
+ const protoViolations = (0, protocol_detector_1.detectProtocolViolations)(seq.calls);
72
+ const safeViolations = (0, protocol_detector_2.detectSafeguardViolations)(seq.calls, seq.functionName, "python");
73
+ const resResult = (0, resource_detector_1.validateResourceLifecycle)(seq.calls);
74
+ const resViolations = resResult.violations || [];
75
+ const totalViolations = protoViolations.length + safeViolations.length + resViolations.length;
76
+ const detected = totalViolations > 0;
77
+ if (detected && hasLabelViolation)
78
+ tp++;
79
+ else if (detected && !hasLabelViolation)
80
+ fp++;
81
+ else if (!detected && hasLabelViolation)
82
+ fn++;
83
+ else
84
+ tn++;
85
+ }
86
+ const precision = tp + fp > 0 ? tp / (tp + fp) : 0;
87
+ const recall = tp + fn > 0 ? tp / (tp + fn) : 0;
88
+ const f1 = precision + recall > 0 ? 2 * (precision * recall) / (precision + recall) : 0;
89
+ // Check for unlabeled functions → treat as true negatives
90
+ const unlabeledCount = sequences.length - labels.length;
91
+ return {
92
+ precision: Math.round(precision * 1000) / 10,
93
+ recall: Math.round(recall * 1000) / 10,
94
+ f1: Math.round(f1 * 1000) / 10,
95
+ tp, fp, fn,
96
+ totalFunctions: sequences.length,
97
+ totalViolations: tp + fp,
98
+ };
99
+ }
100
+ // ── Main ──
101
+ if (require.main === module) {
102
+ const projectPath = process.argv[2] || path.join(__dirname, "..", "test-python-protocol");
103
+ const labelsPath = process.argv[3] || path.join(__dirname, "..", "benchmarks", "python-labels.json");
104
+ console.log(`Python Benchmark Runner`);
105
+ console.log(`Project: ${projectPath}`);
106
+ console.log(`Labels: ${labelsPath}`);
107
+ console.log("");
108
+ if (!fs.existsSync(projectPath)) {
109
+ console.error(`Project path not found: ${projectPath}`);
110
+ process.exit(1);
111
+ }
112
+ const result = runPythonBenchmark(projectPath, labelsPath);
113
+ console.log(`Functions: ${result.totalFunctions}`);
114
+ console.log(`Detected: ${result.totalViolations}`);
115
+ console.log(`TP: ${result.tp} FP: ${result.fp} FN: ${result.fn}`);
116
+ console.log(`Precision: ${result.precision}%`);
117
+ console.log(`Recall: ${result.recall}%`);
118
+ console.log(`F1: ${result.f1}%`);
119
+ process.exit(0);
120
+ }