progmune-runtime 2.1.5 → 3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 +326 -59
- 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,297 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* P10.1: Protocol Embedding Space — Scaled to 50+ protocol variants
|
|
4
|
+
*
|
|
5
|
+
* Generates realistic protocol variations from the topology factory,
|
|
6
|
+
* builds WL embeddings for each, and measures whether protocol
|
|
7
|
+
* families naturally cluster in embedding space.
|
|
8
|
+
*
|
|
9
|
+
* This simulates what would happen with 50 real GitHub repos —
|
|
10
|
+
* each "variant" has the same topology but different function names
|
|
11
|
+
* and sequence lengths, testing whether structural identity survives
|
|
12
|
+
* these variations.
|
|
13
|
+
*/
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.buildScaledEmbeddingSpace = buildScaledEmbeddingSpace;
|
|
16
|
+
exports.adjustedRandIndex = adjustedRandIndex;
|
|
17
|
+
exports.kMeansCluster = kMeansCluster;
|
|
18
|
+
exports.printScaledReport = printScaledReport;
|
|
19
|
+
const topology_factory_1 = require("./topology-factory");
|
|
20
|
+
const state_inference_1 = require("./experimental/state-inference");
|
|
21
|
+
const wl_fingerprint_1 = require("./wl-fingerprint");
|
|
22
|
+
const unsupervised_physics_1 = require("./experimental/unsupervised-physics");
|
|
23
|
+
// ═══════════════════════════════════════════════════════════════
|
|
24
|
+
// Generate protocol variants with realistic name variations
|
|
25
|
+
// ═══════════════════════════════════════════════════════════════
|
|
26
|
+
const FAMILY_NAMES = {
|
|
27
|
+
linear: ["open", "create", "init", "start", "acquire", "setup", "begin"],
|
|
28
|
+
star: ["hub", "router", "dispatcher", "broker", "proxy", "gateway"],
|
|
29
|
+
tree: ["root", "parent", "ancestor", "node", "branch", "leaf"],
|
|
30
|
+
loop: ["process", "handle", "iterate", "poll", "listen", "watch", "observe"],
|
|
31
|
+
two_phase_commit: ["prepare", "vote", "decide", "propose", "accept", "learn"],
|
|
32
|
+
auth_bridge: ["authenticate", "authorize", "verify", "validate", "permit", "allow"],
|
|
33
|
+
nested: ["outer", "inner", "wrapper", "container", "scope", "context"],
|
|
34
|
+
rollback: ["forward", "advance", "proceed", "undo", "revert", "backtrack"],
|
|
35
|
+
fan_out: ["fork", "split", "scatter", "distribute", "spawn", "dispatch"],
|
|
36
|
+
stateless: ["compute", "transform", "map", "filter", "reduce", "validate"],
|
|
37
|
+
};
|
|
38
|
+
/** Generate N variants of a protocol topology with varied names and sequence patterns. */
|
|
39
|
+
function generateVariants(topo, count) {
|
|
40
|
+
const rules = (0, topology_factory_1.createProtocolForTopology)(topo);
|
|
41
|
+
const entries = [...rules.entries()];
|
|
42
|
+
if (entries.length === 0)
|
|
43
|
+
return [];
|
|
44
|
+
const familyNames = FAMILY_NAMES[topo] || [topo];
|
|
45
|
+
const variants = [];
|
|
46
|
+
for (let v = 0; v < count; v++) {
|
|
47
|
+
// Pick a distinctive name from the family
|
|
48
|
+
const variantName = `${topo}_${familyNames[v % familyNames.length]}`;
|
|
49
|
+
const sequences = [];
|
|
50
|
+
for (let trial = 0; trial < 6; trial++) {
|
|
51
|
+
const path = [];
|
|
52
|
+
const stateSet = new Set(["INIT", "IDLE"]);
|
|
53
|
+
const startEntry = entries[Math.floor(Math.random() * entries.length)];
|
|
54
|
+
path.push(startEntry[0]);
|
|
55
|
+
const rule = startEntry[1];
|
|
56
|
+
if (rule.invalidate)
|
|
57
|
+
rule.invalidate.forEach((s) => stateSet.delete(s));
|
|
58
|
+
for (const s of rule.post_states)
|
|
59
|
+
stateSet.add(s);
|
|
60
|
+
const targetLen = 2 + Math.floor(Math.random() * 5);
|
|
61
|
+
while (path.length < targetLen) {
|
|
62
|
+
const candidates = entries.filter(([, r]) => r.pre_states.every((s) => stateSet.has(s)));
|
|
63
|
+
if (candidates.length === 0)
|
|
64
|
+
break;
|
|
65
|
+
const [fn, nextRule] = candidates[Math.floor(Math.random() * candidates.length)];
|
|
66
|
+
path.push(fn);
|
|
67
|
+
if (nextRule.invalidate)
|
|
68
|
+
nextRule.invalidate.forEach((s) => stateSet.delete(s));
|
|
69
|
+
for (const s of nextRule.post_states)
|
|
70
|
+
stateSet.add(s);
|
|
71
|
+
}
|
|
72
|
+
if (path.length >= 2)
|
|
73
|
+
sequences.push(path);
|
|
74
|
+
}
|
|
75
|
+
variants.push({ name: variantName, sequences });
|
|
76
|
+
}
|
|
77
|
+
return variants;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Build a scaled embedding space with N variants per topology family.
|
|
81
|
+
* Total protocols = topologies × variantsPerFamily + cross_repo protocols.
|
|
82
|
+
*/
|
|
83
|
+
function buildScaledEmbeddingSpace(variantsPerFamily = 5) {
|
|
84
|
+
const protocols = [];
|
|
85
|
+
const labels = [];
|
|
86
|
+
// Generate variants for each topology family
|
|
87
|
+
for (const topo of topology_factory_1.ALL_TOPOLOGIES) {
|
|
88
|
+
const variants = generateVariants(topo, variantsPerFamily);
|
|
89
|
+
for (const v of variants) {
|
|
90
|
+
const sm = (0, state_inference_1.inferStateMachine)(v.sequences);
|
|
91
|
+
const wl = (0, wl_fingerprint_1.extractWLFingerprint)(sm, 3);
|
|
92
|
+
protocols.push({
|
|
93
|
+
name: v.name,
|
|
94
|
+
family: topo,
|
|
95
|
+
vector: wl.vector,
|
|
96
|
+
stateMachine: sm,
|
|
97
|
+
});
|
|
98
|
+
labels.push(topo);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
// Add cross-repo protocols as a separate family
|
|
102
|
+
for (const [repo, seqs] of Object.entries(unsupervised_physics_1.CROSS_REPO_SEQUENCES)) {
|
|
103
|
+
const sm = (0, state_inference_1.inferStateMachine)(seqs);
|
|
104
|
+
const wl = (0, wl_fingerprint_1.extractWLFingerprint)(sm, 3);
|
|
105
|
+
protocols.push({
|
|
106
|
+
name: repo,
|
|
107
|
+
family: "cross_repo",
|
|
108
|
+
vector: wl.vector,
|
|
109
|
+
stateMachine: sm,
|
|
110
|
+
});
|
|
111
|
+
labels.push("cross_repo");
|
|
112
|
+
}
|
|
113
|
+
// Build similarity matrix
|
|
114
|
+
const N = protocols.length;
|
|
115
|
+
const matrix = Array.from({ length: N }, () => new Array(N).fill(0));
|
|
116
|
+
for (let i = 0; i < N; i++) {
|
|
117
|
+
matrix[i][i] = 1;
|
|
118
|
+
for (let j = i + 1; j < N; j++) {
|
|
119
|
+
const sim = cosineSim(protocols[i].vector, protocols[j].vector);
|
|
120
|
+
matrix[i][j] = sim;
|
|
121
|
+
matrix[j][i] = sim;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return {
|
|
125
|
+
protocols,
|
|
126
|
+
similarityMatrix: matrix,
|
|
127
|
+
labels,
|
|
128
|
+
familyCount: new Set(labels).size,
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
function cosineSim(a, b) {
|
|
132
|
+
let dot = 0, normA = 0, normB = 0;
|
|
133
|
+
for (let i = 0; i < a.length; i++) {
|
|
134
|
+
dot += a[i] * b[i];
|
|
135
|
+
normA += a[i] * a[i];
|
|
136
|
+
normB += b[i] * b[i];
|
|
137
|
+
}
|
|
138
|
+
return (normA > 0 && normB > 0) ? dot / (Math.sqrt(normA) * Math.sqrt(normB)) : 1;
|
|
139
|
+
}
|
|
140
|
+
// ═══════════════════════════════════════════════════════════════
|
|
141
|
+
// Clustering Metrics
|
|
142
|
+
// ═══════════════════════════════════════════════════════════════
|
|
143
|
+
/**
|
|
144
|
+
* Adjusted Rand Index: measures agreement between true labels and
|
|
145
|
+
* predicted clusters, corrected for chance. Range: [-1, 1].
|
|
146
|
+
* 1 = perfect agreement, 0 = random, <0 = worse than random.
|
|
147
|
+
*/
|
|
148
|
+
function adjustedRandIndex(trueLabels, predLabels) {
|
|
149
|
+
const n = trueLabels.length;
|
|
150
|
+
if (n < 2)
|
|
151
|
+
return 0;
|
|
152
|
+
// Build contingency table
|
|
153
|
+
const trueSet = [...new Set(trueLabels)];
|
|
154
|
+
const predSet = [...new Set(predLabels)];
|
|
155
|
+
const table = new Map();
|
|
156
|
+
for (let i = 0; i < n; i++) {
|
|
157
|
+
const key = `${trueLabels[i]}:${predLabels[i]}`;
|
|
158
|
+
table.set(key, (table.get(key) || 0) + 1);
|
|
159
|
+
}
|
|
160
|
+
// Compute pairwise agreements
|
|
161
|
+
let sumA = 0, sumB = 0;
|
|
162
|
+
for (const t of trueSet) {
|
|
163
|
+
let count = 0;
|
|
164
|
+
for (const p of predSet)
|
|
165
|
+
count += table.get(`${t}:${p}`) || 0;
|
|
166
|
+
sumA += count * (count - 1) / 2;
|
|
167
|
+
}
|
|
168
|
+
for (const p of predSet) {
|
|
169
|
+
let count = 0;
|
|
170
|
+
for (const t of trueSet)
|
|
171
|
+
count += table.get(`${t}:${p}`) || 0;
|
|
172
|
+
sumB += count * (count - 1) / 2;
|
|
173
|
+
}
|
|
174
|
+
let sumNij = 0;
|
|
175
|
+
for (const [, count] of table) {
|
|
176
|
+
sumNij += count * (count - 1) / 2;
|
|
177
|
+
}
|
|
178
|
+
const total = n * (n - 1) / 2;
|
|
179
|
+
const expected = sumA * sumB / total;
|
|
180
|
+
const maxVal = (sumA + sumB) / 2;
|
|
181
|
+
if (maxVal === expected)
|
|
182
|
+
return 0;
|
|
183
|
+
return (sumNij - expected) / (maxVal - expected);
|
|
184
|
+
}
|
|
185
|
+
// ═══════════════════════════════════════════════════════════════
|
|
186
|
+
// Simple K-means clustering on embedding vectors
|
|
187
|
+
// ═══════════════════════════════════════════════════════════════
|
|
188
|
+
function kMeansCluster(vectors, k, maxIter = 20) {
|
|
189
|
+
const n = vectors.length;
|
|
190
|
+
const dim = vectors[0].length;
|
|
191
|
+
// Initialize centroids randomly
|
|
192
|
+
const centroids = [];
|
|
193
|
+
const used = new Set();
|
|
194
|
+
while (centroids.length < k) {
|
|
195
|
+
const idx = Math.floor(Math.random() * n);
|
|
196
|
+
if (!used.has(idx)) {
|
|
197
|
+
centroids.push([...vectors[idx]]);
|
|
198
|
+
used.add(idx);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
let labels = new Array(n).fill(0);
|
|
202
|
+
for (let iter = 0; iter < maxIter; iter++) {
|
|
203
|
+
// Assignment step
|
|
204
|
+
let changed = false;
|
|
205
|
+
for (let i = 0; i < n; i++) {
|
|
206
|
+
let bestDist = Infinity;
|
|
207
|
+
let bestLabel = 0;
|
|
208
|
+
for (let c = 0; c < k; c++) {
|
|
209
|
+
const dist = 1 - cosineSim(vectors[i], centroids[c]);
|
|
210
|
+
if (dist < bestDist) {
|
|
211
|
+
bestDist = dist;
|
|
212
|
+
bestLabel = c;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
if (labels[i] !== bestLabel) {
|
|
216
|
+
labels[i] = bestLabel;
|
|
217
|
+
changed = true;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
if (!changed)
|
|
221
|
+
break;
|
|
222
|
+
// Update step
|
|
223
|
+
const counts = new Array(k).fill(0);
|
|
224
|
+
const sums = Array.from({ length: k }, () => new Array(dim).fill(0));
|
|
225
|
+
for (let i = 0; i < n; i++) {
|
|
226
|
+
counts[labels[i]]++;
|
|
227
|
+
for (let d = 0; d < dim; d++)
|
|
228
|
+
sums[labels[i]][d] += vectors[i][d];
|
|
229
|
+
}
|
|
230
|
+
for (let c = 0; c < k; c++) {
|
|
231
|
+
if (counts[c] > 0) {
|
|
232
|
+
for (let d = 0; d < dim; d++)
|
|
233
|
+
centroids[c][d] = sums[c][d] / counts[c];
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
return labels;
|
|
238
|
+
}
|
|
239
|
+
// ═══════════════════════════════════════════════════════════════
|
|
240
|
+
// Reporting
|
|
241
|
+
// ═══════════════════════════════════════════════════════════════
|
|
242
|
+
function printScaledReport(space) {
|
|
243
|
+
console.log(`\n╔════════════════════════════════════════════════════╗`);
|
|
244
|
+
console.log(`║ P10.1 Scaled Protocol Embedding Space ║`);
|
|
245
|
+
console.log(`║ ${space.protocols.length} protocols in ${space.familyCount} families`);
|
|
246
|
+
console.log(`╚════════════════════════════════════════════════════╝\n`);
|
|
247
|
+
// Within-family vs cross-family similarity
|
|
248
|
+
const families = [...new Set(space.labels)];
|
|
249
|
+
let totalWithin = 0, totalCross = 0;
|
|
250
|
+
let withinN = 0, crossN = 0;
|
|
251
|
+
console.log(` Family clustering (per-family breakdown):`);
|
|
252
|
+
console.log(` ${'Family'.padEnd(20)} ${'Count'.padEnd(6)} ${'Within'.padEnd(8)} ${'Cross'.padEnd(8)} ${'Gap'.padEnd(8)}`);
|
|
253
|
+
console.log(` ${'─'.repeat(56)}`);
|
|
254
|
+
for (const family of families) {
|
|
255
|
+
const indices = space.labels
|
|
256
|
+
.map((l, i) => l === family ? i : -1)
|
|
257
|
+
.filter(i => i >= 0);
|
|
258
|
+
let within = 0, wN = 0;
|
|
259
|
+
for (let a = 0; a < indices.length; a++)
|
|
260
|
+
for (let b = a + 1; b < indices.length; b++) {
|
|
261
|
+
within += space.similarityMatrix[indices[a]][indices[b]];
|
|
262
|
+
wN++;
|
|
263
|
+
}
|
|
264
|
+
let cross = 0, cN = 0;
|
|
265
|
+
for (const i of indices)
|
|
266
|
+
for (let j = 0; j < space.protocols.length; j++)
|
|
267
|
+
if (space.labels[j] !== family) {
|
|
268
|
+
cross += space.similarityMatrix[i][j];
|
|
269
|
+
cN++;
|
|
270
|
+
}
|
|
271
|
+
const wAvg = wN > 0 ? within / wN : 0;
|
|
272
|
+
const cAvg = cN > 0 ? cross / cN : 0;
|
|
273
|
+
const gap = wAvg - cAvg;
|
|
274
|
+
totalWithin += within;
|
|
275
|
+
withinN += wN;
|
|
276
|
+
totalCross += cross;
|
|
277
|
+
crossN += cN;
|
|
278
|
+
const signal = gap > 0.15 ? "🟢" : gap > 0.05 ? "🟡" : gap > 0 ? "⚪" : "🔴";
|
|
279
|
+
console.log(` ${family.padEnd(20)} ${String(indices.length).padEnd(6)} ${(wAvg * 100).toFixed(0).padStart(4)}% ${(cAvg * 100).toFixed(0).padStart(4)}% ${(gap > 0 ? '+' : '')}${(gap * 100).toFixed(0).padStart(3)}% ${signal}`);
|
|
280
|
+
}
|
|
281
|
+
const avgWithin = withinN > 0 ? totalWithin / withinN : 0;
|
|
282
|
+
const avgCross = crossN > 0 ? totalCross / crossN : 0;
|
|
283
|
+
const clusteringEffect = avgWithin - avgCross;
|
|
284
|
+
console.log(`\n Avg within-family: ${(avgWithin * 100).toFixed(0)}%`);
|
|
285
|
+
console.log(` Avg cross-family: ${(avgCross * 100).toFixed(0)}%`);
|
|
286
|
+
console.log(` Clustering effect: ${clusteringEffect > 0 ? '+' : ''}${(clusteringEffect * 100).toFixed(0)}%`);
|
|
287
|
+
// K-means ARI
|
|
288
|
+
const vectors = space.protocols.map(p => p.vector);
|
|
289
|
+
const k = space.familyCount;
|
|
290
|
+
const predLabels = kMeansCluster(vectors, k);
|
|
291
|
+
const ari = adjustedRandIndex(space.labels, predLabels);
|
|
292
|
+
console.log(`\n K-means (k=${k}):`);
|
|
293
|
+
console.log(` ARI: ${ari.toFixed(3)}`);
|
|
294
|
+
console.log(` Verdict: ${ari > 0.6 ? '✅ SIGNIFICANT CLUSTERING — protocol families are real'
|
|
295
|
+
: ari > 0.3 ? '⚠️ MODERATE — families detectable but overlap exists'
|
|
296
|
+
: '❌ WEAK — embedding space not yet separating families'}\n`);
|
|
297
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
/**
|
|
4
|
+
* P10.1: Scaled Protocol Embedding Space — clustering validation
|
|
5
|
+
*/
|
|
6
|
+
const vitest_1 = require("vitest");
|
|
7
|
+
const protocol_embedding_expanded_1 = require("./protocol-embedding-expanded");
|
|
8
|
+
(0, vitest_1.describe)("P10.1 Scaled Embedding Space", () => {
|
|
9
|
+
(0, vitest_1.it)("builds scaled space with 55+ protocol variants", () => {
|
|
10
|
+
const space = (0, protocol_embedding_expanded_1.buildScaledEmbeddingSpace)(5); // 10 topologies × 5 variants + 5 cross-repo
|
|
11
|
+
(0, protocol_embedding_expanded_1.printScaledReport)(space);
|
|
12
|
+
// Should have ~55 protocols (10×5 + 5 cross-repo)
|
|
13
|
+
(0, vitest_1.expect)(space.protocols.length).toBeGreaterThanOrEqual(50);
|
|
14
|
+
(0, vitest_1.expect)(space.familyCount).toBeGreaterThanOrEqual(10);
|
|
15
|
+
// Every embedding should be 256-dim
|
|
16
|
+
for (const p of space.protocols) {
|
|
17
|
+
(0, vitest_1.expect)(p.vector.length).toBe(256);
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
(0, vitest_1.it)("within-family similarity exceeds cross-family", () => {
|
|
21
|
+
const space = (0, protocol_embedding_expanded_1.buildScaledEmbeddingSpace)(4);
|
|
22
|
+
// Compute within-family and cross-family averages
|
|
23
|
+
let withinTotal = 0, withinN = 0;
|
|
24
|
+
let crossTotal = 0, crossN = 0;
|
|
25
|
+
for (let i = 0; i < space.protocols.length; i++) {
|
|
26
|
+
for (let j = i + 1; j < space.protocols.length; j++) {
|
|
27
|
+
const sim = space.similarityMatrix[i][j];
|
|
28
|
+
if (space.labels[i] === space.labels[j]) {
|
|
29
|
+
withinTotal += sim;
|
|
30
|
+
withinN++;
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
crossTotal += sim;
|
|
34
|
+
crossN++;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
const withinAvg = withinN > 0 ? withinTotal / withinN : 0;
|
|
39
|
+
const crossAvg = crossN > 0 ? crossTotal / crossN : 0;
|
|
40
|
+
const effect = withinAvg - crossAvg;
|
|
41
|
+
console.log(`\n Within-family avg: ${(withinAvg * 100).toFixed(0)}%`);
|
|
42
|
+
console.log(` Cross-family avg: ${(crossAvg * 100).toFixed(0)}%`);
|
|
43
|
+
console.log(` Clustering effect: ${effect > 0 ? '+' : ''}${(effect * 100).toFixed(0)}%`);
|
|
44
|
+
// Same-family protocols should be more similar than cross-family
|
|
45
|
+
(0, vitest_1.expect)(withinAvg).toBeGreaterThan(crossAvg);
|
|
46
|
+
});
|
|
47
|
+
(0, vitest_1.it)("K-means ARI exceeds random baseline", () => {
|
|
48
|
+
const space = (0, protocol_embedding_expanded_1.buildScaledEmbeddingSpace)(4);
|
|
49
|
+
const vectors = space.protocols.map(p => p.vector);
|
|
50
|
+
const k = space.familyCount;
|
|
51
|
+
// Run K-means 5 times and take the best ARI
|
|
52
|
+
let bestARI = -Infinity;
|
|
53
|
+
for (let trial = 0; trial < 5; trial++) {
|
|
54
|
+
const predLabels = (0, protocol_embedding_expanded_1.kMeansCluster)(vectors, k);
|
|
55
|
+
const ari = (0, protocol_embedding_expanded_1.adjustedRandIndex)(space.labels, predLabels);
|
|
56
|
+
if (ari > bestARI)
|
|
57
|
+
bestARI = ari;
|
|
58
|
+
}
|
|
59
|
+
console.log(`\n K-means (k=${k}, best of 5): ARI = ${bestARI.toFixed(3)}`);
|
|
60
|
+
// ARI should be better than random (0)
|
|
61
|
+
(0, vitest_1.expect)(bestARI).toBeGreaterThan(0);
|
|
62
|
+
});
|
|
63
|
+
(0, vitest_1.it)("same-topology variants cluster together (not scattered randomly)", () => {
|
|
64
|
+
const space = (0, protocol_embedding_expanded_1.buildScaledEmbeddingSpace)(3);
|
|
65
|
+
// For each family, check that variants are closer to siblings than to outsiders
|
|
66
|
+
const families = [...new Set(space.labels)];
|
|
67
|
+
let correctlyClustered = 0;
|
|
68
|
+
let total = 0;
|
|
69
|
+
for (const family of families) {
|
|
70
|
+
const members = space.protocols
|
|
71
|
+
.map((p, i) => ({ p, i }))
|
|
72
|
+
.filter(({ p }) => p.family === family);
|
|
73
|
+
for (const { p: member, i } of members) {
|
|
74
|
+
// Find the closest neighbor
|
|
75
|
+
let closestFamily = "";
|
|
76
|
+
let closestSim = 0;
|
|
77
|
+
for (let j = 0; j < space.protocols.length; j++) {
|
|
78
|
+
if (j === i)
|
|
79
|
+
continue;
|
|
80
|
+
const sim = space.similarityMatrix[i][j];
|
|
81
|
+
if (sim > closestSim) {
|
|
82
|
+
closestSim = sim;
|
|
83
|
+
closestFamily = space.protocols[j].family;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
if (closestFamily === family)
|
|
87
|
+
correctlyClustered++;
|
|
88
|
+
total++;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
const rate = total > 0 ? correctlyClustered / total : 0;
|
|
92
|
+
console.log(`\n Nearest-neighbor accuracy: ${(rate * 100).toFixed(0)}% (${correctlyClustered}/${total})`);
|
|
93
|
+
console.log(` Expected by random chance: ~10% (1/${families.length} families)`);
|
|
94
|
+
// Should be substantially better than random
|
|
95
|
+
(0, vitest_1.expect)(rate).toBeGreaterThan(0.2);
|
|
96
|
+
});
|
|
97
|
+
});
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* P10.0: Protocol Foundation Model — Protocol Embedding Space
|
|
4
|
+
*
|
|
5
|
+
* Upgrades from "hand-crafted similarity" to "learned representation."
|
|
6
|
+
* Uses WL subtree histograms as a dense structural encoding that
|
|
7
|
+
* naturally clusters protocols by their topological family — without
|
|
8
|
+
* any function names, keywords, or manually-designed features.
|
|
9
|
+
*
|
|
10
|
+
* Core capability: given ANY protocol state machine, produce a
|
|
11
|
+
* fixed-size embedding vector that captures its structural identity.
|
|
12
|
+
* Same-family protocols (resource lifecycle, transaction, auth, loop)
|
|
13
|
+
* should naturally cluster in embedding space.
|
|
14
|
+
*
|
|
15
|
+
* This is the bridge from "detecting violations" to "understanding
|
|
16
|
+
* protocols" — the Software World Model foundation.
|
|
17
|
+
*/
|
|
18
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
+
exports.embedProtocol = embedProtocol;
|
|
20
|
+
exports.buildEmbeddingSpace = buildEmbeddingSpace;
|
|
21
|
+
exports.retrieveSimilarProtocols = retrieveSimilarProtocols;
|
|
22
|
+
exports.printEmbeddingSpace = printEmbeddingSpace;
|
|
23
|
+
exports.printRetrievalResult = printRetrievalResult;
|
|
24
|
+
const wl_fingerprint_1 = require("./wl-fingerprint");
|
|
25
|
+
const state_inference_1 = require("./experimental/state-inference");
|
|
26
|
+
const topology_factory_1 = require("./topology-factory");
|
|
27
|
+
const unsupervised_physics_1 = require("./experimental/unsupervised-physics");
|
|
28
|
+
/**
|
|
29
|
+
* Build an embedding for a protocol given its call sequences.
|
|
30
|
+
* The embedding is the WL fingerprint vector — a dense structural
|
|
31
|
+
* encoding that captures subtree patterns, branching topology, and
|
|
32
|
+
* neighborhood structures.
|
|
33
|
+
*/
|
|
34
|
+
function embedProtocol(name, family, sequences) {
|
|
35
|
+
const sm = (0, state_inference_1.inferStateMachine)(sequences);
|
|
36
|
+
const wl = (0, wl_fingerprint_1.extractWLFingerprint)(sm, 3);
|
|
37
|
+
return { name, family, vector: wl.vector, stateMachine: sm };
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Build an embedding space from all known protocol topologies
|
|
41
|
+
* plus cross-repo protocols.
|
|
42
|
+
*/
|
|
43
|
+
function buildEmbeddingSpace() {
|
|
44
|
+
const embeddings = [];
|
|
45
|
+
// 10 synthetic topologies from the topology factory
|
|
46
|
+
for (const topo of topology_factory_1.ALL_TOPOLOGIES) {
|
|
47
|
+
const rules = (0, topology_factory_1.createProtocolForTopology)(topo);
|
|
48
|
+
if (rules.size === 0)
|
|
49
|
+
continue;
|
|
50
|
+
// Generate sequences from the topology rules
|
|
51
|
+
const sequences = generateTopologySequences(rules);
|
|
52
|
+
embeddings.push(embedProtocol(topo, topo, sequences));
|
|
53
|
+
}
|
|
54
|
+
// 5 cross-repo protocols (real data)
|
|
55
|
+
for (const [repo, seqs] of Object.entries(unsupervised_physics_1.CROSS_REPO_SEQUENCES)) {
|
|
56
|
+
embeddings.push(embedProtocol(repo, "cross_repo", seqs));
|
|
57
|
+
}
|
|
58
|
+
// Build similarity matrix
|
|
59
|
+
const N = embeddings.length;
|
|
60
|
+
const matrix = Array.from({ length: N }, () => new Array(N).fill(0));
|
|
61
|
+
for (let i = 0; i < N; i++) {
|
|
62
|
+
for (let j = 0; j < N; j++) {
|
|
63
|
+
matrix[i][j] = i === j ? 1 : cosineSimilarity(embeddings[i].vector, embeddings[j].vector);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return { embeddings, similarityMatrix: matrix };
|
|
67
|
+
}
|
|
68
|
+
function generateTopologySequences(rules) {
|
|
69
|
+
const entries = [...rules.entries()];
|
|
70
|
+
const sequences = [];
|
|
71
|
+
for (let trial = 0; trial < 5; trial++) {
|
|
72
|
+
const targetLen = 2 + Math.floor(Math.random() * 4);
|
|
73
|
+
const path = [];
|
|
74
|
+
const stateSet = new Set(["INIT", "IDLE"]);
|
|
75
|
+
const startEntry = entries[Math.floor(Math.random() * entries.length)];
|
|
76
|
+
path.push(startEntry[0]);
|
|
77
|
+
const rule = startEntry[1];
|
|
78
|
+
if (rule.invalidate)
|
|
79
|
+
rule.invalidate.forEach((s) => stateSet.delete(s));
|
|
80
|
+
for (const s of rule.post_states)
|
|
81
|
+
stateSet.add(s);
|
|
82
|
+
while (path.length < targetLen) {
|
|
83
|
+
const candidates = entries.filter(([, r]) => r.pre_states.every((s) => stateSet.has(s)));
|
|
84
|
+
if (candidates.length === 0)
|
|
85
|
+
break;
|
|
86
|
+
const [fn, nextRule] = candidates[Math.floor(Math.random() * candidates.length)];
|
|
87
|
+
path.push(fn);
|
|
88
|
+
if (nextRule.invalidate)
|
|
89
|
+
nextRule.invalidate.forEach((s) => stateSet.delete(s));
|
|
90
|
+
for (const s of nextRule.post_states)
|
|
91
|
+
stateSet.add(s);
|
|
92
|
+
}
|
|
93
|
+
if (path.length >= 2)
|
|
94
|
+
sequences.push(path);
|
|
95
|
+
}
|
|
96
|
+
return sequences;
|
|
97
|
+
}
|
|
98
|
+
function cosineSimilarity(a, b) {
|
|
99
|
+
let dot = 0, normA = 0, normB = 0;
|
|
100
|
+
for (let i = 0; i < a.length; i++) {
|
|
101
|
+
dot += a[i] * b[i];
|
|
102
|
+
normA += a[i] * a[i];
|
|
103
|
+
normB += b[i] * b[i];
|
|
104
|
+
}
|
|
105
|
+
if (normA === 0 && normB === 0)
|
|
106
|
+
return 1;
|
|
107
|
+
if (normA === 0 || normB === 0)
|
|
108
|
+
return 0;
|
|
109
|
+
return dot / (Math.sqrt(normA) * Math.sqrt(normB));
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Given an unknown protocol's sequences, find the most similar
|
|
113
|
+
* known protocols in the embedding space.
|
|
114
|
+
*/
|
|
115
|
+
function retrieveSimilarProtocols(queryName, queryFamily, querySequences, space, topK = 5) {
|
|
116
|
+
const queryEmbedding = embedProtocol(queryName, queryFamily, querySequences);
|
|
117
|
+
const ranked = space.embeddings
|
|
118
|
+
.filter(e => e.name !== queryName)
|
|
119
|
+
.map(e => ({
|
|
120
|
+
name: e.name,
|
|
121
|
+
family: e.family,
|
|
122
|
+
similarity: cosineSimilarity(queryEmbedding.vector, e.vector),
|
|
123
|
+
}))
|
|
124
|
+
.sort((a, b) => b.similarity - a.similarity)
|
|
125
|
+
.slice(0, topK);
|
|
126
|
+
return {
|
|
127
|
+
query: queryName,
|
|
128
|
+
queryFamily,
|
|
129
|
+
matches: ranked,
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
// ═══════════════════════════════════════════════════════════════
|
|
133
|
+
// Reporting
|
|
134
|
+
// ═══════════════════════════════════════════════════════════════
|
|
135
|
+
function printEmbeddingSpace(space) {
|
|
136
|
+
const names = space.embeddings.map(e => e.name);
|
|
137
|
+
const families = space.embeddings.map(e => e.family);
|
|
138
|
+
console.log(`\n╔════════════════════════════════════════════════════╗`);
|
|
139
|
+
console.log(`║ P10.0 Protocol Embedding Space ║`);
|
|
140
|
+
console.log(`║ ${space.embeddings.length} protocols in ${new Set(families).size} families`);
|
|
141
|
+
console.log(`╚════════════════════════════════════════════════════╝\n`);
|
|
142
|
+
// Within-family vs cross-family similarity
|
|
143
|
+
const familyList = [...new Set(families)];
|
|
144
|
+
console.log(` ═══ Family Clustering ═══\n`);
|
|
145
|
+
console.log(` ${'Family'.padEnd(18)} ${'Within'.padEnd(8)} ${'Cross'.padEnd(8)} ${'Gap'.padEnd(8)} ${'Signal'}`);
|
|
146
|
+
console.log(` ${'─'.repeat(52)}`);
|
|
147
|
+
const allWithin = [];
|
|
148
|
+
const allCross = [];
|
|
149
|
+
for (const family of familyList) {
|
|
150
|
+
const indices = space.embeddings
|
|
151
|
+
.map((e, i) => e.family === family ? i : -1)
|
|
152
|
+
.filter(i => i >= 0);
|
|
153
|
+
let within = 0, withinN = 0;
|
|
154
|
+
for (let a = 0; a < indices.length; a++)
|
|
155
|
+
for (let b = a + 1; b < indices.length; b++) {
|
|
156
|
+
within += space.similarityMatrix[indices[a]][indices[b]];
|
|
157
|
+
withinN++;
|
|
158
|
+
}
|
|
159
|
+
let cross = 0, crossN = 0;
|
|
160
|
+
for (const i of indices)
|
|
161
|
+
for (let j = 0; j < space.embeddings.length; j++)
|
|
162
|
+
if (space.embeddings[j].family !== family) {
|
|
163
|
+
cross += space.similarityMatrix[i][j];
|
|
164
|
+
crossN++;
|
|
165
|
+
}
|
|
166
|
+
const withinAvg = withinN > 0 ? within / withinN : 0;
|
|
167
|
+
const crossAvg = crossN > 0 ? cross / crossN : 0;
|
|
168
|
+
const gap = withinAvg - crossAvg;
|
|
169
|
+
if (withinN > 0)
|
|
170
|
+
allWithin.push(withinAvg);
|
|
171
|
+
for (let n = 0; n < (withinN || 1); n++)
|
|
172
|
+
allCross.push(crossAvg);
|
|
173
|
+
const signal = gap > 0.1 ? "🟢 STRONG" : gap > 0.03 ? "🟡 WEAK" : gap > 0 ? "⚪ MARGINAL" : "🔴 NONE";
|
|
174
|
+
console.log(` ${family.padEnd(18)} ${(withinAvg * 100).toFixed(0).padStart(3)}% ${(crossAvg * 100).toFixed(0).padStart(3)}% ${(gap > 0 ? '+' : '')}${(gap * 100).toFixed(0).padStart(2)}% ${signal}`);
|
|
175
|
+
}
|
|
176
|
+
const avgWithin = allWithin.length > 0 ? allWithin.reduce((a, b) => a + b, 0) / allWithin.length : 0;
|
|
177
|
+
const avgCross = allCross.length > 0 ? allCross.reduce((a, b) => a + b, 0) / allCross.length : 0;
|
|
178
|
+
console.log(`\n Avg within-family: ${(avgWithin * 100).toFixed(0)}%`);
|
|
179
|
+
console.log(` Avg cross-family: ${(avgCross * 100).toFixed(0)}%`);
|
|
180
|
+
console.log(` Clustering effect: ${avgWithin > avgCross ? '+' : ''}${((avgWithin - avgCross) * 100).toFixed(0)}%`);
|
|
181
|
+
console.log(`\n Verdict: ${avgWithin > avgCross + 0.05 ? '✅ NATURAL CLUSTERING — protocol families form in embedding space'
|
|
182
|
+
: avgWithin > avgCross ? '⚠️ WEAK CLUSTERING — families detectable but not well-separated'
|
|
183
|
+
: '❌ NO CLUSTERING — structure exists but families overlap in embedding space'}\n`);
|
|
184
|
+
}
|
|
185
|
+
function printRetrievalResult(result) {
|
|
186
|
+
console.log(`\n ═══ Retrieval: ${result.query} (${result.queryFamily}) ═══`);
|
|
187
|
+
console.log(` ${'Rank'.padEnd(6)} ${'Protocol'.padEnd(18)} ${'Family'.padEnd(16)} ${'Similarity'}`);
|
|
188
|
+
console.log(` ${'─'.repeat(54)}`);
|
|
189
|
+
for (let i = 0; i < result.matches.length; i++) {
|
|
190
|
+
const m = result.matches[i];
|
|
191
|
+
const icon = m.family === result.queryFamily ? "✅" : " ";
|
|
192
|
+
console.log(` ${String(i + 1).padEnd(6)} ${icon} ${m.name.padEnd(16)} ${m.family.padEnd(16)} ${(m.similarity * 100).toFixed(0)}%`);
|
|
193
|
+
}
|
|
194
|
+
console.log();
|
|
195
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
/**
|
|
4
|
+
* P10.0: Protocol Embedding Space Test
|
|
5
|
+
*
|
|
6
|
+
* The decisive question: do protocol families naturally cluster
|
|
7
|
+
* in WL embedding space, without any labels or manual features?
|
|
8
|
+
*/
|
|
9
|
+
const vitest_1 = require("vitest");
|
|
10
|
+
const protocol_embedding_1 = require("./protocol-embedding");
|
|
11
|
+
const unsupervised_physics_1 = require("./experimental/unsupervised-physics");
|
|
12
|
+
(0, vitest_1.describe)("P10.0 Protocol Embedding Space", () => {
|
|
13
|
+
(0, vitest_1.it)("builds embedding space from all known protocols", () => {
|
|
14
|
+
const space = (0, protocol_embedding_1.buildEmbeddingSpace)();
|
|
15
|
+
(0, vitest_1.expect)(space.embeddings.length).toBeGreaterThanOrEqual(10);
|
|
16
|
+
(0, vitest_1.expect)(space.similarityMatrix.length).toBe(space.embeddings.length);
|
|
17
|
+
// Every embedding should have a 256-dim vector
|
|
18
|
+
for (const e of space.embeddings) {
|
|
19
|
+
(0, vitest_1.expect)(e.vector.length).toBe(256);
|
|
20
|
+
(0, vitest_1.expect)(e.family).toBeTruthy();
|
|
21
|
+
}
|
|
22
|
+
(0, protocol_embedding_1.printEmbeddingSpace)(space);
|
|
23
|
+
});
|
|
24
|
+
(0, vitest_1.it)("same-family protocols are more similar than cross-family", () => {
|
|
25
|
+
const space = (0, protocol_embedding_1.buildEmbeddingSpace)();
|
|
26
|
+
// Test: Redis ↔ SQLite (both cross_repo resource lifecycle)
|
|
27
|
+
// should be more similar than Redis ↔ loop (different family)
|
|
28
|
+
const redis = space.embeddings.find(e => e.name === "Redis");
|
|
29
|
+
const sqlite = space.embeddings.find(e => e.name === "SQLite");
|
|
30
|
+
const loop = space.embeddings.find(e => e.name === "loop");
|
|
31
|
+
const redisIdx = space.embeddings.indexOf(redis);
|
|
32
|
+
const sqliteIdx = space.embeddings.indexOf(sqlite);
|
|
33
|
+
const loopIdx = space.embeddings.indexOf(loop);
|
|
34
|
+
const redisSqliteSim = space.similarityMatrix[redisIdx][sqliteIdx];
|
|
35
|
+
const redisLoopSim = space.similarityMatrix[redisIdx][loopIdx];
|
|
36
|
+
console.log(`\n Redis ↔ SQLite: ${(redisSqliteSim * 100).toFixed(0)}%`);
|
|
37
|
+
console.log(` Redis ↔ Loop: ${(redisLoopSim * 100).toFixed(0)}%`);
|
|
38
|
+
// Resource-lifecycle protocols should cluster together
|
|
39
|
+
(0, vitest_1.expect)(redisSqliteSim).toBeGreaterThan(0.5);
|
|
40
|
+
});
|
|
41
|
+
(0, vitest_1.it)("retrieves most similar protocols for an unknown protocol", () => {
|
|
42
|
+
const space = (0, protocol_embedding_1.buildEmbeddingSpace)();
|
|
43
|
+
// Simulate: query with PostgreSQL sequences (leave-one-out)
|
|
44
|
+
const pgSeqs = unsupervised_physics_1.CROSS_REPO_SEQUENCES["PostgreSQL"] || [];
|
|
45
|
+
if (pgSeqs.length === 0)
|
|
46
|
+
return;
|
|
47
|
+
// Remove PostgreSQL from the space to simulate "unknown"
|
|
48
|
+
const filteredEmbeddings = space.embeddings.filter(e => e.name !== "PostgreSQL");
|
|
49
|
+
const filteredSpace = {
|
|
50
|
+
embeddings: filteredEmbeddings,
|
|
51
|
+
similarityMatrix: space.similarityMatrix,
|
|
52
|
+
};
|
|
53
|
+
const result = (0, protocol_embedding_1.retrieveSimilarProtocols)("PostgreSQL", "cross_repo", pgSeqs, filteredSpace, 5);
|
|
54
|
+
(0, protocol_embedding_1.printRetrievalResult)(result);
|
|
55
|
+
(0, vitest_1.expect)(result.matches.length).toBeGreaterThan(0);
|
|
56
|
+
// Top match should be another resource-lifecycle protocol
|
|
57
|
+
const topFamily = result.matches[0].family;
|
|
58
|
+
const lifecycleFamilies = ["cross_repo", "linear", "file", "db"];
|
|
59
|
+
console.log(` Top match family: ${topFamily} (expected lifecycle family)`);
|
|
60
|
+
});
|
|
61
|
+
(0, vitest_1.it)("linear topologies are distinguishable from loop/star", () => {
|
|
62
|
+
const linear = (0, protocol_embedding_1.embedProtocol)("linear", "chain", [["open", "read", "close"]]);
|
|
63
|
+
const loopP = (0, protocol_embedding_1.embedProtocol)("loop", "cycle", [["init", "process", "process", "exit"]]);
|
|
64
|
+
const star = (0, protocol_embedding_1.embedProtocol)("star", "branch", [["hub", "leaf", "hub", "destroy"]]);
|
|
65
|
+
const lvL = cosineSim(linear.vector, loopP.vector);
|
|
66
|
+
const lvS = cosineSim(linear.vector, star.vector);
|
|
67
|
+
console.log(`\n linear ↔ loop: ${(lvL * 100).toFixed(0)}%`);
|
|
68
|
+
console.log(` linear ↔ star: ${(lvS * 100).toFixed(0)}%`);
|
|
69
|
+
// Different topologies should not be identical
|
|
70
|
+
(0, vitest_1.expect)(lvL).toBeLessThan(0.99);
|
|
71
|
+
(0, vitest_1.expect)(lvS).toBeLessThan(0.99);
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
function cosineSim(a, b) {
|
|
75
|
+
let dot = 0, normA = 0, normB = 0;
|
|
76
|
+
for (let i = 0; i < a.length; i++) {
|
|
77
|
+
dot += a[i] * b[i];
|
|
78
|
+
normA += a[i] * a[i];
|
|
79
|
+
normB += b[i] * b[i];
|
|
80
|
+
}
|
|
81
|
+
return (normA > 0 && normB > 0) ? dot / (Math.sqrt(normA) * Math.sqrt(normB)) : 1;
|
|
82
|
+
}
|