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
@@ -102,7 +102,7 @@ function suggestInvariantRepair(violation, ledger, namespaceInitialStates = (0,
102
102
  const proposals = [];
103
103
  if (violation.invariant === "before-consistency") {
104
104
  // statesBefore is wrong — can be recomputed from rebuildState
105
- const correctStatesBefore = violation.expected;
105
+ const correctStatesBefore = violation.expected || {};
106
106
  const t = ledger[violation.index];
107
107
  if (!t)
108
108
  return [];
@@ -114,7 +114,7 @@ function suggestInvariantRepair(violation, ledger, namespaceInitialStates = (0,
114
114
  try {
115
115
  (0, runtime_invariants_1.assertDeltaConsistency)(correctedTransition);
116
116
  }
117
- catch { }
117
+ catch { /* consistency assertion — best-effort */ }
118
118
  proposals.push({
119
119
  id: `rp_${Date.now()}_${Math.random().toString(36).slice(2, 5)}`,
120
120
  violationIndex: violation.index,
@@ -128,7 +128,7 @@ function suggestInvariantRepair(violation, ledger, namespaceInitialStates = (0,
128
128
  }
129
129
  if (violation.invariant === "delta-consistency") {
130
130
  // statesAfter doesn't match applyDelta(statesBefore, acquired, invalidated)
131
- const correctStatesAfter = violation.expected;
131
+ const correctStatesAfter = violation.expected || {};
132
132
  const t = ledger[violation.index];
133
133
  if (!t)
134
134
  return [];
@@ -139,7 +139,7 @@ function suggestInvariantRepair(violation, ledger, namespaceInitialStates = (0,
139
139
  try {
140
140
  (0, runtime_invariants_1.assertDeltaConsistency)(correctedTransition);
141
141
  }
142
- catch { }
142
+ catch { /* consistency assertion — best-effort */ }
143
143
  proposals.push({
144
144
  id: `rp_${Date.now()}_${Math.random().toString(36).slice(2, 5)}`,
145
145
  violationIndex: violation.index,
@@ -0,0 +1,141 @@
1
+ "use strict";
2
+ /**
3
+ * P2: Repair Ranker — Feature Extraction & Linear Ranking
4
+ *
5
+ * FeatureExtractor: RepairCandidate → CandidateFeatures
6
+ * LinearRanker: CandidateFeatures[] → ranked RepairCandidate[]
7
+ *
8
+ * Default weights (P3 — manual):
9
+ * score = 0.4 * protocolSafety + 0.3 * historicalSuccessRate
10
+ * + 0.2 * performance + 0.1 * auditability
11
+ *
12
+ * Future P4: swap LinearRanker for RewardModelRanker — same interface.
13
+ */
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.extractFeatures = extractFeatures;
16
+ exports.createLinearRanker = createLinearRanker;
17
+ exports.rankCandidates = rankCandidates;
18
+ /**
19
+ * Extract a feature vector from a repair candidate.
20
+ *
21
+ * All features are in [0, 1] range where possible, so the Ranker
22
+ * can combine them with simple linear weights.
23
+ */
24
+ function extractFeatures(candidate, ctx, corpusStats) {
25
+ const actionCount = candidate.actions.length;
26
+ const maxActions = corpusStats?.maxActions || Math.max(actionCount, 8);
27
+ // ── protocolSafety ──
28
+ // Candidates that satisfy more constraints are safer.
29
+ // Shorter paths are inherently safer (fewer things can go wrong).
30
+ const safetyFromLength = 1.0 - actionCount / 10;
31
+ const constraintMatch = ctx.constraints.length > 0
32
+ ? ctx.constraints.filter(c => c.type === "safety" || c.type === "security").length
33
+ / Math.max(1, ctx.constraints.length)
34
+ : 0.5;
35
+ const protocolSafety = Math.max(0, Math.min(1, safetyFromLength * 0.6 + constraintMatch * 0.4));
36
+ // ── historicalSuccessRate ──
37
+ // From corpus strategy metadata, or 0 if not available.
38
+ const historicalSuccessRate = candidate.metadata?.historicalSuccessRate || 0;
39
+ // ── actionCount ──
40
+ // Raw count — used by rankPerformance.
41
+ // ── latencyCost ──
42
+ // Inverted: more actions = higher latency cost.
43
+ const latencyCost = Math.min(1, actionCount / maxActions);
44
+ // ── auditability ──
45
+ // Shorter paths are easier to audit.
46
+ const auditability = Math.max(0, 1.0 - actionCount / maxActions);
47
+ // ── corpusEvidence ──
48
+ const corpusEvidence = candidate.metadata?.corpusEvidenceCount || 0;
49
+ // ── goalMatch (P7.3) ──
50
+ // Candidates from goal-template matching get a 1.0 boost.
51
+ // Cross-protocol and frontier candidates get a 0.3 partial boost
52
+ // since they still represent structured protocol knowledge.
53
+ const metaSource = candidate.metadata?.source;
54
+ const goalMatch = metaSource === "goal-template" ? 1.0
55
+ : metaSource === "cross-protocol" ? 0.3
56
+ : 0.0;
57
+ return {
58
+ protocolSafety,
59
+ historicalSuccessRate,
60
+ actionCount,
61
+ latencyCost,
62
+ auditability,
63
+ corpusEvidence,
64
+ source: candidate.source,
65
+ goalMatch,
66
+ };
67
+ }
68
+ // ═══════════════════════════════════════════════════════════════
69
+ // Linear Ranker
70
+ // ═══════════════════════════════════════════════════════════════
71
+ /** Default P3 manual weights. Tune these from corpus data. */
72
+ const DEFAULT_WEIGHTS = {
73
+ safety: 0.30,
74
+ successRate: 0.15,
75
+ performance: 0.10,
76
+ auditability: 0.10,
77
+ goalMatch: 0.35, // P7.3: boost goal-template candidates heavily
78
+ };
79
+ /**
80
+ * Create a linear ranker with configurable weights.
81
+ *
82
+ * Usage:
83
+ * const ranker = createLinearRanker(); // defaults
84
+ * const ranker = createLinearRanker({ safety: 0.5 }); // safety-first
85
+ */
86
+ function createLinearRanker(weights) {
87
+ const w = { ...DEFAULT_WEIGHTS, ...weights };
88
+ /** Compute performance from features: fewer actions = better. */
89
+ function performanceScore(f) {
90
+ return 1.0 - Math.min(1, f.actionCount / Math.max(1, f.actionCount + 3));
91
+ }
92
+ /** Compute the weighted overall score. */
93
+ function overallScore(f) {
94
+ return (w.safety * f.protocolSafety +
95
+ w.successRate * f.historicalSuccessRate +
96
+ w.performance * performanceScore(f) +
97
+ w.auditability * f.auditability +
98
+ w.goalMatch * (f.goalMatch || 0));
99
+ }
100
+ /** Zip candidates with features and sort by a scoring function. */
101
+ function rankBy(candidates, features, scoreFn) {
102
+ const paired = candidates.map((c, i) => ({
103
+ candidate: c,
104
+ score: scoreFn(features[i]),
105
+ }));
106
+ paired.sort((a, b) => b.score - a.score);
107
+ return paired.map(p => p.candidate);
108
+ }
109
+ return {
110
+ score(features) {
111
+ return overallScore(features);
112
+ },
113
+ rankSafety(candidates, features) {
114
+ return rankBy(candidates, features, f => f.protocolSafety);
115
+ },
116
+ rankPerformance(candidates, features) {
117
+ return rankBy(candidates, features, f => performanceScore(f));
118
+ },
119
+ rankAuditability(candidates, features) {
120
+ return rankBy(candidates, features, f => f.auditability);
121
+ },
122
+ rankOverall(candidates, features) {
123
+ return rankBy(candidates, features, f => overallScore(f));
124
+ },
125
+ };
126
+ }
127
+ // ═══════════════════════════════════════════════════════════════
128
+ // Convenience: rankCandidates
129
+ // ═══════════════════════════════════════════════════════════════
130
+ /**
131
+ * Rank candidates using the linear ranker in one call.
132
+ * Convenience wrapper around extractFeatures + createLinearRanker.
133
+ */
134
+ function rankCandidates(candidates, ctx, mode = "overall") {
135
+ const maxActions = Math.max(...candidates.map(c => c.actions.length), 8);
136
+ const features = candidates.map(c => extractFeatures(c, ctx, { maxActions }));
137
+ const ranker = createLinearRanker();
138
+ const ranked = ranker.rankOverall(candidates, features);
139
+ // Assign rank fields
140
+ return ranked.map((c, i) => ({ ...c, rank: i + 1 }));
141
+ }
@@ -0,0 +1,419 @@
1
+ "use strict";
2
+ /**
3
+ * P2: Repair Search Strategies — Candidate Producers
4
+ *
5
+ * Each strategy searches a different knowledge source for repair candidates.
6
+ * Strategies MUST NOT score candidates — they find, the Ranker ranks.
7
+ *
8
+ * Three knowledge sources:
9
+ * 1. Corpus — historical trajectory data (empirical)
10
+ * 2. Protocol — SSG state graph BFS (logical)
11
+ * 3. Antibody — learned immune rules (heuristic)
12
+ */
13
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ var desc = Object.getOwnPropertyDescriptor(m, k);
16
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
17
+ desc = { enumerable: true, get: function() { return m[k]; } };
18
+ }
19
+ Object.defineProperty(o, k2, desc);
20
+ }) : (function(o, m, k, k2) {
21
+ if (k2 === undefined) k2 = k;
22
+ o[k2] = m[k];
23
+ }));
24
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
25
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
26
+ }) : function(o, v) {
27
+ o["default"] = v;
28
+ });
29
+ var __importStar = (this && this.__importStar) || (function () {
30
+ var ownKeys = function(o) {
31
+ ownKeys = Object.getOwnPropertyNames || function (o) {
32
+ var ar = [];
33
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
34
+ return ar;
35
+ };
36
+ return ownKeys(o);
37
+ };
38
+ return function (mod) {
39
+ if (mod && mod.__esModule) return mod;
40
+ var result = {};
41
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
42
+ __setModuleDefault(result, mod);
43
+ return result;
44
+ };
45
+ })();
46
+ Object.defineProperty(exports, "__esModule", { value: true });
47
+ exports.AntibodySearchStrategy = exports.ProtocolSearchStrategy = exports.CorpusSearchStrategy = void 0;
48
+ exports.createDefaultStrategies = createDefaultStrategies;
49
+ const fs = __importStar(require("fs"));
50
+ const path = __importStar(require("path"));
51
+ const failure_corpus_1 = require("./failure-corpus");
52
+ const ssg_validator_1 = require("./ssg-validator");
53
+ const goal_planner_1 = require("./goal-planner");
54
+ const protocol_frontier_1 = require("./protocol-frontier");
55
+ // ═══════════════════════════════════════════════════════════════
56
+ // Helpers
57
+ // ═══════════════════════════════════════════════════════════════
58
+ /** Convert a string function name to a call Action for the candidate. */
59
+ function fnToAction(name) {
60
+ return { kind: "call", function: name, args: [] };
61
+ }
62
+ /** Generate a stable ID from source + action sequence. */
63
+ function candidateId(source, actions) {
64
+ const sig = actions.map(a => a.kind === "call" ? (a.function || "?") : a.kind).join("-");
65
+ return `${source}-${sig.slice(0, 80)}`;
66
+ }
67
+ /** Find functions that invalidate current states (resource cleanup). */
68
+ function findCleanupFunctions(ctx) {
69
+ const candidates = [];
70
+ // Pass 1: exact match — function invalidates a current state AND all pre-states are satisfied
71
+ for (const [funcName, rule] of ctx.rules) {
72
+ const invalidates = rule.invalidate || [];
73
+ const matchesCurrent = invalidates.some(s => ctx.currentState.includes(s));
74
+ if (matchesCurrent && rule.pre_states.every(p => ctx.currentState.includes(p))) {
75
+ const actions = [fnToAction(funcName)];
76
+ candidates.push({
77
+ id: candidateId("protocol", actions),
78
+ source: "protocol",
79
+ actions,
80
+ explanation: `资源清理: 调用 ${funcName} 以释放 ${invalidates.filter(s => ctx.currentState.includes(s)).join(", ")}`,
81
+ evidence: 0,
82
+ metadata: { pathLength: 1, cleanupTargets: invalidates, source: "cleanup" },
83
+ });
84
+ }
85
+ }
86
+ // Pass 2 (P0): relaxed match — function invalidates a current state even if not all
87
+ // pre-states are satisfied. This catches cases where the current state snapshot
88
+ // is incomplete (e.g., namespace mismatch).
89
+ // But we still require at least one pre-state to be present — completely unrelated
90
+ // cleanup functions should not be suggested.
91
+ if (candidates.length === 0) {
92
+ for (const [funcName, rule] of ctx.rules) {
93
+ const invalidates = rule.invalidate || [];
94
+ const matchesCurrent = invalidates.some(s => ctx.currentState.includes(s));
95
+ const hasAnyPreState = rule.pre_states.length === 0 ||
96
+ rule.pre_states.some(p => ctx.currentState.includes(p));
97
+ if (matchesCurrent && hasAnyPreState) {
98
+ const actions = [fnToAction(funcName)];
99
+ candidates.push({
100
+ id: candidateId("protocol", actions),
101
+ source: "protocol",
102
+ actions,
103
+ explanation: `资源清理(fuzzy): 调用 ${funcName} 以释放 ${invalidates.filter(s => ctx.currentState.includes(s)).join(", ")}`,
104
+ evidence: 0,
105
+ metadata: { pathLength: 1, cleanupTargets: invalidates, source: "cleanup-fuzzy" },
106
+ });
107
+ }
108
+ }
109
+ }
110
+ // Pass 3 (P0): last-resort — ANY function that invalidates ANY resource-like state
111
+ // that looks like it could be leaked (contains OPEN, CONNECTED, ACTIVE, LOCKED).
112
+ if (candidates.length === 0) {
113
+ const leakableStates = ctx.currentState.filter(s => /OPEN|CONNECTED|ACTIVE|LOCKED|ALLOCATED|ACQUIRED|HELD/i.test(s));
114
+ if (leakableStates.length > 0) {
115
+ for (const [funcName, rule] of ctx.rules) {
116
+ const invalidates = rule.invalidate || [];
117
+ if (invalidates.some(s => leakableStates.includes(s))) {
118
+ const actions = [fnToAction(funcName)];
119
+ candidates.push({
120
+ id: candidateId("protocol", actions),
121
+ source: "protocol",
122
+ actions,
123
+ explanation: `推测性资源清理: 调用 ${funcName} 以释放疑似泄漏状态 ${leakableStates.join(", ")}`,
124
+ evidence: 0,
125
+ metadata: { pathLength: 1, cleanupTargets: invalidates, source: "cleanup-heuristic" },
126
+ });
127
+ }
128
+ }
129
+ }
130
+ }
131
+ return candidates;
132
+ }
133
+ // ═══════════════════════════════════════════════════════════════
134
+ // P3.10: Goal-expanded candidate generation
135
+ // ═══════════════════════════════════════════════════════════════
136
+ /** Expand a goal into protocol candidates using Goal Templates. */
137
+ function expandGoalAsCandidates(goal, ctx) {
138
+ const planner = (0, goal_planner_1.getGoalPlanner)();
139
+ const actionSets = planner.getCandidateActions(goal);
140
+ if (actionSets.length === 0)
141
+ return [];
142
+ return actionSets.map(actions => ({
143
+ id: candidateId("protocol", actions.map(fnToAction)),
144
+ source: "protocol",
145
+ actions: actions.map(fnToAction),
146
+ explanation: `目标展开: "${goal}" → ${actions.join(" → ")}`,
147
+ evidence: 0,
148
+ metadata: { pathLength: actions.length, source: "goal-template" },
149
+ }));
150
+ }
151
+ // ═══════════════════════════════════════════════════════════════
152
+ // P0: Protocol rules loader — fallback for empty rules Maps
153
+ // ═══════════════════════════════════════════════════════════════
154
+ let _cachedProtocolRules = null;
155
+ /** Load protocol rules from protocols.json as a fallback. */
156
+ function loadProtocolRules() {
157
+ if (_cachedProtocolRules)
158
+ return _cachedProtocolRules;
159
+ try {
160
+ const protocolsPath = path.resolve(process.env.PROGMUNE_PROJECT_DIR || process.cwd(), "protocols.json");
161
+ if (fs.existsSync(protocolsPath)) {
162
+ const raw = JSON.parse(fs.readFileSync(protocolsPath, "utf-8"));
163
+ _cachedProtocolRules = new Map();
164
+ if (raw.rules) {
165
+ for (const [fn, rule] of Object.entries(raw.rules)) {
166
+ const r = rule;
167
+ _cachedProtocolRules.set(fn, {
168
+ pre_states: r.pre_states || [],
169
+ post_states: r.post_states || [],
170
+ invalidate: r.invalidate,
171
+ namespace: r.namespace,
172
+ });
173
+ }
174
+ }
175
+ }
176
+ }
177
+ catch { /* use whatever rules are available */ }
178
+ return _cachedProtocolRules || new Map();
179
+ }
180
+ /** Ensure rules Map has entries — fall back to protocols.json if empty. */
181
+ function ensureRules(ctx) {
182
+ if (ctx.rules.size > 0)
183
+ return ctx.rules;
184
+ return loadProtocolRules();
185
+ }
186
+ // ═══════════════════════════════════════════════════════════════
187
+ // Strategy 1: Corpus Search — historical trajectory data
188
+ // ═══════════════════════════════════════════════════════════════
189
+ class CorpusSearchStrategy {
190
+ constructor() {
191
+ this.name = "corpus";
192
+ }
193
+ search(ctx) {
194
+ const all = (0, failure_corpus_1.loadTrajectories)().filter(t => t.result === "violation" || t.result === "repair");
195
+ if (all.length === 0)
196
+ return [];
197
+ // Filter: same violation type OR same protocol
198
+ const relevant = all.filter(t => (t.violation?.type === ctx.violationType) || t.protocol === ctx.protocol);
199
+ if (relevant.length === 0)
200
+ return [];
201
+ // Group by fix path (deduplicate)
202
+ const pathGroups = new Map();
203
+ for (const t of relevant) {
204
+ const fixPath = t.violation?.fixPath;
205
+ if (!fixPath || fixPath.length === 0)
206
+ continue;
207
+ const key = fixPath.join("→");
208
+ if (!pathGroups.has(key))
209
+ pathGroups.set(key, []);
210
+ pathGroups.get(key).push(t);
211
+ }
212
+ const candidates = [];
213
+ for (const [pathKey, records] of pathGroups) {
214
+ const fixPath = pathKey.split("→");
215
+ const successRate = records.reduce((s, t) => s + t.successRate, 0) / records.length;
216
+ candidates.push({
217
+ id: candidateId("corpus", fixPath.map(fnToAction)),
218
+ source: "corpus",
219
+ actions: fixPath.map(fnToAction),
220
+ explanation: `根据 ${records.length} 个历史案例,补全路径: ${fixPath.join(" → ")}`,
221
+ evidence: records.length,
222
+ metadata: {
223
+ historicalSuccessRate: successRate,
224
+ corpusEvidenceCount: records.length,
225
+ },
226
+ });
227
+ }
228
+ return candidates;
229
+ }
230
+ }
231
+ exports.CorpusSearchStrategy = CorpusSearchStrategy;
232
+ // ═══════════════════════════════════════════════════════════════
233
+ // Strategy 2: Protocol Search — SSG state graph BFS
234
+ // ═══════════════════════════════════════════════════════════════
235
+ class ProtocolSearchStrategy {
236
+ constructor() {
237
+ this.name = "protocol";
238
+ }
239
+ search(ctx) {
240
+ // P0: Ensure we have rules to work with
241
+ const rules = ensureRules(ctx);
242
+ const effectiveCtx = { ...ctx, rules };
243
+ // Short-circuit: fall back to generic fix path search
244
+ if (effectiveCtx.currentState.length === 0 || effectiveCtx.targetState.length === 0) {
245
+ // Resource cleanup case: no target state means we need to invalidate current states
246
+ if (effectiveCtx.targetState.length === 0 && effectiveCtx.currentState.length > 0) {
247
+ const cleanupCandidates = findCleanupFunctions(effectiveCtx);
248
+ // P3.10: Goal expansion — add prerequisite chains from goal templates
249
+ const goalCandidates = effectiveCtx.goal ? expandGoalAsCandidates(effectiveCtx.goal, effectiveCtx) : [];
250
+ const all = [...cleanupCandidates, ...goalCandidates];
251
+ if (all.length > 0)
252
+ return all;
253
+ }
254
+ // P3.10: Try goal expansion before giving up
255
+ if (effectiveCtx.goal) {
256
+ const goalCandidates = expandGoalAsCandidates(effectiveCtx.goal, effectiveCtx);
257
+ if (goalCandidates.length > 0)
258
+ return goalCandidates;
259
+ }
260
+ // P3.14: Frontier exploration — BFS from current state for any path
261
+ const frontierPaths = (0, protocol_frontier_1.exploreFrontier)(effectiveCtx.rules, effectiveCtx.currentState, 10, 6);
262
+ if (frontierPaths.length > 0) {
263
+ return frontierPaths.map(actions => ({
264
+ id: candidateId("protocol", actions.map(fnToAction)),
265
+ source: "protocol",
266
+ actions: actions.map(fnToAction),
267
+ explanation: `协议前沿探索: ${actions.join(" → ")}`,
268
+ evidence: 0,
269
+ metadata: { pathLength: actions.length, source: "frontier-bfs" },
270
+ }));
271
+ }
272
+ // P3.15: Cross-protocol candidates — expanded to all 9 protocol groups (P7.3)
273
+ const xProtoPaths = (0, protocol_frontier_1.expandCrossProtocolCandidates)(effectiveCtx.goal || "repair", [
274
+ "AuthProtocol", "FileProtocol", "DBProtocol", "IRProtocol",
275
+ "TransactionProtocol", "ConditionalProtocol", "LoopProtocol",
276
+ "CrossProtocol", "StatelessProtocol",
277
+ ]);
278
+ if (xProtoPaths.length > 0) {
279
+ return xProtoPaths.map(actions => ({
280
+ id: candidateId("protocol", actions.map(fnToAction)),
281
+ source: "protocol",
282
+ actions: actions.map(fnToAction),
283
+ explanation: `跨协议规划: ${actions.join(" → ")}`,
284
+ evidence: 0,
285
+ metadata: { pathLength: actions.length, source: "cross-protocol" },
286
+ }));
287
+ }
288
+ const fixPath = (0, ssg_validator_1.findFixPathStatic)(effectiveCtx.rules, effectiveCtx.protocol, effectiveCtx.currentState, effectiveCtx.targetState);
289
+ if (fixPath.length === 0)
290
+ return [];
291
+ return [{
292
+ id: candidateId("protocol", fixPath.map(fnToAction)),
293
+ source: "protocol",
294
+ actions: fixPath.map(fnToAction),
295
+ explanation: `按 SSG 协议,需先经过: ${fixPath.join(" → ")}`,
296
+ evidence: 0,
297
+ metadata: { pathLength: fixPath.length },
298
+ }];
299
+ }
300
+ // Full BFS: find multiple distinct paths from currentState to targetState
301
+ const allPaths = [];
302
+ const queue = [
303
+ { state: [...effectiveCtx.currentState], path: [], depth: 0 },
304
+ ];
305
+ const visited = new Set();
306
+ visited.add(effectiveCtx.currentState.join(","));
307
+ const MAX_PATHS = 10;
308
+ const MAX_DEPTH = 8;
309
+ while (queue.length > 0 && allPaths.length < MAX_PATHS) {
310
+ const { state, path, depth } = queue.shift();
311
+ if (depth >= MAX_DEPTH)
312
+ continue;
313
+ // Check if target states are a subset of current state
314
+ if (effectiveCtx.targetState.every(t => state.includes(t)) && path.length > 0) {
315
+ allPaths.push([...path]);
316
+ continue;
317
+ }
318
+ // Find all functions that can be called from current state
319
+ for (const [funcName, rule] of effectiveCtx.rules) {
320
+ if (rule.pre_states.every((pre) => state.includes(pre))) {
321
+ const newState = [...state];
322
+ if (rule.invalidate)
323
+ rule.invalidate.forEach(s => {
324
+ const idx = newState.indexOf(s);
325
+ if (idx >= 0)
326
+ newState.splice(idx, 1);
327
+ });
328
+ for (const post of rule.post_states) {
329
+ if (!newState.includes(post))
330
+ newState.push(post);
331
+ }
332
+ const stateKey = newState.sort().join(",");
333
+ if (!visited.has(stateKey)) {
334
+ visited.add(stateKey);
335
+ queue.push({
336
+ state: newState,
337
+ path: [...path, funcName],
338
+ depth: depth + 1,
339
+ });
340
+ }
341
+ }
342
+ }
343
+ }
344
+ const candidates = [];
345
+ for (let i = 0; i < allPaths.length; i++) {
346
+ const fp = allPaths[i];
347
+ candidates.push({
348
+ id: candidateId("protocol", fp.map(fnToAction)),
349
+ source: "protocol",
350
+ actions: fp.map(fnToAction),
351
+ explanation: `协议路径 ${i + 1}: ${fp.join(" → ")} (${fp.length} 步)`,
352
+ evidence: 0,
353
+ metadata: { pathLength: fp.length, pathIndex: i },
354
+ });
355
+ }
356
+ return candidates;
357
+ }
358
+ }
359
+ exports.ProtocolSearchStrategy = ProtocolSearchStrategy;
360
+ // ═══════════════════════════════════════════════════════════════
361
+ // Strategy 3: Antibody Search — learned immune rules
362
+ // ═══════════════════════════════════════════════════════════════
363
+ class AntibodySearchStrategy {
364
+ constructor() {
365
+ this.name = "antibody";
366
+ }
367
+ search(ctx) {
368
+ const antibodiesDir = path.resolve(process.env.PROGMUNE_PROJECT_DIR || process.cwd(), ".progmune_corpus", "antibodies");
369
+ if (!fs.existsSync(antibodiesDir))
370
+ return [];
371
+ const candidates = [];
372
+ const files = fs.readdirSync(antibodiesDir).filter(f => f.startsWith("candidates_"));
373
+ for (const file of files) {
374
+ try {
375
+ const raw = JSON.parse(fs.readFileSync(path.join(antibodiesDir, file), "utf-8"));
376
+ if (!Array.isArray(raw))
377
+ continue;
378
+ for (const ab of raw) {
379
+ if (ab.pattern?.violationType !== ctx.violationType)
380
+ continue;
381
+ if (ctx.protocol !== "default" &&
382
+ ab.pattern?.protocol &&
383
+ ab.pattern.protocol !== ctx.protocol)
384
+ continue;
385
+ const fixPath = ab.suggestedFix?.fixPath || [];
386
+ if (fixPath.length === 0)
387
+ continue;
388
+ candidates.push({
389
+ id: candidateId("antibody", fixPath.map(fnToAction)),
390
+ source: "antibody",
391
+ actions: fixPath.map(fnToAction),
392
+ explanation: ab.suggestedFix?.description || `Antibody rule: ${ab.id}`,
393
+ evidence: ab.evidence?.occurrenceCount || 0,
394
+ metadata: {
395
+ avgSuccessRate: ab.evidence?.avgSuccessRate || 0,
396
+ occurrenceCount: ab.evidence?.occurrenceCount || 0,
397
+ },
398
+ });
399
+ }
400
+ }
401
+ catch {
402
+ /* skip corrupted files */
403
+ }
404
+ }
405
+ return candidates;
406
+ }
407
+ }
408
+ exports.AntibodySearchStrategy = AntibodySearchStrategy;
409
+ // ═══════════════════════════════════════════════════════════════
410
+ // Factory
411
+ // ═══════════════════════════════════════════════════════════════
412
+ /** Return the three default search strategies. */
413
+ function createDefaultStrategies() {
414
+ return [
415
+ new CorpusSearchStrategy(),
416
+ new ProtocolSearchStrategy(),
417
+ new AntibodySearchStrategy(),
418
+ ];
419
+ }