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
@@ -35,37 +35,48 @@ var __importStar = (this && this.__importStar) || (function () {
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.emitPython = emitPython;
37
37
  const fs = __importStar(require("fs"));
38
+ const BASIC_TYPES = new Set([
39
+ "str", "int", "float", "bool", "list", "dict", "tuple", "bytes",
40
+ "string", "number", "boolean", "any", "void", "None",
41
+ ]);
38
42
  function toPythonModule(filePath) {
39
43
  let module = filePath.replace(/\.py$/, "").replace(/\//g, ".");
40
44
  module = module.replace(/\.$/, "").replace(/\.__init__$/, "");
41
45
  return module;
42
46
  }
43
47
  function pythonValue(val) {
44
- if (typeof val === 'string')
48
+ if (typeof val === "string")
45
49
  return JSON.stringify(val);
46
- if (typeof val === 'number' || typeof val === 'boolean')
50
+ if (typeof val === "number" || typeof val === "boolean")
47
51
  return String(val);
48
52
  if (val === null || val === undefined)
49
- return 'None';
50
- if (typeof val === 'object') {
53
+ return "None";
54
+ if (typeof val === "object") {
51
55
  const entries = Object.entries(val).map(([k, v]) => `${JSON.stringify(k)}: ${pythonValue(v)}`);
52
- return `{${entries.join(', ')}}`;
56
+ return `{${entries.join(", ")}}`;
53
57
  }
54
- return 'None';
58
+ return "None";
55
59
  }
56
- function emitPython(actions) {
57
- const ir = JSON.parse(fs.readFileSync("ir.json", "utf-8"));
60
+ const STRING_ENUMS = {
61
+ SVL: '"SVL-4"', RootCause: '"F01"', BranchReason: '"repair_attempt"',
62
+ RepairStrategy: '"insert"', ConstraintType: '"protocol"',
63
+ };
64
+ function emitPython(actions, meta) {
65
+ const irRaw = JSON.parse(fs.readFileSync("ir.json", "utf-8"));
66
+ const ir = irRaw.functions || irRaw;
58
67
  const funcToFile = new Map();
59
- const funcToParams = new Map();
68
+ const fnMeta = new Map();
60
69
  for (const f of ir) {
61
70
  funcToFile.set(f.name, f.file);
62
- funcToParams.set(f.name, f.params || []);
71
+ fnMeta.set(f.name, f);
63
72
  }
73
+ // ── Collect imports ──
64
74
  const imports = new Map();
65
75
  const collectImports = (action) => {
66
76
  if (action.kind === "call" && action.function) {
67
77
  const file = funcToFile.get(action.function);
68
- if (file) {
78
+ const meta = fnMeta.get(action.function);
79
+ if (file && file !== "(external)" && meta?.exported !== false) {
69
80
  const mod = toPythonModule(file);
70
81
  if (!imports.has(mod))
71
82
  imports.set(mod, new Set());
@@ -76,74 +87,181 @@ function emitPython(actions) {
76
87
  (action.thenActions || []).forEach(collectImports);
77
88
  (action.elseActions || []).forEach(collectImports);
78
89
  }
90
+ else if (action.kind === "for") {
91
+ (action.bodyActions || []).forEach(collectImports);
92
+ }
79
93
  };
80
94
  for (const a of actions)
81
95
  collectImports(a);
96
+ // ── Variable flow: scan all actions to find inputs ──
97
+ const declared = new Set();
98
+ const referenced = new Set();
99
+ const scanAction = (action) => {
100
+ if (action.kind === "call" && action.assignTo)
101
+ declared.add(action.assignTo);
102
+ else if (action.kind === "assign" && action.target)
103
+ declared.add(action.target);
104
+ else if (action.kind === "for" && action.variable)
105
+ declared.add(action.variable);
106
+ if (action.kind === "call" && action.args) {
107
+ for (const arg of action.args) {
108
+ const v = typeof arg === "object" ? arg?.value : arg;
109
+ if (typeof v === "string" && /^[a-zA-Z_]\w*$/.test(v) && v !== "")
110
+ referenced.add(v);
111
+ }
112
+ }
113
+ if (action.kind === "if") {
114
+ (action.thenActions || []).forEach(scanAction);
115
+ (action.elseActions || []).forEach(scanAction);
116
+ }
117
+ else if (action.kind === "for") {
118
+ (action.bodyActions || []).forEach(scanAction);
119
+ }
120
+ };
121
+ for (const action of actions)
122
+ scanAction(action);
123
+ const rawInputs = [...referenced].filter(v => !declared.has(v) && v !== "");
124
+ // Resolve types from args
125
+ const inputTypes = new Map();
126
+ for (const action of actions) {
127
+ if (action.kind === "call" && action.args) {
128
+ for (const arg of action.args) {
129
+ const v = typeof arg === "object" ? arg?.value : arg;
130
+ const t = typeof arg === "object" ? arg?.type : "str";
131
+ if (typeof v === "string" && rawInputs.includes(v))
132
+ inputTypes.set(v, t);
133
+ }
134
+ }
135
+ }
136
+ // ── Parameter bloat guard ──
137
+ const MAX_PARAMS = 10;
138
+ if (rawInputs.length > MAX_PARAMS) {
139
+ return `# REFINEMENT_NEEDED: ${rawInputs.length} params detected (max ${MAX_PARAMS}). Split into smaller functions.`;
140
+ }
141
+ // ── Build code ──
82
142
  let code = "";
143
+ // Generation marker
144
+ if (meta?.sessionId) {
145
+ code += `# @progmune-generated session=${meta.sessionId} timestamp=${new Date().toISOString()}`;
146
+ if (meta.ruleHash)
147
+ code += ` ruleHash=${meta.ruleHash}`;
148
+ code += "\n";
149
+ const funcs = meta.irFunctionCount ?? ir.length;
150
+ const rules = meta.protocolRuleCount ?? 0;
151
+ code += `# Generated with IR constraint: ${funcs} functions`;
152
+ if (rules > 0)
153
+ code += `, ${rules} protocol rules`;
154
+ code += "\n";
155
+ }
83
156
  for (const [mod, funcs] of imports) {
84
157
  code += `from ${mod} import ${Array.from(funcs).join(", ")}\n`;
85
158
  }
86
- code += "\n\ndef main():\n";
87
- // 使用全局变量跟踪已声明的变量
88
- const declaredVars = new Set();
89
- const argToPython = (val) => {
90
- if (typeof val === 'string') {
91
- if (declaredVars.has(val))
92
- return val;
93
- return JSON.stringify(val);
159
+ const paramList = rawInputs.map(v => `${v}: ${inputTypes.get(v) || "str"}`).join(", ");
160
+ code += `\n\ndef main(${paramList}):\n`;
161
+ const argToPython = (action, i, a, meta) => {
162
+ const paramType = meta?.params?.[i]?.type || "str";
163
+ const val = a?.value;
164
+ // Variable reference
165
+ if (typeof val === "string" && declared.has(val))
166
+ return val;
167
+ if (typeof val === "string" && /^[a-zA-Z_]\w*$/.test(val) && val !== "")
168
+ return val;
169
+ // Empty default → use parameter name
170
+ const isEmpty = (v) => v === "" || v === 0 || v === false || v === null;
171
+ if (isEmpty(val) && a?.name) {
172
+ if (rawInputs.includes(a.name)) {
173
+ declared.add(a.name);
174
+ return a.name;
175
+ }
94
176
  }
177
+ // String enums
178
+ if (STRING_ENUMS[paramType])
179
+ return STRING_ENUMS[paramType];
180
+ // Basic type defaults
181
+ if (paramType === "string" || paramType === "str")
182
+ return '""';
183
+ if (paramType === "number" || paramType === "int" || paramType === "float")
184
+ return "0";
185
+ if (paramType === "boolean" || paramType === "bool")
186
+ return "False";
187
+ if (paramType.endsWith("[]") || paramType === "list")
188
+ return "[]";
189
+ if (paramType.startsWith("Map<") || paramType === "dict")
190
+ return "{}";
191
+ if (paramType.startsWith("Set<"))
192
+ return "set()";
95
193
  return pythonValue(val);
96
194
  };
97
- // 转换为 Python 代码行,使用数字缩进级别以确保一致性
195
+ let counter = 0;
98
196
  const convertLines = (action, indentLevel) => {
99
197
  const indent = " ".repeat(indentLevel);
100
198
  if (!action || !action.kind)
101
199
  return [];
102
200
  if (action.kind === "call") {
103
- const fname = action.function || "unknown";
104
- const args = (action.args || []).map((a) => argToPython(a.value)).join(", ");
105
- const resultVar = action.assignTo || `_res`;
106
- declaredVars.add(resultVar);
107
- return [`${indent}${resultVar} = ${fname}(${args})`];
201
+ const meta = fnMeta.get(action.function || "");
202
+ const args = (action.args || []).map((a, i) => argToPython(action, i, a, meta)).join(", ");
203
+ const resultVar = action.assignTo || `_res${counter++}`;
204
+ declared.add(resultVar);
205
+ return [`${indent}${resultVar} = ${action.function}(${args})`];
108
206
  }
109
207
  if (action.kind === "if") {
110
- const lines = [];
111
- lines.push(`${indent}if ${action.condition}:`);
112
- const thenActions = action.thenActions || [];
113
- const elseActions = action.elseActions || [];
114
- if (thenActions.length > 0) {
115
- for (const a of thenActions) {
208
+ const lines = [`${indent}if ${action.condition}:`];
209
+ if ((action.thenActions || []).length > 0) {
210
+ for (const a of action.thenActions)
116
211
  lines.push(...convertLines(a, indentLevel + 1));
117
- }
118
212
  }
119
213
  else {
120
- // 防止空块
121
214
  lines.push(`${indent} pass`);
122
215
  }
123
- if (elseActions.length > 0) {
216
+ if ((action.elseActions || []).length > 0) {
124
217
  lines.push(`${indent}else:`);
125
- for (const a of elseActions) {
218
+ for (const a of action.elseActions)
126
219
  lines.push(...convertLines(a, indentLevel + 1));
127
- }
128
220
  }
129
221
  return lines;
130
222
  }
223
+ if (action.kind === "for") {
224
+ declared.add(action.variable);
225
+ const lines = [`${indent}for ${action.variable} in ${action.iterable}:`];
226
+ for (const a of (action.bodyActions || []))
227
+ lines.push(...convertLines(a, indentLevel + 1));
228
+ return lines;
229
+ }
230
+ if (action.kind === "assign") {
231
+ const val = typeof action.value === "string"
232
+ ? (declared.has(action.value) ? action.value : JSON.stringify(action.value))
233
+ : pythonValue(action.value);
234
+ if (action.target)
235
+ declared.add(action.target);
236
+ return [`${indent}${action.target} = ${val}`];
237
+ }
131
238
  if (action.kind === "return") {
132
- const val = action.value;
133
- if (typeof val === 'string') {
134
- if (declaredVars.has(val))
135
- return [`${indent}return ${val}`];
136
- return [`${indent}return ${JSON.stringify(val)}`];
239
+ if (typeof action.value === "string") {
240
+ if (declared.has(action.value))
241
+ return [`${indent}return ${action.value}`];
242
+ return [`${indent}return ${JSON.stringify(action.value)}`];
137
243
  }
138
- return [`${indent}return ${pythonValue(val)}`];
244
+ return [`${indent}return ${pythonValue(action.value)}`];
139
245
  }
140
246
  return [];
141
247
  };
142
248
  const lines = [];
143
- for (const a of actions) {
249
+ for (const a of actions)
144
250
  lines.push(...convertLines(a, 1));
145
- }
146
251
  code += lines.join("\n") + "\n";
147
- code += "\nif __name__ == '__main__':\n main()\n";
252
+ // Auto-return injection: if LLM forgot to return
253
+ const lastAction = actions[actions.length - 1];
254
+ if (lastAction && lastAction.kind !== "return") {
255
+ const allCalls = actions.filter(a => a.kind === "call" && a.assignTo);
256
+ if (allCalls.length === 1) {
257
+ const c = allCalls[0];
258
+ code += ` return ${c.assignTo}\n`;
259
+ }
260
+ else if (allCalls.length > 1) {
261
+ const vars = allCalls.map(c => c.assignTo).join(", ");
262
+ code += ` return { ${vars} }\n`;
263
+ }
264
+ }
265
+ code += `\nif __name__ == "__main__":\n main()\n`;
148
266
  return code;
149
267
  }
@@ -0,0 +1,187 @@
1
+ "use strict";
2
+ /**
3
+ * P8.3: Python Protocol Extractor
4
+ *
5
+ * Extracts protocol state machines from Python IR by analyzing call
6
+ * sequences and decorator-based protocol annotations. Bridges the
7
+ * gap between Python IR (tools/extract_ir.py) and the Progmune
8
+ * protocol discovery pipeline (P6).
9
+ *
10
+ * Two modes:
11
+ * 1. Annotation-based: reads @progmune decorators from IR
12
+ * 2. Sequence-based: infers protocol from call co-occurrence patterns
13
+ *
14
+ * Both modes produce SSG-compatible StateAnnotation maps.
15
+ */
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.extractProtocolFromAnnotations = extractProtocolFromAnnotations;
18
+ exports.extractCallSequencesFromIR = extractCallSequencesFromIR;
19
+ exports.inferProtocolFromSequences = inferProtocolFromSequences;
20
+ exports.discoverPythonProtocols = discoverPythonProtocols;
21
+ exports.printPythonDiscoveryResult = printPythonDiscoveryResult;
22
+ const auto_protocol_synthesizer_1 = require("./auto-protocol-synthesizer");
23
+ // ═══════════════════════════════════════════════════════════════
24
+ // Annotation-based extraction
25
+ // ═══════════════════════════════════════════════════════════════
26
+ /**
27
+ * Extract protocol rules from Python IR using @progmune decorators.
28
+ *
29
+ * Each Python function with a @progmune decorator becomes a protocol
30
+ * rule with pre_states, post_states, and optional invalidate states.
31
+ */
32
+ function extractProtocolFromAnnotations(ir) {
33
+ const rules = new Map();
34
+ for (const fn of ir) {
35
+ const proto = fn.protocol;
36
+ if (!proto)
37
+ continue;
38
+ const pre_states = Array.isArray(proto.pre_states) ? proto.pre_states : [];
39
+ const post_states = Array.isArray(proto.post_states) ? proto.post_states : [];
40
+ const invRaw = proto.invalidate;
41
+ const invalidate = Array.isArray(invRaw) && invRaw.length > 0
42
+ ? invRaw : undefined;
43
+ rules.set(fn.name, {
44
+ pre_states,
45
+ post_states,
46
+ invalidate,
47
+ namespace: proto.namespace || "python",
48
+ });
49
+ }
50
+ return rules;
51
+ }
52
+ // ═══════════════════════════════════════════════════════════════
53
+ // Sequence-based inference
54
+ // ═══════════════════════════════════════════════════════════════
55
+ /**
56
+ * Extract call sequences from Python IR.
57
+ *
58
+ * Builds ordered sequences of function calls by analyzing the call
59
+ * graph. For each function that calls others, the called functions
60
+ * form a sequence in source order (approximated by IR order).
61
+ */
62
+ function extractCallSequencesFromIR(ir) {
63
+ const sequences = [];
64
+ // Method 1: Functions that call other functions form natural sequences
65
+ for (const fn of ir) {
66
+ const calls = fn.calls || [];
67
+ if (calls.length >= 2) {
68
+ sequences.push([...calls]);
69
+ }
70
+ }
71
+ // Method 2: Build sequences from cross-function call patterns
72
+ // If fnA calls fnB and fnB calls fnC, we get [fnB, fnC]
73
+ const fnMap = new Map();
74
+ for (const fn of ir)
75
+ fnMap.set(fn.name, fn);
76
+ // Build adjacency: which functions are called by which
77
+ const calledBy = new Map();
78
+ for (const fn of ir) {
79
+ for (const call of (fn.calls || [])) {
80
+ if (!calledBy.has(call))
81
+ calledBy.set(call, []);
82
+ calledBy.get(call).push(fn.name);
83
+ }
84
+ }
85
+ // Method 3: Topological sort of call graph
86
+ // Functions with no callers = entry points → follow call chain
87
+ const entryPoints = ir.filter(fn => !calledBy.has(fn.name) || calledBy.get(fn.name).length === 0);
88
+ for (const entry of entryPoints) {
89
+ const seq = [entry.name];
90
+ const visited = new Set([entry.name]);
91
+ let current = entry;
92
+ // Follow calls until we hit a function that calls nothing new
93
+ for (let depth = 0; depth < 10; depth++) {
94
+ const next = (current.calls || []).find(c => !visited.has(c) && fnMap.has(c));
95
+ if (!next)
96
+ break;
97
+ seq.push(next);
98
+ visited.add(next);
99
+ current = fnMap.get(next);
100
+ }
101
+ if (seq.length >= 2)
102
+ sequences.push(seq);
103
+ }
104
+ return sequences;
105
+ }
106
+ /**
107
+ * Infer protocol rules from call sequences using the auto-protocol-synthesizer.
108
+ */
109
+ function inferProtocolFromSequences(sequences) {
110
+ const synthesized = (0, auto_protocol_synthesizer_1.synthesizeProtocols)(sequences);
111
+ const rules = new Map();
112
+ for (const proto of synthesized) {
113
+ for (const r of proto.rules) {
114
+ rules.set(r.function, {
115
+ pre_states: r.pre_states,
116
+ post_states: r.post_states,
117
+ invalidate: r.invalidate,
118
+ namespace: "python_inferred",
119
+ });
120
+ }
121
+ }
122
+ return rules;
123
+ }
124
+ /**
125
+ * Run the full Python protocol discovery pipeline on a set of IR functions.
126
+ *
127
+ * 1. Extract protocol annotations from @progmune decorators
128
+ * 2. Extract call sequences from the call graph
129
+ * 3. Infer additional protocols from call sequences
130
+ * 4. Merge annotation and inferred rules
131
+ */
132
+ function discoverPythonProtocols(ir) {
133
+ // 1. Annotation-based
134
+ const annotationRules = extractProtocolFromAnnotations(ir);
135
+ const annotationCount = annotationRules.size;
136
+ // 2. Sequence extraction
137
+ const callSequences = extractCallSequencesFromIR(ir);
138
+ const sequenceCount = callSequences.length;
139
+ // 3. Inference-based
140
+ const inferredRules = inferProtocolFromSequences(callSequences);
141
+ const inferredCount = inferredRules.size;
142
+ // 4. Merge (annotation rules take precedence)
143
+ const combinedRules = new Map(inferredRules);
144
+ for (const [fn, rule] of annotationRules) {
145
+ combinedRules.set(fn, rule);
146
+ }
147
+ return {
148
+ annotationRules,
149
+ annotationCount,
150
+ callSequences,
151
+ sequenceCount,
152
+ inferredRules,
153
+ inferredCount,
154
+ combinedRules,
155
+ };
156
+ }
157
+ function printPythonDiscoveryResult(result) {
158
+ console.log("\n─── Python Protocol Discovery ───");
159
+ console.log(` Annotation rules: ${result.annotationCount}`);
160
+ console.log(` Call sequences: ${result.sequenceCount}`);
161
+ console.log(` Inferred rules: ${result.inferredCount}`);
162
+ console.log(` Combined rules: ${result.combinedRules.size}`);
163
+ console.log();
164
+ if (result.annotationCount > 0) {
165
+ console.log(" ── Annotation-based protocols ──");
166
+ for (const [fn, rule] of result.annotationRules) {
167
+ const inv = rule.invalidate ? ` [inv: ${rule.invalidate.join(",")}]` : "";
168
+ console.log(` ${fn}: [${rule.pre_states.join(",")}] → [${rule.post_states.join(",")}]${inv} (${rule.namespace})`);
169
+ }
170
+ console.log();
171
+ }
172
+ if (result.sequenceCount > 0) {
173
+ console.log(" ── Top call sequences ──");
174
+ for (const seq of result.callSequences.slice(0, 10)) {
175
+ console.log(` ${seq.join(" → ")}`);
176
+ }
177
+ console.log();
178
+ }
179
+ if (result.inferredCount > 0) {
180
+ console.log(" ── Inferred protocols ──");
181
+ for (const [fn, rule] of result.inferredRules) {
182
+ const inv = rule.invalidate ? ` [inv: ${rule.invalidate.join(",")}]` : "";
183
+ console.log(` ${fn}: [${rule.pre_states.join(",")}] → [${rule.post_states.join(",")}]${inv}`);
184
+ }
185
+ console.log();
186
+ }
187
+ }
@@ -0,0 +1,116 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ /**
37
+ * P8.3: Python Protocol Discovery — End-to-End Tests
38
+ *
39
+ * Verifies the full pipeline from Python IR extraction through
40
+ * protocol annotation parsing to SSG-compatible rule generation.
41
+ */
42
+ const vitest_1 = require("vitest");
43
+ const path = __importStar(require("path"));
44
+ const extract_ir_python_1 = require("./extract-ir-python");
45
+ const python_protocol_extractor_1 = require("./python-protocol-extractor");
46
+ const state_machine_fingerprint_1 = require("./state-machine-fingerprint");
47
+ const topology_factory_1 = require("./topology-factory");
48
+ const PYTHON_FIXTURE = path.resolve(__dirname, "..", "test-python-protocol");
49
+ (0, vitest_1.describe)("Python Protocol Discovery Pipeline", () => {
50
+ (0, vitest_1.it)("extracts IR from Python project with protocol annotations", () => {
51
+ const ir = (0, extract_ir_python_1.extractIRPython)(PYTHON_FIXTURE);
52
+ (0, vitest_1.expect)(ir.length).toBeGreaterThanOrEqual(8);
53
+ // Verify FunctionInfo-compatible output
54
+ for (const fn of ir) {
55
+ (0, vitest_1.expect)(fn.name).toBeTruthy();
56
+ (0, vitest_1.expect)(Array.isArray(fn.params)).toBe(true);
57
+ (0, vitest_1.expect)(Array.isArray(fn.calls)).toBe(true);
58
+ (0, vitest_1.expect)(typeof fn.exported).toBe("boolean");
59
+ (0, vitest_1.expect)(typeof fn.file).toBe("string");
60
+ }
61
+ });
62
+ (0, vitest_1.it)("extracts protocol annotations from @progmune decorators", () => {
63
+ const ir = (0, extract_ir_python_1.extractIRPython)(PYTHON_FIXTURE);
64
+ const rules = (0, python_protocol_extractor_1.extractProtocolFromAnnotations)(ir);
65
+ // Should find all 8 annotated functions
66
+ (0, vitest_1.expect)(rules.size).toBeGreaterThanOrEqual(8);
67
+ // Auth protocol
68
+ (0, vitest_1.expect)(rules.has("verify_password")).toBe(true);
69
+ (0, vitest_1.expect)(rules.get("verify_password").namespace).toBe("auth");
70
+ (0, vitest_1.expect)(rules.get("verify_password").pre_states).toEqual(["UNAUTHENTICATED"]);
71
+ (0, vitest_1.expect)(rules.get("verify_password").post_states).toEqual(["PASSWORD_VERIFIED"]);
72
+ // generate_jwt has invalidate
73
+ (0, vitest_1.expect)(rules.has("generate_jwt")).toBe(true);
74
+ (0, vitest_1.expect)(rules.get("generate_jwt").invalidate).toEqual(["PASSWORD_VERIFIED"]);
75
+ // File protocol
76
+ (0, vitest_1.expect)(rules.has("open_config")).toBe(true);
77
+ (0, vitest_1.expect)(rules.get("open_config").namespace).toBe("file");
78
+ // Stateless functions should NOT have protocol rules
79
+ (0, vitest_1.expect)(rules.has("compute_hash")).toBe(false);
80
+ (0, vitest_1.expect)(rules.has("validate_input")).toBe(false);
81
+ });
82
+ (0, vitest_1.it)("extracts call sequences from Python call graph", () => {
83
+ const ir = (0, extract_ir_python_1.extractIRPython)(PYTHON_FIXTURE);
84
+ const sequences = (0, python_protocol_extractor_1.extractCallSequencesFromIR)(ir);
85
+ (0, vitest_1.expect)(sequences.length).toBeGreaterThan(0);
86
+ // authenticate_and_open calls: verify_password, create_session, open_config,
87
+ // read_config, close_config, logout
88
+ const crossSeq = sequences.find(s => s.includes("open_config"));
89
+ (0, vitest_1.expect)(crossSeq).toBeTruthy();
90
+ });
91
+ (0, vitest_1.it)("runs full discovery pipeline and produces combined rules", () => {
92
+ const ir = (0, extract_ir_python_1.extractIRPython)(PYTHON_FIXTURE);
93
+ const result = (0, python_protocol_extractor_1.discoverPythonProtocols)(ir);
94
+ (0, python_protocol_extractor_1.printPythonDiscoveryResult)(result);
95
+ // Annotation rules
96
+ (0, vitest_1.expect)(result.annotationCount).toBeGreaterThanOrEqual(8);
97
+ // Call sequences
98
+ (0, vitest_1.expect)(result.sequenceCount).toBeGreaterThan(0);
99
+ // Combined rules should contain all annotation rules
100
+ (0, vitest_1.expect)(result.combinedRules.size).toBeGreaterThanOrEqual(result.annotationCount);
101
+ for (const [fn, rule] of result.annotationRules) {
102
+ (0, vitest_1.expect)(result.combinedRules.has(fn)).toBe(true);
103
+ }
104
+ });
105
+ (0, vitest_1.it)("Python protocol state machine matches hand-written TypeScript equivalent", () => {
106
+ const ir = (0, extract_ir_python_1.extractIRPython)(PYTHON_FIXTURE);
107
+ const pythonRules = (0, python_protocol_extractor_1.extractProtocolFromAnnotations)(ir);
108
+ // Build TypeScript-equivalent auth protocol using topology factory
109
+ const tsAuthRules = (0, topology_factory_1.createProtocolForTopology)("linear", 4); // has similar shape
110
+ const pythonFp = (0, state_machine_fingerprint_1.extractStateMachine)(pythonRules);
111
+ const tsFp = (0, state_machine_fingerprint_1.extractStateMachine)(tsAuthRules);
112
+ const comp = (0, state_machine_fingerprint_1.compareStateMachines)(pythonFp, tsFp);
113
+ console.log(`\n Python auth ↔ TypeScript linear: ${(comp.similarity * 100).toFixed(0)}%`);
114
+ (0, vitest_1.expect)(comp.similarity).toBeGreaterThan(0);
115
+ });
116
+ });