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,442 @@
1
+ "use strict";
2
+ /**
3
+ * Progmune V3.2 — Behavior Mining Engine
4
+ * =======================================
5
+ * 从代码的实际行为(不是方法名)中恢复业务逻辑。
6
+ *
7
+ * 三个核心改进(vs V3.1):
8
+ * 1. CFG-based workflow — 分析函数体内的真实调用序列,不依赖命名
9
+ * 2. Business-layer projection — 将调用图投影到 Controller/Service/Repo 层
10
+ * 3. Decomposed confidence — Frequency × Topology × Consistency
11
+ *
12
+ * 输入: TypeScript 项目路径
13
+ * 输出: BehaviorGraph — 一张包含实体、状态机、业务工作流、约束的治理图谱
14
+ */
15
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
16
+ if (k2 === undefined) k2 = k;
17
+ var desc = Object.getOwnPropertyDescriptor(m, k);
18
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
19
+ desc = { enumerable: true, get: function() { return m[k]; } };
20
+ }
21
+ Object.defineProperty(o, k2, desc);
22
+ }) : (function(o, m, k, k2) {
23
+ if (k2 === undefined) k2 = k;
24
+ o[k2] = m[k];
25
+ }));
26
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
27
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
28
+ }) : function(o, v) {
29
+ o["default"] = v;
30
+ });
31
+ var __importStar = (this && this.__importStar) || (function () {
32
+ var ownKeys = function(o) {
33
+ ownKeys = Object.getOwnPropertyNames || function (o) {
34
+ var ar = [];
35
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
36
+ return ar;
37
+ };
38
+ return ownKeys(o);
39
+ };
40
+ return function (mod) {
41
+ if (mod && mod.__esModule) return mod;
42
+ var result = {};
43
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
44
+ __setModuleDefault(result, mod);
45
+ return result;
46
+ };
47
+ })();
48
+ Object.defineProperty(exports, "__esModule", { value: true });
49
+ exports.buildBehaviorGraph = buildBehaviorGraph;
50
+ const ts_morph_1 = require("ts-morph");
51
+ const path = __importStar(require("path"));
52
+ const fs = __importStar(require("fs"));
53
+ // ══════════════════════════════════════════════
54
+ // L1: BUSINESS LAYER CLASSIFICATION
55
+ // ══════════════════════════════════════════════
56
+ /**
57
+ * Classify a function into its business layer based on:
58
+ * - File path (server/ vs client/)
59
+ * - File name (router, controller, service, db, repository)
60
+ * - Function name (handle*, process*, get*, create*)
61
+ */
62
+ function classifyLayer(funcName, filePath, className) {
63
+ const fileLower = filePath.toLowerCase();
64
+ const nameLower = funcName.toLowerCase();
65
+ const classLower = (className || "").toLowerCase();
66
+ // Strong signals from file naming
67
+ if (fileLower.includes("router") || fileLower.includes("routes")) {
68
+ return { layer: "controller", confidence: 0.9 };
69
+ }
70
+ if (fileLower.includes("controller")) {
71
+ return { layer: "controller", confidence: 0.95 };
72
+ }
73
+ if (fileLower.includes("service") || classLower.includes("service")) {
74
+ return { layer: "service", confidence: 0.9 };
75
+ }
76
+ if (fileLower.includes("repository") || fileLower.includes("db") || fileLower.includes("dao")) {
77
+ return { layer: "repository", confidence: 0.9 };
78
+ }
79
+ if (fileLower.includes("sdk") || fileLower.includes("api") || fileLower.includes("client")) {
80
+ return { layer: "external", confidence: 0.7 };
81
+ }
82
+ // Medium signals from function naming
83
+ if (nameLower.startsWith("handle") || nameLower.includes("route")) {
84
+ return { layer: "controller", confidence: 0.6 };
85
+ }
86
+ if (nameLower.includes("process") || nameLower.includes("verify") || nameLower.includes("validate")) {
87
+ return { layer: "service", confidence: 0.5 };
88
+ }
89
+ if (nameLower.includes("insert") || nameLower.includes("update") || nameLower.includes("delete") || nameLower.includes("query") || nameLower.includes("select")) {
90
+ return { layer: "repository", confidence: 0.6 };
91
+ }
92
+ // Default
93
+ return { layer: "unknown", confidence: 0.3 };
94
+ }
95
+ // ══════════════════════════════════════════════
96
+ // L2: CFG-BASED CALL SEQUENCE EXTRACTION
97
+ // ══════════════════════════════════════════════
98
+ /**
99
+ * Extract the ordered call sequence from a function body.
100
+ * This is CFG-based — we read the AST in execution order,
101
+ * not by method name convention.
102
+ */
103
+ function extractCallSequence(funcNode) {
104
+ const calls = [];
105
+ const body = funcNode.getBody();
106
+ if (!body)
107
+ return calls;
108
+ // Walk the body in statement order (which maps to execution order)
109
+ body.forEachDescendant((node) => {
110
+ if (ts_morph_1.Node.isCallExpression(node)) {
111
+ const expr = node.getExpression();
112
+ const calleeName = expr.getText();
113
+ // Filter out literals, property access on primitives
114
+ if (!calleeName.startsWith("'") && !calleeName.startsWith('"') && calleeName.length > 1) {
115
+ calls.push(calleeName);
116
+ }
117
+ }
118
+ });
119
+ return calls;
120
+ }
121
+ // ══════════════════════════════════════════════
122
+ // L3: BEHAVIOR GRAPH CONSTRUCTION
123
+ // ══════════════════════════════════════════════
124
+ /**
125
+ * Build the full Behavior Graph from a project.
126
+ * L1: Classify functions → L2: Extract call sequences → L3: Build edges → L4: Discover workflows
127
+ */
128
+ function buildBehaviorGraph(projectPath) {
129
+ const project = new ts_morph_1.Project({
130
+ tsConfigFilePath: path.join(projectPath, "tsconfig.json"),
131
+ skipAddingFilesFromTsConfig: false,
132
+ });
133
+ const functions = [];
134
+ const sequenceMap = new Map();
135
+ const edgeMap = new Map();
136
+ console.log("🔬 Progmune Behavior Mining Engine — V3.2");
137
+ console.log(" Project:", projectPath);
138
+ // ── Step 1: Classify all functions + Extract call sequences ──
139
+ console.log("\nL1+L2 · Function Classification + CFG Extraction...");
140
+ let funcCount = 0;
141
+ let seqCount = 0;
142
+ for (const sourceFile of project.getSourceFiles()) {
143
+ const filePath = sourceFile.getFilePath().replace(projectPath + "/", "");
144
+ if (filePath.includes("node_modules") || filePath.includes(".test."))
145
+ continue;
146
+ // Named functions
147
+ for (const funcDecl of sourceFile.getFunctions()) {
148
+ const name = funcDecl.getName() || "(anonymous)";
149
+ if (name === "(anonymous)")
150
+ continue;
151
+ const classification = classifyLayer(name, filePath);
152
+ const calls = extractCallSequence(funcDecl);
153
+ functions.push({
154
+ name,
155
+ file: filePath,
156
+ layer: classification.layer,
157
+ calls,
158
+ callCount: calls.length,
159
+ layerConfidence: classification.confidence,
160
+ });
161
+ funcCount++;
162
+ // Record call sequence if it has 2+ business-relevant calls
163
+ const businessCalls = calls.filter(c => !isUtilityCall(c));
164
+ if (businessCalls.length >= 2) {
165
+ const key = `${name}::${businessCalls.join("→")}`;
166
+ if (sequenceMap.has(key)) {
167
+ sequenceMap.get(key).frequency++;
168
+ }
169
+ else {
170
+ sequenceMap.set(key, {
171
+ caller: name,
172
+ callerLayer: classification.layer,
173
+ callees: businessCalls,
174
+ file: filePath,
175
+ frequency: 1,
176
+ });
177
+ seqCount++;
178
+ }
179
+ }
180
+ }
181
+ // Class methods
182
+ for (const classDecl of sourceFile.getClasses()) {
183
+ const className = classDecl.getName() || "";
184
+ for (const method of classDecl.getMethods()) {
185
+ const name = method.getName();
186
+ const fullName = `${className}.${name}`;
187
+ const classification = classifyLayer(name, filePath, className);
188
+ const calls = extractCallSequence(method);
189
+ functions.push({
190
+ name: fullName,
191
+ file: filePath,
192
+ layer: classification.layer,
193
+ calls,
194
+ callCount: calls.length,
195
+ layerConfidence: classification.confidence,
196
+ });
197
+ funcCount++;
198
+ const businessCalls = calls.filter(c => !isUtilityCall(c));
199
+ if (businessCalls.length >= 2) {
200
+ const key = `${fullName}::${businessCalls.join("→")}`;
201
+ if (sequenceMap.has(key)) {
202
+ sequenceMap.get(key).frequency++;
203
+ }
204
+ else {
205
+ sequenceMap.set(key, {
206
+ caller: fullName,
207
+ callerLayer: classification.layer,
208
+ callees: businessCalls,
209
+ file: filePath,
210
+ frequency: 1,
211
+ });
212
+ seqCount++;
213
+ }
214
+ }
215
+ }
216
+ }
217
+ }
218
+ // ── Step 1b: Build project function name registry ──
219
+ const projectFuncNames = new Set(functions.map(f => f.name));
220
+ // Also index by short name (method name without class prefix)
221
+ const shortToFull = new Map();
222
+ for (const f of functions) {
223
+ const parts = f.name.split(".");
224
+ if (parts.length > 1) {
225
+ const short = parts[parts.length - 1];
226
+ if (!shortToFull.has(short))
227
+ shortToFull.set(short, []);
228
+ shortToFull.get(short).push(f.name);
229
+ }
230
+ }
231
+ // ── Step 2: Build edges from cross-function calls ──
232
+ // An edge exists when one project-defined function calls another project-defined function.
233
+ // This is the "business projection" — we only care about business→business relationships.
234
+ console.log("\nL3 · Building Business Edges (function→function)...");
235
+ for (const func of functions) {
236
+ if (func.layer === "external" || func.layer === "unknown")
237
+ continue;
238
+ for (const calleeName of func.calls) {
239
+ // Skip utility calls
240
+ if (isUtilityCall(calleeName))
241
+ continue;
242
+ // Check if callee is a project-defined function
243
+ let resolvedName = calleeName;
244
+ let resolvedLayer = "unknown";
245
+ if (projectFuncNames.has(calleeName)) {
246
+ resolvedLayer = functions.find(f => f.name === calleeName)?.layer || "unknown";
247
+ }
248
+ else if (shortToFull.has(calleeName)) {
249
+ // This is a method call — match by method name
250
+ const fullNames = shortToFull.get(calleeName);
251
+ resolvedName = fullNames[0];
252
+ resolvedLayer = functions.find(f => f.name === resolvedName)?.layer || "unknown";
253
+ }
254
+ else {
255
+ continue; // Not a project-defined function — skip
256
+ }
257
+ const edgeKey = `${func.name}→${resolvedName}`;
258
+ if (edgeMap.has(edgeKey)) {
259
+ const existing = edgeMap.get(edgeKey);
260
+ existing.frequency++;
261
+ if (!existing.files.includes(func.file)) {
262
+ existing.files.push(func.file);
263
+ }
264
+ existing.consistencyScore = Math.min(1.0, (existing.files.length + existing.frequency) / 6);
265
+ const freqNorm = Math.min(1.0, existing.frequency / 3);
266
+ existing.confidence = Math.round((freqNorm * 0.4 + existing.topologyScore * 0.35 + existing.consistencyScore * 0.25) * 100);
267
+ }
268
+ else {
269
+ edgeMap.set(edgeKey, {
270
+ from: func.name,
271
+ to: resolvedName,
272
+ fromLayer: func.layer,
273
+ toLayer: resolvedLayer,
274
+ frequency: 1,
275
+ topologyScore: 1.0,
276
+ consistencyScore: 0.2,
277
+ confidence: 35,
278
+ files: [func.file],
279
+ });
280
+ }
281
+ }
282
+ }
283
+ const edges = Array.from(edgeMap.values())
284
+ .filter(e => e.confidence >= 30)
285
+ .sort((a, b) => b.confidence - a.confidence);
286
+ // Remove the old pairwise edge building code
287
+ // (edges are now built from function→function calls only)
288
+ const highConfEdges = edges.filter(e => e.confidence >= 60).length;
289
+ console.log(` ${edges.length} business edges (${highConfEdges} high confidence ≥60%)`);
290
+ // ── Step 3: Discover Business Workflows ──
291
+ console.log("\nL4 · Workflow Discovery...");
292
+ const workflows = [];
293
+ // Group edges by their fromLayer → toLayer chain
294
+ // A workflow is: Controller → Service → Repository → External (or any chain of high-conf edges)
295
+ const highConfEdgeSet = new Set(edges.filter(e => e.confidence >= 40));
296
+ // Find chains of 2+ connected high-confidence edges
297
+ const visited = new Set();
298
+ for (const edge of highConfEdgeSet) {
299
+ if (visited.has(`${edge.from}→${edge.to}`))
300
+ continue;
301
+ const chain = [edge];
302
+ visited.add(`${edge.from}→${edge.to}`);
303
+ // Extend forward
304
+ let current = edge.to;
305
+ let extended = true;
306
+ while (extended) {
307
+ extended = false;
308
+ for (const next of highConfEdgeSet) {
309
+ if (next.from === current && !visited.has(`${next.from}→${next.to}`)) {
310
+ chain.push(next);
311
+ visited.add(`${next.from}→${next.to}`);
312
+ current = next.to;
313
+ extended = true;
314
+ break;
315
+ }
316
+ }
317
+ }
318
+ if (chain.length >= 2) {
319
+ // Build workflow name from the business domain
320
+ const layers = chain.map(e => e.fromLayer);
321
+ const uniqueLayers = [...new Set(layers)];
322
+ // Determine business domain
323
+ const domainKeywords = ["payment", "order", "user", "auth", "product", "upload", "supplier", "notification"];
324
+ const allNames = chain.flatMap(e => [e.from, e.to]).join(" ").toLowerCase();
325
+ const domain = domainKeywords.find(kw => allNames.includes(kw)) || "business";
326
+ const avgConf = Math.round(chain.reduce((s, e) => s + e.confidence, 0) / chain.length);
327
+ const steps = [chain[0].from, ...chain.map(e => e.to)];
328
+ const stepLayers = [chain[0].fromLayer, ...chain.map(e => e.toLayer)];
329
+ workflows.push({
330
+ name: `${domain.charAt(0).toUpperCase() + domain.slice(1)} Workflow`,
331
+ steps,
332
+ layers: stepLayers,
333
+ edges: chain,
334
+ totalFrequency: chain.reduce((s, e) => s + e.frequency, 0),
335
+ confidence: avgConf,
336
+ description: `${steps.length} steps · ${uniqueLayers.join(" → ")} · avg confidence ${avgConf}%`,
337
+ });
338
+ }
339
+ }
340
+ console.log(` ${workflows.length} workflows discovered`);
341
+ // ── Print summary ──
342
+ for (const wf of workflows) {
343
+ console.log(`\n 📋 ${wf.name} [${wf.confidence}%]`);
344
+ console.log(` ${wf.steps.join(" → ")}`);
345
+ console.log(` ${wf.description}`);
346
+ for (const e of wf.edges) {
347
+ console.log(` ${e.from} → ${e.to} (freq=${e.frequency}, topo=${e.topologyScore}, cons=${e.consistencyScore.toFixed(1)})`);
348
+ }
349
+ }
350
+ // Top edges
351
+ console.log("\n Top Behavior Edges:");
352
+ for (const e of edges.slice(0, 5)) {
353
+ console.log(` ${e.from.padEnd(30)} → ${e.to.padEnd(30)} [${e.fromLayer}→${e.toLayer}] conf=${e.confidence}% (×${e.frequency})`);
354
+ }
355
+ const report = {
356
+ projectPath,
357
+ timestamp: new Date().toISOString(),
358
+ functions,
359
+ sequences: [], // Deprecated — edges now come from business projection
360
+ edges,
361
+ workflows,
362
+ summary: {
363
+ functionsFound: funcCount,
364
+ sequencesFound: edges.length, // Edge count serves as the meaningful metric
365
+ edgesFound: edges.length,
366
+ workflowsFound: workflows.length,
367
+ highConfidenceEdges: highConfEdges,
368
+ highConfidenceWorkflows: workflows.filter(w => w.confidence >= 60).length,
369
+ },
370
+ };
371
+ return report;
372
+ }
373
+ // ══════════════════════════════════════════════
374
+ // UTILITY
375
+ // ══════════════════════════════════════════════
376
+ /**
377
+ * Filter out calls that are clearly not business logic.
378
+ */
379
+ function isUtilityCall(name) {
380
+ const utilityPatterns = [
381
+ // Standard utilities
382
+ "console.", "z.", "JSON.", "Math.", "Object.", "Array.",
383
+ "parseInt", "parseFloat", "String", "Number", "Boolean",
384
+ "log", "error", "warn", "debug",
385
+ "map", "filter", "reduce", "forEach", "find",
386
+ "toString", "valueOf", "hasOwnProperty",
387
+ "require", "import",
388
+ // React hooks
389
+ "useState", "useEffect", "useCallback", "useMemo", "useRef",
390
+ "useLocation", "useParams", "useAuth",
391
+ "navigate", "localStorage.", "sessionStorage.",
392
+ "setTimeout", "setInterval", "clearTimeout",
393
+ // Drizzle query builder (infrastructure, not business)
394
+ "db.select", "db.update", "db.insert", "db.delete",
395
+ "db.transaction", "getDb",
396
+ "tx.select", "tx.update", "tx.insert", "tx.delete",
397
+ ".select()", ".from(", ".where(", ".limit(", ".orderBy",
398
+ "eq(", "and(", "or(", "desc(", "asc(",
399
+ "conditions.push", "whereConditions.push",
400
+ // General utilities
401
+ "console.error", "console.log", "console.warn",
402
+ "new Date(", "Date.now", "crypto.randomBytes",
403
+ "res.status", "res.json", "res.send",
404
+ "app.post", "app.get", "app.use",
405
+ // String/number formatting
406
+ ".toString()", ".toLowerCase()", ".toUpperCase()",
407
+ ".split(", ".replace(", ".join(",
408
+ "JSON.stringify", "JSON.parse",
409
+ "params.get", "url.searchParams",
410
+ "formData.append", "xhr.",
411
+ "Array.isArray", ".push(", ".pop(",
412
+ "parseInt(", "parseFloat(", "isNaN(",
413
+ "trpc.", ".useQuery", ".useMutation",
414
+ ".refetch", ".invalidate",
415
+ ];
416
+ for (const p of utilityPatterns) {
417
+ if (name.includes(p))
418
+ return true;
419
+ }
420
+ return false;
421
+ }
422
+ // ══════════════════════════════════════════════
423
+ // CLI
424
+ // ══════════════════════════════════════════════
425
+ if (require.main === module) {
426
+ const targetProject = process.argv[2];
427
+ if (!targetProject) {
428
+ console.error("Usage: npx ts-node src/behavior-miner.ts <project-path>");
429
+ process.exit(1);
430
+ }
431
+ const graph = buildBehaviorGraph(targetProject);
432
+ // Write output
433
+ const outputPath = path.join(targetProject, ".progmune_behavior_graph.json");
434
+ fs.writeFileSync(outputPath, JSON.stringify(graph, null, 2));
435
+ console.log(`\n✅ Behavior Graph saved to: ${outputPath}`);
436
+ console.log("\n═══ Behavior Mining Summary ═══");
437
+ console.log(` Functions: ${graph.summary.functionsFound}`);
438
+ console.log(` Sequences: ${graph.summary.sequencesFound}`);
439
+ console.log(` Edges: ${graph.summary.edgesFound} (${graph.summary.highConfidenceEdges} high confidence)`);
440
+ console.log(` Workflows: ${graph.summary.workflowsFound} (${graph.summary.highConfidenceWorkflows} high confidence)`);
441
+ console.log();
442
+ }