progmune-runtime 2.1.6 → 3.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +119 -461
- package/dist/ablation-study.js +144 -0
- package/dist/ablation-study.test.js +18 -0
- package/dist/action-runtime.js +3 -1
- package/dist/active-learning.js +211 -0
- package/dist/analytics.js +139 -0
- package/dist/asset-factory.js +309 -0
- package/dist/asset-growth.js +244 -0
- package/dist/asset-promotion.js +382 -0
- package/dist/asset-quality.js +550 -0
- package/dist/audit/business-translator.js +285 -0
- package/dist/audit/cli.js +66 -0
- package/dist/audit/formatters/html.js +379 -0
- package/dist/audit/formatters/json.js +11 -0
- package/dist/audit/formatters/markdown.js +192 -0
- package/dist/audit/formatters/terminal.js +189 -0
- package/dist/audit/index.js +25 -0
- package/dist/audit/report-builder.js +318 -0
- package/dist/audit/types.js +8 -0
- package/dist/audit.js +3 -3
- package/dist/auto-benchmark-generator.js +137 -0
- package/dist/auto-benchmark-generator.test.js +45 -0
- package/dist/auto-protocol-synthesizer.js +362 -0
- package/dist/auto-protocol-synthesizer.test.js +82 -0
- package/dist/autonomous-patch.js +175 -0
- package/dist/autonomous-patch.test.js +128 -0
- package/dist/badge/badge-server.js +98 -0
- package/dist/behavior-miner.js +442 -0
- package/dist/belief-layer.js +475 -0
- package/dist/benchmark-count.js +5 -0
- package/dist/benchmark-generator.js +211 -0
- package/dist/benchmark-harness.js +201 -0
- package/dist/benchmark-pass-rate.js +7 -0
- package/dist/benchmark-report.js +8 -3
- package/dist/benchmark-save.js +14 -1
- package/dist/bootstrap-validation.js +197 -0
- package/dist/bootstrap-validation.test.js +51 -0
- package/dist/branch-ledger.js +1 -1
- package/dist/capability-gap.js +130 -0
- package/dist/certify-html.js +351 -0
- package/dist/certify.js +326 -0
- package/dist/check.js +4 -4
- package/dist/compliance-miner.js +447 -0
- package/dist/continuous-benchmark.js +194 -0
- package/dist/continuous-benchmark.test.js +116 -0
- package/dist/corpus-stats.js +173 -0
- package/dist/counterfactual-engine.js +288 -0
- package/dist/coverage-dashboard.js +109 -0
- package/dist/coverage-system.test.js +205 -0
- package/dist/cross-repo-precision.js +352 -0
- package/dist/cve-benchmark.js +180 -0
- package/dist/cve-benchmark.test.js +28 -0
- package/dist/cve-collector.js +73 -0
- package/dist/data-quality.js +141 -0
- package/dist/decision-engine.js +388 -0
- package/dist/derive-metadata.js +250 -0
- package/dist/difficulty-active.test.js +198 -0
- package/dist/difficulty-map.js +244 -0
- package/dist/discovery-analytics.js +125 -0
- package/dist/discovery-model.js +149 -0
- package/dist/discovery-optimize.test.js +199 -0
- package/dist/discovery-trace.js +276 -0
- package/dist/discovery-trace.test.js +97 -0
- package/dist/emitter.js +83 -1
- package/dist/enterprise-dashboard.js +405 -0
- package/dist/eval-hardening.js +297 -0
- package/dist/eval-hardening.test.js +85 -0
- package/dist/evaluation-campaign.js +359 -0
- package/dist/evaluation-campaign.test.js +181 -0
- package/dist/evidence-growth.js +143 -0
- package/dist/evidence-repository.js +209 -0
- package/dist/evidence-system.js +441 -0
- package/dist/execute.js +15 -7
- package/dist/experimental/software-physics.js +291 -0
- package/dist/experimental/state-inference.js +516 -0
- package/dist/experimental/unsupervised-physics.js +230 -0
- package/dist/extract-ir-python.js +54 -7
- package/dist/extract-ir.js +376 -12
- package/dist/failure-collector.js +2 -2
- package/dist/failure-corpus.js +322 -9
- package/dist/feedback.js +16 -5
- package/dist/feedback.test.js +49 -0
- package/dist/file-lock.js +1 -1
- package/dist/flywheel-batch.js +292 -0
- package/dist/frameworks/express-cli.js +237 -0
- package/dist/frameworks/express-detector.js +445 -0
- package/dist/frameworks/express-detector.test.js +206 -0
- package/dist/frameworks/index.js +30 -0
- package/dist/frameworks/nestjs-detector.js +302 -0
- package/dist/frameworks/trpc-detector.js +161 -0
- package/dist/frameworks/version-awareness.js +179 -0
- package/dist/function-synonyms.js +164 -0
- package/dist/function-synonyms.test.js +68 -0
- package/dist/generalization.test.js +352 -0
- package/dist/goal-annotator.js +113 -0
- package/dist/goal-planner.js +563 -0
- package/dist/gold-cve.js +164 -0
- package/dist/gold-cve.test.js +104 -0
- package/dist/gold-quality.js +206 -0
- package/dist/gold-tiers.js +241 -0
- package/dist/governance-dashboard.js +327 -0
- package/dist/graph-viz.js +240 -0
- package/dist/guided-frontier.js +195 -0
- package/dist/hierarchical-planner.js +148 -0
- package/dist/identifier-parser.js +260 -0
- package/dist/immune-metrics.js +93 -0
- package/dist/immune-receiver.js +158 -0
- package/dist/immune-reporter.js +1 -1
- package/dist/improvement-orchestrator.js +206 -0
- package/dist/inject-p0-vocabulary.js +300 -0
- package/dist/intent-parser.js +218 -0
- package/dist/invariant-algebra.js +476 -0
- package/dist/invariant-calculus.js +533 -0
- package/dist/ir-utils.js +70 -0
- package/dist/ir-utils.test.js +50 -0
- package/dist/knowledge-api.js +312 -0
- package/dist/knowledge-evolution.js +452 -0
- package/dist/knowledge-explorer.js +506 -0
- package/dist/knowledge-flywheel.js +274 -0
- package/dist/knowledge-governance.js +338 -0
- package/dist/knowledge-governance.test.js +150 -0
- package/dist/knowledge-graph.js +181 -0
- package/dist/knowledge-guided-synth.js +246 -0
- package/dist/knowledge-loop.test.js +77 -0
- package/dist/knowledge-object.js +316 -0
- package/dist/knowledge-package.js +98 -0
- package/dist/kpi-dashboard.js +561 -0
- package/dist/l3-cross-function.js +280 -0
- package/dist/learning-ranker.js +148 -0
- package/dist/learning-ranker.test.js +291 -0
- package/dist/ledger/accountability.js +322 -0
- package/dist/ledger/chain-builder.js +185 -0
- package/dist/ledger/cli.js +222 -0
- package/dist/ledger/index.js +13 -0
- package/dist/ledger/signatures.js +193 -0
- package/dist/ledger/types.js +9 -0
- package/dist/llm.js +74 -3
- package/dist/load-benchmarks.js +8 -3
- package/dist/logger.js +66 -0
- package/dist/logger.test.js +37 -0
- package/dist/logistic-reward.js +339 -0
- package/dist/logistic-reward.test.js +180 -0
- package/dist/macro-graph.js +193 -0
- package/dist/macro-repair.js +183 -0
- package/dist/mcp-server.mjs +1202 -483
- package/dist/memory-layer.js +42 -5
- package/dist/multi-repo-precision.js +422 -0
- package/dist/name-free-protocol.js +425 -0
- package/dist/name-free-protocol.test.js +170 -0
- package/dist/name-scrambling.js +138 -0
- package/dist/name-scrambling.test.js +16 -0
- package/dist/p3-observability.test.js +281 -0
- package/dist/p5-orchestrator.test.js +225 -0
- package/dist/pairwise-preference.js +294 -0
- package/dist/pairwise-preference.test.js +140 -0
- package/dist/planner-constraints.js +104 -0
- package/dist/planner-prompts.js +155 -0
- package/dist/planner-telemetry.js +415 -0
- package/dist/planner-trace.js +214 -0
- package/dist/planner.js +162 -167
- package/dist/plsb/artifact.js +116 -0
- package/dist/plsb/cli.js +71 -0
- package/dist/plsb/index.js +19 -0
- package/dist/plsb/leaderboard.js +249 -0
- package/dist/plsb/report-md.js +156 -0
- package/dist/plsb/schema.js +179 -0
- package/dist/plsb-benchmark.js +284 -0
- package/dist/plsb-benchmark.test.js +119 -0
- package/dist/policy/cli.js +134 -0
- package/dist/policy/engine.js +333 -0
- package/dist/policy/index.js +12 -0
- package/dist/policy/types.js +59 -0
- package/dist/policy-miner.js +505 -0
- package/dist/precision-analyze.js +229 -0
- package/dist/precision-benchmark.js +147 -0
- package/dist/precision-label-c.js +134 -0
- package/dist/precision-label.js +193 -0
- package/dist/precision-report-c.js +149 -0
- package/dist/precision-report.js +246 -0
- package/dist/progmune-status.js +108 -0
- package/dist/proof-engine.js +479 -0
- package/dist/proof-provenance.js +315 -0
- package/dist/protocol-coverage.js +294 -0
- package/dist/protocol-detector.js +1189 -0
- package/dist/protocol-embedding-expanded.js +297 -0
- package/dist/protocol-embedding-expanded.test.js +97 -0
- package/dist/protocol-embedding.js +195 -0
- package/dist/protocol-embedding.test.js +82 -0
- package/dist/protocol-extractor-v2.js +354 -0
- package/dist/protocol-extractor-v2.test.js +140 -0
- package/dist/protocol-extractor.js +310 -0
- package/dist/protocol-extractor.test.js +113 -0
- package/dist/protocol-foundation.js +322 -0
- package/dist/protocol-foundation.test.js +163 -0
- package/dist/protocol-frontier.js +243 -0
- package/dist/protocol-frontier.test.js +92 -0
- package/dist/protocol-gap-analyzer.js +228 -0
- package/dist/protocol-gap-analyzer.test.js +49 -0
- package/dist/protocol-invariants.js +276 -0
- package/dist/protocol-invariants.test.js +111 -0
- package/dist/protocol-knowledge.js +464 -0
- package/dist/protocol-miner.js +343 -0
- package/dist/protocol-mining.js +207 -0
- package/dist/protocol-mining.test.js +37 -0
- package/dist/protocol-registry.js +1 -1
- package/dist/protocol-security-benchmark.js +222 -0
- package/dist/protocol-vulnerability.js +257 -0
- package/dist/protocol-vulnerability.test.js +60 -0
- package/dist/python-benchmark.js +120 -0
- package/dist/python-emitter.js +163 -45
- package/dist/python-protocol-extractor.js +187 -0
- package/dist/python-protocol-extractor.test.js +116 -0
- package/dist/realworld-benchmark.js +646 -0
- package/dist/realworld-benchmark.test.js +36 -0
- package/dist/repair-arch.test.js +411 -0
- package/dist/repair-evolution.test.js +454 -0
- package/dist/repair-executor.js +719 -0
- package/dist/repair-proposal.js +4 -4
- package/dist/repair-ranker.js +141 -0
- package/dist/repair-strategies.js +419 -0
- package/dist/repair-taxonomy.js +234 -0
- package/dist/repair-types.js +12 -0
- package/dist/repo-evaluator.js +250 -0
- package/dist/repo-evaluator.test.js +128 -0
- package/dist/resource-abstraction.js +242 -0
- package/dist/resource-detector.js +211 -0
- package/dist/result.test.js +43 -0
- package/dist/reward-system.js +411 -0
- package/dist/reward-system.test.js +175 -0
- package/dist/risk-model.js +215 -0
- package/dist/rule-miner.js +234 -7
- package/dist/rule-specificity.js +254 -0
- package/dist/runtime-types.js +27 -0
- package/dist/scaffold.js +208 -0
- package/dist/scale-collector.test.js +101 -0
- package/dist/scale-trajectory-collector.js +128 -0
- package/dist/sdk.js +250 -0
- package/dist/search-planner.js +4 -41
- package/dist/semantic-snapshot.js +1 -1
- package/dist/semantic-topology.js +121 -0
- package/dist/semantic-trace.js +310 -317
- package/dist/sequence-extractor.js +343 -0
- package/dist/skill-library.js +245 -0
- package/dist/skill-planner.test.js +189 -0
- package/dist/software-physics.js +291 -0
- package/dist/software-physics.test.js +81 -0
- package/dist/ssg-precision.js +478 -0
- package/dist/ssg-validator.js +71 -21
- package/dist/state-inference-doubleblind.test.js +160 -0
- package/dist/state-inference.js +516 -0
- package/dist/state-inference.test.js +115 -0
- package/dist/state-machine-fingerprint.js +345 -0
- package/dist/state-machine-fingerprint.test.js +120 -0
- package/dist/state-miner.js +386 -0
- package/dist/state-name-inference.js +213 -0
- package/dist/state-name-inference.test.js +69 -0
- package/dist/strategy-planner.js +262 -96
- package/dist/strategy-planner.test.js +135 -0
- package/dist/telemetry-analytics.test.js +402 -0
- package/dist/terminal-format.js +68 -0
- package/dist/terminal-format.test.js +83 -0
- package/dist/topology-factory.js +196 -0
- package/dist/topology-representation.js +242 -0
- package/dist/topology-representation.test.js +27 -0
- package/dist/trajectory-augmentation.js +254 -0
- package/dist/trajectory-augmentation.test.js +63 -0
- package/dist/trajectory-corpus.js +440 -0
- package/dist/trajectory-corpus.test.js +32 -0
- package/dist/trajectory-feedback.test.js +116 -0
- package/dist/transition-synthesizer.js +286 -0
- package/dist/transition-synthesizer.test.js +123 -0
- package/dist/trust/api-semantic-mapper.js +809 -0
- package/dist/trust/call-graph-propagator.js +225 -0
- package/dist/trust/cli.js +122 -0
- package/dist/trust/compliance-scorer.js +283 -0
- package/dist/trust/confidence-calculator.js +261 -0
- package/dist/trust/engine.js +1145 -0
- package/dist/trust/explainability.js +85 -0
- package/dist/trust/formatters/ci.js +42 -0
- package/dist/trust/formatters/json.js +11 -0
- package/dist/trust/formatters/terminal.js +152 -0
- package/dist/trust/index.js +39 -0
- package/dist/trust/phase1-verify.js +171 -0
- package/dist/trust/protocol-domain-validator.js +697 -0
- package/dist/trust/score-calculator.js +282 -0
- package/dist/trust/ssg-bridge.js +641 -0
- package/dist/trust/ssg-bridge.test.js +269 -0
- package/dist/trust/types.js +67 -0
- package/dist/trust/violation-trace.js +335 -0
- package/dist/trust-api.js +179 -0
- package/dist/trust-calibration.js +279 -0
- package/dist/unknown-protocol-discovery.js +339 -0
- package/dist/unknown-protocol-discovery.test.js +102 -0
- package/dist/unsupervised-physics.js +230 -0
- package/dist/unsupervised-physics.test.js +95 -0
- package/dist/utils.test.js +37 -0
- package/dist/validator.js +187 -10
- package/dist/verification-intelligence.js +475 -0
- package/dist/verify-api.js +432 -0
- package/dist/vi-impact-report.js +293 -0
- package/dist/wl-fingerprint.js +162 -0
- package/dist/wl-fingerprint.test.js +130 -0
- package/dist/zeroshot-strategy.js +139 -0
- 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
- package/docs/Progmune_/351/241/271/347/233/256/345/205/250/350/247/243.html +721 -0
- package/package.json +73 -6
- package/protocols.json +1956 -50
- package/.dockerignore +0 -14
- package/.mcp.json +0 -11
- package/.progmune_allowlist +0 -50
- package/.test_report/test_report.md +0 -87
- package/Dockerfile +0 -9
- package/FAQ.md +0 -167
- package/WHITEPAPER.md +0 -540
- package/demo-project/auth.ts +0 -55
- package/demo-project/tsconfig.json +0 -8
- package/dist/acl-breakdown.js +0 -13
- package/dist/all-sessions.js +0 -11
- package/dist/antibody-stats.js +0 -11
- package/dist/branch-tree-count.js +0 -14
- package/dist/common-fixpath.js +0 -12
- package/dist/constraint-types.js +0 -12
- package/dist/exec-metrics.js +0 -11
- package/dist/failure-report.js +0 -11
- package/dist/fast-path-hits.js +0 -13
- package/dist/fingerprint-list.js +0 -15
- package/dist/gen-history-log.js +0 -13
- package/dist/heatmap-data.js +0 -11
- package/dist/recent-session.js +0 -12
- package/dist/svl-distribution.js +0 -11
- package/dist/terminal-status.js +0 -11
- package/dist/token-savings.js +0 -11
- package/dist/total-repairs.js +0 -12
- package/dist/unresolved-count.js +0 -12
- package/dist/valid-fingerprints.js +0 -13
- package/dist/verify-ledgers.js +0 -11
- package/docs/whitepaper-style.css +0 -77
- package/docs/whitepaper-v2.1.md +0 -609
- package/docs/whitepaper-v2.2.md +0 -1064
- package/docs/whitepaper-v2.2.pdf +0 -0
- package/fly.toml +0 -31
- package/public/dashboard.html +0 -119
- package/server/hub.js +0 -116
- package/test/replay-golden/sess_1780063202050_mgeld.json +0 -9
- package/test/replay-golden/sess_1780064032560_gocld.json +0 -354
- package/test/replay-golden/sess_1780064413331_s2709.json +0 -606
- package/test/replay-golden/sess_1780064792710_y3avo.json +0 -614
- package/test/replay-golden.ts +0 -84
- package/test_benchmark.js +0 -165
- package/test_comprehensive.mjs +0 -638
- package/test_concurrency.js +0 -129
- package/test_ir_robustness.js +0 -85
- package/test_semantic_contracts.js +0 -269
- package/test_ssg_stress.js +0 -156
- package/test_svl3.js +0 -58
- package/tsconfig.json +0 -17
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* L3 Cross-Function Resource Lifecycle Analysis
|
|
4
|
+
*
|
|
5
|
+
* Same-file alloc/free pairing check.
|
|
6
|
+
* For each function that calls an allocator,
|
|
7
|
+
* verifies there exists a call-graph path to a function that calls
|
|
8
|
+
* the corresponding deallocator.
|
|
9
|
+
*
|
|
10
|
+
* Phase 1: Experimental — curl openssl.c + redis server.c
|
|
11
|
+
*/
|
|
12
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
13
|
+
if (k2 === undefined) k2 = k;
|
|
14
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
15
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
16
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
17
|
+
}
|
|
18
|
+
Object.defineProperty(o, k2, desc);
|
|
19
|
+
}) : (function(o, m, k, k2) {
|
|
20
|
+
if (k2 === undefined) k2 = k;
|
|
21
|
+
o[k2] = m[k];
|
|
22
|
+
}));
|
|
23
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
24
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
25
|
+
}) : function(o, v) {
|
|
26
|
+
o["default"] = v;
|
|
27
|
+
});
|
|
28
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
29
|
+
var ownKeys = function(o) {
|
|
30
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
31
|
+
var ar = [];
|
|
32
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
33
|
+
return ar;
|
|
34
|
+
};
|
|
35
|
+
return ownKeys(o);
|
|
36
|
+
};
|
|
37
|
+
return function (mod) {
|
|
38
|
+
if (mod && mod.__esModule) return mod;
|
|
39
|
+
var result = {};
|
|
40
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
41
|
+
__setModuleDefault(result, mod);
|
|
42
|
+
return result;
|
|
43
|
+
};
|
|
44
|
+
})();
|
|
45
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
46
|
+
exports.analyzeL3 = analyzeL3;
|
|
47
|
+
exports.runL3Experiment = runL3Experiment;
|
|
48
|
+
const fs = __importStar(require("fs"));
|
|
49
|
+
const path = __importStar(require("path"));
|
|
50
|
+
const ALLOC_FREE_PAIRS = [
|
|
51
|
+
// OpenSSL
|
|
52
|
+
{ type: "SSL_CTX", allocPattern: /\bSSL_CTX_new\b/, freePattern: /\bSSL_CTX_free\b/ },
|
|
53
|
+
{ type: "SSL", allocPattern: /\bSSL_new\b/, freePattern: /\bSSL_free\b/ },
|
|
54
|
+
{ type: "BIO", allocPattern: /\bBIO_new\b/, freePattern: /\bBIO_free\b/ },
|
|
55
|
+
{ type: "EVP_PKEY", allocPattern: /\bEVP_PKEY_new\b/, freePattern: /\bEVP_PKEY_free\b/ },
|
|
56
|
+
// curl
|
|
57
|
+
{ type: "curl_easy", allocPattern: /\bcurl_easy_init\b/, freePattern: /\bcurl_easy_cleanup\b/ },
|
|
58
|
+
{ type: "curl_multi", allocPattern: /\bcurl_multi_init\b/, freePattern: /\bcurl_multi_cleanup\b/ },
|
|
59
|
+
{ type: "curl_slist", allocPattern: /\bcurl_slist_append\b/, freePattern: /\bcurl_slist_free_all\b/ },
|
|
60
|
+
// nghttp2
|
|
61
|
+
{ type: "nghttp2_session", allocPattern: /\bnghttp2_session_(new|server_new|client_new)\b/, freePattern: /\bnghttp2_session_del\b/ },
|
|
62
|
+
{ type: "nghttp2_mem", allocPattern: /\bnghttp2_mem_(malloc|calloc|realloc)\b/, freePattern: /\bnghttp2_mem_free\b/ },
|
|
63
|
+
// libssh
|
|
64
|
+
{ type: "ssh_session", allocPattern: /\bssh_(new|session_new)\b/, freePattern: /\bssh_free\b/ },
|
|
65
|
+
{ type: "ssh_string", allocPattern: /\bssh_string_(new|from_char)\b/, freePattern: /\bssh_string_(free|burn)\b/ },
|
|
66
|
+
// redis
|
|
67
|
+
{ type: "sds", allocPattern: /\bsds(new|newlen|empty|dup)\b/, freePattern: /\bsds(free|clear)\b/ },
|
|
68
|
+
{ type: "zmalloc", allocPattern: /\bz(malloc|calloc|realloc|trymalloc)\b/, freePattern: /\bzfree\b/ },
|
|
69
|
+
// nginx
|
|
70
|
+
{ type: "ngx_pool", allocPattern: /\bngx_(create_pool|palloc|pcalloc)\b/, freePattern: /\bngx_(destroy_pool|pfree)\b/ },
|
|
71
|
+
{ type: "ngx_array", allocPattern: /\bngx_(array_create|array_push)\b/, freePattern: /\bngx_array_destroy\b/ },
|
|
72
|
+
// Apache
|
|
73
|
+
{ type: "apr_pool", allocPattern: /\bapr_p(alloc|calloc|create)\b/, freePattern: /\bapr_p(free|ool_destroy|ool_clear)\b/ },
|
|
74
|
+
// Generic C
|
|
75
|
+
{ type: "malloc", allocPattern: /\b(malloc|calloc|realloc)\b/, freePattern: /\bfree\b/ },
|
|
76
|
+
];
|
|
77
|
+
// ── Call Graph ──
|
|
78
|
+
function buildCallGraph(funcs) {
|
|
79
|
+
const callers = new Map();
|
|
80
|
+
const callees = new Map();
|
|
81
|
+
const funcFiles = new Map();
|
|
82
|
+
for (const f of funcs) {
|
|
83
|
+
funcFiles.set(f.name, f.file);
|
|
84
|
+
if (!callees.has(f.name))
|
|
85
|
+
callees.set(f.name, []);
|
|
86
|
+
callees.get(f.name).push(...f.calls);
|
|
87
|
+
for (const c of f.calls) {
|
|
88
|
+
if (!callers.has(c))
|
|
89
|
+
callers.set(c, []);
|
|
90
|
+
callers.get(c).push(f.name);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return { callers, callees, funcFiles };
|
|
94
|
+
}
|
|
95
|
+
// ── Path Finding (BFS from alloc function to any free function) ──
|
|
96
|
+
function canReach(start, targets, callees, maxDepth = 5) {
|
|
97
|
+
if (targets.includes(start))
|
|
98
|
+
return { reachable: true, path: [start] };
|
|
99
|
+
const visited = new Set();
|
|
100
|
+
const queue = [{ func: start, path: [start] }];
|
|
101
|
+
visited.add(start);
|
|
102
|
+
while (queue.length > 0) {
|
|
103
|
+
const { func, path: currentPath } = queue.shift();
|
|
104
|
+
if (currentPath.length > maxDepth)
|
|
105
|
+
continue;
|
|
106
|
+
const called = callees.get(func) || [];
|
|
107
|
+
for (const c of called) {
|
|
108
|
+
if (targets.includes(c)) {
|
|
109
|
+
return { reachable: true, path: [...currentPath, c] };
|
|
110
|
+
}
|
|
111
|
+
if (!visited.has(c)) {
|
|
112
|
+
visited.add(c);
|
|
113
|
+
queue.push({ func: c, path: [...currentPath, c] });
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return { reachable: false, path: [] };
|
|
118
|
+
}
|
|
119
|
+
function analyzeL3(repo, sequences) {
|
|
120
|
+
const { callees, funcFiles } = buildCallGraph(sequences);
|
|
121
|
+
// Find alloc/free sites
|
|
122
|
+
const allocSites = [];
|
|
123
|
+
const freeSites = [];
|
|
124
|
+
for (const func of sequences) {
|
|
125
|
+
for (const call of func.calls) {
|
|
126
|
+
for (const pair of ALLOC_FREE_PAIRS) {
|
|
127
|
+
if (pair.allocPattern.test(call)) {
|
|
128
|
+
allocSites.push({
|
|
129
|
+
func: func.name,
|
|
130
|
+
file: func.file,
|
|
131
|
+
allocCall: call,
|
|
132
|
+
allocType: pair.type,
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
if (pair.freePattern.test(call)) {
|
|
136
|
+
freeSites.push({
|
|
137
|
+
func: func.name,
|
|
138
|
+
file: func.file,
|
|
139
|
+
freeCall: call,
|
|
140
|
+
allocType: pair.type,
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
// Group by file
|
|
147
|
+
const fileAllocs = new Map();
|
|
148
|
+
const fileFrees = new Map();
|
|
149
|
+
for (const a of allocSites) {
|
|
150
|
+
if (!fileAllocs.has(a.file))
|
|
151
|
+
fileAllocs.set(a.file, []);
|
|
152
|
+
fileAllocs.get(a.file).push(a);
|
|
153
|
+
}
|
|
154
|
+
for (const f of freeSites) {
|
|
155
|
+
if (!fileFrees.has(f.file))
|
|
156
|
+
fileFrees.set(f.file, []);
|
|
157
|
+
fileFrees.get(f.file).push(f);
|
|
158
|
+
}
|
|
159
|
+
// For each same-file alloc/free pair, check reachability
|
|
160
|
+
const violations = [];
|
|
161
|
+
let sameFilePairs = 0;
|
|
162
|
+
for (const [file, allocs] of fileAllocs) {
|
|
163
|
+
const frees = fileFrees.get(file) || [];
|
|
164
|
+
if (frees.length === 0)
|
|
165
|
+
continue;
|
|
166
|
+
for (const alloc of allocs) {
|
|
167
|
+
// Find matching free functions (same type)
|
|
168
|
+
const matchingFrees = frees.filter(f => f.allocType === alloc.allocType);
|
|
169
|
+
if (matchingFrees.length === 0)
|
|
170
|
+
continue;
|
|
171
|
+
sameFilePairs++;
|
|
172
|
+
const matchingFreeFuncs = matchingFrees.map(f => f.func);
|
|
173
|
+
const { reachable, path: foundPath } = canReach(alloc.func, matchingFreeFuncs, callees);
|
|
174
|
+
if (!reachable) {
|
|
175
|
+
violations.push({
|
|
176
|
+
allocFunc: alloc.func,
|
|
177
|
+
freeFunc: matchingFreeFuncs[0] || null,
|
|
178
|
+
file,
|
|
179
|
+
allocCall: alloc.allocCall,
|
|
180
|
+
allocType: alloc.allocType,
|
|
181
|
+
reason: foundPath.length > 0
|
|
182
|
+
? `path too deep (${foundPath.length} > 5)`
|
|
183
|
+
: `no path from ${alloc.func} to any of [${matchingFreeFuncs.join(", ")}]`,
|
|
184
|
+
reachableFrees: matchingFreeFuncs,
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
return {
|
|
190
|
+
repo,
|
|
191
|
+
totalFuncs: sequences.length,
|
|
192
|
+
allocSites: allocSites.length,
|
|
193
|
+
freeSites: freeSites.length,
|
|
194
|
+
sameFilePairs,
|
|
195
|
+
violations,
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
// ── CLI ──
|
|
199
|
+
function runL3Experiment() {
|
|
200
|
+
const BENCH_DIR = path.resolve(__dirname, "..", "benchmarks");
|
|
201
|
+
// Try full IR first, fall back to sequence data
|
|
202
|
+
for (const repo of ["curl"]) {
|
|
203
|
+
const irFile = path.join(BENCH_DIR, repo, "ir.json");
|
|
204
|
+
const seqFile = path.join(BENCH_DIR, `${repo}-sequences.json`);
|
|
205
|
+
let seqs = [];
|
|
206
|
+
if (fs.existsSync(irFile)) {
|
|
207
|
+
const data = JSON.parse(fs.readFileSync(irFile, "utf-8"));
|
|
208
|
+
seqs = (data.functions || []).map((f) => ({
|
|
209
|
+
name: f.name || "",
|
|
210
|
+
file: f.file || "",
|
|
211
|
+
calls: f.calls || [],
|
|
212
|
+
}));
|
|
213
|
+
console.error(`Loaded ${seqs.length} functions from ir.json`);
|
|
214
|
+
}
|
|
215
|
+
else if (fs.existsSync(seqFile)) {
|
|
216
|
+
const data = JSON.parse(fs.readFileSync(seqFile, "utf-8"));
|
|
217
|
+
seqs = (data.sequences || data).map((s) => ({
|
|
218
|
+
name: s.function || "",
|
|
219
|
+
file: s.file || "",
|
|
220
|
+
calls: s.calls || [],
|
|
221
|
+
}));
|
|
222
|
+
console.error(`Loaded ${seqs.length} functions from sequences (no ir.json)`);
|
|
223
|
+
}
|
|
224
|
+
else {
|
|
225
|
+
console.log(`${repo}: no data`);
|
|
226
|
+
continue;
|
|
227
|
+
}
|
|
228
|
+
const result = analyzeL3(repo, seqs);
|
|
229
|
+
console.log(`\n═══ L3 Analysis: ${repo} (FULL IR) ═══`);
|
|
230
|
+
console.log(` Functions: ${result.totalFuncs}`);
|
|
231
|
+
console.log(` Alloc sites: ${result.allocSites}`);
|
|
232
|
+
console.log(` Free sites: ${result.freeSites}`);
|
|
233
|
+
console.log(` Same-file pairs: ${result.sameFilePairs}`);
|
|
234
|
+
console.log(` Unreachable (violations): ${result.violations.length}`);
|
|
235
|
+
// Show top files with violations
|
|
236
|
+
const byFile = new Map();
|
|
237
|
+
for (const v of result.violations) {
|
|
238
|
+
if (!byFile.has(v.file))
|
|
239
|
+
byFile.set(v.file, []);
|
|
240
|
+
byFile.get(v.file).push(v);
|
|
241
|
+
}
|
|
242
|
+
const sortedFiles = [...byFile.entries()].sort((a, b) => b[1].length - a[1].length);
|
|
243
|
+
console.log(`\n Top files with L3 violations:`);
|
|
244
|
+
for (const [file, viols] of sortedFiles.slice(0, 10)) {
|
|
245
|
+
console.log(` ${file}: ${viols.length} violations`);
|
|
246
|
+
// Show most common alloc types
|
|
247
|
+
const types = new Map();
|
|
248
|
+
for (const v of viols) {
|
|
249
|
+
types.set(v.allocType, (types.get(v.allocType) || 0) + 1);
|
|
250
|
+
}
|
|
251
|
+
const topTypes = [...types.entries()].sort((a, b) => b[1] - a[1]).slice(0, 3);
|
|
252
|
+
console.log(` types: ${topTypes.map(([t, c]) => `${t}(${c})`).join(", ")}`);
|
|
253
|
+
}
|
|
254
|
+
// Sample violations from top file
|
|
255
|
+
if (sortedFiles.length > 0) {
|
|
256
|
+
const [topFile, topViols] = sortedFiles[0];
|
|
257
|
+
console.log(`\n Sample violations (${topFile}):`);
|
|
258
|
+
for (const v of topViols.slice(0, 5)) {
|
|
259
|
+
const isKnownFP = /return|caller|library/i.test(v.reason);
|
|
260
|
+
const verdict = isKnownFP ? "FP" : "?";
|
|
261
|
+
console.log(` [${verdict}] ${v.allocFunc} → ${v.allocCall} (${v.allocType})`);
|
|
262
|
+
console.log(` free: [${v.reachableFrees.slice(0, 3).join(", ")}] | ${v.reason}`);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
// Summary: potential TPs vs known FPs
|
|
266
|
+
const potentialTPs = result.violations.filter(v => {
|
|
267
|
+
// Heuristic: functions that allocate and return (not library constructors)
|
|
268
|
+
return !/new$|init$|create$/.test(v.allocFunc) && v.reachableFrees.length <= 3;
|
|
269
|
+
});
|
|
270
|
+
console.log(`\n Summary:`);
|
|
271
|
+
console.log(` Total violations: ${result.violations.length}`);
|
|
272
|
+
console.log(` Potential TPs (narrow free targets): ${potentialTPs.length}`);
|
|
273
|
+
console.log(` FP rate estimate: ${result.violations.length > 0 ? ((1 - potentialTPs.length / result.violations.length) * 100).toFixed(0) : 0}%`);
|
|
274
|
+
console.log();
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
// Run if called directly
|
|
278
|
+
if (require.main === module) {
|
|
279
|
+
runL3Experiment();
|
|
280
|
+
}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* P2.6: Learning Ranker — Feedback-Weighted Ranking
|
|
4
|
+
*
|
|
5
|
+
* Wraps a base Ranker and adjusts scores using real acceptance data
|
|
6
|
+
* from the TelemetryIndex. This is the first self-improving loop:
|
|
7
|
+
*
|
|
8
|
+
* Planner → Feedback → Telemetry → LearningRanker → Better Ranking
|
|
9
|
+
*
|
|
10
|
+
* Architecture:
|
|
11
|
+
* LearningRanker WRAPS Ranker (does not implement it).
|
|
12
|
+
* Base Ranker handles protocolSafety / performance / auditability.
|
|
13
|
+
* LearningRanker adds feedback correction on top.
|
|
14
|
+
*
|
|
15
|
+
* Evolution path:
|
|
16
|
+
* HeuristicRanker (P3) → LearningRanker (P2.6) → RewardModelRanker (P4)
|
|
17
|
+
*/
|
|
18
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
+
exports.LearningRanker = void 0;
|
|
20
|
+
exports.createLearningRanker = createLearningRanker;
|
|
21
|
+
const planner_telemetry_1 = require("./planner-telemetry");
|
|
22
|
+
const repair_ranker_1 = require("./repair-ranker");
|
|
23
|
+
const DEFAULT_CONFIG = {
|
|
24
|
+
baseWeight: 0.7,
|
|
25
|
+
feedbackWeight: 0.3,
|
|
26
|
+
minSamples: 5,
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* LearningRanker wraps a base CandidateRanker and applies
|
|
30
|
+
* feedback correction from the TelemetryIndex.
|
|
31
|
+
*
|
|
32
|
+
* Usage:
|
|
33
|
+
* const base = createLinearRanker();
|
|
34
|
+
* const learner = new LearningRanker(base, telemetry);
|
|
35
|
+
* const ranked = learner.rank(candidates, features, ctx);
|
|
36
|
+
*/
|
|
37
|
+
class LearningRanker {
|
|
38
|
+
constructor(baseRanker, telemetry, config, rewardModel, modelWeight = 0.5) {
|
|
39
|
+
this.base = baseRanker;
|
|
40
|
+
this.telemetry = telemetry;
|
|
41
|
+
this.config = { ...DEFAULT_CONFIG, ...config };
|
|
42
|
+
this.rewardModel = rewardModel;
|
|
43
|
+
this.modelWeight = modelWeight;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Rank candidates by base heuristic score, then adjust
|
|
47
|
+
* using acceptance data from the telemetry index.
|
|
48
|
+
*
|
|
49
|
+
* @param candidates Repair candidates to rank
|
|
50
|
+
* @param features Feature vectors (same index as candidates)
|
|
51
|
+
* @param ctx Search context (for protocol/violationType)
|
|
52
|
+
*/
|
|
53
|
+
rank(candidates, features, ctx) {
|
|
54
|
+
// 1. Score with base ranker
|
|
55
|
+
const baseScores = features.map(f => this.base.score(f));
|
|
56
|
+
// 2. Adjust with telemetry feedback + reward model (if available)
|
|
57
|
+
const ranked = candidates.map((c, i) => {
|
|
58
|
+
const fp = this.fingerprintFor(c, ctx);
|
|
59
|
+
const acceptance = this.telemetry.getCandidateAcceptance(fp, this.config.minSamples);
|
|
60
|
+
const effectiveReward = this.telemetry.getCandidateReward(fp, this.config.minSamples);
|
|
61
|
+
const baseScore = baseScores[i];
|
|
62
|
+
let adjustedScore;
|
|
63
|
+
if (this.rewardModel && this.rewardModel.isTrained) {
|
|
64
|
+
// Reward model: blend base + telemetry + model prediction
|
|
65
|
+
const acceptTotal = acceptance;
|
|
66
|
+
const execTotal = this.telemetry.getCandidateStats(fp);
|
|
67
|
+
const execRate = (execTotal.executionSuccess + execTotal.executionFailure) > 0
|
|
68
|
+
? execTotal.executionSuccess / (execTotal.executionSuccess + execTotal.executionFailure) : 0.5;
|
|
69
|
+
const modelScore = this.rewardModel.score(features[i], { acceptanceRate: acceptTotal, executionSuccessRate: execRate });
|
|
70
|
+
adjustedScore =
|
|
71
|
+
baseScore * this.config.baseWeight * 0.5 +
|
|
72
|
+
effectiveReward * this.config.feedbackWeight * 0.3 +
|
|
73
|
+
modelScore * this.modelWeight;
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
// Fallback: base + telemetry feedback only
|
|
77
|
+
adjustedScore =
|
|
78
|
+
baseScore * this.config.baseWeight +
|
|
79
|
+
effectiveReward * this.config.feedbackWeight;
|
|
80
|
+
}
|
|
81
|
+
return {
|
|
82
|
+
...c,
|
|
83
|
+
score: adjustedScore,
|
|
84
|
+
acceptance,
|
|
85
|
+
effectiveReward,
|
|
86
|
+
baseScore,
|
|
87
|
+
};
|
|
88
|
+
});
|
|
89
|
+
// 3. Sort by adjusted score descending
|
|
90
|
+
ranked.sort((a, b) => b.score - a.score);
|
|
91
|
+
return ranked;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Single-candidate score (used by backwards-compat code).
|
|
95
|
+
*/
|
|
96
|
+
score(candidate, features, ctx) {
|
|
97
|
+
const fp = this.fingerprintFor(candidate, ctx);
|
|
98
|
+
const baseScore = this.base.score(features);
|
|
99
|
+
const effectiveReward = this.telemetry.getCandidateReward(fp, this.config.minSamples);
|
|
100
|
+
return (baseScore * this.config.baseWeight +
|
|
101
|
+
effectiveReward * this.config.feedbackWeight);
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Record a single feedback event for incremental learning.
|
|
105
|
+
* Convenience method for integration tests and CLI usage.
|
|
106
|
+
*/
|
|
107
|
+
onFeedback(event) {
|
|
108
|
+
const fp = this.fingerprintFor({ id: event.candidateId, source: "protocol", actions: event.fixPath.map(fn => ({ kind: "call", function: fn, args: [] })), explanation: "" }, { protocol: "default", violationType: undefined });
|
|
109
|
+
if (event.accepted) {
|
|
110
|
+
this.telemetry.recordFeedback(event.candidateId, {
|
|
111
|
+
decision: "accepted",
|
|
112
|
+
executionResult: { success: event.accepted, violations: [] },
|
|
113
|
+
timestamp: Date.now(),
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
/** Compute the v2 fingerprint for a candidate. */
|
|
118
|
+
fingerprintFor(candidate, ctx) {
|
|
119
|
+
const actions = candidate.actions
|
|
120
|
+
.filter(a => a.kind === "call")
|
|
121
|
+
.map(a => a.function);
|
|
122
|
+
return (0, planner_telemetry_1.candidateFingerprint)(ctx.protocol, actions, ctx.violationType);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
exports.LearningRanker = LearningRanker;
|
|
126
|
+
// ═══════════════════════════════════════════════════════════════
|
|
127
|
+
// Convenience factory
|
|
128
|
+
// ═══════════════════════════════════════════════════════════════
|
|
129
|
+
/**
|
|
130
|
+
* Create a fully wired learning ranker:
|
|
131
|
+
* LinearRanker (base) + TelemetryIndex (feedback) = LearningRanker
|
|
132
|
+
*/
|
|
133
|
+
function createLearningRanker(baseRankerOrTelemetry, telemetryOrConfig, compatConfig) {
|
|
134
|
+
// Backward compat: createLearningRanker(baseRanker, telemetry, config)
|
|
135
|
+
if (telemetryOrConfig instanceof planner_telemetry_1.PlannerTelemetry) {
|
|
136
|
+
const base = baseRankerOrTelemetry;
|
|
137
|
+
const telemetry = telemetryOrConfig;
|
|
138
|
+
// Map learningRate/feedbackWindow to baseWeight/feedbackWeight/minSamples
|
|
139
|
+
const config = {};
|
|
140
|
+
if (compatConfig?.learningRate !== undefined)
|
|
141
|
+
config.feedbackWeight = compatConfig.learningRate;
|
|
142
|
+
if (compatConfig?.feedbackWindow !== undefined)
|
|
143
|
+
config.minSamples = compatConfig.feedbackWindow;
|
|
144
|
+
return new LearningRanker(base, telemetry, { ...config, ...compatConfig });
|
|
145
|
+
}
|
|
146
|
+
// New API: createLearningRanker(telemetry, config)
|
|
147
|
+
return new LearningRanker((0, repair_ranker_1.createLinearRanker)(), baseRankerOrTelemetry, telemetryOrConfig);
|
|
148
|
+
}
|