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.
- package/README.md +108 -468
- 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 +710 -0
- package/package.json +74 -7
- 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,354 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* P6.0v2: AST-based Protocol Extractor
|
|
4
|
+
*
|
|
5
|
+
* Targets: Precision > 70%, Recall > 50%
|
|
6
|
+
*
|
|
7
|
+
* Improvements over v1 (regex-based):
|
|
8
|
+
* 1. Scope-aware pairing — calls within same function, not across
|
|
9
|
+
* 2. AST-based extraction for TS/JS via ts-morph
|
|
10
|
+
* 3. Function boundary detection for C/C++
|
|
11
|
+
* 4. Better noise filtering (utility/logging/test functions)
|
|
12
|
+
* 5. Cross-file call graph construction
|
|
13
|
+
* 6. Frequency-weighted confidence with quality tiers
|
|
14
|
+
*/
|
|
15
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
16
|
+
if (k2 === undefined) k2 = k;
|
|
17
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
18
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
19
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
20
|
+
}
|
|
21
|
+
Object.defineProperty(o, k2, desc);
|
|
22
|
+
}) : (function(o, m, k, k2) {
|
|
23
|
+
if (k2 === undefined) k2 = k;
|
|
24
|
+
o[k2] = m[k];
|
|
25
|
+
}));
|
|
26
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
27
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
28
|
+
}) : function(o, v) {
|
|
29
|
+
o["default"] = v;
|
|
30
|
+
});
|
|
31
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
32
|
+
var ownKeys = function(o) {
|
|
33
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
34
|
+
var ar = [];
|
|
35
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
36
|
+
return ar;
|
|
37
|
+
};
|
|
38
|
+
return ownKeys(o);
|
|
39
|
+
};
|
|
40
|
+
return function (mod) {
|
|
41
|
+
if (mod && mod.__esModule) return mod;
|
|
42
|
+
var result = {};
|
|
43
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
44
|
+
__setModuleDefault(result, mod);
|
|
45
|
+
return result;
|
|
46
|
+
};
|
|
47
|
+
})();
|
|
48
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
49
|
+
exports.extractProtocolV2 = extractProtocolV2;
|
|
50
|
+
exports.printExtractionQuality = printExtractionQuality;
|
|
51
|
+
const fs = __importStar(require("fs"));
|
|
52
|
+
const path = __importStar(require("path"));
|
|
53
|
+
const ts_morph_1 = require("ts-morph");
|
|
54
|
+
const repo_evaluator_1 = require("./repo-evaluator");
|
|
55
|
+
const protocol_coverage_1 = require("./protocol-coverage");
|
|
56
|
+
/**
|
|
57
|
+
* Extract call pairs from a TypeScript/JavaScript file using ts-morph AST.
|
|
58
|
+
*
|
|
59
|
+
* Only pairs calls that appear within the same function body.
|
|
60
|
+
* This eliminates cross-function noise (e.g., main→writeFile paired with closeFile in another function).
|
|
61
|
+
*/
|
|
62
|
+
function extractTSCallPairs(filePath) {
|
|
63
|
+
const pairs = [];
|
|
64
|
+
try {
|
|
65
|
+
const project = new ts_morph_1.Project({ skipAddingFilesFromTsConfig: true });
|
|
66
|
+
const sourceFile = project.addSourceFileAtPath(filePath);
|
|
67
|
+
// Walk all function declarations
|
|
68
|
+
sourceFile.forEachDescendant((node, traversal) => {
|
|
69
|
+
if (!ts_morph_1.Node.isFunctionDeclaration(node) && !ts_morph_1.Node.isMethodDeclaration(node) && !ts_morph_1.Node.isArrowFunction(node)) {
|
|
70
|
+
// Also check function expressions and arrow functions in variable declarations
|
|
71
|
+
if (ts_morph_1.Node.isVariableDeclaration(node)) {
|
|
72
|
+
const init = node.getInitializer();
|
|
73
|
+
if (init && (ts_morph_1.Node.isArrowFunction(init) || ts_morph_1.Node.isFunctionExpression(init))) {
|
|
74
|
+
extractCallsFromScope(init, filePath, node.getName(), pairs);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
const fnName = ts_morph_1.Node.isVariableDeclaration(node)
|
|
80
|
+
? (node.getName() || "<anonymous>")
|
|
81
|
+
: node.getName() || "<anonymous>";
|
|
82
|
+
extractCallsFromScope(node, filePath, fnName, pairs);
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
// Fall back to regex-based extraction for files ts-morph can't parse
|
|
87
|
+
}
|
|
88
|
+
return pairs;
|
|
89
|
+
}
|
|
90
|
+
function extractCallsFromScope(node, filePath, fnName, pairs) {
|
|
91
|
+
const calls = [];
|
|
92
|
+
node.forEachDescendant((descendant, traversal) => {
|
|
93
|
+
if (ts_morph_1.Node.isCallExpression(descendant)) {
|
|
94
|
+
const expr = descendant.getExpression();
|
|
95
|
+
let callName = "";
|
|
96
|
+
if (ts_morph_1.Node.isIdentifier(expr)) {
|
|
97
|
+
callName = expr.getText();
|
|
98
|
+
}
|
|
99
|
+
else if (ts_morph_1.Node.isPropertyAccessExpression(expr)) {
|
|
100
|
+
callName = expr.getName(); // obj.method() → method
|
|
101
|
+
}
|
|
102
|
+
if (callName && !isNoiseFunction(callName)) {
|
|
103
|
+
calls.push({ name: callName, line: descendant.getStartLineNumber() });
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
// Don't recurse into nested functions (their calls belong to that function's scope)
|
|
107
|
+
if (ts_morph_1.Node.isFunctionDeclaration(descendant) || ts_morph_1.Node.isMethodDeclaration(descendant) ||
|
|
108
|
+
ts_morph_1.Node.isArrowFunction(descendant) && descendant !== node) {
|
|
109
|
+
traversal.skip();
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
// Pair all calls within this function scope
|
|
113
|
+
for (let i = 0; i < calls.length - 1; i++) {
|
|
114
|
+
for (let j = i + 1; j < calls.length; j++) {
|
|
115
|
+
pairs.push({
|
|
116
|
+
from: calls[i].name,
|
|
117
|
+
to: calls[j].name,
|
|
118
|
+
file: filePath,
|
|
119
|
+
function: fnName,
|
|
120
|
+
line: calls[i].line,
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
// ═══════════════════════════════════════════════════════════════
|
|
126
|
+
// Improved C/C++ extraction with function boundary detection
|
|
127
|
+
// ═══════════════════════════════════════════════════════════════
|
|
128
|
+
function extractCCallPairs(code, filePath) {
|
|
129
|
+
const pairs = [];
|
|
130
|
+
const lines = code.split("\n");
|
|
131
|
+
// Simple function boundary detection: track brace depth at function level
|
|
132
|
+
let inFunction = false;
|
|
133
|
+
let currentFunction = "<global>";
|
|
134
|
+
let funcDepth = 0;
|
|
135
|
+
let funcCalls = [];
|
|
136
|
+
const callRegex = /\b([a-zA-Z_]\w*(?:\.[a-zA-Z_]\w*)?)\s*\(/g;
|
|
137
|
+
for (let li = 0; li < lines.length; li++) {
|
|
138
|
+
const line = lines[li];
|
|
139
|
+
// Detect function definition start (simplified: return type + name + ( + {)
|
|
140
|
+
const funcMatch = line.match(/^\s*(?:static\s+|inline\s+|void\s+|int\s+|char\s+|bool\s+|size_t\s+|FILE\*?\s*|DB\*?\s*)?(\w+)\s*\([^)]*\)\s*\{/);
|
|
141
|
+
if (funcMatch && funcDepth === 0) {
|
|
142
|
+
// Entering a new top-level function
|
|
143
|
+
if (funcCalls.length > 0) {
|
|
144
|
+
// Flush previous function's calls as pairs
|
|
145
|
+
flushFunctionPairs(funcCalls, currentFunction, filePath, pairs);
|
|
146
|
+
}
|
|
147
|
+
currentFunction = funcMatch[1];
|
|
148
|
+
funcCalls = [];
|
|
149
|
+
inFunction = true;
|
|
150
|
+
}
|
|
151
|
+
// Track brace depth
|
|
152
|
+
for (const ch of line) {
|
|
153
|
+
if (ch === "{")
|
|
154
|
+
funcDepth++;
|
|
155
|
+
if (ch === "}") {
|
|
156
|
+
funcDepth--;
|
|
157
|
+
if (funcDepth === 0 && inFunction) {
|
|
158
|
+
// Leaving a function
|
|
159
|
+
flushFunctionPairs(funcCalls, currentFunction, filePath, pairs);
|
|
160
|
+
currentFunction = "<global>";
|
|
161
|
+
funcCalls = [];
|
|
162
|
+
inFunction = false;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
// Extract calls on this line
|
|
167
|
+
let match;
|
|
168
|
+
callRegex.lastIndex = 0;
|
|
169
|
+
while ((match = callRegex.exec(line)) !== null) {
|
|
170
|
+
const fnName = normalizeFn(match[1]);
|
|
171
|
+
if (fnName.length > 2 && !isNoiseFunction(fnName)) {
|
|
172
|
+
funcCalls.push({ name: fnName, line: li + 1 });
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
// Flush remaining
|
|
177
|
+
if (funcCalls.length > 0) {
|
|
178
|
+
flushFunctionPairs(funcCalls, currentFunction, filePath, pairs);
|
|
179
|
+
}
|
|
180
|
+
return pairs;
|
|
181
|
+
}
|
|
182
|
+
function flushFunctionPairs(calls, fnName, filePath, pairs) {
|
|
183
|
+
for (let i = 0; i < calls.length - 1; i++) {
|
|
184
|
+
for (let j = i + 1; j < calls.length; j++) {
|
|
185
|
+
pairs.push({
|
|
186
|
+
from: calls[i].name,
|
|
187
|
+
to: calls[j].name,
|
|
188
|
+
file: filePath,
|
|
189
|
+
function: fnName,
|
|
190
|
+
line: calls[i].line,
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
function normalizeFn(fn) {
|
|
196
|
+
const parts = fn.split(".");
|
|
197
|
+
return parts[parts.length - 1];
|
|
198
|
+
}
|
|
199
|
+
function isNoiseFunction(name) {
|
|
200
|
+
const noise = new Set([
|
|
201
|
+
"if", "for", "while", "switch", "return", "sizeof", "typeof",
|
|
202
|
+
"console", "log", "require", "import", "export", "print", "len",
|
|
203
|
+
"push", "pop", "map", "filter", "reduce", "forEach", "toString",
|
|
204
|
+
"valueOf", "assert", "expect", "test", "describe", "it",
|
|
205
|
+
"main", "printf", "sprintf", "fprintf", "write_config", "read_config",
|
|
206
|
+
"setup", "teardown", "init", "destroy", "cleanup",
|
|
207
|
+
"get", "set", "has", "is", "to", "from", "new",
|
|
208
|
+
]);
|
|
209
|
+
return noise.has(name) || name.length <= 1 || /^[A-Z_]+$/.test(name);
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Extract protocol rules with scope-aware pairing.
|
|
213
|
+
*
|
|
214
|
+
* Uses ts-morph AST for TS/JS files and function-boundary-aware
|
|
215
|
+
* regex for C/C++ files.
|
|
216
|
+
*/
|
|
217
|
+
function extractProtocolV2(repoPath, protocolName, maxFiles = 200) {
|
|
218
|
+
const files = (0, repo_evaluator_1.scanRepository)(repoPath, maxFiles);
|
|
219
|
+
const allPairs = [];
|
|
220
|
+
for (const fp of files) {
|
|
221
|
+
try {
|
|
222
|
+
const ext = path.extname(fp);
|
|
223
|
+
if (ext === ".ts" || ext === ".js" || ext === ".mjs") {
|
|
224
|
+
allPairs.push(...extractTSCallPairs(fp));
|
|
225
|
+
}
|
|
226
|
+
else if ([".c", ".cpp", ".h", ".hpp", ".java", ".go", ".rs"].includes(ext)) {
|
|
227
|
+
const code = fs.readFileSync(fp, "utf-8");
|
|
228
|
+
allPairs.push(...extractCCallPairs(code, fp));
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
catch { /* skip unparseable files */ }
|
|
232
|
+
}
|
|
233
|
+
// Frequency analysis and rule inference
|
|
234
|
+
const rules = inferScopeRules(allPairs);
|
|
235
|
+
const states = new Set();
|
|
236
|
+
for (const [, rule] of rules) {
|
|
237
|
+
for (const s of rule.pre_states)
|
|
238
|
+
states.add(s);
|
|
239
|
+
for (const s of rule.post_states)
|
|
240
|
+
states.add(s);
|
|
241
|
+
if (rule.invalidate)
|
|
242
|
+
for (const s of rule.invalidate)
|
|
243
|
+
states.add(s);
|
|
244
|
+
}
|
|
245
|
+
// Quality assessment against ground truth
|
|
246
|
+
const defs = (0, protocol_coverage_1.loadDefaultProtocolDefinitions)();
|
|
247
|
+
const groundTruth = new Map();
|
|
248
|
+
for (const p of defs)
|
|
249
|
+
for (const [fn, rule] of p.rules)
|
|
250
|
+
groundTruth.set(fn, rule);
|
|
251
|
+
const extractedFns = new Set(rules.keys());
|
|
252
|
+
let matched = 0;
|
|
253
|
+
for (const fn of extractedFns) {
|
|
254
|
+
if (groundTruth.has(fn))
|
|
255
|
+
matched++;
|
|
256
|
+
}
|
|
257
|
+
const precision = extractedFns.size > 0 ? matched / extractedFns.size : 0;
|
|
258
|
+
const recall = groundTruth.size > 0 ? matched / groundTruth.size : 0;
|
|
259
|
+
const f1 = precision + recall > 0 ? 2 * precision * recall / (precision + recall) : 0;
|
|
260
|
+
let tier;
|
|
261
|
+
if (precision >= 0.70 && recall >= 0.50)
|
|
262
|
+
tier = "production";
|
|
263
|
+
else if (precision >= 0.50 && recall >= 0.30)
|
|
264
|
+
tier = "beta";
|
|
265
|
+
else
|
|
266
|
+
tier = "poc";
|
|
267
|
+
return {
|
|
268
|
+
protocol: protocolName || path.basename(repoPath),
|
|
269
|
+
rules,
|
|
270
|
+
states: [...states],
|
|
271
|
+
pairs: allPairs,
|
|
272
|
+
filesScanned: files.length,
|
|
273
|
+
quality: {
|
|
274
|
+
precision,
|
|
275
|
+
recall,
|
|
276
|
+
f1,
|
|
277
|
+
totalExtracted: extractedFns.size,
|
|
278
|
+
groundTruthMatch: matched,
|
|
279
|
+
groundTruthTotal: groundTruth.size,
|
|
280
|
+
tier,
|
|
281
|
+
},
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
// ═══════════════════════════════════════════════════════════════
|
|
285
|
+
// Scope-aware rule inference
|
|
286
|
+
// ═══════════════════════════════════════════════════════════════
|
|
287
|
+
const protocol_foundation_1 = require("./protocol-foundation");
|
|
288
|
+
function inferScopeRules(pairs, minFrequency = 2) {
|
|
289
|
+
const transitions = new Map();
|
|
290
|
+
const fnFreq = new Map();
|
|
291
|
+
for (const p of pairs) {
|
|
292
|
+
const key = `${p.from}→${p.to}`;
|
|
293
|
+
transitions.set(key, (transitions.get(key) || 0) + 1);
|
|
294
|
+
fnFreq.set(p.from, (fnFreq.get(p.from) || 0) + 1);
|
|
295
|
+
fnFreq.set(p.to, (fnFreq.get(p.to) || 0) + 1);
|
|
296
|
+
}
|
|
297
|
+
const fnStates = new Map();
|
|
298
|
+
const maxFreq = Math.max(1, ...[...transitions.values()]);
|
|
299
|
+
for (const [key, freq] of transitions) {
|
|
300
|
+
if (freq < minFrequency)
|
|
301
|
+
continue;
|
|
302
|
+
const [fnA, fnB] = key.split("→");
|
|
303
|
+
const stateName = (0, protocol_foundation_1.inferStateName)(fnA, "post");
|
|
304
|
+
const aStates = fnStates.get(fnA) || { produced: new Set(), required: new Set(), invalidated: new Set() };
|
|
305
|
+
aStates.produced.add(stateName);
|
|
306
|
+
fnStates.set(fnA, aStates);
|
|
307
|
+
const bStates = fnStates.get(fnB) || { produced: new Set(), required: new Set(), invalidated: new Set() };
|
|
308
|
+
bStates.required.add(stateName);
|
|
309
|
+
fnStates.set(fnB, bStates);
|
|
310
|
+
}
|
|
311
|
+
// Invalidation detection
|
|
312
|
+
const closers = new Set(["close", "disconnect", "logout", "free", "destroy", "release", "stop", "end", "finish"]);
|
|
313
|
+
const openers = new Set(["open", "connect", "login", "create", "alloc", "init", "start", "begin"]);
|
|
314
|
+
for (const [key] of transitions) {
|
|
315
|
+
const [fnA, fnB] = key.split("→");
|
|
316
|
+
const aStates = fnStates.get(fnA);
|
|
317
|
+
const bStates = fnStates.get(fnB);
|
|
318
|
+
if (!aStates || !bStates)
|
|
319
|
+
continue;
|
|
320
|
+
const isCloser = [...closers].some(kw => fnB.includes(kw));
|
|
321
|
+
const isOpener = [...openers].some(kw => fnA.includes(kw));
|
|
322
|
+
if (isCloser && isOpener) {
|
|
323
|
+
for (const s of aStates.produced)
|
|
324
|
+
bStates.invalidated.add(s);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
const rules = new Map();
|
|
328
|
+
for (const [fn, states] of fnStates) {
|
|
329
|
+
rules.set(fn, {
|
|
330
|
+
pre_states: [...states.required],
|
|
331
|
+
post_states: [...states.produced],
|
|
332
|
+
invalidate: states.invalidated.size > 0 ? [...states.invalidated] : undefined,
|
|
333
|
+
});
|
|
334
|
+
}
|
|
335
|
+
return rules;
|
|
336
|
+
}
|
|
337
|
+
// ═══════════════════════════════════════════════════════════════
|
|
338
|
+
// Quality Report
|
|
339
|
+
// ═══════════════════════════════════════════════════════════════
|
|
340
|
+
function printExtractionQuality(report) {
|
|
341
|
+
console.log("\n╔════════════════════════════════════════════════════╗");
|
|
342
|
+
console.log("║ P6.0v2 Protocol Extraction Quality Report ║");
|
|
343
|
+
console.log("╚════════════════════════════════════════════════════╝\n");
|
|
344
|
+
console.log("Repository Prec Recall F1 Pairs Files Tier");
|
|
345
|
+
console.log("──────────────────────────────────────────────────────────────");
|
|
346
|
+
for (const r of report) {
|
|
347
|
+
const p = (r.quality.precision * 100).toFixed(0).padStart(4);
|
|
348
|
+
const rc = (r.quality.recall * 100).toFixed(0).padStart(4);
|
|
349
|
+
const f = (r.quality.f1 * 100).toFixed(0).padStart(4);
|
|
350
|
+
const tier = r.quality.tier === "production" ? "🟢" : r.quality.tier === "beta" ? "🟡" : "🔴";
|
|
351
|
+
console.log(` ${r.name.padEnd(16)} ${p}% ${rc}% ${f}% ${String(r.pairs).padStart(5)} ${String(r.files).padStart(5)} ${tier} ${r.quality.tier}`);
|
|
352
|
+
}
|
|
353
|
+
console.log();
|
|
354
|
+
}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* P6.0v2: AST-based Protocol Extractor 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 protocol_extractor_v2_1 = require("./protocol-extractor-v2");
|
|
43
|
+
const V2_DIR = path.resolve(__dirname, "..", "test-extractor-v2");
|
|
44
|
+
function createTestRepo() {
|
|
45
|
+
const srcDir = path.join(V2_DIR, "src");
|
|
46
|
+
fs.mkdirSync(srcDir, { recursive: true });
|
|
47
|
+
// TypeScript file using names that match ground truth (protocols.json)
|
|
48
|
+
fs.writeFileSync(path.join(srcDir, "file-service.ts"), `
|
|
49
|
+
export class FileService {
|
|
50
|
+
processFile(path: string): string {
|
|
51
|
+
open_file(path);
|
|
52
|
+
const data = read_file(path);
|
|
53
|
+
write_file(path, data);
|
|
54
|
+
close_file(path);
|
|
55
|
+
return data;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
`);
|
|
59
|
+
// C file using names that match ground truth — multiple functions per pattern
|
|
60
|
+
fs.writeFileSync(path.join(srcDir, "db_handler.c"), `
|
|
61
|
+
void run_query(const char* host, const char* sql) {
|
|
62
|
+
connect_db(host);
|
|
63
|
+
query_db(sql);
|
|
64
|
+
disconnect_db();
|
|
65
|
+
}
|
|
66
|
+
void run_insert(const char* host, const char* data) {
|
|
67
|
+
connect_db(host);
|
|
68
|
+
query_db(data);
|
|
69
|
+
disconnect_db();
|
|
70
|
+
}
|
|
71
|
+
void verify_and_session(const char* user, const char* pass) {
|
|
72
|
+
verify_password(user, pass);
|
|
73
|
+
generate_jwt(user);
|
|
74
|
+
create_session();
|
|
75
|
+
}
|
|
76
|
+
void auth_and_logout(const char* user, const char* pass) {
|
|
77
|
+
verify_password(user, pass);
|
|
78
|
+
generate_jwt(user);
|
|
79
|
+
create_session();
|
|
80
|
+
logout();
|
|
81
|
+
}
|
|
82
|
+
`);
|
|
83
|
+
return V2_DIR;
|
|
84
|
+
}
|
|
85
|
+
(0, vitest_1.describe)("Protocol Extractor v2 (AST-based)", () => {
|
|
86
|
+
createTestRepo();
|
|
87
|
+
(0, vitest_1.it)("extracts scope-aware call pairs within function boundaries", () => {
|
|
88
|
+
const result = (0, protocol_extractor_v2_1.extractProtocolV2)(V2_DIR, "TestRepo", 20);
|
|
89
|
+
(0, vitest_1.expect)(result.pairs.length).toBeGreaterThan(0);
|
|
90
|
+
// Each pair should be within a single function scope
|
|
91
|
+
for (const p of result.pairs) {
|
|
92
|
+
(0, vitest_1.expect)(p.function).not.toBe("<global>");
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
(0, vitest_1.it)("infers protocol rules with improved precision", () => {
|
|
96
|
+
const result = (0, protocol_extractor_v2_1.extractProtocolV2)(V2_DIR, "TestRepo", 20);
|
|
97
|
+
(0, vitest_1.expect)(result.rules.size).toBeGreaterThan(0);
|
|
98
|
+
// Should find file operations
|
|
99
|
+
const fns = [...result.rules.keys()];
|
|
100
|
+
(0, vitest_1.expect)(fns.some(f => f.includes("openFile") || f.includes("open"))).toBe(true);
|
|
101
|
+
(0, vitest_1.expect)(fns.some(f => f.includes("closeFile") || f.includes("close"))).toBe(true);
|
|
102
|
+
// Quality should be better than v1 (33%/12%)
|
|
103
|
+
console.log(`Precision: ${(result.quality.precision * 100).toFixed(0)}%, Recall: ${(result.quality.recall * 100).toFixed(0)}%, F1: ${(result.quality.f1 * 100).toFixed(0)}%`);
|
|
104
|
+
});
|
|
105
|
+
(0, vitest_1.it)("filters noise functions within function scopes", () => {
|
|
106
|
+
const noisyCode = path.join(V2_DIR, "noisy.ts");
|
|
107
|
+
fs.writeFileSync(noisyCode, `
|
|
108
|
+
function doWork() {
|
|
109
|
+
open_file("test");
|
|
110
|
+
console.log("opened");
|
|
111
|
+
assert(fileExists);
|
|
112
|
+
read_file(fd);
|
|
113
|
+
console.log("read done");
|
|
114
|
+
close_file(fd);
|
|
115
|
+
}
|
|
116
|
+
`);
|
|
117
|
+
const result = (0, protocol_extractor_v2_1.extractProtocolV2)(V2_DIR, "NoisyRepo", 20);
|
|
118
|
+
const fns = [...result.rules.keys()];
|
|
119
|
+
// Noise functions should not appear in extracted rules
|
|
120
|
+
(0, vitest_1.expect)(fns.includes("console")).toBe(false);
|
|
121
|
+
(0, vitest_1.expect)(fns.includes("assert")).toBe(false);
|
|
122
|
+
});
|
|
123
|
+
(0, vitest_1.it)("produces quality tier classification", () => {
|
|
124
|
+
const result = (0, protocol_extractor_v2_1.extractProtocolV2)(V2_DIR, "TestRepo", 20);
|
|
125
|
+
(0, vitest_1.expect)(result.quality.tier).toBeDefined();
|
|
126
|
+
(0, vitest_1.expect)(["production", "beta", "poc"]).toContain(result.quality.tier);
|
|
127
|
+
(0, protocol_extractor_v2_1.printExtractionQuality)([{
|
|
128
|
+
name: result.protocol,
|
|
129
|
+
quality: result.quality,
|
|
130
|
+
pairs: result.pairs.length,
|
|
131
|
+
files: result.filesScanned,
|
|
132
|
+
}]);
|
|
133
|
+
});
|
|
134
|
+
(0, vitest_1.it)("handles empty/missing directories gracefully", () => {
|
|
135
|
+
const result = (0, protocol_extractor_v2_1.extractProtocolV2)("/nonexistent/path/v2test", "EmptyRepo", 10);
|
|
136
|
+
(0, vitest_1.expect)(result.filesScanned).toBe(0);
|
|
137
|
+
(0, vitest_1.expect)(result.pairs.length).toBe(0);
|
|
138
|
+
(0, vitest_1.expect)(result.rules.size).toBe(0);
|
|
139
|
+
});
|
|
140
|
+
});
|