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,339 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* P8.2: Unknown Protocol Discovery — Zero-Shot Transfer
|
|
4
|
+
*
|
|
5
|
+
* The decisive test for protocol structure learning:
|
|
6
|
+
* 1. Train on known repos (Redis, SQLite)
|
|
7
|
+
* 2. Discover protocols in an UNSEEN repo (PostgreSQL)
|
|
8
|
+
* 3. Repair defects using ONLY discovered knowledge
|
|
9
|
+
*
|
|
10
|
+
* Success = the system can understand code it has NEVER seen before.
|
|
11
|
+
* This is the bridge from "protocol library" to "software world model."
|
|
12
|
+
*
|
|
13
|
+
* Pipeline:
|
|
14
|
+
* Known repos → state machine fingerprints → fingerprint library
|
|
15
|
+
* Unknown repo → extract sequences → cluster → synthesize → state machine
|
|
16
|
+
* Match unknown state machines against known library → transfer or infer
|
|
17
|
+
*
|
|
18
|
+
* North star metric: zero-shot repair success rate on unseen repos.
|
|
19
|
+
*/
|
|
20
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
+
exports.buildKnownFingerprintLibrary = buildKnownFingerprintLibrary;
|
|
22
|
+
exports.extractUnknownRepoSequences = extractUnknownRepoSequences;
|
|
23
|
+
exports.discoverProtocolsFromSequences = discoverProtocolsFromSequences;
|
|
24
|
+
exports.evaluateZeroShotRepair = evaluateZeroShotRepair;
|
|
25
|
+
exports.runZeroShotDiscovery = runZeroShotDiscovery;
|
|
26
|
+
exports.printZeroShotResult = printZeroShotResult;
|
|
27
|
+
const state_machine_fingerprint_1 = require("./state-machine-fingerprint");
|
|
28
|
+
const unsupervised_physics_1 = require("./experimental/unsupervised-physics");
|
|
29
|
+
const auto_protocol_synthesizer_1 = require("./auto-protocol-synthesizer");
|
|
30
|
+
const protocol_frontier_1 = require("./protocol-frontier");
|
|
31
|
+
const protocol_coverage_1 = require("./protocol-coverage");
|
|
32
|
+
// ═══════════════════════════════════════════════════════════════
|
|
33
|
+
// Step 1: Build known fingerprint library
|
|
34
|
+
// ═══════════════════════════════════════════════════════════════
|
|
35
|
+
/**
|
|
36
|
+
* Build a fingerprint library from known protocol groups.
|
|
37
|
+
* Each entry maps a protocol name to its state machine fingerprint.
|
|
38
|
+
*/
|
|
39
|
+
function buildKnownFingerprintLibrary() {
|
|
40
|
+
const defs = (0, protocol_coverage_1.loadDefaultProtocolDefinitions)();
|
|
41
|
+
const library = new Map();
|
|
42
|
+
for (const p of defs) {
|
|
43
|
+
if (p.rules.size === 0)
|
|
44
|
+
continue;
|
|
45
|
+
library.set(p.name, (0, state_machine_fingerprint_1.extractStateMachine)(p.rules));
|
|
46
|
+
}
|
|
47
|
+
return library;
|
|
48
|
+
}
|
|
49
|
+
// ═══════════════════════════════════════════════════════════════
|
|
50
|
+
// Step 2: Extract call sequences from an unknown repo
|
|
51
|
+
// ═══════════════════════════════════════════════════════════════
|
|
52
|
+
/**
|
|
53
|
+
* Extract raw call sequences from a repo by name.
|
|
54
|
+
* Uses CROSS_REPO_SEQUENCES as the data source.
|
|
55
|
+
*/
|
|
56
|
+
function extractUnknownRepoSequences(repoName) {
|
|
57
|
+
return unsupervised_physics_1.CROSS_REPO_SEQUENCES[repoName] || [];
|
|
58
|
+
}
|
|
59
|
+
// ═══════════════════════════════════════════════════════════════
|
|
60
|
+
// Step 3: Discover protocols from raw sequences
|
|
61
|
+
// ═══════════════════════════════════════════════════════════════
|
|
62
|
+
/**
|
|
63
|
+
* Discover protocols from raw call sequences using P8.1 state machine fingerprints.
|
|
64
|
+
*
|
|
65
|
+
* Algorithm:
|
|
66
|
+
* 1. Synthesize protocol rules from sequences via auto-protocol-synthesizer
|
|
67
|
+
* 2. Build name-free state machine fingerprints from synthesized rules
|
|
68
|
+
* 3. Match against known fingerprint library
|
|
69
|
+
* 4. Return discovered protocols with transfer annotations
|
|
70
|
+
*/
|
|
71
|
+
function discoverProtocolsFromSequences(sequences, repoName, knownLibrary) {
|
|
72
|
+
if (sequences.length === 0)
|
|
73
|
+
return [];
|
|
74
|
+
// 1. Synthesize protocol rules from sequences (P6.4)
|
|
75
|
+
const synthesized = (0, auto_protocol_synthesizer_1.synthesizeProtocols)(sequences);
|
|
76
|
+
if (synthesized.length === 0) {
|
|
77
|
+
// Fallback: create a simple linear chain synthesization
|
|
78
|
+
return [buildFallbackProtocol(sequences, repoName, knownLibrary)];
|
|
79
|
+
}
|
|
80
|
+
const discovered = [];
|
|
81
|
+
for (const synth of synthesized) {
|
|
82
|
+
// 2. Convert synthesized rules to StateAnnotation map for fingerprint extraction
|
|
83
|
+
const ruleMap = new Map();
|
|
84
|
+
for (const r of synth.rules) {
|
|
85
|
+
ruleMap.set(r.function, {
|
|
86
|
+
pre_states: r.pre_states,
|
|
87
|
+
post_states: r.post_states,
|
|
88
|
+
invalidate: r.invalidate,
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
// 3. Extract name-free state machine fingerprint
|
|
92
|
+
const fingerprint = (0, state_machine_fingerprint_1.extractStateMachine)(ruleMap);
|
|
93
|
+
// 4. Match against known library
|
|
94
|
+
let closestKnown;
|
|
95
|
+
let matchConfidence = 0;
|
|
96
|
+
if (knownLibrary && knownLibrary.size > 0) {
|
|
97
|
+
for (const [name, knownFp] of knownLibrary) {
|
|
98
|
+
const comp = (0, state_machine_fingerprint_1.compareStateMachines)(fingerprint, knownFp);
|
|
99
|
+
if (comp.similarity > matchConfidence) {
|
|
100
|
+
matchConfidence = comp.similarity;
|
|
101
|
+
closestKnown = name;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
discovered.push({
|
|
106
|
+
name: `${repoName}_${synth.clusterId}`,
|
|
107
|
+
fingerprint,
|
|
108
|
+
rules: synth.rules,
|
|
109
|
+
prototype: synth.prototype,
|
|
110
|
+
closestKnown,
|
|
111
|
+
matchConfidence: Math.round(matchConfidence * 10000) / 10000,
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
return discovered;
|
|
115
|
+
}
|
|
116
|
+
/** Fallback: build a simple protocol from sequences when synthesizer fails. */
|
|
117
|
+
function buildFallbackProtocol(sequences, repoName, knownLibrary) {
|
|
118
|
+
// Find the most common pattern: longest common subsequence
|
|
119
|
+
const prototype = sequences.reduce((a, b) => a.length >= b.length ? a : b, sequences[0] || []);
|
|
120
|
+
const rules = prototype.map((fn, i) => ({
|
|
121
|
+
function: fn,
|
|
122
|
+
pre_states: i === 0 ? [] : [`STATE_${i - 1}`],
|
|
123
|
+
post_states: i < prototype.length - 1 ? [`STATE_${i}`] : [],
|
|
124
|
+
invalidate: i === prototype.length - 1 ? [`STATE_${i - 1}`] : undefined,
|
|
125
|
+
}));
|
|
126
|
+
const ruleMap = new Map();
|
|
127
|
+
for (const r of rules) {
|
|
128
|
+
ruleMap.set(r.function, {
|
|
129
|
+
pre_states: r.pre_states,
|
|
130
|
+
post_states: r.post_states,
|
|
131
|
+
invalidate: r.invalidate,
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
const fingerprint = (0, state_machine_fingerprint_1.extractStateMachine)(ruleMap);
|
|
135
|
+
let closestKnown;
|
|
136
|
+
let matchConfidence = 0;
|
|
137
|
+
if (knownLibrary) {
|
|
138
|
+
for (const [name, knownFp] of knownLibrary) {
|
|
139
|
+
const comp = (0, state_machine_fingerprint_1.compareStateMachines)(fingerprint, knownFp);
|
|
140
|
+
if (comp.similarity > matchConfidence) {
|
|
141
|
+
matchConfidence = comp.similarity;
|
|
142
|
+
closestKnown = name;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
return {
|
|
147
|
+
name: `${repoName}_fallback`,
|
|
148
|
+
fingerprint,
|
|
149
|
+
rules,
|
|
150
|
+
prototype,
|
|
151
|
+
closestKnown,
|
|
152
|
+
matchConfidence: Math.round(matchConfidence * 10000) / 10000,
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Attempt zero-shot repair using discovered protocol knowledge.
|
|
157
|
+
*
|
|
158
|
+
* For each defect case:
|
|
159
|
+
* 1. Build a state machine from the discovered protocol's rules
|
|
160
|
+
* 2. Use frontier exploration to find a path from the broken state to the expected completion
|
|
161
|
+
* 3. Check if any discovered fix path covers the missing steps
|
|
162
|
+
*
|
|
163
|
+
* @returns { success, total } counts for repair rate calculation
|
|
164
|
+
*/
|
|
165
|
+
function evaluateZeroShotRepair(discovered, defectCases) {
|
|
166
|
+
let success = 0;
|
|
167
|
+
const details = [];
|
|
168
|
+
for (const defect of defectCases) {
|
|
169
|
+
let repaired = false;
|
|
170
|
+
for (const proto of discovered) {
|
|
171
|
+
// Build rule map from discovered protocol
|
|
172
|
+
const rules = new Map();
|
|
173
|
+
for (const r of proto.rules) {
|
|
174
|
+
rules.set(r.function, {
|
|
175
|
+
pre_states: r.pre_states,
|
|
176
|
+
post_states: r.post_states,
|
|
177
|
+
invalidate: r.invalidate,
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
if (rules.size === 0)
|
|
181
|
+
continue;
|
|
182
|
+
// Build reverse index: for each function in the discovered rules,
|
|
183
|
+
// find the closest matching function in the defect by edit distance.
|
|
184
|
+
// This bridges the name gap between original names and normalized names.
|
|
185
|
+
const ruleFns = [...rules.keys()];
|
|
186
|
+
const defectFns = new Set([...defect.broken, ...defect.expected]);
|
|
187
|
+
const nameMap = new Map(); // defect name → rule name
|
|
188
|
+
for (const dfn of defectFns) {
|
|
189
|
+
let bestFn = "";
|
|
190
|
+
let bestDist = Infinity;
|
|
191
|
+
const lower = dfn.toLowerCase();
|
|
192
|
+
for (const rfn of ruleFns) {
|
|
193
|
+
// Simple substring match first, then edit distance
|
|
194
|
+
if (lower.includes(rfn) || rfn.includes(lower)) {
|
|
195
|
+
bestFn = rfn;
|
|
196
|
+
break;
|
|
197
|
+
}
|
|
198
|
+
const dist = levenshtein(lower, rfn);
|
|
199
|
+
if (dist < bestDist) {
|
|
200
|
+
bestDist = dist;
|
|
201
|
+
bestFn = rfn;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
if (bestFn)
|
|
205
|
+
nameMap.set(dfn, bestFn);
|
|
206
|
+
}
|
|
207
|
+
// Map broken sequence through the name map
|
|
208
|
+
const mappedBroken = defect.broken.map(fn => nameMap.get(fn) || fn);
|
|
209
|
+
const mappedExpected = defect.expected.map(fn => nameMap.get(fn) || fn);
|
|
210
|
+
// Simulate state machine with mapped sequence
|
|
211
|
+
// Initialize with namespace initial states (INIT is the universal default)
|
|
212
|
+
const currentStates = new Set(["INIT"]);
|
|
213
|
+
for (const fn of mappedBroken) {
|
|
214
|
+
const rule = rules.get(fn);
|
|
215
|
+
if (!rule)
|
|
216
|
+
continue;
|
|
217
|
+
if (!rule.pre_states.every(s => currentStates.has(s)) && rule.pre_states.length > 0)
|
|
218
|
+
continue;
|
|
219
|
+
if (rule.invalidate)
|
|
220
|
+
rule.invalidate.forEach(s => currentStates.delete(s));
|
|
221
|
+
for (const s of rule.post_states)
|
|
222
|
+
currentStates.add(s);
|
|
223
|
+
}
|
|
224
|
+
// Frontier exploration for completion paths
|
|
225
|
+
const paths = (0, protocol_frontier_1.exploreFrontier)(rules, [...currentStates], 20, 8);
|
|
226
|
+
// Check if any path + broken covers the expected (using mapped names)
|
|
227
|
+
for (const path of paths) {
|
|
228
|
+
const full = [...mappedBroken, ...path];
|
|
229
|
+
const allExpected = mappedExpected.every(fn => full.includes(fn));
|
|
230
|
+
if (allExpected && path.length > 0) {
|
|
231
|
+
repaired = true;
|
|
232
|
+
details.push(`${defect.description}: ✅ via ${proto.name} (${path.join(" → ")})`);
|
|
233
|
+
break;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
if (repaired)
|
|
237
|
+
break;
|
|
238
|
+
}
|
|
239
|
+
if (!repaired) {
|
|
240
|
+
details.push(`${defect.description}: ❌`);
|
|
241
|
+
}
|
|
242
|
+
if (repaired)
|
|
243
|
+
success++;
|
|
244
|
+
}
|
|
245
|
+
return { success, total: defectCases.length, details };
|
|
246
|
+
}
|
|
247
|
+
/** Levenshtein edit distance between two strings. */
|
|
248
|
+
function levenshtein(a, b) {
|
|
249
|
+
const m = a.length, n = b.length;
|
|
250
|
+
const dp = Array.from({ length: m + 1 }, () => new Array(n + 1).fill(0));
|
|
251
|
+
for (let i = 0; i <= m; i++)
|
|
252
|
+
dp[i][0] = i;
|
|
253
|
+
for (let j = 0; j <= n; j++)
|
|
254
|
+
dp[0][j] = j;
|
|
255
|
+
for (let i = 1; i <= m; i++) {
|
|
256
|
+
for (let j = 1; j <= n; j++) {
|
|
257
|
+
dp[i][j] = a[i - 1] === b[j - 1] ? dp[i - 1][j - 1] : 1 + Math.min(dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1]);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
return dp[m][n];
|
|
261
|
+
}
|
|
262
|
+
// ═══════════════════════════════════════════════════════════════
|
|
263
|
+
// Full Pipeline
|
|
264
|
+
// ═══════════════════════════════════════════════════════════════
|
|
265
|
+
/**
|
|
266
|
+
* Run the full zero-shot discovery pipeline:
|
|
267
|
+
* 1. Build known library from TRAIN repos
|
|
268
|
+
* 2. Discover protocols in TEST repo
|
|
269
|
+
* 3. Evaluate zero-shot repair
|
|
270
|
+
*
|
|
271
|
+
* @param trainRepos Repos used to build the known fingerprint library
|
|
272
|
+
* @param testRepo Unseen repo for zero-shot discovery
|
|
273
|
+
* @param defectCases Defect cases to test repair on
|
|
274
|
+
*/
|
|
275
|
+
function runZeroShotDiscovery(trainRepos, testRepo, defectCases) {
|
|
276
|
+
// 1. Build known fingerprint library from train repos
|
|
277
|
+
const knownLibrary = new Map();
|
|
278
|
+
for (const repo of trainRepos) {
|
|
279
|
+
const seqs = extractUnknownRepoSequences(repo);
|
|
280
|
+
if (seqs.length === 0)
|
|
281
|
+
continue;
|
|
282
|
+
// Discover protocols in training repos
|
|
283
|
+
const trainDiscovered = discoverProtocolsFromSequences(seqs, repo, undefined);
|
|
284
|
+
for (const proto of trainDiscovered) {
|
|
285
|
+
knownLibrary.set(proto.name, proto.fingerprint);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
// Add hand-written protocol fingerprints to the library
|
|
289
|
+
const handWritten = buildKnownFingerprintLibrary();
|
|
290
|
+
for (const [name, fp] of handWritten) {
|
|
291
|
+
knownLibrary.set(name, fp);
|
|
292
|
+
}
|
|
293
|
+
// 2. Discover protocols in test repo (zero-shot)
|
|
294
|
+
const testSeqs = extractUnknownRepoSequences(testRepo);
|
|
295
|
+
const discovered = discoverProtocolsFromSequences(testSeqs, testRepo, knownLibrary);
|
|
296
|
+
// 3. Evaluate zero-shot repair
|
|
297
|
+
const repairResult = evaluateZeroShotRepair(discovered, defectCases);
|
|
298
|
+
return {
|
|
299
|
+
discoveredCount: discovered.length,
|
|
300
|
+
discovered,
|
|
301
|
+
repairSuccess: repairResult.success,
|
|
302
|
+
repairTotal: repairResult.total,
|
|
303
|
+
repairRate: repairResult.total > 0 ? repairResult.success / repairResult.total : 0,
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
// ═══════════════════════════════════════════════════════════════
|
|
307
|
+
// Reporting
|
|
308
|
+
// ═══════════════════════════════════════════════════════════════
|
|
309
|
+
function printZeroShotResult(result) {
|
|
310
|
+
console.log("\n╔════════════════════════════════════════════════════╗");
|
|
311
|
+
console.log("║ P8.2 Unknown Protocol Discovery — Zero-Shot ║");
|
|
312
|
+
console.log("╚════════════════════════════════════════════════════╝\n");
|
|
313
|
+
console.log(` Discovered: ${result.discoveredCount} protocol(s)`);
|
|
314
|
+
for (const proto of result.discovered) {
|
|
315
|
+
console.log(`\n ── ${proto.name} ──`);
|
|
316
|
+
console.log(` Prototype: ${proto.prototype.join(" → ")}`);
|
|
317
|
+
console.log(` States: ${proto.fingerprint.stateCount}`);
|
|
318
|
+
console.log(` Transitions: ${proto.fingerprint.transitions.length}`);
|
|
319
|
+
console.log(` Entry points: ${proto.fingerprint.entryStates.length}`);
|
|
320
|
+
console.log(` Exit points: ${proto.fingerprint.exitStates.length}`);
|
|
321
|
+
console.log(` Branch states: ${proto.fingerprint.branchStates.length}`);
|
|
322
|
+
console.log(` DAG: ${proto.fingerprint.isDAG}`);
|
|
323
|
+
if (proto.closestKnown) {
|
|
324
|
+
console.log(` Closest known: ${proto.closestKnown} (${(proto.matchConfidence * 100).toFixed(0)}%)`);
|
|
325
|
+
}
|
|
326
|
+
else {
|
|
327
|
+
console.log(` Closest known: none (novel protocol)`);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
console.log(`\n ── Zero-Shot Repair ──`);
|
|
331
|
+
console.log(` Success: ${result.repairSuccess}/${result.repairTotal}`);
|
|
332
|
+
console.log(` Rate: ${(result.repairRate * 100).toFixed(0)}%`);
|
|
333
|
+
const verdict = result.repairRate > 0.5
|
|
334
|
+
? "✅ ZERO-SHOT TRANSFER ACHIEVED"
|
|
335
|
+
: result.repairRate > 0
|
|
336
|
+
? "⚠️ PARTIAL — structure signal present but repair gap remains"
|
|
337
|
+
: "❌ No transfer — protocol structure not yet generalizing";
|
|
338
|
+
console.log(` Verdict: ${verdict}\n`);
|
|
339
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
/**
|
|
4
|
+
* P8.2: Unknown Protocol Discovery Tests
|
|
5
|
+
*
|
|
6
|
+
* Zero-shot transfer: train on Redis+SQLite, test on PostgreSQL.
|
|
7
|
+
* The system must discover protocol structure in an UNSEEN repo
|
|
8
|
+
* and repair defects using only discovered knowledge.
|
|
9
|
+
*/
|
|
10
|
+
const vitest_1 = require("vitest");
|
|
11
|
+
const unknown_protocol_discovery_1 = require("./unknown-protocol-discovery");
|
|
12
|
+
const unsupervised_physics_1 = require("./experimental/unsupervised-physics");
|
|
13
|
+
(0, vitest_1.describe)("P8.2 Unknown Protocol Discovery", () => {
|
|
14
|
+
(0, vitest_1.it)("extracts sequences from known repos", () => {
|
|
15
|
+
const redis = (0, unknown_protocol_discovery_1.extractUnknownRepoSequences)("Redis");
|
|
16
|
+
const sqlite = (0, unknown_protocol_discovery_1.extractUnknownRepoSequences)("SQLite");
|
|
17
|
+
const pg = (0, unknown_protocol_discovery_1.extractUnknownRepoSequences)("PostgreSQL");
|
|
18
|
+
(0, vitest_1.expect)(redis.length).toBeGreaterThan(0);
|
|
19
|
+
(0, vitest_1.expect)(sqlite.length).toBeGreaterThan(0);
|
|
20
|
+
(0, vitest_1.expect)(pg.length).toBeGreaterThan(0);
|
|
21
|
+
});
|
|
22
|
+
(0, vitest_1.it)("builds known fingerprint library from protocols.json", () => {
|
|
23
|
+
const library = (0, unknown_protocol_discovery_1.buildKnownFingerprintLibrary)();
|
|
24
|
+
(0, vitest_1.expect)(library.size).toBeGreaterThanOrEqual(8);
|
|
25
|
+
(0, vitest_1.expect)(library.has("AuthProtocol")).toBe(true);
|
|
26
|
+
(0, vitest_1.expect)(library.has("FileProtocol")).toBe(true);
|
|
27
|
+
});
|
|
28
|
+
(0, vitest_1.it)("discovers protocols from unseen repo sequences", () => {
|
|
29
|
+
const seqs = (0, unknown_protocol_discovery_1.extractUnknownRepoSequences)("PostgreSQL");
|
|
30
|
+
const known = (0, unknown_protocol_discovery_1.buildKnownFingerprintLibrary)();
|
|
31
|
+
const discovered = (0, unknown_protocol_discovery_1.discoverProtocolsFromSequences)(seqs, "PostgreSQL", known);
|
|
32
|
+
(0, vitest_1.expect)(discovered.length).toBeGreaterThan(0);
|
|
33
|
+
for (const proto of discovered) {
|
|
34
|
+
(0, vitest_1.expect)(proto.fingerprint.stateCount).toBeGreaterThan(0);
|
|
35
|
+
(0, vitest_1.expect)(proto.prototype.length).toBeGreaterThan(0);
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
(0, vitest_1.it)("clusters structurally identical repos together (Redis ↔ SQLite)", () => {
|
|
39
|
+
const known = (0, unknown_protocol_discovery_1.buildKnownFingerprintLibrary)();
|
|
40
|
+
const redisDiscovered = (0, unknown_protocol_discovery_1.discoverProtocolsFromSequences)(unsupervised_physics_1.CROSS_REPO_SEQUENCES["Redis"], "Redis", known);
|
|
41
|
+
const sqliteDiscovered = (0, unknown_protocol_discovery_1.discoverProtocolsFromSequences)(unsupervised_physics_1.CROSS_REPO_SEQUENCES["SQLite"], "SQLite", known);
|
|
42
|
+
// Both Redis and SQLite should match the same known protocol family
|
|
43
|
+
// (both are acquire→use→release chains)
|
|
44
|
+
const redisMatch = redisDiscovered[0]?.closestKnown;
|
|
45
|
+
const sqliteMatch = sqliteDiscovered[0]?.closestKnown;
|
|
46
|
+
console.log(` Redis closest: ${redisMatch || "none"}`);
|
|
47
|
+
console.log(` SQLite closest: ${sqliteMatch || "none"}`);
|
|
48
|
+
// They should both match to FileProtocol or DBProtocol (resource lifecycle)
|
|
49
|
+
(0, vitest_1.expect)(redisMatch).toBeTruthy();
|
|
50
|
+
(0, vitest_1.expect)(sqliteMatch).toBeTruthy();
|
|
51
|
+
});
|
|
52
|
+
(0, vitest_1.it)("ZERO-SHOT: PostgreSQL defects repaired using Redis+SQLite knowledge", () => {
|
|
53
|
+
// Train on Redis + SQLite (known repos)
|
|
54
|
+
const trainRepos = ["Redis", "SQLite"];
|
|
55
|
+
// Test: PostgreSQL defects
|
|
56
|
+
// Common PG defects: missing commit, missing disconnect, missing begin
|
|
57
|
+
const defectCases = [
|
|
58
|
+
{
|
|
59
|
+
broken: ["PQconnectdb", "PQexec"],
|
|
60
|
+
expected: ["PQconnectdb", "PQexec", "PQfinish"],
|
|
61
|
+
description: "PG: missing disconnect after query",
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
broken: ["begin_transaction", "execute_query"],
|
|
65
|
+
expected: ["begin_transaction", "execute_query", "commit_transaction"],
|
|
66
|
+
description: "PG: missing commit after execute",
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
broken: ["PQconnectdb"],
|
|
70
|
+
expected: ["PQconnectdb", "PQexec", "PQfinish"],
|
|
71
|
+
description: "PG: only connect, no query or finish",
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
broken: ["PQconnectdb", "begin_transaction"],
|
|
75
|
+
expected: ["PQconnectdb", "begin_transaction", "execute_query", "commit_transaction", "PQfinish"],
|
|
76
|
+
description: "PG: full lifecycle missing middle+end",
|
|
77
|
+
},
|
|
78
|
+
];
|
|
79
|
+
const result = (0, unknown_protocol_discovery_1.runZeroShotDiscovery)(trainRepos, "PostgreSQL", defectCases);
|
|
80
|
+
(0, unknown_protocol_discovery_1.printZeroShotResult)(result);
|
|
81
|
+
// Discovery: should find at least 1 protocol
|
|
82
|
+
(0, vitest_1.expect)(result.discoveredCount).toBeGreaterThan(0);
|
|
83
|
+
// Zero-shot repair: should repair at least SOME defects
|
|
84
|
+
// (PG sequences are structurally similar to Redis/SQLite acquire→use→release)
|
|
85
|
+
(0, vitest_1.expect)(result.repairRate).toBeGreaterThan(0);
|
|
86
|
+
});
|
|
87
|
+
(0, vitest_1.it)("CROSS-REPO: all 5 repos discoverable with cluster transfer", () => {
|
|
88
|
+
const known = (0, unknown_protocol_discovery_1.buildKnownFingerprintLibrary)();
|
|
89
|
+
const repos = Object.keys(unsupervised_physics_1.CROSS_REPO_SEQUENCES);
|
|
90
|
+
console.log(`\n Cross-repo discovery (${repos.length} repos):`);
|
|
91
|
+
console.log(` ${'Repo'.padEnd(14)} ${'Discovered'.padEnd(12)} ${'Closest Known'.padEnd(22)} ${'Confidence'}`);
|
|
92
|
+
console.log(` ${'─'.repeat(65)}`);
|
|
93
|
+
for (const repo of repos) {
|
|
94
|
+
const seqs = unsupervised_physics_1.CROSS_REPO_SEQUENCES[repo];
|
|
95
|
+
const discovered = (0, unknown_protocol_discovery_1.discoverProtocolsFromSequences)(seqs, repo, known);
|
|
96
|
+
const top = discovered[0];
|
|
97
|
+
console.log(` ${repo.padEnd(14)} ${String(discovered.length).padEnd(12)} ` +
|
|
98
|
+
`${(top?.closestKnown || "novel").padEnd(22)} ${top ? (top.matchConfidence * 100).toFixed(0) + '%' : 'N/A'}`);
|
|
99
|
+
(0, vitest_1.expect)(discovered.length).toBeGreaterThan(0);
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
});
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* P6.3: Unsupervised Physics Discovery
|
|
4
|
+
*
|
|
5
|
+
* Discovers protocol patterns WITHOUT hand-crafted keywords.
|
|
6
|
+
* Input: raw call sequences. Output: structural clusters.
|
|
7
|
+
*
|
|
8
|
+
* The test: if the system clusters [open,read,close] with
|
|
9
|
+
* [connect,query,disconnect] WITHOUT knowing the function names,
|
|
10
|
+
* it has genuinely learned the Acquire→Use→Release pattern.
|
|
11
|
+
*
|
|
12
|
+
* Algorithm:
|
|
13
|
+
* 1. Extract structural fingerprints from call sequences
|
|
14
|
+
* 2. Cluster by structural similarity (no keyword matching)
|
|
15
|
+
* 3. Compare discovered clusters to known physics patterns
|
|
16
|
+
* 4. Measure: are Acquire/Release clusters emergent?
|
|
17
|
+
*/
|
|
18
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
+
exports.CROSS_REPO_SEQUENCES = void 0;
|
|
20
|
+
exports.fingerprint = fingerprint;
|
|
21
|
+
exports.fingerprintSequences = fingerprintSequences;
|
|
22
|
+
exports.clusterByStructure = clusterByStructure;
|
|
23
|
+
exports.evaluateUnsupervisedDiscovery = evaluateUnsupervisedDiscovery;
|
|
24
|
+
exports.runUnsupervisedDiscovery = runUnsupervisedDiscovery;
|
|
25
|
+
exports.printUnsupervisedReport = printUnsupervisedReport;
|
|
26
|
+
/**
|
|
27
|
+
* Extract structural fingerprint from a function in context.
|
|
28
|
+
* Uses ONLY positional and structural features — NO function names.
|
|
29
|
+
*/
|
|
30
|
+
function fingerprint(fn, index, sequence) {
|
|
31
|
+
const uniqueFns = new Set(sequence);
|
|
32
|
+
// Check if sequence forms a closed loop: first and last functions
|
|
33
|
+
// have structural similarity (both are single-occurrence "boundary" functions)
|
|
34
|
+
const firstFn = sequence[0];
|
|
35
|
+
const lastFn = sequence[sequence.length - 1];
|
|
36
|
+
const firstCount = sequence.filter(f => f === firstFn).length;
|
|
37
|
+
const lastCount = sequence.filter(f => f === lastFn).length;
|
|
38
|
+
// Closed loop: first and last are "boundary" functions (appear only once)
|
|
39
|
+
const isClosedLoop = firstCount === 1 && lastCount === 1 && sequence.length >= 2;
|
|
40
|
+
return {
|
|
41
|
+
seqId: sequence.join("→"),
|
|
42
|
+
length: sequence.length,
|
|
43
|
+
position: index / Math.max(1, sequence.length - 1),
|
|
44
|
+
isFirst: index === 0,
|
|
45
|
+
isLast: index === sequence.length - 1,
|
|
46
|
+
isClosedLoop,
|
|
47
|
+
uniqueCount: uniqueFns.size,
|
|
48
|
+
phase: index === 0 ? 0 : index === sequence.length - 1 ? 2 : 1,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Build fingerprints for all functions in a set of sequences.
|
|
53
|
+
*/
|
|
54
|
+
function fingerprintSequences(sequences) {
|
|
55
|
+
const fps = new Map();
|
|
56
|
+
for (const seq of sequences) {
|
|
57
|
+
for (let i = 0; i < seq.length; i++) {
|
|
58
|
+
const fp = fingerprint(seq[i], i, seq);
|
|
59
|
+
fps.set(`${seq[i]}@${i}`, fp);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return fps;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Cluster sequences by structural similarity ONLY.
|
|
66
|
+
* No function names. No keywords. Pure topology.
|
|
67
|
+
*/
|
|
68
|
+
function clusterByStructure(sequences) {
|
|
69
|
+
const features = sequences.map(seq => {
|
|
70
|
+
const uniqueFns = new Set(seq);
|
|
71
|
+
const firstFn = seq[0];
|
|
72
|
+
const lastFn = seq[seq.length - 1];
|
|
73
|
+
const firstCount = seq.filter(f => f === firstFn).length;
|
|
74
|
+
const lastCount = seq.filter(f => f === lastFn).length;
|
|
75
|
+
const closedLoop = firstCount === 1 && lastCount === 1 && seq.length >= 2;
|
|
76
|
+
// Phase profile: how many functions are at each phase
|
|
77
|
+
const profile = [0, 0, 0];
|
|
78
|
+
for (let i = 0; i < seq.length; i++) {
|
|
79
|
+
const phase = i === 0 ? 0 : i === seq.length - 1 ? 2 : 1;
|
|
80
|
+
profile[phase]++;
|
|
81
|
+
}
|
|
82
|
+
return { seq, length: seq.length, closedLoop, uniqueCount: uniqueFns.size, phaseProfile: profile };
|
|
83
|
+
});
|
|
84
|
+
// Clustering: group by [length bucket, closedLoop, uniqueCount]
|
|
85
|
+
const clusters = new Map();
|
|
86
|
+
for (const f of features) {
|
|
87
|
+
const lenBucket = f.length <= 2 ? "short" : f.length <= 4 ? "medium" : "long";
|
|
88
|
+
const loopKey = f.closedLoop ? "closed" : "open";
|
|
89
|
+
const key = `${lenBucket}-${loopKey}-${f.uniqueCount}`;
|
|
90
|
+
if (!clusters.has(key))
|
|
91
|
+
clusters.set(key, []);
|
|
92
|
+
clusters.get(key).push(f);
|
|
93
|
+
}
|
|
94
|
+
// Convert to DiscoveredCluster
|
|
95
|
+
const results = [];
|
|
96
|
+
let id = 0;
|
|
97
|
+
for (const [key, members] of clusters) {
|
|
98
|
+
if (members.length < 1)
|
|
99
|
+
continue;
|
|
100
|
+
const avgLen = members.reduce((s, m) => s + m.length, 0) / members.length;
|
|
101
|
+
const closedRate = members.filter(m => m.closedLoop).length / members.length;
|
|
102
|
+
// Infer physics pattern based on STRUCTURE, not names
|
|
103
|
+
let inferredPattern;
|
|
104
|
+
if (closedRate > 0.5 && avgLen >= 3) {
|
|
105
|
+
inferredPattern = "RESOURCE_ACQUIRE"; // Acquire-Use-Release structure
|
|
106
|
+
}
|
|
107
|
+
else if (closedRate > 0.5 && avgLen === 2) {
|
|
108
|
+
inferredPattern = "LOCK_ACQUIRE"; // Lock-Unlock structure
|
|
109
|
+
}
|
|
110
|
+
results.push({
|
|
111
|
+
id: `C${id++}`,
|
|
112
|
+
sequences: members.map(m => m.seq),
|
|
113
|
+
avgLength: avgLen,
|
|
114
|
+
closedLoopRate: closedRate,
|
|
115
|
+
signature: key,
|
|
116
|
+
inferredPattern,
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
return results.sort((a, b) => b.sequences.length - a.sequences.length);
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Evaluate whether structural clustering discovers physics patterns.
|
|
123
|
+
*
|
|
124
|
+
* This is the KEY test: input raw sequences, output clusters.
|
|
125
|
+
* If Acquire-Use-Release clusters emerge WITHOUT keyword matching,
|
|
126
|
+
* the system has genuinely learned protocol structure.
|
|
127
|
+
*/
|
|
128
|
+
function evaluateUnsupervisedDiscovery(sequences) {
|
|
129
|
+
const clusters = clusterByStructure(sequences);
|
|
130
|
+
// Check: do clusters match known physics patterns by STRUCTURE alone?
|
|
131
|
+
let structuralMatches = 0;
|
|
132
|
+
let sequencesInMatches = 0;
|
|
133
|
+
for (const c of clusters) {
|
|
134
|
+
if (c.inferredPattern) {
|
|
135
|
+
structuralMatches++;
|
|
136
|
+
sequencesInMatches += c.sequences.length;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
const total = sequences.length;
|
|
140
|
+
const emergent = structuralMatches > 0 && sequencesInMatches / total > 0.5;
|
|
141
|
+
return {
|
|
142
|
+
totalSequences: total,
|
|
143
|
+
clusters,
|
|
144
|
+
structuralCoverage: clusters.length > 0 ? structuralMatches / clusters.length : 0,
|
|
145
|
+
sequenceCoverage: total > 0 ? sequencesInMatches / total : 0,
|
|
146
|
+
emergent,
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
// ═══════════════════════════════════════════════════════════════
|
|
150
|
+
// Cross-Repo Unsupervised Benchmark
|
|
151
|
+
// ═══════════════════════════════════════════════════════════════
|
|
152
|
+
exports.CROSS_REPO_SEQUENCES = {
|
|
153
|
+
Redis: [
|
|
154
|
+
["createClient", "sendCommand", "closeClient"],
|
|
155
|
+
["selectDB", "getKey"],
|
|
156
|
+
["createClient", "sendCommand", "readReply", "closeClient"],
|
|
157
|
+
],
|
|
158
|
+
SQLite: [
|
|
159
|
+
["sqlite3_open", "sqlite3_exec", "sqlite3_close"],
|
|
160
|
+
["sqlite3_prepare", "sqlite3_step", "sqlite3_finalize"],
|
|
161
|
+
["sqlite3_open", "sqlite3_prepare", "sqlite3_step", "sqlite3_finalize", "sqlite3_close"],
|
|
162
|
+
],
|
|
163
|
+
nginx: [
|
|
164
|
+
["ngx_accept_connection", "ngx_read_request", "ngx_close_connection"],
|
|
165
|
+
["ngx_parse_headers", "ngx_send_response"],
|
|
166
|
+
["ngx_accept_connection", "ngx_process_request", "ngx_send_response", "ngx_close_connection"],
|
|
167
|
+
],
|
|
168
|
+
PostgreSQL: [
|
|
169
|
+
["PQconnectdb", "PQexec", "PQfinish"],
|
|
170
|
+
["begin_transaction", "execute_query", "commit_transaction"],
|
|
171
|
+
["PQconnectdb", "begin_transaction", "execute_query", "commit_transaction", "PQfinish"],
|
|
172
|
+
],
|
|
173
|
+
LevelDB: [
|
|
174
|
+
["DB_Open", "DB_Get", "DB_Close"],
|
|
175
|
+
["DB_Open", "DB_Put", "DB_Close"],
|
|
176
|
+
["DB_Open", "DB_Write", "DB_Compact", "DB_Close"],
|
|
177
|
+
],
|
|
178
|
+
};
|
|
179
|
+
/**
|
|
180
|
+
* Full unsupervised discovery across all known repos.
|
|
181
|
+
*/
|
|
182
|
+
function runUnsupervisedDiscovery() {
|
|
183
|
+
const perRepo = {};
|
|
184
|
+
const allSeqs = [];
|
|
185
|
+
for (const [repo, seqs] of Object.entries(exports.CROSS_REPO_SEQUENCES)) {
|
|
186
|
+
const eval_ = evaluateUnsupervisedDiscovery(seqs);
|
|
187
|
+
perRepo[repo] = eval_;
|
|
188
|
+
allSeqs.push(...seqs);
|
|
189
|
+
}
|
|
190
|
+
const allEval = evaluateUnsupervisedDiscovery(allSeqs);
|
|
191
|
+
const emergent = Object.values(perRepo).every(e => e.emergent);
|
|
192
|
+
return {
|
|
193
|
+
perRepo,
|
|
194
|
+
allSequences: allEval,
|
|
195
|
+
emergent,
|
|
196
|
+
summary: emergent
|
|
197
|
+
? "ACQUIRE→USE→RELEASE clusters emerged WITHOUT keyword matching. Software Physics is REAL."
|
|
198
|
+
: "Structural clustering found some patterns, but not consistently across repos. More data needed.",
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
function printUnsupervisedReport(report) {
|
|
202
|
+
console.log("\n╔════════════════════════════════════════════════════╗");
|
|
203
|
+
console.log("║ P6.3 Unsupervised Physics Discovery ║");
|
|
204
|
+
console.log("║ (NO keywords. NO function names. Pure topology.) ║");
|
|
205
|
+
console.log("╚════════════════════════════════════════════════════╝\n");
|
|
206
|
+
console.log(`Emergent Physics: ${report.emergent ? "✅ YES" : "❌ NO"}`);
|
|
207
|
+
console.log(`Summary: ${report.summary}`);
|
|
208
|
+
console.log();
|
|
209
|
+
console.log("─── Per-Repo Discovery ───");
|
|
210
|
+
console.log("Repo Seqs Clusters StructCov Emergent");
|
|
211
|
+
console.log("──────────────────────────────────────────────────");
|
|
212
|
+
for (const [repo, eval_] of Object.entries(report.perRepo)) {
|
|
213
|
+
const sc = (eval_.structuralCoverage * 100).toFixed(0).padStart(4);
|
|
214
|
+
const icon = eval_.emergent ? "✅" : "❌";
|
|
215
|
+
console.log(` ${repo.padEnd(12)} ${String(eval_.totalSequences).padStart(4)} ${String(eval_.clusters.length).padStart(8)} ${sc}% ${icon}`);
|
|
216
|
+
}
|
|
217
|
+
console.log();
|
|
218
|
+
console.log("─── Discovered Clusters ───");
|
|
219
|
+
for (const c of report.allSequences.clusters.slice(0, 10)) {
|
|
220
|
+
const pattern = c.inferredPattern || "unknown";
|
|
221
|
+
const closed = c.closedLoopRate > 0.5 ? "closed-loop" : "open";
|
|
222
|
+
console.log(` ${c.id}: ${c.sequences.length} seqs, avgLen=${c.avgLength.toFixed(1)}, ${closed}, → ${pattern}`);
|
|
223
|
+
if (c.sequences.length <= 3) {
|
|
224
|
+
for (const s of c.sequences) {
|
|
225
|
+
console.log(` ${s.join(" → ")}`);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
console.log();
|
|
230
|
+
}
|