progmune-runtime 2.1.6 → 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 +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 +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,150 @@
1
+ "use strict";
2
+ /**
3
+ * P3.21-23: Knowledge Governance Tests
4
+ */
5
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k;
7
+ var desc = Object.getOwnPropertyDescriptor(m, k);
8
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
9
+ desc = { enumerable: true, get: function() { return m[k]; } };
10
+ }
11
+ Object.defineProperty(o, k2, desc);
12
+ }) : (function(o, m, k, k2) {
13
+ if (k2 === undefined) k2 = k;
14
+ o[k2] = m[k];
15
+ }));
16
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
17
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
18
+ }) : function(o, v) {
19
+ o["default"] = v;
20
+ });
21
+ var __importStar = (this && this.__importStar) || (function () {
22
+ var ownKeys = function(o) {
23
+ ownKeys = Object.getOwnPropertyNames || function (o) {
24
+ var ar = [];
25
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
26
+ return ar;
27
+ };
28
+ return ownKeys(o);
29
+ };
30
+ return function (mod) {
31
+ if (mod && mod.__esModule) return mod;
32
+ var result = {};
33
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
34
+ __setModuleDefault(result, mod);
35
+ return result;
36
+ };
37
+ })();
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ const vitest_1 = require("vitest");
40
+ const fs = __importStar(require("fs"));
41
+ const path = __importStar(require("path"));
42
+ const knowledge_governance_1 = require("./knowledge-governance");
43
+ const GOV_DIR = path.resolve(__dirname, "..", "test-knowledge-gov");
44
+ process.env.PROGMUNE_PROJECT_DIR = GOV_DIR;
45
+ fs.mkdirSync(GOV_DIR, { recursive: true });
46
+ fs.mkdirSync(path.join(GOV_DIR, ".progmune_corpus", "knowledge"), { recursive: true });
47
+ function makeBaseRules() {
48
+ return new Map([
49
+ ["open_file", { pre_states: [], post_states: ["FILE_OPEN"] }],
50
+ ["write_file", { pre_states: ["FILE_OPEN"], post_states: ["FILE_DIRTY"] }],
51
+ ["close_file", { pre_states: ["FILE_OPEN", "FILE_DIRTY"], post_states: [], invalidate: ["FILE_OPEN", "FILE_DIRTY"] }],
52
+ ]);
53
+ }
54
+ (0, vitest_1.describe)("Inference Validator", () => {
55
+ (0, vitest_1.it)("classifies inferences as proposed/verified/rejected", () => {
56
+ const inferences = [
57
+ { from: "FILE_OPEN", to: "FILE_DIRTY", action: "open_file → flush_file", protocol: "FileProtocol", confidence: 1.0, evidenceCount: 1, examples: ["test"] },
58
+ { from: "FILE_OPEN", to: "FILE_DIRTY", action: "open_file → flush_file", protocol: "FileProtocol", confidence: 1.0, evidenceCount: 3, examples: ["a", "b", "c"] },
59
+ ];
60
+ const validated = (0, knowledge_governance_1.validateInferences)(inferences, 5); // 5 trajectory support
61
+ // First: only 1 benchmark → proposed
62
+ (0, vitest_1.expect)(validated[0].validation.status).toBe("proposed");
63
+ (0, vitest_1.expect)(validated[0].validation.benchmarkSupport).toBe(1);
64
+ (0, vitest_1.expect)(validated[0].validation.trajectorySupport).toBe(5);
65
+ // Second: 3 benchmarks + 5 trajectories → verified
66
+ (0, vitest_1.expect)(validated[1].validation.status).toBe("verified");
67
+ });
68
+ });
69
+ (0, vitest_1.describe)("Knowledge Patch Store", () => {
70
+ (0, vitest_1.it)("proposes, approves, rejects, and rolls back patches", () => {
71
+ const store = new knowledge_governance_1.KnowledgePatchStore(path.join(GOV_DIR, ".progmune_corpus", "knowledge", `test-${Date.now()}.json`));
72
+ const inference = {
73
+ from: "FILE_OPEN", to: "FILE_DIRTY", action: "open_file → flush_file",
74
+ protocol: "FileProtocol", confidence: 1.0, evidenceCount: 3, examples: ["a", "b", "c"],
75
+ validation: { benchmarkSupport: 3, trajectorySupport: 5, contradictionCount: 0, status: "verified" },
76
+ };
77
+ // Propose
78
+ const patch = store.propose(inference);
79
+ (0, vitest_1.expect)(patch.status).toBe("proposed");
80
+ (0, vitest_1.expect)(patch.id).toMatch(/^KP-/);
81
+ (0, vitest_1.expect)(store.proposed.length).toBe(1);
82
+ // Approve
83
+ const ok = store.approve(patch.id, { top1Before: 0.5, top1After: 0.55, top3Before: 0.7, top3After: 0.75 });
84
+ (0, vitest_1.expect)(ok).toBe(true);
85
+ (0, vitest_1.expect)(store.approved.length).toBe(1);
86
+ (0, vitest_1.expect)(store.approved[0].approvalMetrics?.top1After).toBe(0.55);
87
+ // Rollback
88
+ const rb = store.rollback(patch.id);
89
+ (0, vitest_1.expect)(rb).toBe(true);
90
+ (0, vitest_1.expect)(store.approved.length).toBe(0);
91
+ // Reject a new one
92
+ const p2 = store.propose(inference);
93
+ store.reject(p2.id);
94
+ (0, vitest_1.expect)(store.all.filter(p => p.status === "rejected").length).toBe(1);
95
+ });
96
+ (0, vitest_1.it)("builds augmented rules from approved patches", () => {
97
+ const store = new knowledge_governance_1.KnowledgePatchStore(path.join(GOV_DIR, ".progmune_corpus", "knowledge", `aug-${Date.now()}.json`));
98
+ const inference = {
99
+ from: "FILE_OPEN", to: "FILE_DIRTY", action: "open_file → flush_file",
100
+ protocol: "FileProtocol", confidence: 1.0, evidenceCount: 3, examples: ["a"],
101
+ validation: { benchmarkSupport: 3, trajectorySupport: 5, contradictionCount: 0, status: "verified" },
102
+ };
103
+ const patch = store.propose(inference);
104
+ store.approve(patch.id, { top1Before: 0.5, top1After: 0.6, top3Before: 0.7, top3After: 0.8 });
105
+ const baseRules = makeBaseRules();
106
+ const augmented = store.buildAugmentedRules(baseRules);
107
+ // Should have base rules + 1 patch bridge
108
+ (0, vitest_1.expect)(augmented.size).toBe(baseRules.size + 1);
109
+ const hasBridge = [...augmented.keys()].some(k => k.startsWith("_patch_"));
110
+ (0, vitest_1.expect)(hasBridge).toBe(true);
111
+ });
112
+ });
113
+ (0, vitest_1.describe)("Regression Test", () => {
114
+ (0, vitest_1.it)("auto-approves if Top-1/Top-3 improves", () => {
115
+ const store = new knowledge_governance_1.KnowledgePatchStore(path.join(GOV_DIR, ".progmune_corpus", "knowledge", `reg-${Date.now()}.json`));
116
+ const patch = store.propose({
117
+ from: "FILE_OPEN", to: "FILE_DIRTY", action: "open_file → flush_file",
118
+ protocol: "FileProtocol", confidence: 1.0, evidenceCount: 3, examples: ["a", "b", "c"],
119
+ validation: { benchmarkSupport: 3, trajectorySupport: 5, contradictionCount: 0, status: "verified" },
120
+ });
121
+ const baseRules = makeBaseRules();
122
+ // Test case: from FILE_OPEN to FILE_DIRTY — this path doesn't exist in base rules (open→write exists, but open→flush is missing)
123
+ const testCases = [
124
+ { currentState: ["FILE_OPEN"], targetState: ["FILE_DIRTY"] },
125
+ ];
126
+ const result = (0, knowledge_governance_1.autoApprovePatch)(patch, baseRules, testCases, store);
127
+ // With augmented rules, the patch adds open_file→flush_file bridge
128
+ // This should improve Top-1 (found paths increase)
129
+ (0, vitest_1.expect)(result.passed).toBe(true);
130
+ (0, vitest_1.expect)(result.top1After).toBeGreaterThanOrEqual(result.top1Before);
131
+ });
132
+ });
133
+ (0, vitest_1.describe)("Full Governance Pipeline", () => {
134
+ (0, vitest_1.it)("runs synthesize → validate → propose → regression → approve", () => {
135
+ // revoke_token produces UNAUTHENTICATED, create_session needs TOKEN_ISSUED
136
+ // These are NOT connected (UNAUTHENTICATED ≠ TOKEN_ISSUED) → genuine gap
137
+ // Both functions exist in AuthProtocol (protocols.json)
138
+ const failures = [
139
+ { goal: "revoke then create session", protocol: "AuthProtocol", expectedRepair: ["revoke_token", "create_session"] },
140
+ { goal: "revoke then create session v2", protocol: "AuthProtocol", expectedRepair: ["revoke_token", "create_session"] },
141
+ ];
142
+ const testCases = [
143
+ { currentState: ["FILE_OPEN"], targetState: ["FILE_DIRTY"] },
144
+ ];
145
+ const store = new knowledge_governance_1.KnowledgePatchStore(path.join(GOV_DIR, ".progmune_corpus", "knowledge", `full-${Date.now()}.json`));
146
+ const report = (0, knowledge_governance_1.runKnowledgeGovernance)(failures, testCases, store);
147
+ (0, vitest_1.expect)(report.proposed).toBeGreaterThanOrEqual(1);
148
+ (0, knowledge_governance_1.printGovernanceReport)(report);
149
+ });
150
+ });
@@ -0,0 +1,181 @@
1
+ "use strict";
2
+ /**
3
+ * Knowledge Network — Cross-protocol reference graph
4
+ *
5
+ * Transforms flat Knowledge Units into an interconnected graph.
6
+ * Protocols reference each other: TLS depends_on TCP, HTTP/2 extends HTTP, etc.
7
+ *
8
+ * Usage:
9
+ * npx ts-node src/knowledge-graph.ts
10
+ * npx ts-node src/knowledge-graph.ts --tree
11
+ * npx ts-node src/knowledge-graph.ts --dependents TLS
12
+ */
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ exports.buildKnowledgeGraph = buildKnowledgeGraph;
15
+ exports.getDependents = getDependents;
16
+ exports.getDependencies = getDependencies;
17
+ const protocol_knowledge_1 = require("./protocol-knowledge");
18
+ // Cross-protocol relations that go beyond existing unit.relations
19
+ const CROSS_PROTOCOL_EDGES = [
20
+ // Transport layer
21
+ { from: "PROTO-TLS", to: "PROTO-CONN", type: "depends_on", description: "TLS handshake runs over a TCP connection" },
22
+ { from: "PROTO-QUIC", to: "PROTO-CONN", type: "depends_on", description: "QUIC runs over UDP connection" },
23
+ // HTTP stack
24
+ { from: "PROTO-H2", to: "PROTO-HTTP", type: "extends", description: "HTTP/2 extends HTTP/1.1 request semantics" },
25
+ { from: "PROTO-TLS-ALPN", to: "PROTO-TLS", type: "extends", description: "ALPN negotiation extends TLS handshake" },
26
+ { from: "PROTO-TLS-CERT", to: "PROTO-TLS", type: "extends", description: "Certificate validation extends TLS handshake" },
27
+ { from: "PROTO-TLS-SESS", to: "PROTO-TLS", type: "depends_on", description: "Session resumption requires completed handshake" },
28
+ // Auth
29
+ { from: "PROTO-SSH", to: "PROTO-AUTH", type: "depends_on", description: "SSH requires authentication" },
30
+ { from: "PROTO-HTTP", to: "PROTO-AUTH", type: "compatible_with", description: "HTTP can use authentication headers" },
31
+ // Cross-domain
32
+ { from: "PROTO-TLS", to: "PROTO-AUTH", type: "compatible_with", description: "TLS can carry client certificates for authentication" },
33
+ { from: "PROTO-SSH", to: "PROTO-CONN", type: "depends_on", description: "SSH runs over TCP connection" },
34
+ ];
35
+ function buildKnowledgeGraph() {
36
+ const kb = (0, protocol_knowledge_1.buildKnowledgeBase)();
37
+ const nodes = kb.units.map(u => ({
38
+ id: u.id, name: u.name, domain: u.domain, maturity: u.maturity, confidence: u.confidence,
39
+ }));
40
+ // Collect all edges: both intra-unit relations and cross-protocol relations
41
+ const edges = [...CROSS_PROTOCOL_EDGES];
42
+ // Add intra-unit relations
43
+ for (const u of kb.units) {
44
+ for (const r of u.relations || []) {
45
+ edges.push({ from: u.id, to: r.targetId, type: r.type, description: r.description });
46
+ }
47
+ }
48
+ // Build adjacency
49
+ const adj = {};
50
+ const inDeg = {};
51
+ const outDeg = {};
52
+ for (const n of nodes) {
53
+ adj[n.id] = [];
54
+ inDeg[n.id] = 0;
55
+ outDeg[n.id] = 0;
56
+ }
57
+ for (const e of edges) {
58
+ if (!adj[e.from])
59
+ adj[e.from] = [];
60
+ if (!adj[e.to])
61
+ adj[e.to] = [];
62
+ adj[e.from].push(e.to);
63
+ outDeg[e.from] = (outDeg[e.from] || 0) + 1;
64
+ inDeg[e.to] = (inDeg[e.to] || 0) + 1;
65
+ }
66
+ return { nodes, edges, adjacency: adj, inDegree: inDeg, outDegree: outDeg };
67
+ }
68
+ // ═══════════════════════════════════════════════════════════════
69
+ // Queries
70
+ // ═══════════════════════════════════════════════════════════════
71
+ function getDependents(graph, nodeId) {
72
+ const ids = graph.edges.filter(e => e.to === nodeId).map(e => e.from);
73
+ return graph.nodes.filter(n => ids.includes(n.id));
74
+ }
75
+ function getDependencies(graph, nodeId) {
76
+ const ids = graph.edges.filter(e => e.from === nodeId).map(e => e.to);
77
+ return graph.nodes.filter(n => ids.includes(n.id));
78
+ }
79
+ // ═══════════════════════════════════════════════════════════════
80
+ // Formatters
81
+ // ═══════════════════════════════════════════════════════════════
82
+ function formatTree(graph) {
83
+ const C = { r: "\x1b[0m", b: "\x1b[1m", d: "\x1b[2m", g: "\x1b[32m", y: "\x1b[33m", r2: "\x1b[31m", c: "\x1b[36m", m: "\x1b[35m" };
84
+ const l = [];
85
+ l.push(`\n${C.b}${C.c}Protocol Knowledge Graph${C.r}\n`);
86
+ // Find root nodes (no incoming edges from other protocols)
87
+ const roots = graph.nodes.filter(n => graph.inDegree[n.id] === 0 || (graph.inDegree[n.id] <= 1 && graph.outDegree[n.id] >= 2));
88
+ const visited = new Set();
89
+ function renderNode(id, prefix, isLast) {
90
+ if (visited.has(id))
91
+ return;
92
+ visited.add(id);
93
+ const n = graph.nodes.find(x => x.id === id);
94
+ if (!n)
95
+ return;
96
+ const connector = isLast ? "└── " : "├── ";
97
+ const matIcon = n.maturity === "stable" ? C.g + "★" + C.r : n.maturity === "validated" ? C.y + "◉" + C.r : C.r2 + "●" + C.r;
98
+ l.push(`${prefix}${connector}${matIcon} ${C.b}${n.name}${C.r} ${C.d}(${n.domain}, ${n.confidence}%)${C.r}`);
99
+ const children = graph.edges.filter(e => e.from === id);
100
+ const childPrefix = prefix + (isLast ? " " : "│ ");
101
+ children.forEach((e, i) => {
102
+ l.push(`${childPrefix}${i === children.length - 1 ? "└── " : "├── "}${C.d}${e.type}${C.r} → ${e.description.slice(0, 50)}`);
103
+ });
104
+ // Don't recurse into children to avoid cycles — just show direct edges
105
+ }
106
+ // Render starting from connection/transport layer (roots)
107
+ const transportRoots = graph.nodes.filter(n => n.domain === "Connection" || n.domain === "QUIC");
108
+ for (const r of transportRoots) {
109
+ renderNode(r.id, "", true);
110
+ }
111
+ // Then TLS, SSH, HTTP
112
+ const appRoots = graph.nodes.filter(n => ["TLS", "SSH", "HTTP"].includes(n.domain) && !transportRoots.includes(n));
113
+ for (const r of appRoots) {
114
+ if (!visited.has(r.id))
115
+ renderNode(r.id, "", true);
116
+ }
117
+ return l.join("\n") + "\n";
118
+ }
119
+ function formatMatrix(graph) {
120
+ const C = { r: "\x1b[0m", b: "\x1b[1m", d: "\x1b[2m", g: "\x1b[32m" };
121
+ const l = [];
122
+ l.push(`\n${C.b}Cross-Reference Matrix${C.r}\n`);
123
+ l.push(`${C.d}Rows point TO columns (row depends_on / extends column)${C.r}\n`);
124
+ const ids = graph.nodes.map(n => n.id);
125
+ const names = graph.nodes.map(n => n.name.slice(0, 8));
126
+ l.push(` ${names.join(" ")}`);
127
+ l.push(` ${names.map(() => "──").join(" ")}`);
128
+ for (const n of graph.nodes) {
129
+ const row = ids.map(targetId => {
130
+ const edge = graph.edges.find(e => e.from === n.id && e.to === targetId);
131
+ return edge ? (edge.type === "depends_on" ? "↓ " : edge.type === "extends" ? "↗ " : "· ") : " ";
132
+ }).join(" ");
133
+ l.push(`${n.name.slice(0, 8).padEnd(8)} ${row}`);
134
+ }
135
+ return l.join("\n") + "\n";
136
+ }
137
+ // ═══════════════════════════════════════════════════════════════
138
+ // CLI
139
+ // ═══════════════════════════════════════════════════════════════
140
+ if (require.main === module) {
141
+ const g = buildKnowledgeGraph();
142
+ const args = process.argv.slice(2);
143
+ const C = { r: "\x1b[0m", b: "\x1b[1m", d: "\x1b[2m", g: "\x1b[32m", c: "\x1b[36m" };
144
+ if (args.includes("--tree")) {
145
+ console.log(formatTree(g));
146
+ }
147
+ else if (args.includes("--matrix")) {
148
+ console.log(formatMatrix(g));
149
+ }
150
+ else if (args.includes("--dependents") && args[1]) {
151
+ const deps = getDependents(g, args[1]);
152
+ console.log(`\nNodes that depend on ${args[1]}:`);
153
+ deps.forEach(d => console.log(` ${d.name} (${d.domain}, ${d.maturity})`));
154
+ }
155
+ else if (args.includes("--dependencies") && args[1]) {
156
+ const deps = getDependencies(g, args[1]);
157
+ console.log(`\nNodes that ${args[1]} depends on:`);
158
+ deps.forEach(d => console.log(` ${d.name} (${d.domain}, ${d.maturity})`));
159
+ }
160
+ else {
161
+ // Default: summary
162
+ console.log(`\n${C.b}${C.c}Knowledge Network${C.r}`);
163
+ console.log(`${C.d}${g.nodes.length} nodes, ${g.edges.length} edges${C.r}`);
164
+ // Top nodes by connections
165
+ const ranked = g.nodes.map(n => ({
166
+ name: n.name, domain: n.domain, maturity: n.maturity,
167
+ total: (g.inDegree[n.id] || 0) + (g.outDegree[n.id] || 0),
168
+ in: g.inDegree[n.id] || 0, out: g.outDegree[n.id] || 0,
169
+ })).sort((a, b) => b.total - a.total);
170
+ console.log(`\n Node Domain In Out Total`);
171
+ for (const r of ranked.slice(0, 8)) {
172
+ console.log(` ${r.name.padEnd(20)} ${r.domain.padEnd(10)} ${String(r.in).padStart(2)} ${String(r.out).padStart(2)} ${r.total}`);
173
+ }
174
+ // Cross-references
175
+ console.log(`\n Cross-protocol edges:`);
176
+ for (const e of g.edges) {
177
+ console.log(` ${e.from.padEnd(14)} ${e.type.padEnd(14)} → ${e.to.padEnd(14)} ${C.d}${e.description.slice(0, 50)}${C.r}`);
178
+ }
179
+ console.log("");
180
+ }
181
+ }
@@ -0,0 +1,246 @@
1
+ "use strict";
2
+ /**
3
+ * P6: Knowledge-Guided Rule Synthesis
4
+ *
5
+ * The existing synthesizer generates too many rules (452 from 61 sequences)
6
+ * because it blindly clusters ALL observed patterns. This module adds
7
+ * knowledge-based filtering to produce fewer, higher-quality rules.
8
+ *
9
+ * Three filters:
10
+ * 1. DOMAIN_FILTER — Only generate rules for protocol-relevant functions
11
+ * 2. SPECIFICITY_FILTER — Require minimum pre/post state specificity
12
+ * 3. FREQUENCY_FILTER — Require pattern observed in ≥N sequences
13
+ *
14
+ * Target: 452 rules → ~50 high-quality rules (89% reduction)
15
+ */
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.synthesizeWithKnowledge = synthesizeWithKnowledge;
18
+ exports.formatKGSynthesisStats = formatKGSynthesisStats;
19
+ const auto_protocol_synthesizer_1 = require("./auto-protocol-synthesizer");
20
+ // ═══════════════════════════════════════════════════════════════
21
+ // Knowledge Base — Protocol-Relevant Function Patterns
22
+ // ═══════════════════════════════════════════════════════════════
23
+ /**
24
+ * Protocol domain patterns — functions matching these patterns
25
+ * are likely to be part of real protocols (TLS, SSH, HTTP, File, Auth).
26
+ *
27
+ * Functions NOT matching any pattern are likely utilities, helpers,
28
+ * or internal functions that should be excluded from rule generation.
29
+ */
30
+ const PROTOCOL_DOMAINS = [
31
+ {
32
+ domain: "TLS/SSL",
33
+ patterns: [
34
+ /ssl/i, /tls/i, /handshake/i, /cipher/i, /cert/i, /verify/i,
35
+ /encrypt/i, /decrypt/i, /key/i, /x509/i, /pki/i,
36
+ /SSL_/i, /TLS_/i, /ossl_/i,
37
+ ],
38
+ },
39
+ {
40
+ domain: "SSH",
41
+ patterns: [
42
+ /ssh_/i, /sftp/i, /scp/i, /auth_/i, /kex/i, /hostkey/i,
43
+ /SSH_/i, /ssh_/i,
44
+ ],
45
+ },
46
+ {
47
+ domain: "HTTP",
48
+ patterns: [
49
+ /http/i, /request/i, /response/i, /header/i, /cookie/i,
50
+ /session/i, /url/i, /uri/i, /CURL/i, /curl_/i, /ngx_http/i,
51
+ ],
52
+ },
53
+ {
54
+ domain: "File I/O",
55
+ patterns: [
56
+ /open_/i, /close_/i, /read_/i, /write_/i, /file_/i,
57
+ /fopen/i, /fclose/i, /fread/i, /fwrite/i, /fd_/i,
58
+ ],
59
+ },
60
+ {
61
+ domain: "Auth",
62
+ patterns: [
63
+ /auth/i, /login/i, /logout/i, /password/i, /token/i,
64
+ /verify_/i, /credential/i, /oauth/i, /jwt/i,
65
+ ],
66
+ },
67
+ {
68
+ domain: "Connection",
69
+ patterns: [
70
+ /connect/i, /disconnect/i, /bind/i, /listen/i, /accept/i,
71
+ /socket/i, /resolve/i, /dns/i,
72
+ ],
73
+ },
74
+ {
75
+ domain: "Memory/Resource",
76
+ patterns: [
77
+ /alloc/i, /free/i, /init/i, /cleanup/i, /destroy/i,
78
+ /create_/i, /delete_/i, /new_/i, /release/i, /acquire/i,
79
+ ],
80
+ },
81
+ ];
82
+ /**
83
+ * Generic utility functions that are NOT protocol-relevant.
84
+ * Rules generated from these functions are almost always false positives.
85
+ */
86
+ const GENERIC_FUNCTIONS = new Set([
87
+ // Standard library
88
+ "memset", "memcpy", "memmove", "memcmp", "strlen", "strcmp", "strcasecmp",
89
+ "strdup", "strcpy", "strncpy", "strcat", "sprintf", "snprintf",
90
+ "malloc", "calloc", "realloc", "free",
91
+ "printf", "fprintf", "assert", "abort", "exit",
92
+ // Preprocessor / compiler
93
+ "defined", "UNUSED", "FALLTHROUGH", "GOOD_MULTI_HANDLE",
94
+ // Data structures
95
+ "STACK_OF", "ERR_clear_error", "curlx_dyn_init",
96
+ // Generic utility
97
+ "time", "delay", "sleep", "usleep",
98
+ "buffer", "files", "multi_now", "scheme",
99
+ "curl_socket", "curl_dynhds_init", "curl_global_trace",
100
+ "is_pkcs11_uri", "ossl_do_file_type",
101
+ // One-off internal helpers
102
+ "init_telnet", "rfc2228", "myssh_to_error",
103
+ "libssh2_sftp_stat_ex",
104
+ ]);
105
+ const DEFAULT_KG_OPTIONS = {
106
+ minFrequency: 3, // Cluster must have ≥3 sequences
107
+ minSpecificity: 1,
108
+ filterGenerics: true,
109
+ requireDomain: false,
110
+ };
111
+ /**
112
+ * Check if a function name matches any known protocol domain.
113
+ */
114
+ function matchesDomain(fnName) {
115
+ for (const domain of PROTOCOL_DOMAINS) {
116
+ if (domain.patterns.some(p => p.test(fnName))) {
117
+ return domain.domain;
118
+ }
119
+ }
120
+ return null;
121
+ }
122
+ function classifySemanticRole(fnName, preStates, postStates, invalidate) {
123
+ const fn = fnName.toLowerCase();
124
+ // Init: creates/acquires resources — empty pre_states, produces post_states
125
+ if (preStates.length === 0 && postStates.length > 0)
126
+ return "init";
127
+ // Cleanup: releases/invalidates resources
128
+ if (invalidate && invalidate.length > 0)
129
+ return "cleanup";
130
+ // Use: requires pre_states, may produce post_states, no invalidation
131
+ if (preStates.length > 0)
132
+ return "use";
133
+ return "unknown";
134
+ }
135
+ function synthesizeWithKnowledge(sequences, options = {}) {
136
+ const opts = { ...DEFAULT_KG_OPTIONS, ...options };
137
+ const stats = {
138
+ inputSequences: sequences.length,
139
+ filteredSequences: sequences.length, // Don't filter sequences — filter rules instead
140
+ rawProtocols: 0,
141
+ rawRules: 0,
142
+ filteredProtocols: 0,
143
+ filteredRules: 0,
144
+ byFilter: { domain: 0, generic: 0, frequency: 0, specificity: 0 },
145
+ domainBreakdown: {},
146
+ };
147
+ // Step 1: Run the existing synthesizer on ALL sequences (don't pre-filter)
148
+ const rawProtocols = (0, auto_protocol_synthesizer_1.synthesizeProtocols)(sequences);
149
+ stats.rawProtocols = rawProtocols.length;
150
+ let totalRawRules = 0;
151
+ for (const p of rawProtocols)
152
+ totalRawRules += p.rules.length;
153
+ stats.rawRules = totalRawRules;
154
+ // Step 2: Filter synthesized rules by quality
155
+ const rules = new Map();
156
+ const namespaces = new Set();
157
+ // Count function frequency across ALL sequences
158
+ const fnFrequency = new Map();
159
+ for (const seq of sequences) {
160
+ const seen = new Set();
161
+ for (const fn of seq) {
162
+ if (!seen.has(fn)) {
163
+ fnFrequency.set(fn, (fnFrequency.get(fn) || 0) + 1);
164
+ seen.add(fn);
165
+ }
166
+ }
167
+ }
168
+ for (const proto of rawProtocols) {
169
+ // Frequency/confidence filter: cluster must have sufficient confidence
170
+ // (closedLoopRate from clustering — higher = stronger pattern)
171
+ if (proto.confidence < 0.3 && proto.prototype.length < 5) {
172
+ stats.byFilter.frequency++;
173
+ continue;
174
+ }
175
+ let keptRules = 0;
176
+ for (const r of proto.rules) {
177
+ // Filter 1: Generic/utility functions — these match everywhere, always FP
178
+ if (opts.filterGenerics && GENERIC_FUNCTIONS.has(r.function)) {
179
+ stats.byFilter.generic++;
180
+ continue;
181
+ }
182
+ // Filter 2: Frequency — function must appear in ≥minFrequency sequences
183
+ const freq = fnFrequency.get(r.function) || 0;
184
+ if (freq < opts.minFrequency) {
185
+ stats.byFilter.frequency++;
186
+ continue;
187
+ }
188
+ // Filter 3: Semantic role
189
+ const role = classifySemanticRole(r.function, r.pre_states, r.post_states, r.invalidate);
190
+ if (role === "unknown") {
191
+ stats.byFilter.specificity++;
192
+ continue;
193
+ }
194
+ // Filter 4: Domain annotation
195
+ const domain = matchesDomain(r.function);
196
+ const ns = domain || proto.inferredPattern || "discovered";
197
+ namespaces.add(ns);
198
+ stats.domainBreakdown[domain || "unknown"] =
199
+ (stats.domainBreakdown[domain || "unknown"] || 0) + 1;
200
+ rules.set(r.function, {
201
+ pre_states: r.pre_states,
202
+ post_states: r.post_states,
203
+ invalidate: r.invalidate,
204
+ namespace: ns,
205
+ });
206
+ keptRules++;
207
+ }
208
+ if (keptRules > 0) {
209
+ stats.filteredProtocols++;
210
+ }
211
+ }
212
+ stats.filteredRules = rules.size;
213
+ // Build namespace initial states
214
+ const nsInit = new Map();
215
+ nsInit.set("_global", "INIT");
216
+ for (const ns of namespaces) {
217
+ nsInit.set(ns, "INIT");
218
+ }
219
+ return { rules, nsInit, stats };
220
+ }
221
+ function formatKGSynthesisStats(stats) {
222
+ const lines = [];
223
+ const reduction = stats.rawRules > 0
224
+ ? ((1 - stats.filteredRules / stats.rawRules) * 100).toFixed(0)
225
+ : "0";
226
+ lines.push("");
227
+ lines.push("── Knowledge-Guided Synthesis ──");
228
+ lines.push(` Input sequences: ${stats.inputSequences}`);
229
+ lines.push(` After domain filter: ${stats.filteredSequences} (${stats.byFilter.domain} removed by domain, ${stats.byFilter.generic} generics)`);
230
+ lines.push(` Raw protocols: ${stats.rawProtocols}`);
231
+ lines.push(` Raw rules: ${stats.rawRules}`);
232
+ lines.push(` Filtered rules: ${stats.filteredRules} (${reduction}% reduction)`);
233
+ lines.push("");
234
+ lines.push(" ── Filter breakdown ──");
235
+ lines.push(` Domain mismatch: ${stats.byFilter.domain}`);
236
+ lines.push(` Generic function: ${stats.byFilter.generic}`);
237
+ lines.push(` Low frequency: ${stats.byFilter.frequency}`);
238
+ lines.push(` Low specificity: ${stats.byFilter.specificity}`);
239
+ lines.push("");
240
+ lines.push(" ── Domain distribution ──");
241
+ for (const [domain, count] of Object.entries(stats.domainBreakdown).sort((a, b) => b[1] - a[1])) {
242
+ lines.push(` ${domain.padEnd(20)} ${count} rules`);
243
+ }
244
+ lines.push("");
245
+ return lines.join("\n");
246
+ }
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ /**
4
+ * Knowledge loop integration test.
5
+ *
6
+ * Verifies the full feedback loop end-to-end:
7
+ * Failure → Record → Aggregate → Antibody → L1 Hint / L2 Fast Path / L3 Credit
8
+ *
9
+ * Tests run against real feedback.json and .progmune_corpus data on disk.
10
+ */
11
+ const vitest_1 = require("vitest");
12
+ const failure_corpus_1 = require("./failure-corpus");
13
+ const feedback_1 = require("./feedback");
14
+ const logger_1 = require("./logger");
15
+ // ── L3: Credit scoring works with real data ──
16
+ (0, vitest_1.describe)("L3: Credit scoring", () => {
17
+ (0, vitest_1.it)("getFailureAdjustedCredit returns Laplace-smoothed value for unknown function", () => {
18
+ const credit = (0, feedback_1.getFailureAdjustedCredit)("__nonexistent_xyz__");
19
+ (0, vitest_1.expect)(credit).toBe(0.5);
20
+ });
21
+ (0, vitest_1.it)("getFailureAdjustedCredit for known functions is between 0.3 and 1.0", () => {
22
+ // Test a few functions that may or may not have history
23
+ for (const fn of ["generateJWT", "validatePassword", "loadIR", "plan"]) {
24
+ const credit = (0, feedback_1.getFailureAdjustedCredit)(fn);
25
+ (0, vitest_1.expect)(credit).toBeGreaterThanOrEqual(0.3);
26
+ (0, vitest_1.expect)(credit).toBeLessThanOrEqual(1.0);
27
+ }
28
+ });
29
+ (0, vitest_1.it)("getFunctionSuccessRate returns 0.5 for cold start", () => {
30
+ (0, vitest_1.expect)((0, feedback_1.getFunctionSuccessRate)("__never_called__")).toBe(0.5);
31
+ });
32
+ });
33
+ // ── L1/L2: Antibody generation ──
34
+ (0, vitest_1.describe)("L1/L2: Antibody pipeline", () => {
35
+ (0, vitest_1.it)("getLearnedPatterns returns a valid structure", () => {
36
+ const result = (0, failure_corpus_1.getLearnedPatterns)();
37
+ (0, vitest_1.expect)(result).toHaveProperty("failureToFix");
38
+ (0, vitest_1.expect)(Array.isArray(result.failureToFix)).toBe(true);
39
+ });
40
+ (0, vitest_1.it)("getFailureGenome returns summary statistics", () => {
41
+ const genome = (0, failure_corpus_1.getFailureGenome)();
42
+ (0, vitest_1.expect)(genome).toHaveProperty("totalFailures");
43
+ (0, vitest_1.expect)(genome).toHaveProperty("bySVL");
44
+ (0, vitest_1.expect)(genome).toHaveProperty("averageRetriesToSuccess");
45
+ (0, vitest_1.expect)(typeof genome.totalFailures).toBe("number");
46
+ });
47
+ (0, vitest_1.it)("getTopFailurePatterns returns sorted patterns", () => {
48
+ const patterns = (0, failure_corpus_1.getTopFailurePatterns)(5);
49
+ (0, vitest_1.expect)(Array.isArray(patterns)).toBe(true);
50
+ // Verify sorted by count descending
51
+ for (let i = 1; i < patterns.length; i++) {
52
+ (0, vitest_1.expect)(patterns[i].count).toBeLessThanOrEqual(patterns[i - 1].count);
53
+ }
54
+ });
55
+ (0, vitest_1.it)("queryAntibodies returns ACL-3+ matches", () => {
56
+ const antibodies = (0, failure_corpus_1.queryAntibodies)("test intent", "ACL-3");
57
+ (0, vitest_1.expect)(Array.isArray(antibodies)).toBe(true);
58
+ // All returned antibodies should be ACL-3 or ACL-4
59
+ for (const ab of antibodies) {
60
+ (0, vitest_1.expect)(["ACL-3", "ACL-4"]).toContain(ab.antibodyLevel);
61
+ }
62
+ });
63
+ (0, vitest_1.it)("queryAntibodies returns results sorted by relevance", () => {
64
+ const antibodies = (0, failure_corpus_1.queryAntibodies)("authenticate user password", "ACL-3");
65
+ for (let i = 1; i < antibodies.length; i++) {
66
+ (0, vitest_1.expect)(antibodies[i]._score).toBeLessThanOrEqual(antibodies[i - 1]._score);
67
+ }
68
+ });
69
+ });
70
+ // ── Logger integration ──
71
+ (0, vitest_1.describe)("Structured logger", () => {
72
+ (0, vitest_1.it)("createLogger produces distinguishable module names", () => {
73
+ const plan = (0, logger_1.createLogger)("planner");
74
+ const val = (0, logger_1.createLogger)("validator");
75
+ (0, vitest_1.expect)(plan).not.toBe(val);
76
+ });
77
+ });