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,243 @@
1
+ "use strict";
2
+ /**
3
+ * P3.14-15: Protocol Frontier Explorer + Cross-Protocol Planner
4
+ *
5
+ * P3.14: BFS-based state→state search without template dependency.
6
+ * Given currentState and targetState, auto-discovers paths like
7
+ * SESSION_ACTIVE → logout → SESSION_CLOSED without needing
8
+ * a template for every goal variant.
9
+ *
10
+ * P3.15: Cross-protocol meta-graph for multi-protocol repair chains.
11
+ * Auth → File → DB → IR protocol composition.
12
+ * Enables repairs like "auth then file write then db insert".
13
+ *
14
+ * Target: reduce missing_candidate from 49% to <20%.
15
+ */
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.searchFrontier = searchFrontier;
18
+ exports.searchFrontierMulti = searchFrontierMulti;
19
+ exports.exploreFrontier = exploreFrontier;
20
+ exports.planCrossProtocol = planCrossProtocol;
21
+ exports.getProtocolBridges = getProtocolBridges;
22
+ exports.expandCrossProtocolCandidates = expandCrossProtocolCandidates;
23
+ const protocol_coverage_1 = require("./protocol-coverage");
24
+ /**
25
+ * BFS from currentState to find the shortest path reaching targetState.
26
+ *
27
+ * Unlike Goal Templates (which require manual patterns), this searches
28
+ * the protocol state graph directly. It discovers paths like:
29
+ * - SESSION_ACTIVE → logout → UNAUTHENTICATED
30
+ * - FILE_OPEN → close_file → (FILE_OPEN invalidated)
31
+ * - DB_CONNECTED → disconnect_db → (DB_CONNECTED invalidated)
32
+ *
33
+ * Works for any state pair defined in the protocol rules.
34
+ */
35
+ function searchFrontier(rules, currentStates, targetStates, maxDepth = 8) {
36
+ if (currentStates.length === 0) {
37
+ // If no current states, start from rules with no pre_states
38
+ const startable = new Set();
39
+ for (const [fn, rule] of rules) {
40
+ if (rule.pre_states.length === 0) {
41
+ for (const post of rule.post_states)
42
+ startable.add(post);
43
+ }
44
+ }
45
+ if (startable.size > 0) {
46
+ currentStates = [...startable];
47
+ }
48
+ }
49
+ const currentSet = new Set(currentStates);
50
+ const targetSet = new Set(targetStates);
51
+ // BFS
52
+ const visited = new Set();
53
+ const queue = [
54
+ { states: new Set(currentStates), actions: [], stateList: [...currentStates], cost: 0 },
55
+ ];
56
+ visited.add([...currentStates].sort().join(","));
57
+ while (queue.length > 0) {
58
+ const { states, actions, stateList, cost } = queue.shift();
59
+ // Target reached?
60
+ if (targetStates.length > 0 && targetStates.every(t => states.has(t))) {
61
+ return { actions, states: stateList, cost, found: true };
62
+ }
63
+ // Resource cleanup: if target is empty, found when all current states are invalidated
64
+ if (targetStates.length === 0 && actions.length > 0) {
65
+ // Check if any state was successfully invalidated
66
+ const remainingFileOpen = states.has("FILE_OPEN");
67
+ const remainingDbConnected = states.has("DB_CONNECTED");
68
+ if (!remainingFileOpen && !remainingDbConnected && actions.length > 0) {
69
+ return { actions, states: stateList, cost, found: true };
70
+ }
71
+ }
72
+ if (cost >= maxDepth)
73
+ continue;
74
+ for (const [fn, rule] of rules) {
75
+ // Can we apply this rule from current states?
76
+ const preStatesOk = rule.pre_states.length === 0 || rule.pre_states.every(p => states.has(p));
77
+ if (!preStatesOk)
78
+ continue;
79
+ const nextStates = new Set(states);
80
+ if (rule.invalidate)
81
+ rule.invalidate.forEach(s => nextStates.delete(s));
82
+ for (const post of rule.post_states)
83
+ nextStates.add(post);
84
+ const stateKey = [...nextStates].sort().join(",");
85
+ if (visited.has(stateKey))
86
+ continue;
87
+ visited.add(stateKey);
88
+ queue.push({
89
+ states: nextStates,
90
+ actions: [...actions, fn],
91
+ stateList: [...stateList, ...rule.post_states],
92
+ cost: cost + 1,
93
+ });
94
+ }
95
+ }
96
+ return { actions: [], states: [], cost: 0, found: false };
97
+ }
98
+ /**
99
+ * Multi-start frontier search: tries multiple initial state combinations
100
+ * to find the best path. Useful when currentState is ambiguous.
101
+ */
102
+ function searchFrontierMulti(rules, currentStatesCandidates, targetStates, maxDepth = 8) {
103
+ let best = { actions: [], states: [], cost: Infinity, found: false };
104
+ for (const startStates of currentStatesCandidates) {
105
+ const result = searchFrontier(rules, startStates, targetStates, maxDepth);
106
+ if (result.found && result.cost < best.cost) {
107
+ best = result;
108
+ }
109
+ }
110
+ return best;
111
+ }
112
+ /**
113
+ * Generate all reachable action sequences from a given state.
114
+ * Used as a candidate generator for Monte-Carlo style planning (P3.16).
115
+ */
116
+ function exploreFrontier(rules, currentStates, maxPaths = 20, maxDepth = 6) {
117
+ const paths = [];
118
+ const visited = new Set();
119
+ const queue = [
120
+ { states: new Set(currentStates), actions: [], cost: 0 },
121
+ ];
122
+ while (queue.length > 0 && paths.length < maxPaths) {
123
+ const { states, actions, cost } = queue.shift();
124
+ if (cost >= maxDepth)
125
+ continue;
126
+ for (const [fn, rule] of rules) {
127
+ const preOk = rule.pre_states.length === 0 || rule.pre_states.every(p => states.has(p));
128
+ if (!preOk)
129
+ continue;
130
+ const next = new Set(states);
131
+ if (rule.invalidate)
132
+ rule.invalidate.forEach(s => next.delete(s));
133
+ for (const post of rule.post_states)
134
+ next.add(post);
135
+ const key = [...next].sort().join(",");
136
+ if (visited.has(key))
137
+ continue;
138
+ visited.add(key);
139
+ const newActions = [...actions, fn];
140
+ if (newActions.length >= 1)
141
+ paths.push(newActions);
142
+ queue.push({ states: next, actions: newActions, cost: cost + 1 });
143
+ }
144
+ }
145
+ return paths;
146
+ }
147
+ /** Known bridges between protocols. */
148
+ const PROTOCOL_BRIDGES = [
149
+ // Original bridges
150
+ { from: "AuthProtocol", to: "FileProtocol", outputState: "SESSION_ACTIVE", inputState: "INIT" },
151
+ { from: "AuthProtocol", to: "DBProtocol", outputState: "SESSION_ACTIVE", inputState: "INIT" },
152
+ { from: "FileProtocol", to: "DBProtocol", outputState: "FILE_OPEN", inputState: "INIT" },
153
+ { from: "DBProtocol", to: "IRProtocol", outputState: "DB_CONNECTED", inputState: "IR_STALE" },
154
+ { from: "IRProtocol", to: "FileProtocol", outputState: "CODE_EMITTED", inputState: "INIT" },
155
+ // P7.3: New protocol bridges
156
+ { from: "AuthProtocol", to: "TransactionProtocol", outputState: "SESSION_ACTIVE", inputState: "TX_IDLE" },
157
+ { from: "AuthProtocol", to: "ConditionalProtocol", outputState: "SESSION_ACTIVE", inputState: "COND_IDLE" },
158
+ { from: "AuthProtocol", to: "LoopProtocol", outputState: "SESSION_ACTIVE", inputState: "LOOP_IDLE" },
159
+ { from: "AuthProtocol", to: "CrossProtocol", outputState: "SESSION_ACTIVE", inputState: "UNAUTHENTICATED" },
160
+ { from: "TransactionProtocol", to: "DBProtocol", outputState: "TX_IDLE", inputState: "INIT" },
161
+ { from: "ConditionalProtocol", to: "FileProtocol", outputState: "COND_ACCEPTED", inputState: "INIT" },
162
+ { from: "ConditionalProtocol", to: "DBProtocol", outputState: "COND_ACCEPTED", inputState: "INIT" },
163
+ { from: "LoopProtocol", to: "FileProtocol", outputState: "LOOP_DONE", inputState: "INIT" },
164
+ { from: "LoopProtocol", to: "DBProtocol", outputState: "LOOP_DONE", inputState: "INIT" },
165
+ { from: "FileProtocol", to: "CrossProtocol", outputState: "FILE_OPEN", inputState: "AUTH_FILE_GATE" },
166
+ { from: "DBProtocol", to: "CrossProtocol", outputState: "DB_CONNECTED", inputState: "AUTH_DB_GATE" },
167
+ { from: "StatelessProtocol", to: "FileProtocol", outputState: "IDLE", inputState: "INIT" },
168
+ { from: "StatelessProtocol", to: "DBProtocol", outputState: "IDLE", inputState: "INIT" },
169
+ { from: "StatelessProtocol", to: "TransactionProtocol", outputState: "IDLE", inputState: "TX_IDLE" },
170
+ ];
171
+ /**
172
+ * Find a cross-protocol action chain for a multi-protocol goal.
173
+ *
174
+ * Decomposes the goal into protocol segments, plans each segment
175
+ * using the frontier explorer, and stitches them together via bridges.
176
+ */
177
+ function planCrossProtocol(goal, protocols, targetProtocols, initialStates = {}) {
178
+ const bridges = [];
179
+ const allActions = [];
180
+ const orderedProtocols = [];
181
+ // Order protocols by bridge connectivity
182
+ if (targetProtocols.length <= 1) {
183
+ // Single protocol: just use frontier
184
+ const proto = protocols.find(p => p.name === targetProtocols[0]);
185
+ if (proto) {
186
+ const path = searchFrontier(proto.rules, initialStates[proto.name] || [], [], 8);
187
+ return { protocols: [proto.name], bridges: [], actions: path.actions };
188
+ }
189
+ }
190
+ // Multi-protocol: chain through bridges
191
+ for (let i = 0; i < targetProtocols.length; i++) {
192
+ const current = targetProtocols[i];
193
+ orderedProtocols.push(current);
194
+ if (i < targetProtocols.length - 1) {
195
+ const next = targetProtocols[i + 1];
196
+ const bridge = PROTOCOL_BRIDGES.find(b => b.from === current && b.to === next);
197
+ if (bridge)
198
+ bridges.push(bridge);
199
+ }
200
+ }
201
+ // Plan each protocol segment
202
+ for (const protoName of orderedProtocols) {
203
+ const proto = protocols.find(p => p.name === protoName);
204
+ if (!proto)
205
+ continue;
206
+ const init = initialStates[protoName] || [];
207
+ const path = searchFrontier(proto.rules, init, [], 8);
208
+ if (path.found)
209
+ allActions.push(...path.actions);
210
+ }
211
+ return { protocols: orderedProtocols, bridges, actions: allActions };
212
+ }
213
+ /** Get protocol bridges for visualization. */
214
+ function getProtocolBridges() {
215
+ return [...PROTOCOL_BRIDGES];
216
+ }
217
+ /**
218
+ * Generate cross-protocol candidate actions for a multi-protocol goal.
219
+ * Used by ProtocolStrategy to expand candidates beyond single-protocol BFS.
220
+ */
221
+ function expandCrossProtocolCandidates(goal, targetProtocols) {
222
+ const allDefs = (0, protocol_coverage_1.loadDefaultProtocolDefinitions)();
223
+ const protoMap = new Map(allDefs.map(p => [p.name, p]));
224
+ const candidates = [];
225
+ // For each target protocol, generate frontier paths
226
+ for (const tp of targetProtocols) {
227
+ const proto = protoMap.get(tp);
228
+ if (!proto)
229
+ continue;
230
+ const frontierPaths = exploreFrontier(proto.rules, [], 10, 6);
231
+ for (const path of frontierPaths) {
232
+ if (path.length > 0)
233
+ candidates.push(path);
234
+ }
235
+ }
236
+ // For multi-protocol: stitch via bridges
237
+ if (targetProtocols.length > 1) {
238
+ const plan = planCrossProtocol(goal, allDefs, targetProtocols);
239
+ if (plan.actions.length > 0)
240
+ candidates.push(plan.actions);
241
+ }
242
+ return candidates;
243
+ }
@@ -0,0 +1,92 @@
1
+ "use strict";
2
+ /**
3
+ * P3.14-15: Protocol Frontier Explorer Tests
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const vitest_1 = require("vitest");
7
+ const protocol_frontier_1 = require("./protocol-frontier");
8
+ function makeRules() {
9
+ return new Map([
10
+ ["verify_password", { pre_states: ["UNAUTHENTICATED"], post_states: ["PASSWORD_VERIFIED"] }],
11
+ ["generate_jwt", { pre_states: ["PASSWORD_VERIFIED"], post_states: ["TOKEN_ISSUED"], invalidate: ["PASSWORD_VERIFIED"] }],
12
+ ["create_session", { pre_states: ["TOKEN_ISSUED"], post_states: ["SESSION_ACTIVE"], invalidate: ["TOKEN_ISSUED"] }],
13
+ ["logout", { pre_states: ["SESSION_ACTIVE"], post_states: ["UNAUTHENTICATED"], invalidate: ["SESSION_ACTIVE"] }],
14
+ ["open_file", { pre_states: [], post_states: ["FILE_OPEN"] }],
15
+ ["close_file", { pre_states: ["FILE_OPEN"], post_states: [], invalidate: ["FILE_OPEN"] }],
16
+ ["connect_db", { pre_states: [], post_states: ["DB_CONNECTED"] }],
17
+ ["disconnect_db", { pre_states: ["DB_CONNECTED"], post_states: [], invalidate: ["DB_CONNECTED"] }],
18
+ ]);
19
+ }
20
+ (0, vitest_1.describe)("Frontier Explorer", () => {
21
+ (0, vitest_1.it)("finds auth path from UNAUTHENTICATED to SESSION_ACTIVE", () => {
22
+ const rules = makeRules();
23
+ const path = (0, protocol_frontier_1.searchFrontier)(rules, ["UNAUTHENTICATED"], ["SESSION_ACTIVE"]);
24
+ (0, vitest_1.expect)(path.found).toBe(true);
25
+ (0, vitest_1.expect)(path.actions).toContain("verify_password");
26
+ (0, vitest_1.expect)(path.actions).toContain("generate_jwt");
27
+ (0, vitest_1.expect)(path.actions).toContain("create_session");
28
+ (0, vitest_1.expect)(path.cost).toBe(3);
29
+ });
30
+ (0, vitest_1.it)("finds logout path from SESSION_ACTIVE to UNAUTHENTICATED", () => {
31
+ const rules = makeRules();
32
+ const path = (0, protocol_frontier_1.searchFrontier)(rules, ["SESSION_ACTIVE"], ["UNAUTHENTICATED"]);
33
+ (0, vitest_1.expect)(path.found).toBe(true);
34
+ (0, vitest_1.expect)(path.actions).toEqual(["logout"]);
35
+ (0, vitest_1.expect)(path.cost).toBe(1);
36
+ });
37
+ (0, vitest_1.it)("finds close_file cleanup from FILE_OPEN", () => {
38
+ const rules = makeRules();
39
+ const path = (0, protocol_frontier_1.searchFrontier)(rules, ["FILE_OPEN"], []);
40
+ (0, vitest_1.expect)(path.found).toBe(true);
41
+ (0, vitest_1.expect)(path.actions).toContain("close_file");
42
+ });
43
+ (0, vitest_1.it)("returns not found for unreachable target", () => {
44
+ const rules = makeRules();
45
+ const path = (0, protocol_frontier_1.searchFrontier)(rules, ["UNAUTHENTICATED"], ["NONEXISTENT"]);
46
+ (0, vitest_1.expect)(path.found).toBe(false);
47
+ });
48
+ (0, vitest_1.it)("explores frontier: generates multiple paths", () => {
49
+ const rules = makeRules();
50
+ const paths = (0, protocol_frontier_1.exploreFrontier)(rules, ["UNAUTHENTICATED"], 20, 6);
51
+ (0, vitest_1.expect)(paths.length).toBeGreaterThan(1);
52
+ // Should include auth chain
53
+ const hasAuth = paths.some(p => p.includes("verify_password") && p.includes("generate_jwt") && p.includes("create_session"));
54
+ (0, vitest_1.expect)(hasAuth).toBe(true);
55
+ });
56
+ (0, vitest_1.it)("multi-start finds best path among candidates", () => {
57
+ const rules = makeRules();
58
+ const path = (0, protocol_frontier_1.searchFrontierMulti)(rules, [
59
+ ["FILE_OPEN"],
60
+ ["SESSION_ACTIVE"],
61
+ ], ["UNAUTHENTICATED"]);
62
+ // SESSION_ACTIVE→logout→UNAUTHENTICATED is 1 step, better than FILE_OPEN→close→open→auth→...
63
+ (0, vitest_1.expect)(path.found).toBe(true);
64
+ (0, vitest_1.expect)(path.cost).toBe(1);
65
+ (0, vitest_1.expect)(path.actions).toContain("logout");
66
+ });
67
+ });
68
+ (0, vitest_1.describe)("Cross-Protocol Planner", () => {
69
+ (0, vitest_1.it)("has protocol bridges", () => {
70
+ const bridges = (0, protocol_frontier_1.getProtocolBridges)();
71
+ (0, vitest_1.expect)(bridges.length).toBeGreaterThanOrEqual(3);
72
+ (0, vitest_1.expect)(bridges.some(b => b.from === "AuthProtocol" && b.to === "FileProtocol")).toBe(true);
73
+ (0, vitest_1.expect)(bridges.some(b => b.from === "AuthProtocol" && b.to === "DBProtocol")).toBe(true);
74
+ });
75
+ (0, vitest_1.it)("plans single protocol", () => {
76
+ const rules = makeRules();
77
+ const plan = (0, protocol_frontier_1.planCrossProtocol)("logout", [
78
+ { name: "AuthProtocol", rules },
79
+ ], ["AuthProtocol"], { AuthProtocol: ["SESSION_ACTIVE"] });
80
+ (0, vitest_1.expect)(plan.actions.length).toBeGreaterThan(0);
81
+ (0, vitest_1.expect)(plan.actions).toContain("logout");
82
+ });
83
+ (0, vitest_1.it)("generates cross-protocol candidates", () => {
84
+ const candidates = (0, protocol_frontier_1.expandCrossProtocolCandidates)("multi-step repair", ["FileProtocol", "DBProtocol"]);
85
+ // Should find paths for both protocols
86
+ (0, vitest_1.expect)(candidates.length).toBeGreaterThan(1);
87
+ // At least one file path and one db path
88
+ const hasFile = candidates.some(p => p.includes("open_file") || p.includes("close_file"));
89
+ const hasDb = candidates.some(p => p.includes("connect_db") || p.includes("disconnect_db"));
90
+ (0, vitest_1.expect)(hasFile || hasDb).toBe(true);
91
+ });
92
+ });
@@ -0,0 +1,228 @@
1
+ "use strict";
2
+ /**
3
+ * P3.16-17: Protocol Gap Mining + Knowledge Acquisition Planner
4
+ *
5
+ * Decomposes the 57% missing_candidate into actionable categories:
6
+ * - Missing Actions: functions in expected repair but not in any protocol rule
7
+ * - Missing Transitions: state pairs not connected by any rule
8
+ * - Missing Cross-Protocol Bridges: protocol pairs with no bridge definition
9
+ *
10
+ * This transforms protocol expansion from guesswork to data-driven prioritization.
11
+ *
12
+ * Fourth flywheel:
13
+ * Failures → Missing Knowledge → Protocol Expansion → Better Candidates
14
+ */
15
+ Object.defineProperty(exports, "__esModule", { value: true });
16
+ exports.analyzeProtocolGaps = analyzeProtocolGaps;
17
+ exports.computeKnowledgeScores = computeKnowledgeScores;
18
+ exports.printGapReport = printGapReport;
19
+ exports.printKnowledgeScores = printKnowledgeScores;
20
+ const protocol_coverage_1 = require("./protocol-coverage");
21
+ const protocol_frontier_1 = require("./protocol-frontier");
22
+ // ═══════════════════════════════════════════════════════════════
23
+ // Gap Analyzer
24
+ // ═══════════════════════════════════════════════════════════════
25
+ /**
26
+ * Analyze benchmark failures to identify which actions/transitions
27
+ * are missing from the protocol definitions.
28
+ */
29
+ function analyzeProtocolGaps(attributed, rules // protocol → set of function names
30
+ ) {
31
+ const failures = attributed.filter(a => a.failureReason !== "success");
32
+ const gapMap = new Map();
33
+ for (const f of failures) {
34
+ for (const fn of f.expectedRepair) {
35
+ // Check if this function exists in any protocol
36
+ let found = false;
37
+ for (const [, fns] of rules) {
38
+ if (fns.has(fn)) {
39
+ found = true;
40
+ break;
41
+ }
42
+ }
43
+ if (!found) {
44
+ const key = `action:${fn}`;
45
+ const existing = gapMap.get(key);
46
+ if (existing) {
47
+ existing.protocols.add(f.protocol);
48
+ existing.examples.push(f.goal);
49
+ }
50
+ else {
51
+ gapMap.set(key, {
52
+ kind: "missing_action",
53
+ protocols: new Set([f.protocol]),
54
+ examples: [f.goal],
55
+ });
56
+ }
57
+ }
58
+ }
59
+ // Check for missing transitions: consecutive function pairs in expected
60
+ for (let i = 0; i < f.expectedRepair.length - 1; i++) {
61
+ const from = f.expectedRepair[i];
62
+ const to = f.expectedRepair[i + 1];
63
+ const key = `transition:${from}→${to}`;
64
+ if (!gapMap.has(key)) {
65
+ gapMap.set(key, {
66
+ kind: "missing_transition",
67
+ protocols: new Set([f.protocol]),
68
+ examples: [f.goal],
69
+ });
70
+ }
71
+ else {
72
+ gapMap.get(key).examples.push(f.goal);
73
+ }
74
+ }
75
+ }
76
+ // Cross-protocol bridge gaps
77
+ const bridges = (0, protocol_frontier_1.getProtocolBridges)();
78
+ const bridgePairs = new Set(bridges.map(b => `${b.from}→${b.to}`));
79
+ const crossProtocolFailures = failures.filter(f => f.expectedRepair.some(fn => fn.includes("file")) &&
80
+ f.expectedRepair.some(fn => fn.includes("db")));
81
+ for (const f of crossProtocolFailures) {
82
+ // Check if there's a bridge connecting the protocols involved
83
+ const protoSet = new Set();
84
+ for (const fn of f.expectedRepair) {
85
+ for (const [proto, fns] of rules) {
86
+ if (fns.has(fn))
87
+ protoSet.add(proto);
88
+ }
89
+ }
90
+ const protoList = [...protoSet];
91
+ for (let i = 0; i < protoList.length - 1; i++) {
92
+ const pair = `${protoList[i]}→${protoList[i + 1]}`;
93
+ if (!bridgePairs.has(pair)) {
94
+ const key = `bridge:${pair}`;
95
+ if (!gapMap.has(key)) {
96
+ gapMap.set(key, {
97
+ kind: "missing_bridge",
98
+ protocols: new Set(protoList),
99
+ examples: [f.goal],
100
+ });
101
+ }
102
+ else {
103
+ gapMap.get(key).examples.push(f.goal);
104
+ }
105
+ }
106
+ }
107
+ }
108
+ // Convert to sorted list with priority scores
109
+ const totalFailures = failures.length;
110
+ const gaps = [];
111
+ const byKind = {
112
+ missing_action: { count: 0, items: [] },
113
+ missing_transition: { count: 0, items: [] },
114
+ missing_bridge: { count: 0, items: [] },
115
+ missing_protocol: { count: 0, items: [] },
116
+ };
117
+ for (const [key, entry] of gapMap) {
118
+ const kind = entry.kind;
119
+ const item = key.split(":")[1] || key;
120
+ const frequency = entry.examples.length;
121
+ const priority = Math.min(1, frequency / Math.max(1, totalFailures));
122
+ byKind[kind].count++;
123
+ byKind[kind].items.push(item);
124
+ gaps.push({
125
+ kind,
126
+ item,
127
+ protocols: [...entry.protocols],
128
+ frequency,
129
+ examples: entry.examples.slice(0, 3),
130
+ priority,
131
+ });
132
+ }
133
+ gaps.sort((a, b) => b.priority - a.priority);
134
+ return {
135
+ totalFailures,
136
+ failuresAnalyzed: failures.length,
137
+ gaps,
138
+ byKind: byKind,
139
+ topMissingActions: gaps.filter(g => g.kind === "missing_action").slice(0, 10).map(g => g.item),
140
+ topMissingTransitions: gaps.filter(g => g.kind === "missing_transition").slice(0, 10).map(g => g.item),
141
+ topMissingBridges: gaps.filter(g => g.kind === "missing_bridge").slice(0, 5).map(g => g.item),
142
+ };
143
+ }
144
+ /**
145
+ * Compute a per-protocol knowledge score.
146
+ * score = 0.4*coverage + 0.3*successRate + 0.2*benchmarkPassRate + 0.1*corpusSupport
147
+ */
148
+ function computeKnowledgeScores(failures) {
149
+ const protocols = (0, protocol_coverage_1.loadDefaultProtocolDefinitions)();
150
+ return protocols.map(p => {
151
+ const relevant = failures.filter(f => f.protocol === p.name || f.expectedRepair.some(fn => p.rules.has(fn)));
152
+ const passed = relevant.filter(f => f.failureReason === "success").length;
153
+ const total = relevant.length;
154
+ // Coverage: states defined / total transitions
155
+ const coverage = p.states.length > 0 ? Math.min(1, p.states.length / 20) : 0;
156
+ const successRate = total > 0 ? passed / total : 0;
157
+ const benchmarkPassRate = total > 0 ? passed / total : 0;
158
+ const corpusSupport = total > 0 ? Math.min(1, total / 50) : 0;
159
+ const score = 0.4 * coverage + 0.3 * successRate + 0.2 * benchmarkPassRate + 0.1 * corpusSupport;
160
+ return {
161
+ protocol: p.name,
162
+ coverage,
163
+ successRate,
164
+ benchmarkPassRate,
165
+ corpusSupport,
166
+ score,
167
+ gaps: relevant.filter(f => f.failureReason !== "success").length,
168
+ };
169
+ }).sort((a, b) => b.score - a.score);
170
+ }
171
+ // ═══════════════════════════════════════════════════════════════
172
+ // Dashboard
173
+ // ═══════════════════════════════════════════════════════════════
174
+ function printGapReport(report) {
175
+ console.log("\n╔════════════════════════════════════════════════════╗");
176
+ console.log("║ Protocol Gap Mining Report ║");
177
+ console.log("╚════════════════════════════════════════════════════╝\n");
178
+ console.log(`Failures Analyzed: ${report.failuresAnalyzed}/${report.totalFailures}`);
179
+ console.log(`Gaps Found: ${report.gaps.length}`);
180
+ console.log();
181
+ console.log("─── Gap Breakdown ───");
182
+ for (const [kind, info] of Object.entries(report.byKind)) {
183
+ if (info.count === 0)
184
+ continue;
185
+ const label = kind.replace(/_/g, " ").padEnd(22);
186
+ console.log(` ${label} ${String(info.count).padStart(4)} items`);
187
+ }
188
+ console.log();
189
+ if (report.topMissingActions.length > 0) {
190
+ console.log("─── Top Missing Actions (add to protocol rules) ───");
191
+ const tops = report.gaps.filter(g => g.kind === "missing_action").slice(0, 10);
192
+ for (const g of tops) {
193
+ console.log(` ${g.item.padEnd(25)} freq=${g.frequency} pri=${(g.priority * 100).toFixed(0)}%`);
194
+ }
195
+ console.log();
196
+ }
197
+ if (report.topMissingTransitions.length > 0) {
198
+ console.log("─── Top Missing Transitions ───");
199
+ for (const t of report.topMissingTransitions.slice(0, 5)) {
200
+ console.log(` ${t}`);
201
+ }
202
+ console.log();
203
+ }
204
+ if (report.topMissingBridges.length > 0) {
205
+ console.log("─── Top Missing Bridges ───");
206
+ for (const b of report.topMissingBridges) {
207
+ console.log(` ${b}`);
208
+ }
209
+ console.log();
210
+ }
211
+ }
212
+ function printKnowledgeScores(scores) {
213
+ console.log("\n╔════════════════════════════════════════════════════╗");
214
+ console.log("║ Protocol Knowledge Scoreboard ║");
215
+ console.log("╚════════════════════════════════════════════════════╝\n");
216
+ console.log("Protocol Covrg Succ Bench Corpus Score Gaps");
217
+ console.log("──────────────────────────────────────────────────────────");
218
+ for (const s of scores) {
219
+ const cov = (s.coverage * 100).toFixed(0).padStart(4);
220
+ const suc = (s.successRate * 100).toFixed(0).padStart(4);
221
+ const ben = (s.benchmarkPassRate * 100).toFixed(0).padStart(4);
222
+ const cor = (s.corpusSupport * 100).toFixed(0).padStart(4);
223
+ const scr = (s.score * 100).toFixed(0).padStart(4);
224
+ const icon = s.score > 0.7 ? "🟢" : s.score > 0.4 ? "🟡" : "🔴";
225
+ console.log(` ${s.protocol.padEnd(16)} ${cov}% ${suc}% ${ben}% ${cor}% ${scr}% ${String(s.gaps).padStart(4)} ${icon}`);
226
+ }
227
+ console.log();
228
+ }
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ /**
3
+ * P3.16-17: Protocol Gap Mining Tests
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const vitest_1 = require("vitest");
7
+ const protocol_gap_analyzer_1 = require("./protocol-gap-analyzer");
8
+ function makeAttributedCases() {
9
+ return [
10
+ { caseId: "c1", goal: "authenticate user", protocol: "AuthProtocol", violationType: "missing_prerequisite", expectedRepair: ["verify_password", "generate_jwt", "create_session"], plannerTop1: ["logout"], candidatesReturned: 1, rank: null, failureReason: "missing_candidate" },
11
+ { caseId: "c2", goal: "authenticate user", protocol: "AuthProtocol", violationType: "missing_prerequisite", expectedRepair: ["verify_password", "generate_jwt", "create_session"], plannerTop1: ["logout"], candidatesReturned: 1, rank: null, failureReason: "missing_candidate" },
12
+ { caseId: "c3", goal: "full auth lifecycle", protocol: "AuthProtocol", violationType: "missing_prerequisite", expectedRepair: ["verify_password", "generate_jwt", "create_session", "logout"], plannerTop1: ["logout"], candidatesReturned: 1, rank: null, failureReason: "missing_candidate" },
13
+ { caseId: "c4", goal: "safely write file", protocol: "FileProtocol", violationType: "resource_leak", expectedRepair: ["open_file", "write_file", "flush_file", "close_file"], plannerTop1: ["close_file"], candidatesReturned: 1, rank: null, failureReason: "missing_candidate" },
14
+ { caseId: "c5", goal: "safely write file", protocol: "FileProtocol", violationType: "resource_leak", expectedRepair: ["open_file", "write_file", "flush_file", "close_file"], plannerTop1: ["close_file"], candidatesReturned: 1, rank: null, failureReason: "missing_candidate" },
15
+ { caseId: "c6", goal: "query db safely", protocol: "DBProtocol", violationType: "missing_prerequisite", expectedRepair: ["connect_db", "query_db", "disconnect_db"], plannerTop1: ["disconnect_db"], candidatesReturned: 1, rank: null, failureReason: "missing_candidate" },
16
+ { caseId: "c7", goal: "auth then file then db", protocol: "FileProtocol", violationType: "resource_leak", expectedRepair: ["verify_password", "open_file", "write_file", "close_file", "connect_db", "query_db", "disconnect_db"], plannerTop1: ["close_file"], candidatesReturned: 1, rank: null, failureReason: "missing_candidate" },
17
+ { caseId: "c8", goal: "success case", protocol: "FileProtocol", violationType: "resource_leak", expectedRepair: ["open_file", "write_file", "close_file"], plannerTop1: ["open_file", "write_file", "close_file"], candidatesReturned: 3, rank: 1, failureReason: "success" },
18
+ ];
19
+ }
20
+ (0, vitest_1.describe)("Protocol Gap Analyzer", () => {
21
+ (0, vitest_1.it)("identifies missing actions from failures", () => {
22
+ const cases = makeAttributedCases();
23
+ // Build rules map: only existing protocol functions
24
+ const rules = new Map();
25
+ rules.set("AuthProtocol", new Set(["verify_password", "generate_jwt", "create_session", "logout", "revoke_token"]));
26
+ rules.set("FileProtocol", new Set(["open_file", "read_file", "write_file", "close_file"]));
27
+ rules.set("DBProtocol", new Set(["connect_db", "query_db", "disconnect_db"]));
28
+ rules.set("IRProtocol", new Set(["extractIR", "validateAction", "validateActionSequence", "emitCode", "recordSession"]));
29
+ const report = (0, protocol_gap_analyzer_1.analyzeProtocolGaps)(cases, rules);
30
+ (0, vitest_1.expect)(report.failuresAnalyzed).toBe(7); // 8 total, 1 success
31
+ (0, vitest_1.expect)(report.gaps.length).toBeGreaterThan(0);
32
+ // flush_file should appear as a missing action
33
+ const missingActions = report.gaps.filter(g => g.kind === "missing_action");
34
+ (0, vitest_1.expect)(missingActions.some(g => g.item === "flush_file")).toBe(true);
35
+ // flush_file appears in 2 cases (c4, c5)
36
+ const flushGap = missingActions.find(g => g.item === "flush_file");
37
+ (0, vitest_1.expect)(flushGap?.frequency).toBe(2);
38
+ (0, protocol_gap_analyzer_1.printGapReport)(report);
39
+ });
40
+ (0, vitest_1.it)("computes knowledge scores per protocol", () => {
41
+ const cases = makeAttributedCases();
42
+ const scores = (0, protocol_gap_analyzer_1.computeKnowledgeScores)(cases);
43
+ (0, vitest_1.expect)(scores.length).toBeGreaterThanOrEqual(4); // P7.3: 9 protocol groups
44
+ // FileProtocol has success case → higher score
45
+ const file = scores.find(s => s.protocol === "FileProtocol");
46
+ (0, vitest_1.expect)(file.successRate).toBeGreaterThan(0);
47
+ (0, protocol_gap_analyzer_1.printKnowledgeScores)(scores);
48
+ });
49
+ });