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,243 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* P3.14-15: Protocol Frontier Explorer + Cross-Protocol Planner
|
|
4
|
+
*
|
|
5
|
+
* P3.14: BFS-based state→state search without template dependency.
|
|
6
|
+
* Given currentState and targetState, auto-discovers paths like
|
|
7
|
+
* SESSION_ACTIVE → logout → SESSION_CLOSED without needing
|
|
8
|
+
* a template for every goal variant.
|
|
9
|
+
*
|
|
10
|
+
* P3.15: Cross-protocol meta-graph for multi-protocol repair chains.
|
|
11
|
+
* Auth → File → DB → IR protocol composition.
|
|
12
|
+
* Enables repairs like "auth then file write then db insert".
|
|
13
|
+
*
|
|
14
|
+
* Target: reduce missing_candidate from 49% to <20%.
|
|
15
|
+
*/
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.searchFrontier = searchFrontier;
|
|
18
|
+
exports.searchFrontierMulti = searchFrontierMulti;
|
|
19
|
+
exports.exploreFrontier = exploreFrontier;
|
|
20
|
+
exports.planCrossProtocol = planCrossProtocol;
|
|
21
|
+
exports.getProtocolBridges = getProtocolBridges;
|
|
22
|
+
exports.expandCrossProtocolCandidates = expandCrossProtocolCandidates;
|
|
23
|
+
const protocol_coverage_1 = require("./protocol-coverage");
|
|
24
|
+
/**
|
|
25
|
+
* BFS from currentState to find the shortest path reaching targetState.
|
|
26
|
+
*
|
|
27
|
+
* Unlike Goal Templates (which require manual patterns), this searches
|
|
28
|
+
* the protocol state graph directly. It discovers paths like:
|
|
29
|
+
* - SESSION_ACTIVE → logout → UNAUTHENTICATED
|
|
30
|
+
* - FILE_OPEN → close_file → (FILE_OPEN invalidated)
|
|
31
|
+
* - DB_CONNECTED → disconnect_db → (DB_CONNECTED invalidated)
|
|
32
|
+
*
|
|
33
|
+
* Works for any state pair defined in the protocol rules.
|
|
34
|
+
*/
|
|
35
|
+
function searchFrontier(rules, currentStates, targetStates, maxDepth = 8) {
|
|
36
|
+
if (currentStates.length === 0) {
|
|
37
|
+
// If no current states, start from rules with no pre_states
|
|
38
|
+
const startable = new Set();
|
|
39
|
+
for (const [fn, rule] of rules) {
|
|
40
|
+
if (rule.pre_states.length === 0) {
|
|
41
|
+
for (const post of rule.post_states)
|
|
42
|
+
startable.add(post);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
if (startable.size > 0) {
|
|
46
|
+
currentStates = [...startable];
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
const currentSet = new Set(currentStates);
|
|
50
|
+
const targetSet = new Set(targetStates);
|
|
51
|
+
// BFS
|
|
52
|
+
const visited = new Set();
|
|
53
|
+
const queue = [
|
|
54
|
+
{ states: new Set(currentStates), actions: [], stateList: [...currentStates], cost: 0 },
|
|
55
|
+
];
|
|
56
|
+
visited.add([...currentStates].sort().join(","));
|
|
57
|
+
while (queue.length > 0) {
|
|
58
|
+
const { states, actions, stateList, cost } = queue.shift();
|
|
59
|
+
// Target reached?
|
|
60
|
+
if (targetStates.length > 0 && targetStates.every(t => states.has(t))) {
|
|
61
|
+
return { actions, states: stateList, cost, found: true };
|
|
62
|
+
}
|
|
63
|
+
// Resource cleanup: if target is empty, found when all current states are invalidated
|
|
64
|
+
if (targetStates.length === 0 && actions.length > 0) {
|
|
65
|
+
// Check if any state was successfully invalidated
|
|
66
|
+
const remainingFileOpen = states.has("FILE_OPEN");
|
|
67
|
+
const remainingDbConnected = states.has("DB_CONNECTED");
|
|
68
|
+
if (!remainingFileOpen && !remainingDbConnected && actions.length > 0) {
|
|
69
|
+
return { actions, states: stateList, cost, found: true };
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
if (cost >= maxDepth)
|
|
73
|
+
continue;
|
|
74
|
+
for (const [fn, rule] of rules) {
|
|
75
|
+
// Can we apply this rule from current states?
|
|
76
|
+
const preStatesOk = rule.pre_states.length === 0 || rule.pre_states.every(p => states.has(p));
|
|
77
|
+
if (!preStatesOk)
|
|
78
|
+
continue;
|
|
79
|
+
const nextStates = new Set(states);
|
|
80
|
+
if (rule.invalidate)
|
|
81
|
+
rule.invalidate.forEach(s => nextStates.delete(s));
|
|
82
|
+
for (const post of rule.post_states)
|
|
83
|
+
nextStates.add(post);
|
|
84
|
+
const stateKey = [...nextStates].sort().join(",");
|
|
85
|
+
if (visited.has(stateKey))
|
|
86
|
+
continue;
|
|
87
|
+
visited.add(stateKey);
|
|
88
|
+
queue.push({
|
|
89
|
+
states: nextStates,
|
|
90
|
+
actions: [...actions, fn],
|
|
91
|
+
stateList: [...stateList, ...rule.post_states],
|
|
92
|
+
cost: cost + 1,
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return { actions: [], states: [], cost: 0, found: false };
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Multi-start frontier search: tries multiple initial state combinations
|
|
100
|
+
* to find the best path. Useful when currentState is ambiguous.
|
|
101
|
+
*/
|
|
102
|
+
function searchFrontierMulti(rules, currentStatesCandidates, targetStates, maxDepth = 8) {
|
|
103
|
+
let best = { actions: [], states: [], cost: Infinity, found: false };
|
|
104
|
+
for (const startStates of currentStatesCandidates) {
|
|
105
|
+
const result = searchFrontier(rules, startStates, targetStates, maxDepth);
|
|
106
|
+
if (result.found && result.cost < best.cost) {
|
|
107
|
+
best = result;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return best;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Generate all reachable action sequences from a given state.
|
|
114
|
+
* Used as a candidate generator for Monte-Carlo style planning (P3.16).
|
|
115
|
+
*/
|
|
116
|
+
function exploreFrontier(rules, currentStates, maxPaths = 20, maxDepth = 6) {
|
|
117
|
+
const paths = [];
|
|
118
|
+
const visited = new Set();
|
|
119
|
+
const queue = [
|
|
120
|
+
{ states: new Set(currentStates), actions: [], cost: 0 },
|
|
121
|
+
];
|
|
122
|
+
while (queue.length > 0 && paths.length < maxPaths) {
|
|
123
|
+
const { states, actions, cost } = queue.shift();
|
|
124
|
+
if (cost >= maxDepth)
|
|
125
|
+
continue;
|
|
126
|
+
for (const [fn, rule] of rules) {
|
|
127
|
+
const preOk = rule.pre_states.length === 0 || rule.pre_states.every(p => states.has(p));
|
|
128
|
+
if (!preOk)
|
|
129
|
+
continue;
|
|
130
|
+
const next = new Set(states);
|
|
131
|
+
if (rule.invalidate)
|
|
132
|
+
rule.invalidate.forEach(s => next.delete(s));
|
|
133
|
+
for (const post of rule.post_states)
|
|
134
|
+
next.add(post);
|
|
135
|
+
const key = [...next].sort().join(",");
|
|
136
|
+
if (visited.has(key))
|
|
137
|
+
continue;
|
|
138
|
+
visited.add(key);
|
|
139
|
+
const newActions = [...actions, fn];
|
|
140
|
+
if (newActions.length >= 1)
|
|
141
|
+
paths.push(newActions);
|
|
142
|
+
queue.push({ states: next, actions: newActions, cost: cost + 1 });
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
return paths;
|
|
146
|
+
}
|
|
147
|
+
/** Known bridges between protocols. */
|
|
148
|
+
const PROTOCOL_BRIDGES = [
|
|
149
|
+
// Original bridges
|
|
150
|
+
{ from: "AuthProtocol", to: "FileProtocol", outputState: "SESSION_ACTIVE", inputState: "INIT" },
|
|
151
|
+
{ from: "AuthProtocol", to: "DBProtocol", outputState: "SESSION_ACTIVE", inputState: "INIT" },
|
|
152
|
+
{ from: "FileProtocol", to: "DBProtocol", outputState: "FILE_OPEN", inputState: "INIT" },
|
|
153
|
+
{ from: "DBProtocol", to: "IRProtocol", outputState: "DB_CONNECTED", inputState: "IR_STALE" },
|
|
154
|
+
{ from: "IRProtocol", to: "FileProtocol", outputState: "CODE_EMITTED", inputState: "INIT" },
|
|
155
|
+
// P7.3: New protocol bridges
|
|
156
|
+
{ from: "AuthProtocol", to: "TransactionProtocol", outputState: "SESSION_ACTIVE", inputState: "TX_IDLE" },
|
|
157
|
+
{ from: "AuthProtocol", to: "ConditionalProtocol", outputState: "SESSION_ACTIVE", inputState: "COND_IDLE" },
|
|
158
|
+
{ from: "AuthProtocol", to: "LoopProtocol", outputState: "SESSION_ACTIVE", inputState: "LOOP_IDLE" },
|
|
159
|
+
{ from: "AuthProtocol", to: "CrossProtocol", outputState: "SESSION_ACTIVE", inputState: "UNAUTHENTICATED" },
|
|
160
|
+
{ from: "TransactionProtocol", to: "DBProtocol", outputState: "TX_IDLE", inputState: "INIT" },
|
|
161
|
+
{ from: "ConditionalProtocol", to: "FileProtocol", outputState: "COND_ACCEPTED", inputState: "INIT" },
|
|
162
|
+
{ from: "ConditionalProtocol", to: "DBProtocol", outputState: "COND_ACCEPTED", inputState: "INIT" },
|
|
163
|
+
{ from: "LoopProtocol", to: "FileProtocol", outputState: "LOOP_DONE", inputState: "INIT" },
|
|
164
|
+
{ from: "LoopProtocol", to: "DBProtocol", outputState: "LOOP_DONE", inputState: "INIT" },
|
|
165
|
+
{ from: "FileProtocol", to: "CrossProtocol", outputState: "FILE_OPEN", inputState: "AUTH_FILE_GATE" },
|
|
166
|
+
{ from: "DBProtocol", to: "CrossProtocol", outputState: "DB_CONNECTED", inputState: "AUTH_DB_GATE" },
|
|
167
|
+
{ from: "StatelessProtocol", to: "FileProtocol", outputState: "IDLE", inputState: "INIT" },
|
|
168
|
+
{ from: "StatelessProtocol", to: "DBProtocol", outputState: "IDLE", inputState: "INIT" },
|
|
169
|
+
{ from: "StatelessProtocol", to: "TransactionProtocol", outputState: "IDLE", inputState: "TX_IDLE" },
|
|
170
|
+
];
|
|
171
|
+
/**
|
|
172
|
+
* Find a cross-protocol action chain for a multi-protocol goal.
|
|
173
|
+
*
|
|
174
|
+
* Decomposes the goal into protocol segments, plans each segment
|
|
175
|
+
* using the frontier explorer, and stitches them together via bridges.
|
|
176
|
+
*/
|
|
177
|
+
function planCrossProtocol(goal, protocols, targetProtocols, initialStates = {}) {
|
|
178
|
+
const bridges = [];
|
|
179
|
+
const allActions = [];
|
|
180
|
+
const orderedProtocols = [];
|
|
181
|
+
// Order protocols by bridge connectivity
|
|
182
|
+
if (targetProtocols.length <= 1) {
|
|
183
|
+
// Single protocol: just use frontier
|
|
184
|
+
const proto = protocols.find(p => p.name === targetProtocols[0]);
|
|
185
|
+
if (proto) {
|
|
186
|
+
const path = searchFrontier(proto.rules, initialStates[proto.name] || [], [], 8);
|
|
187
|
+
return { protocols: [proto.name], bridges: [], actions: path.actions };
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
// Multi-protocol: chain through bridges
|
|
191
|
+
for (let i = 0; i < targetProtocols.length; i++) {
|
|
192
|
+
const current = targetProtocols[i];
|
|
193
|
+
orderedProtocols.push(current);
|
|
194
|
+
if (i < targetProtocols.length - 1) {
|
|
195
|
+
const next = targetProtocols[i + 1];
|
|
196
|
+
const bridge = PROTOCOL_BRIDGES.find(b => b.from === current && b.to === next);
|
|
197
|
+
if (bridge)
|
|
198
|
+
bridges.push(bridge);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
// Plan each protocol segment
|
|
202
|
+
for (const protoName of orderedProtocols) {
|
|
203
|
+
const proto = protocols.find(p => p.name === protoName);
|
|
204
|
+
if (!proto)
|
|
205
|
+
continue;
|
|
206
|
+
const init = initialStates[protoName] || [];
|
|
207
|
+
const path = searchFrontier(proto.rules, init, [], 8);
|
|
208
|
+
if (path.found)
|
|
209
|
+
allActions.push(...path.actions);
|
|
210
|
+
}
|
|
211
|
+
return { protocols: orderedProtocols, bridges, actions: allActions };
|
|
212
|
+
}
|
|
213
|
+
/** Get protocol bridges for visualization. */
|
|
214
|
+
function getProtocolBridges() {
|
|
215
|
+
return [...PROTOCOL_BRIDGES];
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Generate cross-protocol candidate actions for a multi-protocol goal.
|
|
219
|
+
* Used by ProtocolStrategy to expand candidates beyond single-protocol BFS.
|
|
220
|
+
*/
|
|
221
|
+
function expandCrossProtocolCandidates(goal, targetProtocols) {
|
|
222
|
+
const allDefs = (0, protocol_coverage_1.loadDefaultProtocolDefinitions)();
|
|
223
|
+
const protoMap = new Map(allDefs.map(p => [p.name, p]));
|
|
224
|
+
const candidates = [];
|
|
225
|
+
// For each target protocol, generate frontier paths
|
|
226
|
+
for (const tp of targetProtocols) {
|
|
227
|
+
const proto = protoMap.get(tp);
|
|
228
|
+
if (!proto)
|
|
229
|
+
continue;
|
|
230
|
+
const frontierPaths = exploreFrontier(proto.rules, [], 10, 6);
|
|
231
|
+
for (const path of frontierPaths) {
|
|
232
|
+
if (path.length > 0)
|
|
233
|
+
candidates.push(path);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
// For multi-protocol: stitch via bridges
|
|
237
|
+
if (targetProtocols.length > 1) {
|
|
238
|
+
const plan = planCrossProtocol(goal, allDefs, targetProtocols);
|
|
239
|
+
if (plan.actions.length > 0)
|
|
240
|
+
candidates.push(plan.actions);
|
|
241
|
+
}
|
|
242
|
+
return candidates;
|
|
243
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* P3.14-15: Protocol Frontier Explorer Tests
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const vitest_1 = require("vitest");
|
|
7
|
+
const protocol_frontier_1 = require("./protocol-frontier");
|
|
8
|
+
function makeRules() {
|
|
9
|
+
return new Map([
|
|
10
|
+
["verify_password", { pre_states: ["UNAUTHENTICATED"], post_states: ["PASSWORD_VERIFIED"] }],
|
|
11
|
+
["generate_jwt", { pre_states: ["PASSWORD_VERIFIED"], post_states: ["TOKEN_ISSUED"], invalidate: ["PASSWORD_VERIFIED"] }],
|
|
12
|
+
["create_session", { pre_states: ["TOKEN_ISSUED"], post_states: ["SESSION_ACTIVE"], invalidate: ["TOKEN_ISSUED"] }],
|
|
13
|
+
["logout", { pre_states: ["SESSION_ACTIVE"], post_states: ["UNAUTHENTICATED"], invalidate: ["SESSION_ACTIVE"] }],
|
|
14
|
+
["open_file", { pre_states: [], post_states: ["FILE_OPEN"] }],
|
|
15
|
+
["close_file", { pre_states: ["FILE_OPEN"], post_states: [], invalidate: ["FILE_OPEN"] }],
|
|
16
|
+
["connect_db", { pre_states: [], post_states: ["DB_CONNECTED"] }],
|
|
17
|
+
["disconnect_db", { pre_states: ["DB_CONNECTED"], post_states: [], invalidate: ["DB_CONNECTED"] }],
|
|
18
|
+
]);
|
|
19
|
+
}
|
|
20
|
+
(0, vitest_1.describe)("Frontier Explorer", () => {
|
|
21
|
+
(0, vitest_1.it)("finds auth path from UNAUTHENTICATED to SESSION_ACTIVE", () => {
|
|
22
|
+
const rules = makeRules();
|
|
23
|
+
const path = (0, protocol_frontier_1.searchFrontier)(rules, ["UNAUTHENTICATED"], ["SESSION_ACTIVE"]);
|
|
24
|
+
(0, vitest_1.expect)(path.found).toBe(true);
|
|
25
|
+
(0, vitest_1.expect)(path.actions).toContain("verify_password");
|
|
26
|
+
(0, vitest_1.expect)(path.actions).toContain("generate_jwt");
|
|
27
|
+
(0, vitest_1.expect)(path.actions).toContain("create_session");
|
|
28
|
+
(0, vitest_1.expect)(path.cost).toBe(3);
|
|
29
|
+
});
|
|
30
|
+
(0, vitest_1.it)("finds logout path from SESSION_ACTIVE to UNAUTHENTICATED", () => {
|
|
31
|
+
const rules = makeRules();
|
|
32
|
+
const path = (0, protocol_frontier_1.searchFrontier)(rules, ["SESSION_ACTIVE"], ["UNAUTHENTICATED"]);
|
|
33
|
+
(0, vitest_1.expect)(path.found).toBe(true);
|
|
34
|
+
(0, vitest_1.expect)(path.actions).toEqual(["logout"]);
|
|
35
|
+
(0, vitest_1.expect)(path.cost).toBe(1);
|
|
36
|
+
});
|
|
37
|
+
(0, vitest_1.it)("finds close_file cleanup from FILE_OPEN", () => {
|
|
38
|
+
const rules = makeRules();
|
|
39
|
+
const path = (0, protocol_frontier_1.searchFrontier)(rules, ["FILE_OPEN"], []);
|
|
40
|
+
(0, vitest_1.expect)(path.found).toBe(true);
|
|
41
|
+
(0, vitest_1.expect)(path.actions).toContain("close_file");
|
|
42
|
+
});
|
|
43
|
+
(0, vitest_1.it)("returns not found for unreachable target", () => {
|
|
44
|
+
const rules = makeRules();
|
|
45
|
+
const path = (0, protocol_frontier_1.searchFrontier)(rules, ["UNAUTHENTICATED"], ["NONEXISTENT"]);
|
|
46
|
+
(0, vitest_1.expect)(path.found).toBe(false);
|
|
47
|
+
});
|
|
48
|
+
(0, vitest_1.it)("explores frontier: generates multiple paths", () => {
|
|
49
|
+
const rules = makeRules();
|
|
50
|
+
const paths = (0, protocol_frontier_1.exploreFrontier)(rules, ["UNAUTHENTICATED"], 20, 6);
|
|
51
|
+
(0, vitest_1.expect)(paths.length).toBeGreaterThan(1);
|
|
52
|
+
// Should include auth chain
|
|
53
|
+
const hasAuth = paths.some(p => p.includes("verify_password") && p.includes("generate_jwt") && p.includes("create_session"));
|
|
54
|
+
(0, vitest_1.expect)(hasAuth).toBe(true);
|
|
55
|
+
});
|
|
56
|
+
(0, vitest_1.it)("multi-start finds best path among candidates", () => {
|
|
57
|
+
const rules = makeRules();
|
|
58
|
+
const path = (0, protocol_frontier_1.searchFrontierMulti)(rules, [
|
|
59
|
+
["FILE_OPEN"],
|
|
60
|
+
["SESSION_ACTIVE"],
|
|
61
|
+
], ["UNAUTHENTICATED"]);
|
|
62
|
+
// SESSION_ACTIVE→logout→UNAUTHENTICATED is 1 step, better than FILE_OPEN→close→open→auth→...
|
|
63
|
+
(0, vitest_1.expect)(path.found).toBe(true);
|
|
64
|
+
(0, vitest_1.expect)(path.cost).toBe(1);
|
|
65
|
+
(0, vitest_1.expect)(path.actions).toContain("logout");
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
(0, vitest_1.describe)("Cross-Protocol Planner", () => {
|
|
69
|
+
(0, vitest_1.it)("has protocol bridges", () => {
|
|
70
|
+
const bridges = (0, protocol_frontier_1.getProtocolBridges)();
|
|
71
|
+
(0, vitest_1.expect)(bridges.length).toBeGreaterThanOrEqual(3);
|
|
72
|
+
(0, vitest_1.expect)(bridges.some(b => b.from === "AuthProtocol" && b.to === "FileProtocol")).toBe(true);
|
|
73
|
+
(0, vitest_1.expect)(bridges.some(b => b.from === "AuthProtocol" && b.to === "DBProtocol")).toBe(true);
|
|
74
|
+
});
|
|
75
|
+
(0, vitest_1.it)("plans single protocol", () => {
|
|
76
|
+
const rules = makeRules();
|
|
77
|
+
const plan = (0, protocol_frontier_1.planCrossProtocol)("logout", [
|
|
78
|
+
{ name: "AuthProtocol", rules },
|
|
79
|
+
], ["AuthProtocol"], { AuthProtocol: ["SESSION_ACTIVE"] });
|
|
80
|
+
(0, vitest_1.expect)(plan.actions.length).toBeGreaterThan(0);
|
|
81
|
+
(0, vitest_1.expect)(plan.actions).toContain("logout");
|
|
82
|
+
});
|
|
83
|
+
(0, vitest_1.it)("generates cross-protocol candidates", () => {
|
|
84
|
+
const candidates = (0, protocol_frontier_1.expandCrossProtocolCandidates)("multi-step repair", ["FileProtocol", "DBProtocol"]);
|
|
85
|
+
// Should find paths for both protocols
|
|
86
|
+
(0, vitest_1.expect)(candidates.length).toBeGreaterThan(1);
|
|
87
|
+
// At least one file path and one db path
|
|
88
|
+
const hasFile = candidates.some(p => p.includes("open_file") || p.includes("close_file"));
|
|
89
|
+
const hasDb = candidates.some(p => p.includes("connect_db") || p.includes("disconnect_db"));
|
|
90
|
+
(0, vitest_1.expect)(hasFile || hasDb).toBe(true);
|
|
91
|
+
});
|
|
92
|
+
});
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* P3.16-17: Protocol Gap Mining + Knowledge Acquisition Planner
|
|
4
|
+
*
|
|
5
|
+
* Decomposes the 57% missing_candidate into actionable categories:
|
|
6
|
+
* - Missing Actions: functions in expected repair but not in any protocol rule
|
|
7
|
+
* - Missing Transitions: state pairs not connected by any rule
|
|
8
|
+
* - Missing Cross-Protocol Bridges: protocol pairs with no bridge definition
|
|
9
|
+
*
|
|
10
|
+
* This transforms protocol expansion from guesswork to data-driven prioritization.
|
|
11
|
+
*
|
|
12
|
+
* Fourth flywheel:
|
|
13
|
+
* Failures → Missing Knowledge → Protocol Expansion → Better Candidates
|
|
14
|
+
*/
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.analyzeProtocolGaps = analyzeProtocolGaps;
|
|
17
|
+
exports.computeKnowledgeScores = computeKnowledgeScores;
|
|
18
|
+
exports.printGapReport = printGapReport;
|
|
19
|
+
exports.printKnowledgeScores = printKnowledgeScores;
|
|
20
|
+
const protocol_coverage_1 = require("./protocol-coverage");
|
|
21
|
+
const protocol_frontier_1 = require("./protocol-frontier");
|
|
22
|
+
// ═══════════════════════════════════════════════════════════════
|
|
23
|
+
// Gap Analyzer
|
|
24
|
+
// ═══════════════════════════════════════════════════════════════
|
|
25
|
+
/**
|
|
26
|
+
* Analyze benchmark failures to identify which actions/transitions
|
|
27
|
+
* are missing from the protocol definitions.
|
|
28
|
+
*/
|
|
29
|
+
function analyzeProtocolGaps(attributed, rules // protocol → set of function names
|
|
30
|
+
) {
|
|
31
|
+
const failures = attributed.filter(a => a.failureReason !== "success");
|
|
32
|
+
const gapMap = new Map();
|
|
33
|
+
for (const f of failures) {
|
|
34
|
+
for (const fn of f.expectedRepair) {
|
|
35
|
+
// Check if this function exists in any protocol
|
|
36
|
+
let found = false;
|
|
37
|
+
for (const [, fns] of rules) {
|
|
38
|
+
if (fns.has(fn)) {
|
|
39
|
+
found = true;
|
|
40
|
+
break;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
if (!found) {
|
|
44
|
+
const key = `action:${fn}`;
|
|
45
|
+
const existing = gapMap.get(key);
|
|
46
|
+
if (existing) {
|
|
47
|
+
existing.protocols.add(f.protocol);
|
|
48
|
+
existing.examples.push(f.goal);
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
gapMap.set(key, {
|
|
52
|
+
kind: "missing_action",
|
|
53
|
+
protocols: new Set([f.protocol]),
|
|
54
|
+
examples: [f.goal],
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
// Check for missing transitions: consecutive function pairs in expected
|
|
60
|
+
for (let i = 0; i < f.expectedRepair.length - 1; i++) {
|
|
61
|
+
const from = f.expectedRepair[i];
|
|
62
|
+
const to = f.expectedRepair[i + 1];
|
|
63
|
+
const key = `transition:${from}→${to}`;
|
|
64
|
+
if (!gapMap.has(key)) {
|
|
65
|
+
gapMap.set(key, {
|
|
66
|
+
kind: "missing_transition",
|
|
67
|
+
protocols: new Set([f.protocol]),
|
|
68
|
+
examples: [f.goal],
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
gapMap.get(key).examples.push(f.goal);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
// Cross-protocol bridge gaps
|
|
77
|
+
const bridges = (0, protocol_frontier_1.getProtocolBridges)();
|
|
78
|
+
const bridgePairs = new Set(bridges.map(b => `${b.from}→${b.to}`));
|
|
79
|
+
const crossProtocolFailures = failures.filter(f => f.expectedRepair.some(fn => fn.includes("file")) &&
|
|
80
|
+
f.expectedRepair.some(fn => fn.includes("db")));
|
|
81
|
+
for (const f of crossProtocolFailures) {
|
|
82
|
+
// Check if there's a bridge connecting the protocols involved
|
|
83
|
+
const protoSet = new Set();
|
|
84
|
+
for (const fn of f.expectedRepair) {
|
|
85
|
+
for (const [proto, fns] of rules) {
|
|
86
|
+
if (fns.has(fn))
|
|
87
|
+
protoSet.add(proto);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
const protoList = [...protoSet];
|
|
91
|
+
for (let i = 0; i < protoList.length - 1; i++) {
|
|
92
|
+
const pair = `${protoList[i]}→${protoList[i + 1]}`;
|
|
93
|
+
if (!bridgePairs.has(pair)) {
|
|
94
|
+
const key = `bridge:${pair}`;
|
|
95
|
+
if (!gapMap.has(key)) {
|
|
96
|
+
gapMap.set(key, {
|
|
97
|
+
kind: "missing_bridge",
|
|
98
|
+
protocols: new Set(protoList),
|
|
99
|
+
examples: [f.goal],
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
gapMap.get(key).examples.push(f.goal);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
// Convert to sorted list with priority scores
|
|
109
|
+
const totalFailures = failures.length;
|
|
110
|
+
const gaps = [];
|
|
111
|
+
const byKind = {
|
|
112
|
+
missing_action: { count: 0, items: [] },
|
|
113
|
+
missing_transition: { count: 0, items: [] },
|
|
114
|
+
missing_bridge: { count: 0, items: [] },
|
|
115
|
+
missing_protocol: { count: 0, items: [] },
|
|
116
|
+
};
|
|
117
|
+
for (const [key, entry] of gapMap) {
|
|
118
|
+
const kind = entry.kind;
|
|
119
|
+
const item = key.split(":")[1] || key;
|
|
120
|
+
const frequency = entry.examples.length;
|
|
121
|
+
const priority = Math.min(1, frequency / Math.max(1, totalFailures));
|
|
122
|
+
byKind[kind].count++;
|
|
123
|
+
byKind[kind].items.push(item);
|
|
124
|
+
gaps.push({
|
|
125
|
+
kind,
|
|
126
|
+
item,
|
|
127
|
+
protocols: [...entry.protocols],
|
|
128
|
+
frequency,
|
|
129
|
+
examples: entry.examples.slice(0, 3),
|
|
130
|
+
priority,
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
gaps.sort((a, b) => b.priority - a.priority);
|
|
134
|
+
return {
|
|
135
|
+
totalFailures,
|
|
136
|
+
failuresAnalyzed: failures.length,
|
|
137
|
+
gaps,
|
|
138
|
+
byKind: byKind,
|
|
139
|
+
topMissingActions: gaps.filter(g => g.kind === "missing_action").slice(0, 10).map(g => g.item),
|
|
140
|
+
topMissingTransitions: gaps.filter(g => g.kind === "missing_transition").slice(0, 10).map(g => g.item),
|
|
141
|
+
topMissingBridges: gaps.filter(g => g.kind === "missing_bridge").slice(0, 5).map(g => g.item),
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Compute a per-protocol knowledge score.
|
|
146
|
+
* score = 0.4*coverage + 0.3*successRate + 0.2*benchmarkPassRate + 0.1*corpusSupport
|
|
147
|
+
*/
|
|
148
|
+
function computeKnowledgeScores(failures) {
|
|
149
|
+
const protocols = (0, protocol_coverage_1.loadDefaultProtocolDefinitions)();
|
|
150
|
+
return protocols.map(p => {
|
|
151
|
+
const relevant = failures.filter(f => f.protocol === p.name || f.expectedRepair.some(fn => p.rules.has(fn)));
|
|
152
|
+
const passed = relevant.filter(f => f.failureReason === "success").length;
|
|
153
|
+
const total = relevant.length;
|
|
154
|
+
// Coverage: states defined / total transitions
|
|
155
|
+
const coverage = p.states.length > 0 ? Math.min(1, p.states.length / 20) : 0;
|
|
156
|
+
const successRate = total > 0 ? passed / total : 0;
|
|
157
|
+
const benchmarkPassRate = total > 0 ? passed / total : 0;
|
|
158
|
+
const corpusSupport = total > 0 ? Math.min(1, total / 50) : 0;
|
|
159
|
+
const score = 0.4 * coverage + 0.3 * successRate + 0.2 * benchmarkPassRate + 0.1 * corpusSupport;
|
|
160
|
+
return {
|
|
161
|
+
protocol: p.name,
|
|
162
|
+
coverage,
|
|
163
|
+
successRate,
|
|
164
|
+
benchmarkPassRate,
|
|
165
|
+
corpusSupport,
|
|
166
|
+
score,
|
|
167
|
+
gaps: relevant.filter(f => f.failureReason !== "success").length,
|
|
168
|
+
};
|
|
169
|
+
}).sort((a, b) => b.score - a.score);
|
|
170
|
+
}
|
|
171
|
+
// ═══════════════════════════════════════════════════════════════
|
|
172
|
+
// Dashboard
|
|
173
|
+
// ═══════════════════════════════════════════════════════════════
|
|
174
|
+
function printGapReport(report) {
|
|
175
|
+
console.log("\n╔════════════════════════════════════════════════════╗");
|
|
176
|
+
console.log("║ Protocol Gap Mining Report ║");
|
|
177
|
+
console.log("╚════════════════════════════════════════════════════╝\n");
|
|
178
|
+
console.log(`Failures Analyzed: ${report.failuresAnalyzed}/${report.totalFailures}`);
|
|
179
|
+
console.log(`Gaps Found: ${report.gaps.length}`);
|
|
180
|
+
console.log();
|
|
181
|
+
console.log("─── Gap Breakdown ───");
|
|
182
|
+
for (const [kind, info] of Object.entries(report.byKind)) {
|
|
183
|
+
if (info.count === 0)
|
|
184
|
+
continue;
|
|
185
|
+
const label = kind.replace(/_/g, " ").padEnd(22);
|
|
186
|
+
console.log(` ${label} ${String(info.count).padStart(4)} items`);
|
|
187
|
+
}
|
|
188
|
+
console.log();
|
|
189
|
+
if (report.topMissingActions.length > 0) {
|
|
190
|
+
console.log("─── Top Missing Actions (add to protocol rules) ───");
|
|
191
|
+
const tops = report.gaps.filter(g => g.kind === "missing_action").slice(0, 10);
|
|
192
|
+
for (const g of tops) {
|
|
193
|
+
console.log(` ${g.item.padEnd(25)} freq=${g.frequency} pri=${(g.priority * 100).toFixed(0)}%`);
|
|
194
|
+
}
|
|
195
|
+
console.log();
|
|
196
|
+
}
|
|
197
|
+
if (report.topMissingTransitions.length > 0) {
|
|
198
|
+
console.log("─── Top Missing Transitions ───");
|
|
199
|
+
for (const t of report.topMissingTransitions.slice(0, 5)) {
|
|
200
|
+
console.log(` ${t}`);
|
|
201
|
+
}
|
|
202
|
+
console.log();
|
|
203
|
+
}
|
|
204
|
+
if (report.topMissingBridges.length > 0) {
|
|
205
|
+
console.log("─── Top Missing Bridges ───");
|
|
206
|
+
for (const b of report.topMissingBridges) {
|
|
207
|
+
console.log(` ${b}`);
|
|
208
|
+
}
|
|
209
|
+
console.log();
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
function printKnowledgeScores(scores) {
|
|
213
|
+
console.log("\n╔════════════════════════════════════════════════════╗");
|
|
214
|
+
console.log("║ Protocol Knowledge Scoreboard ║");
|
|
215
|
+
console.log("╚════════════════════════════════════════════════════╝\n");
|
|
216
|
+
console.log("Protocol Covrg Succ Bench Corpus Score Gaps");
|
|
217
|
+
console.log("──────────────────────────────────────────────────────────");
|
|
218
|
+
for (const s of scores) {
|
|
219
|
+
const cov = (s.coverage * 100).toFixed(0).padStart(4);
|
|
220
|
+
const suc = (s.successRate * 100).toFixed(0).padStart(4);
|
|
221
|
+
const ben = (s.benchmarkPassRate * 100).toFixed(0).padStart(4);
|
|
222
|
+
const cor = (s.corpusSupport * 100).toFixed(0).padStart(4);
|
|
223
|
+
const scr = (s.score * 100).toFixed(0).padStart(4);
|
|
224
|
+
const icon = s.score > 0.7 ? "🟢" : s.score > 0.4 ? "🟡" : "🔴";
|
|
225
|
+
console.log(` ${s.protocol.padEnd(16)} ${cov}% ${suc}% ${ben}% ${cor}% ${scr}% ${String(s.gaps).padStart(4)} ${icon}`);
|
|
226
|
+
}
|
|
227
|
+
console.log();
|
|
228
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* P3.16-17: Protocol Gap Mining Tests
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const vitest_1 = require("vitest");
|
|
7
|
+
const protocol_gap_analyzer_1 = require("./protocol-gap-analyzer");
|
|
8
|
+
function makeAttributedCases() {
|
|
9
|
+
return [
|
|
10
|
+
{ caseId: "c1", goal: "authenticate user", protocol: "AuthProtocol", violationType: "missing_prerequisite", expectedRepair: ["verify_password", "generate_jwt", "create_session"], plannerTop1: ["logout"], candidatesReturned: 1, rank: null, failureReason: "missing_candidate" },
|
|
11
|
+
{ caseId: "c2", goal: "authenticate user", protocol: "AuthProtocol", violationType: "missing_prerequisite", expectedRepair: ["verify_password", "generate_jwt", "create_session"], plannerTop1: ["logout"], candidatesReturned: 1, rank: null, failureReason: "missing_candidate" },
|
|
12
|
+
{ caseId: "c3", goal: "full auth lifecycle", protocol: "AuthProtocol", violationType: "missing_prerequisite", expectedRepair: ["verify_password", "generate_jwt", "create_session", "logout"], plannerTop1: ["logout"], candidatesReturned: 1, rank: null, failureReason: "missing_candidate" },
|
|
13
|
+
{ caseId: "c4", goal: "safely write file", protocol: "FileProtocol", violationType: "resource_leak", expectedRepair: ["open_file", "write_file", "flush_file", "close_file"], plannerTop1: ["close_file"], candidatesReturned: 1, rank: null, failureReason: "missing_candidate" },
|
|
14
|
+
{ caseId: "c5", goal: "safely write file", protocol: "FileProtocol", violationType: "resource_leak", expectedRepair: ["open_file", "write_file", "flush_file", "close_file"], plannerTop1: ["close_file"], candidatesReturned: 1, rank: null, failureReason: "missing_candidate" },
|
|
15
|
+
{ caseId: "c6", goal: "query db safely", protocol: "DBProtocol", violationType: "missing_prerequisite", expectedRepair: ["connect_db", "query_db", "disconnect_db"], plannerTop1: ["disconnect_db"], candidatesReturned: 1, rank: null, failureReason: "missing_candidate" },
|
|
16
|
+
{ caseId: "c7", goal: "auth then file then db", protocol: "FileProtocol", violationType: "resource_leak", expectedRepair: ["verify_password", "open_file", "write_file", "close_file", "connect_db", "query_db", "disconnect_db"], plannerTop1: ["close_file"], candidatesReturned: 1, rank: null, failureReason: "missing_candidate" },
|
|
17
|
+
{ caseId: "c8", goal: "success case", protocol: "FileProtocol", violationType: "resource_leak", expectedRepair: ["open_file", "write_file", "close_file"], plannerTop1: ["open_file", "write_file", "close_file"], candidatesReturned: 3, rank: 1, failureReason: "success" },
|
|
18
|
+
];
|
|
19
|
+
}
|
|
20
|
+
(0, vitest_1.describe)("Protocol Gap Analyzer", () => {
|
|
21
|
+
(0, vitest_1.it)("identifies missing actions from failures", () => {
|
|
22
|
+
const cases = makeAttributedCases();
|
|
23
|
+
// Build rules map: only existing protocol functions
|
|
24
|
+
const rules = new Map();
|
|
25
|
+
rules.set("AuthProtocol", new Set(["verify_password", "generate_jwt", "create_session", "logout", "revoke_token"]));
|
|
26
|
+
rules.set("FileProtocol", new Set(["open_file", "read_file", "write_file", "close_file"]));
|
|
27
|
+
rules.set("DBProtocol", new Set(["connect_db", "query_db", "disconnect_db"]));
|
|
28
|
+
rules.set("IRProtocol", new Set(["extractIR", "validateAction", "validateActionSequence", "emitCode", "recordSession"]));
|
|
29
|
+
const report = (0, protocol_gap_analyzer_1.analyzeProtocolGaps)(cases, rules);
|
|
30
|
+
(0, vitest_1.expect)(report.failuresAnalyzed).toBe(7); // 8 total, 1 success
|
|
31
|
+
(0, vitest_1.expect)(report.gaps.length).toBeGreaterThan(0);
|
|
32
|
+
// flush_file should appear as a missing action
|
|
33
|
+
const missingActions = report.gaps.filter(g => g.kind === "missing_action");
|
|
34
|
+
(0, vitest_1.expect)(missingActions.some(g => g.item === "flush_file")).toBe(true);
|
|
35
|
+
// flush_file appears in 2 cases (c4, c5)
|
|
36
|
+
const flushGap = missingActions.find(g => g.item === "flush_file");
|
|
37
|
+
(0, vitest_1.expect)(flushGap?.frequency).toBe(2);
|
|
38
|
+
(0, protocol_gap_analyzer_1.printGapReport)(report);
|
|
39
|
+
});
|
|
40
|
+
(0, vitest_1.it)("computes knowledge scores per protocol", () => {
|
|
41
|
+
const cases = makeAttributedCases();
|
|
42
|
+
const scores = (0, protocol_gap_analyzer_1.computeKnowledgeScores)(cases);
|
|
43
|
+
(0, vitest_1.expect)(scores.length).toBeGreaterThanOrEqual(4); // P7.3: 9 protocol groups
|
|
44
|
+
// FileProtocol has success case → higher score
|
|
45
|
+
const file = scores.find(s => s.protocol === "FileProtocol");
|
|
46
|
+
(0, vitest_1.expect)(file.successRate).toBeGreaterThan(0);
|
|
47
|
+
(0, protocol_gap_analyzer_1.printKnowledgeScores)(scores);
|
|
48
|
+
});
|
|
49
|
+
});
|