progmune-runtime 2.1.6 → 3.2.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 (356) hide show
  1. package/README.md +119 -461
  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 +721 -0
  306. package/package.json +73 -6
  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
@@ -175,15 +175,52 @@ function saveSemantic(templates) {
175
175
  }
176
176
  function consolidateSemantic(minOccurrences = 3) {
177
177
  const episodes = getSuccessfulEpisodes(MAX_EPISODES);
178
+ // Extract the first 3 meaningful keywords as the grouping key
179
+ // (replaces fragile 20-char prefix — two intents with the same first
180
+ // 3 keywords are far more likely to be semantically similar)
181
+ function keywordKey(intent) {
182
+ const words = intent
183
+ .toLowerCase()
184
+ .split(/[\s,,、。!?:;]+/)
185
+ .filter(w => w.length > 2 && !["the", "and", "for", "with", "from", "that", "this"].includes(w));
186
+ return words.slice(0, 3).join("|");
187
+ }
188
+ // Group episodes by keyword key
178
189
  const grouped = new Map();
179
190
  for (const ep of episodes) {
180
- const pattern = ep.intent.substring(0, 20);
181
- if (!grouped.has(pattern))
182
- grouped.set(pattern, []);
183
- grouped.get(pattern).push(ep);
191
+ const key = keywordKey(ep.intent);
192
+ if (!key)
193
+ continue; // skip intents too short to produce keywords
194
+ if (!grouped.has(key))
195
+ grouped.set(key, []);
196
+ grouped.get(key).push(ep);
197
+ }
198
+ // Merge small groups into larger ones by Jaccard overlap
199
+ const keys = [...grouped.keys()];
200
+ const merged = new Map();
201
+ const processed = new Set();
202
+ for (const k of keys) {
203
+ if (processed.has(k))
204
+ continue;
205
+ const cluster = [...grouped.get(k)];
206
+ processed.add(k);
207
+ // Find nearby groups with high keyword overlap
208
+ for (const other of keys) {
209
+ if (processed.has(other))
210
+ continue;
211
+ const kWords = new Set(k.split("|").filter(w => w.length > 0));
212
+ const oWords = new Set(other.split("|").filter(w => w.length > 0));
213
+ const intersection = [...kWords].filter(w => oWords.has(w)).length;
214
+ const union = new Set([...kWords, ...oWords]).size;
215
+ if (union > 0 && intersection / union >= 0.5) {
216
+ cluster.push(...grouped.get(other));
217
+ processed.add(other);
218
+ }
219
+ }
220
+ merged.set(k, cluster);
184
221
  }
185
222
  const templates = loadSemantic();
186
- for (const [pattern, eps] of grouped) {
223
+ for (const [pattern, eps] of merged) {
187
224
  if (eps.length >= minOccurrences) {
188
225
  const existing = templates.find(t => t.intentPattern === pattern);
189
226
  if (existing) {
@@ -0,0 +1,422 @@
1
+ "use strict";
2
+ /**
3
+ * P0: Multi-Repository SSG Precision Validation
4
+ *
5
+ * Runs SSG protocol extraction + precision measurement across
6
+ * multiple real-world repositories. Generates a transparent,
7
+ * reproducible precision report.
8
+ *
9
+ * Target repos: curl, nginx, redis, sqlite, libuv
10
+ * (small → medium → large)
11
+ *
12
+ * Usage:
13
+ * npx ts-node src/multi-repo-precision.ts
14
+ * npx ts-node src/multi-repo-precision.ts --repos curl,redis
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.runMultiRepoPrecision = runMultiRepoPrecision;
51
+ exports.formatMultiRepoReportTerminal = formatMultiRepoReportTerminal;
52
+ exports.exportMultiRepoReportJSON = exportMultiRepoReportJSON;
53
+ const fs = __importStar(require("fs"));
54
+ const path = __importStar(require("path"));
55
+ const child_process_1 = require("child_process");
56
+ const extract_ir_1 = require("./extract-ir");
57
+ const ssg_precision_1 = require("./ssg-precision");
58
+ // Default targets — local repos + external repos (auto-cloned)
59
+ const DEFAULT_TARGETS = [
60
+ {
61
+ name: "progmune-self",
62
+ size: "small",
63
+ localPath: process.cwd(),
64
+ expectedProtocols: ["extractIR", "validateAction", "emitCode", "recordSession", "checkLedgerConsistency"],
65
+ },
66
+ {
67
+ name: "demo-xlike",
68
+ size: "small",
69
+ localPath: path.resolve(process.cwd(), "demo-xlike"),
70
+ expectedProtocols: ["insertPost", "getRecentPosts", "deletePost", "validatePostContent", "initDatabase"],
71
+ },
72
+ // External precision-program repos (auto-cloned into benchmarks/)
73
+ {
74
+ name: "curl",
75
+ size: "medium",
76
+ localPath: path.resolve(process.cwd(), "benchmarks", "curl"),
77
+ expectedProtocols: ["curl_easy_init", "curl_easy_perform", "curl_easy_cleanup", "curl_easy_setopt"],
78
+ },
79
+ {
80
+ name: "nginx",
81
+ size: "large",
82
+ localPath: path.resolve(process.cwd(), "benchmarks", "nginx"),
83
+ expectedProtocols: ["ngx_http_init_connection", "ngx_http_process_request", "ngx_http_finalize_request"],
84
+ },
85
+ {
86
+ name: "redis",
87
+ size: "medium",
88
+ localPath: path.resolve(process.cwd(), "benchmarks", "redis"),
89
+ expectedProtocols: ["createClient", "readQueryFromClient", "freeClient", "processCommand"],
90
+ },
91
+ ];
92
+ const EXTERNAL_REPOS = {
93
+ curl: { url: "https://github.com/curl/curl.git", depth: 100 },
94
+ nginx: { url: "https://github.com/nginx/nginx.git", depth: 100 },
95
+ redis: { url: "https://github.com/redis/redis.git", depth: 100 },
96
+ };
97
+ /** Clone or pull an external repo into benchmarks/<name>/ */
98
+ function ensureRepo(name) {
99
+ const dir = path.resolve(process.cwd(), "benchmarks", name);
100
+ if (fs.existsSync(path.join(dir, ".git"))) {
101
+ console.error(` ↻ Updating ${name}...`);
102
+ try {
103
+ (0, child_process_1.execSync)(`cd ${dir} && git pull --ff-only 2>/dev/null || true`, { stdio: "ignore", timeout: 30000 });
104
+ }
105
+ catch { /* skip */ }
106
+ }
107
+ else {
108
+ const cfg = EXTERNAL_REPOS[name];
109
+ if (!cfg)
110
+ throw new Error(`No clone URL for: ${name}`);
111
+ console.error(` ↓ Cloning ${name} (depth=${cfg.depth || 100})...`);
112
+ const parent = path.dirname(dir);
113
+ if (!fs.existsSync(parent))
114
+ fs.mkdirSync(parent, { recursive: true });
115
+ (0, child_process_1.execSync)(`git clone --depth=${cfg.depth || 100} ${cfg.url} ${dir}`, { stdio: "ignore", timeout: 120000 });
116
+ }
117
+ return dir;
118
+ }
119
+ // ═══════════════════════════════════════════════════════════════
120
+ // Engine
121
+ // ═══════════════════════════════════════════════════════════════
122
+ function countLinesOfCode(dir) {
123
+ let count = 0;
124
+ try {
125
+ const files = walkFiles(dir, [".ts", ".js", ".c", ".h", ".py"]);
126
+ for (const f of files) {
127
+ try {
128
+ count += fs.readFileSync(f, "utf-8").split("\n").length;
129
+ }
130
+ catch { /* skip */ }
131
+ }
132
+ }
133
+ catch { /* skip */ }
134
+ return count;
135
+ }
136
+ function walkFiles(dir, exts) {
137
+ const results = [];
138
+ try {
139
+ for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
140
+ if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "dist")
141
+ continue;
142
+ const full = path.join(dir, entry.name);
143
+ if (entry.isDirectory()) {
144
+ results.push(...walkFiles(full, exts));
145
+ }
146
+ else if (exts.some(e => entry.name.endsWith(e))) {
147
+ results.push(full);
148
+ }
149
+ }
150
+ }
151
+ catch { /* skip */ }
152
+ return results;
153
+ }
154
+ /** Extract call sequences from IR: group functions by file, build adjacency pairs */
155
+ function extractCallSequences(ir) {
156
+ const sequences = [];
157
+ const funcNames = ir.map((f) => f.name);
158
+ // Build sequences from IR: each protocol chain is a sequence
159
+ // For functions with protocol annotations, extract the implied sequence
160
+ for (const fn of ir) {
161
+ if (fn.protocol) {
162
+ const seq = [];
163
+ if (fn.protocol.pre_states)
164
+ seq.push(...fn.protocol.pre_states);
165
+ seq.push(fn.name);
166
+ if (fn.protocol.post_states)
167
+ seq.push(...fn.protocol.post_states);
168
+ if (seq.length >= 2)
169
+ sequences.push(seq);
170
+ }
171
+ }
172
+ // If no protocol annotations, build adjacency pairs from function names
173
+ if (sequences.length === 0 && funcNames.length >= 2) {
174
+ // Group by common prefixes (e.g., "open_", "close_", "read_", "write_")
175
+ const groups = groupByPrefix(funcNames);
176
+ for (const [, fns] of Object.entries(groups)) {
177
+ if (fns.length >= 2) {
178
+ sequences.push(fns);
179
+ }
180
+ }
181
+ }
182
+ // Fallback: create sequences from all function pairs in same file
183
+ if (sequences.length === 0) {
184
+ sequences.push(funcNames.slice(0, 10));
185
+ }
186
+ return sequences;
187
+ }
188
+ function groupByPrefix(names) {
189
+ const groups = {};
190
+ for (const name of names) {
191
+ // Extract prefix: everything before the last underscore or verb
192
+ const parts = name.split("_");
193
+ const prefix = parts.length >= 2 ? parts.slice(0, -1).join("_") : name;
194
+ if (!groups[prefix])
195
+ groups[prefix] = [];
196
+ groups[prefix].push(name);
197
+ }
198
+ // Only keep groups with >= 2 members
199
+ const result = {};
200
+ for (const [k, v] of Object.entries(groups)) {
201
+ if (v.length >= 2)
202
+ result[k] = v;
203
+ }
204
+ return result;
205
+ }
206
+ function runRepoPrecision(target) {
207
+ const errors = [];
208
+ // Auto-clone external repos
209
+ let dir = target.localPath || process.cwd();
210
+ if (EXTERNAL_REPOS[target.name] && !fs.existsSync(path.join(dir, ".git"))) {
211
+ try {
212
+ dir = ensureRepo(target.name);
213
+ }
214
+ catch (e) {
215
+ errors.push(`Clone failed: ${e.message}`);
216
+ }
217
+ }
218
+ // 1. Count lines of code
219
+ const loc = countLinesOfCode(dir);
220
+ // 2. Extract IR
221
+ let ir = [];
222
+ try {
223
+ ir = (0, extract_ir_1.extractIR)(dir);
224
+ }
225
+ catch (e) {
226
+ errors.push(`IR extraction: ${e.message}`);
227
+ }
228
+ // 3. Extract call sequences
229
+ const sequences = extractCallSequences(ir);
230
+ // 4. Discover protocol rules
231
+ let rulesDiscovered = 0;
232
+ let protocolsFound = [];
233
+ let cveMatched = 0;
234
+ try {
235
+ const cleanSeqs = sequences.filter(s => s.length >= 2);
236
+ if (cleanSeqs.length > 0) {
237
+ const { rules, nsInit } = (0, ssg_precision_1.discoverRulesFromSequences)(cleanSeqs);
238
+ rulesDiscovered = rules.size;
239
+ protocolsFound = [...rules.keys()];
240
+ // Check PLSB coverage: which known CVE patterns appear?
241
+ const { PROTOCOL_WEAKNESS_TAXONOMY } = require("./plsb-benchmark");
242
+ for (const t of PROTOCOL_WEAKNESS_TAXONOMY) {
243
+ for (const seq of sequences) {
244
+ const hasMatch = t.example_broken.some((step) => seq.some((s) => s.toLowerCase().includes(step.toLowerCase())));
245
+ if (hasMatch) {
246
+ cveMatched++;
247
+ break;
248
+ }
249
+ }
250
+ }
251
+ }
252
+ }
253
+ catch (e) {
254
+ errors.push(`Rule discovery: ${e.message}`);
255
+ }
256
+ // 5. Run precision (if we have both clean and violation-labeled sequences)
257
+ let precision;
258
+ let annotatedSamples = 0;
259
+ let needsAnnotation = true;
260
+ try {
261
+ // Check for hand-labeled data
262
+ const labelPath = path.join(dir, ".progmune_labels.json");
263
+ if (fs.existsSync(labelPath)) {
264
+ const labels = JSON.parse(fs.readFileSync(labelPath, "utf-8"));
265
+ annotatedSamples = Object.keys(labels).length;
266
+ // Run SSG precision with labels
267
+ const { runSSGPrecisionBenchmark, discoverRulesFromSequences } = require("./ssg-precision");
268
+ const labeledSeqs = sequences.map((calls, i) => ({ index: i, calls, functionName: calls[0] || `seq_${i}` }));
269
+ const result = runSSGPrecisionBenchmark(labeledSeqs, labels);
270
+ precision = {
271
+ total: result.total,
272
+ truePositive: result.truePositive,
273
+ falsePositive: result.falsePositive,
274
+ trueNegative: result.trueNegative,
275
+ falseNegative: result.falseNegative,
276
+ precision: result.precision,
277
+ recall: result.recall,
278
+ f1: result.f1,
279
+ };
280
+ needsAnnotation = result.total === 0;
281
+ }
282
+ }
283
+ catch (e) {
284
+ errors.push(`Precision benchmark: ${e.message}`);
285
+ }
286
+ return {
287
+ repo: target.name,
288
+ size: target.size,
289
+ linesOfCode: loc,
290
+ functionsExtracted: ir.length,
291
+ sequencesExtracted: sequences.length,
292
+ rulesDiscovered,
293
+ precision,
294
+ protocolsFound: protocolsFound.slice(0, 20),
295
+ cvePatternsMatched: cveMatched,
296
+ annotatedSamples,
297
+ needsAnnotation,
298
+ errors,
299
+ };
300
+ }
301
+ // ═══════════════════════════════════════════════════════════════
302
+ // Report Generator
303
+ // ═══════════════════════════════════════════════════════════════
304
+ function runMultiRepoPrecision(targets = DEFAULT_TARGETS) {
305
+ const repos = [];
306
+ for (const target of targets) {
307
+ console.error(`\n🔍 ${target.name} (${target.size})...`);
308
+ const result = runRepoPrecision(target);
309
+ repos.push(result);
310
+ console.error(` IR: ${result.functionsExtracted} functions`);
311
+ console.error(` Sequences: ${result.sequencesExtracted}`);
312
+ console.error(` Rules: ${result.rulesDiscovered}`);
313
+ if (result.precision) {
314
+ console.error(` Precision: F1=${(result.precision.f1 * 100).toFixed(0)}% (P=${(result.precision.precision * 100).toFixed(0)}%, R=${(result.precision.recall * 100).toFixed(0)}%)`);
315
+ }
316
+ if (result.needsAnnotation) {
317
+ console.error(` ⚠️ Needs hand-labeling (${result.annotatedSamples} samples)`);
318
+ }
319
+ if (result.errors.length) {
320
+ for (const e of result.errors)
321
+ console.error(` ❌ ${e}`);
322
+ }
323
+ }
324
+ // Summary
325
+ const reposWithPrecision = repos.filter(r => r.precision && r.precision.total > 0);
326
+ const avgF1 = reposWithPrecision.length > 0
327
+ ? reposWithPrecision.reduce((s, r) => s + (r.precision?.f1 || 0), 0) / reposWithPrecision.length
328
+ : 0;
329
+ return {
330
+ generated: new Date().toISOString(),
331
+ version: "1.0.0",
332
+ repos,
333
+ summary: {
334
+ totalRepos: repos.length,
335
+ reposWithPrecision: reposWithPrecision.length,
336
+ reposNeedingAnnotation: repos.filter(r => r.needsAnnotation).length,
337
+ averageF1: avgF1,
338
+ totalFunctions: repos.reduce((s, r) => s + r.functionsExtracted, 0),
339
+ totalSequences: repos.reduce((s, r) => s + r.sequencesExtracted, 0),
340
+ totalRules: repos.reduce((s, r) => s + r.rulesDiscovered, 0),
341
+ },
342
+ };
343
+ }
344
+ // ═══════════════════════════════════════════════════════════════
345
+ // Formatters
346
+ // ═══════════════════════════════════════════════════════════════
347
+ function formatMultiRepoReportTerminal(report) {
348
+ const lines = [];
349
+ const C = { reset: "\x1b[0m", bold: "\x1b[1m", dim: "\x1b[2m", green: "\x1b[32m", red: "\x1b[31m", yellow: "\x1b[33m", cyan: "\x1b[36m" };
350
+ lines.push("");
351
+ lines.push(`${C.bold}${C.cyan}╔══════════════════════════════════════════════════════════════╗${C.reset}`);
352
+ lines.push(`${C.bold}${C.cyan}║${C.reset} ${C.bold}Multi-Repo SSG Precision Report${C.reset} ${C.bold}${C.cyan}║${C.reset}`);
353
+ lines.push(`${C.bold}${C.cyan}╚══════════════════════════════════════════════════════════════╝${C.reset}`);
354
+ lines.push("");
355
+ lines.push(` Generated: ${report.generated}`);
356
+ lines.push(` Repos: ${report.summary.totalRepos} (${report.summary.reposWithPrecision} with precision data)`);
357
+ lines.push(` Functions: ${report.summary.totalFunctions} | Sequences: ${report.summary.totalSequences} | Rules: ${report.summary.totalRules}`);
358
+ lines.push(` Avg F1: ${(report.summary.averageF1 * 100).toFixed(0)}%`);
359
+ lines.push("");
360
+ lines.push(` ${C.dim}Repo Size LOC Funcs Seqs Rules F1 Precision Recall Status${C.reset}`);
361
+ lines.push(` ${C.dim}─────────────── ────── ────── ────── ────── ────── ────── ──────── ────── ──────────${C.reset}`);
362
+ for (const r of report.repos) {
363
+ const f1Str = r.precision ? `${(r.precision.f1 * 100).toFixed(0)}%`.padStart(5) : " N/A ";
364
+ const pStr = r.precision ? `${(r.precision.precision * 100).toFixed(0)}%`.padStart(6) : " N/A ";
365
+ const rStr = r.precision ? `${(r.precision.recall * 100).toFixed(0)}%`.padStart(6) : " N/A ";
366
+ const status = r.precision ? `${C.green}MEASURED${C.reset}`
367
+ : r.needsAnnotation ? `${C.yellow}NEEDS LABELS${C.reset}` : `${C.dim}NO DATA${C.reset}`;
368
+ lines.push(` ${r.repo.padEnd(15)} ${r.size.padEnd(6)} ${String(r.linesOfCode).padEnd(6)} ${String(r.functionsExtracted).padEnd(6)} ${String(r.sequencesExtracted).padEnd(6)} ${String(r.rulesDiscovered).padEnd(6)} ${f1Str} ${pStr} ${rStr} ${status}`);
369
+ }
370
+ lines.push("");
371
+ lines.push(` ${C.yellow}⚠️ Repos marked "NEEDS LABELS" require hand-annotated ground truth for precision measurement.${C.reset}`);
372
+ lines.push(` ${C.dim}→ Create .progmune_labels.json in the repo root with format: {"0":"clean","1":"violation",...}${C.reset}`);
373
+ lines.push("");
374
+ if (report.summary.reposNeedingAnnotation > 0) {
375
+ lines.push(` ${C.bold}Next Steps:${C.reset}`);
376
+ lines.push(` 1. Hand-label 20-50 call sequences per repo as "clean" or "violation"`);
377
+ lines.push(` 2. Re-run this benchmark for full precision metrics`);
378
+ lines.push(` 3. Add external repos: curl, nginx, redis, sqlite`);
379
+ lines.push("");
380
+ }
381
+ return lines.join("\n");
382
+ }
383
+ function exportMultiRepoReportJSON(report, outputPath) {
384
+ const json = JSON.stringify(report, null, 2);
385
+ if (outputPath) {
386
+ const dir = path.dirname(outputPath);
387
+ if (!fs.existsSync(dir))
388
+ fs.mkdirSync(dir, { recursive: true });
389
+ fs.writeFileSync(outputPath, json, "utf-8");
390
+ }
391
+ return json;
392
+ }
393
+ // ═══════════════════════════════════════════════════════════════
394
+ // CLI
395
+ // ═══════════════════════════════════════════════════════════════
396
+ if (require.main === module) {
397
+ const args = process.argv.slice(2);
398
+ const reposArg = args.includes("--repos") ? args[args.indexOf("--repos") + 1] : null;
399
+ const all = args.includes("--all");
400
+ const localOnly = args.includes("--local");
401
+ let targets = DEFAULT_TARGETS;
402
+ if (reposArg) {
403
+ const names = new Set(reposArg.split(","));
404
+ targets = DEFAULT_TARGETS.filter(t => names.has(t.name));
405
+ }
406
+ else if (localOnly) {
407
+ targets = DEFAULT_TARGETS.filter(t => !EXTERNAL_REPOS[t.name]);
408
+ }
409
+ else if (all) {
410
+ // all targets including external
411
+ }
412
+ else {
413
+ // default: local only (fast)
414
+ targets = DEFAULT_TARGETS.filter(t => !EXTERNAL_REPOS[t.name]);
415
+ }
416
+ const report = runMultiRepoPrecision(targets);
417
+ console.log(formatMultiRepoReportTerminal(report));
418
+ // Write JSON report
419
+ const outPath = "benchmarks/multi-repo-precision.json";
420
+ exportMultiRepoReportJSON(report, outPath);
421
+ console.error(`\n📁 Report saved: ${outPath}`);
422
+ }