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,454 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* P2→P4 Evolution Path Verification Tests
|
|
4
|
+
*
|
|
5
|
+
* These tests verify that the refactored architecture truly opens
|
|
6
|
+
* the path from Counterfactual Planner → Reward Model.
|
|
7
|
+
*
|
|
8
|
+
* Five architecture-level invariants:
|
|
9
|
+
* 1. Strategy never knows about ranking
|
|
10
|
+
* 2. Same candidate from multiple sources = merged evidence
|
|
11
|
+
* 3. Same candidate ranks differently under different objectives
|
|
12
|
+
* 4. Feedback + cost survive trajectory persistence (P4 pre-burial)
|
|
13
|
+
* 5. Goal → Repair → Feedback → Corpus closed loop (the flywheel)
|
|
14
|
+
*/
|
|
15
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
16
|
+
if (k2 === undefined) k2 = k;
|
|
17
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
18
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
19
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
20
|
+
}
|
|
21
|
+
Object.defineProperty(o, k2, desc);
|
|
22
|
+
}) : (function(o, m, k, k2) {
|
|
23
|
+
if (k2 === undefined) k2 = k;
|
|
24
|
+
o[k2] = m[k];
|
|
25
|
+
}));
|
|
26
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
27
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
28
|
+
}) : function(o, v) {
|
|
29
|
+
o["default"] = v;
|
|
30
|
+
});
|
|
31
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
32
|
+
var ownKeys = function(o) {
|
|
33
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
34
|
+
var ar = [];
|
|
35
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
36
|
+
return ar;
|
|
37
|
+
};
|
|
38
|
+
return ownKeys(o);
|
|
39
|
+
};
|
|
40
|
+
return function (mod) {
|
|
41
|
+
if (mod && mod.__esModule) return mod;
|
|
42
|
+
var result = {};
|
|
43
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
44
|
+
__setModuleDefault(result, mod);
|
|
45
|
+
return result;
|
|
46
|
+
};
|
|
47
|
+
})();
|
|
48
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
49
|
+
const vitest_1 = require("vitest");
|
|
50
|
+
const fs = __importStar(require("fs"));
|
|
51
|
+
const path = __importStar(require("path"));
|
|
52
|
+
const repair_ranker_1 = require("./repair-ranker");
|
|
53
|
+
const counterfactual_engine_1 = require("./counterfactual-engine");
|
|
54
|
+
const ssg_validator_1 = require("./ssg-validator");
|
|
55
|
+
// ── Helpers ──
|
|
56
|
+
function fileProtocolRules() {
|
|
57
|
+
const protoDef = JSON.parse(fs.readFileSync(path.resolve(__dirname, "..", "protocols.json"), "utf-8"));
|
|
58
|
+
const protocols = (0, ssg_validator_1.parseProtocolsFromJSON)(protoDef);
|
|
59
|
+
const rules = new Map();
|
|
60
|
+
for (const p of protocols)
|
|
61
|
+
rules.set(p.function, p.protocol);
|
|
62
|
+
return rules;
|
|
63
|
+
}
|
|
64
|
+
function fileProtocolContext(targetState) {
|
|
65
|
+
return {
|
|
66
|
+
protocol: "_global",
|
|
67
|
+
currentState: ["FILE_OPEN"],
|
|
68
|
+
targetState: targetState || [],
|
|
69
|
+
violationType: "resource_leak",
|
|
70
|
+
constraints: [],
|
|
71
|
+
rules: fileProtocolRules(),
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
// ════════════════════════════════════════════════════════
|
|
75
|
+
// Test 1: Strategy completely unaware of ranking
|
|
76
|
+
// ════════════════════════════════════════════════════════
|
|
77
|
+
class DummyStrategy {
|
|
78
|
+
constructor() {
|
|
79
|
+
this.name = "dummy";
|
|
80
|
+
}
|
|
81
|
+
search(_) {
|
|
82
|
+
return [{
|
|
83
|
+
id: "dummy-1",
|
|
84
|
+
source: "protocol",
|
|
85
|
+
actions: [
|
|
86
|
+
{ kind: "call", function: "open_file", args: [] },
|
|
87
|
+
{ kind: "call", function: "write_file", args: [] },
|
|
88
|
+
{ kind: "call", function: "close_file", args: [] },
|
|
89
|
+
],
|
|
90
|
+
explanation: "dummy test candidate",
|
|
91
|
+
}];
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
(0, vitest_1.describe)("Test 1: Strategy unaware of ranking", () => {
|
|
95
|
+
(0, vitest_1.it)("strategy returns candidates without score or rank", () => {
|
|
96
|
+
const s = new DummyStrategy();
|
|
97
|
+
const result = s.search({});
|
|
98
|
+
(0, vitest_1.expect)(result.length).toBe(1);
|
|
99
|
+
(0, vitest_1.expect)(result[0].score).toBeUndefined();
|
|
100
|
+
(0, vitest_1.expect)(result[0].rank).toBeUndefined();
|
|
101
|
+
// Has required RepairCandidate shape
|
|
102
|
+
(0, vitest_1.expect)(result[0].id).toBeDefined();
|
|
103
|
+
(0, vitest_1.expect)(result[0].source).toBe("protocol");
|
|
104
|
+
(0, vitest_1.expect)(result[0].actions.length).toBe(3);
|
|
105
|
+
(0, vitest_1.expect)(result[0].explanation).toBeDefined();
|
|
106
|
+
});
|
|
107
|
+
(0, vitest_1.it)("future LLMRepairStrategy would not need Ranker changes", () => {
|
|
108
|
+
// Any class implementing CandidateSearchStrategy works
|
|
109
|
+
const iface = new DummyStrategy();
|
|
110
|
+
(0, vitest_1.expect)(iface.name).toBe("dummy");
|
|
111
|
+
(0, vitest_1.expect)(typeof iface.search).toBe("function");
|
|
112
|
+
// The Ranker consumes RepairCandidate[], not strategy-specific types
|
|
113
|
+
const ranker = (0, repair_ranker_1.createLinearRanker)();
|
|
114
|
+
const ctx = {
|
|
115
|
+
protocol: "test", currentState: [], targetState: ["DONE"],
|
|
116
|
+
violationType: "test", constraints: [], rules: new Map(),
|
|
117
|
+
};
|
|
118
|
+
const candidate = iface.search(ctx)[0];
|
|
119
|
+
const features = (0, repair_ranker_1.extractFeatures)(candidate, ctx);
|
|
120
|
+
const score = ranker.score(features);
|
|
121
|
+
(0, vitest_1.expect)(score).toBeGreaterThanOrEqual(0);
|
|
122
|
+
(0, vitest_1.expect)(score).toBeLessThanOrEqual(1);
|
|
123
|
+
});
|
|
124
|
+
});
|
|
125
|
+
// ════════════════════════════════════════════════════════
|
|
126
|
+
// Test 2: Cross-source evidence merging
|
|
127
|
+
// ════════════════════════════════════════════════════════
|
|
128
|
+
(0, vitest_1.describe)("Test 2: Cross-source evidence merge", () => {
|
|
129
|
+
(0, vitest_1.it)("merges identical action sequences from different sources", () => {
|
|
130
|
+
const candidates = [
|
|
131
|
+
{
|
|
132
|
+
id: "corpus-close",
|
|
133
|
+
source: "corpus",
|
|
134
|
+
actions: [{ kind: "call", function: "close_file", args: [] }],
|
|
135
|
+
explanation: "From historical data: close the file",
|
|
136
|
+
evidence: 42,
|
|
137
|
+
metadata: { historicalSuccessRate: 0.85 },
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
id: "protocol-close",
|
|
141
|
+
source: "protocol",
|
|
142
|
+
actions: [{ kind: "call", function: "close_file", args: [] }],
|
|
143
|
+
explanation: "From SSG: close_file invalidates FILE_OPEN",
|
|
144
|
+
evidence: 0,
|
|
145
|
+
metadata: { pathLength: 1 },
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
id: "antibody-close",
|
|
149
|
+
source: "antibody",
|
|
150
|
+
actions: [{ kind: "call", function: "close_file", args: [] }],
|
|
151
|
+
explanation: "From antibody: resource leak → close_file",
|
|
152
|
+
evidence: 0,
|
|
153
|
+
metadata: { avgSuccessRate: 0.5 },
|
|
154
|
+
},
|
|
155
|
+
];
|
|
156
|
+
const merged = (0, counterfactual_engine_1.deduplicateCandidates)(candidates);
|
|
157
|
+
(0, vitest_1.expect)(merged.length).toBe(1);
|
|
158
|
+
(0, vitest_1.expect)(merged[0].evidenceSources).toBeDefined();
|
|
159
|
+
(0, vitest_1.expect)(merged[0].evidenceSources.sort()).toEqual(["antibody", "corpus", "protocol"]);
|
|
160
|
+
// Evidence count takes max from all sources
|
|
161
|
+
(0, vitest_1.expect)(merged[0].evidence).toBe(42);
|
|
162
|
+
// Metadata merges: highest historicalSuccessRate survives
|
|
163
|
+
(0, vitest_1.expect)(merged[0].metadata?.historicalSuccessRate).toBe(0.85);
|
|
164
|
+
});
|
|
165
|
+
(0, vitest_1.it)("single-source candidate has evidenceSources = [source]", () => {
|
|
166
|
+
const candidates = [{
|
|
167
|
+
id: "solo",
|
|
168
|
+
source: "protocol",
|
|
169
|
+
actions: [{ kind: "call", function: "verify_email", args: [] }],
|
|
170
|
+
explanation: "Only from protocol",
|
|
171
|
+
}];
|
|
172
|
+
const merged = (0, counterfactual_engine_1.deduplicateCandidates)(candidates);
|
|
173
|
+
(0, vitest_1.expect)(merged.length).toBe(1);
|
|
174
|
+
(0, vitest_1.expect)(merged[0].evidenceSources).toEqual(["protocol"]);
|
|
175
|
+
});
|
|
176
|
+
(0, vitest_1.it)("different action sequences stay separate", () => {
|
|
177
|
+
const candidates = [
|
|
178
|
+
{
|
|
179
|
+
id: "a", source: "protocol",
|
|
180
|
+
actions: [{ kind: "call", function: "close_file", args: [] }],
|
|
181
|
+
explanation: "close",
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
id: "b", source: "corpus",
|
|
185
|
+
actions: [
|
|
186
|
+
{ kind: "call", function: "flush", args: [] },
|
|
187
|
+
{ kind: "call", function: "close_file", args: [] },
|
|
188
|
+
],
|
|
189
|
+
explanation: "flush then close",
|
|
190
|
+
},
|
|
191
|
+
];
|
|
192
|
+
const merged = (0, counterfactual_engine_1.deduplicateCandidates)(candidates);
|
|
193
|
+
(0, vitest_1.expect)(merged.length).toBe(2);
|
|
194
|
+
// Each has its own evidenceSources
|
|
195
|
+
for (const m of merged) {
|
|
196
|
+
(0, vitest_1.expect)(m.evidenceSources.length).toBe(1);
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
});
|
|
200
|
+
// ════════════════════════════════════════════════════════
|
|
201
|
+
// Test 3: Ranking mode switching
|
|
202
|
+
// ════════════════════════════════════════════════════════
|
|
203
|
+
(0, vitest_1.describe)("Test 3: Ranking mode switching", () => {
|
|
204
|
+
const safeCandidate = {
|
|
205
|
+
id: "safe", source: "protocol",
|
|
206
|
+
actions: [
|
|
207
|
+
{ kind: "call", function: "open_file", args: [] },
|
|
208
|
+
{ kind: "call", function: "write_file", args: [] },
|
|
209
|
+
{ kind: "call", function: "close_file", args: [] },
|
|
210
|
+
],
|
|
211
|
+
explanation: "Safe: full open-write-close sequence",
|
|
212
|
+
};
|
|
213
|
+
const fastCandidate = {
|
|
214
|
+
id: "fast", source: "corpus",
|
|
215
|
+
actions: [
|
|
216
|
+
{ kind: "call", function: "atomic_write", args: [] },
|
|
217
|
+
],
|
|
218
|
+
explanation: "Fast: single atomic operation",
|
|
219
|
+
evidence: 42,
|
|
220
|
+
metadata: { historicalSuccessRate: 0.99, corpusEvidenceCount: 42 },
|
|
221
|
+
};
|
|
222
|
+
const safeFeatures = {
|
|
223
|
+
protocolSafety: 1.0,
|
|
224
|
+
historicalSuccessRate: 0.5,
|
|
225
|
+
actionCount: 3,
|
|
226
|
+
latencyCost: 0.6,
|
|
227
|
+
auditability: 0.8,
|
|
228
|
+
corpusEvidence: 0,
|
|
229
|
+
source: "protocol",
|
|
230
|
+
goalMatch: 0,
|
|
231
|
+
};
|
|
232
|
+
const fastFeatures = {
|
|
233
|
+
protocolSafety: 0.7,
|
|
234
|
+
historicalSuccessRate: 0.99,
|
|
235
|
+
actionCount: 1,
|
|
236
|
+
latencyCost: 0.1,
|
|
237
|
+
auditability: 0.5,
|
|
238
|
+
corpusEvidence: 42,
|
|
239
|
+
source: "corpus",
|
|
240
|
+
goalMatch: 0,
|
|
241
|
+
};
|
|
242
|
+
(0, vitest_1.it)("ranks safe higher under safety objective", () => {
|
|
243
|
+
const ranker = (0, repair_ranker_1.createLinearRanker)();
|
|
244
|
+
const ranked = ranker.rankSafety([fastCandidate, safeCandidate], [fastFeatures, safeFeatures]);
|
|
245
|
+
(0, vitest_1.expect)(ranked[0].id).toBe("safe");
|
|
246
|
+
});
|
|
247
|
+
(0, vitest_1.it)("ranks fast higher under performance objective", () => {
|
|
248
|
+
const ranker = (0, repair_ranker_1.createLinearRanker)();
|
|
249
|
+
const ranked = ranker.rankPerformance([safeCandidate, fastCandidate], [safeFeatures, fastFeatures]);
|
|
250
|
+
(0, vitest_1.expect)(ranked[0].id).toBe("fast");
|
|
251
|
+
});
|
|
252
|
+
(0, vitest_1.it)("different objectives produce different orderings", () => {
|
|
253
|
+
const ranker = (0, repair_ranker_1.createLinearRanker)();
|
|
254
|
+
const bySafety = ranker.rankSafety([safeCandidate, fastCandidate], [safeFeatures, fastFeatures]);
|
|
255
|
+
const byPerf = ranker.rankPerformance([safeCandidate, fastCandidate], [safeFeatures, fastFeatures]);
|
|
256
|
+
// Same candidates, different orderings
|
|
257
|
+
(0, vitest_1.expect)(bySafety[0].id).not.toBe(byPerf[0].id);
|
|
258
|
+
});
|
|
259
|
+
(0, vitest_1.it)("future RewardModelRanker would use same interface", () => {
|
|
260
|
+
// The Ranker interface is { score(features: CandidateFeatures): number }
|
|
261
|
+
// Any implementation works — linear weights, learned model, etc.
|
|
262
|
+
const ranker = (0, repair_ranker_1.createLinearRanker)();
|
|
263
|
+
const score = ranker.score(safeFeatures);
|
|
264
|
+
(0, vitest_1.expect)(score).toBeGreaterThanOrEqual(0);
|
|
265
|
+
(0, vitest_1.expect)(score).toBeLessThanOrEqual(1);
|
|
266
|
+
});
|
|
267
|
+
});
|
|
268
|
+
// ════════════════════════════════════════════════════════
|
|
269
|
+
// Test 4: P4 pre-burial — feedback + cost persistence
|
|
270
|
+
// ════════════════════════════════════════════════════════
|
|
271
|
+
// Set env BEFORE importing from failure-corpus
|
|
272
|
+
const FEEDBACK_DIR = path.resolve(__dirname, "..", "test-evolution-feedback");
|
|
273
|
+
process.env.PROGMUNE_PROJECT_DIR = FEEDBACK_DIR;
|
|
274
|
+
fs.mkdirSync(FEEDBACK_DIR, { recursive: true });
|
|
275
|
+
fs.mkdirSync(path.join(FEEDBACK_DIR, ".progmune_corpus"), { recursive: true });
|
|
276
|
+
fs.mkdirSync(path.join(FEEDBACK_DIR, ".progmune_corpus", "trajectories"), { recursive: true });
|
|
277
|
+
const failure_corpus_1 = require("./failure-corpus");
|
|
278
|
+
// ── Wait helper (recordTrajectory writes via setImmediate) ──
|
|
279
|
+
function flushWrites() {
|
|
280
|
+
return new Promise(resolve => setImmediate(resolve));
|
|
281
|
+
}
|
|
282
|
+
(0, vitest_1.describe)("Test 4: P4 pre-burial", () => {
|
|
283
|
+
(0, vitest_1.it)("feedback {accepted, rejected} survives write→read roundtrip", async () => {
|
|
284
|
+
const uniqueSig = `test-evo-accepted-${Date.now()}`;
|
|
285
|
+
(0, failure_corpus_1.recordTrajectory)({
|
|
286
|
+
protocol: "FileProtocol",
|
|
287
|
+
initialState: ["FILE_OPEN"],
|
|
288
|
+
finalState: [],
|
|
289
|
+
trajectory: ["open_file", "write_file", "close_file"],
|
|
290
|
+
result: "repair",
|
|
291
|
+
violationType: "resource_leak",
|
|
292
|
+
violationDesc: uniqueSig,
|
|
293
|
+
fixPath: ["close_file"],
|
|
294
|
+
successRate: 1.0,
|
|
295
|
+
source: "planner",
|
|
296
|
+
feedback: { accepted: true, rejected: false },
|
|
297
|
+
cost: { latency: 12, actions: 3 },
|
|
298
|
+
});
|
|
299
|
+
await flushWrites();
|
|
300
|
+
const loaded = (0, failure_corpus_1.loadTrajectories)();
|
|
301
|
+
const repair = loaded.find(t => t.result === "repair" && t.violation?.description === uniqueSig);
|
|
302
|
+
(0, vitest_1.expect)(repair).toBeDefined();
|
|
303
|
+
(0, vitest_1.expect)(repair.feedback?.accepted).toBe(true);
|
|
304
|
+
(0, vitest_1.expect)(repair.feedback?.rejected).toBe(false);
|
|
305
|
+
(0, vitest_1.expect)(repair.cost?.latency).toBe(12);
|
|
306
|
+
(0, vitest_1.expect)(repair.cost?.actions).toBe(3);
|
|
307
|
+
});
|
|
308
|
+
(0, vitest_1.it)("rejected repair is also recorded", async () => {
|
|
309
|
+
const uniqueSig = `test-evo-rejected-${Date.now()}`;
|
|
310
|
+
(0, failure_corpus_1.recordTrajectory)({
|
|
311
|
+
protocol: "FileProtocol",
|
|
312
|
+
initialState: ["FILE_OPEN"],
|
|
313
|
+
finalState: ["FILE_OPEN"],
|
|
314
|
+
trajectory: ["open_file", "write_file"],
|
|
315
|
+
result: "repair",
|
|
316
|
+
violationType: "resource_leak",
|
|
317
|
+
violationDesc: uniqueSig,
|
|
318
|
+
fixPath: ["close_file"],
|
|
319
|
+
successRate: 0.0,
|
|
320
|
+
source: "llm",
|
|
321
|
+
feedback: { accepted: false, rejected: true },
|
|
322
|
+
cost: { latency: 7, actions: 2 },
|
|
323
|
+
});
|
|
324
|
+
await flushWrites();
|
|
325
|
+
const loaded = (0, failure_corpus_1.loadTrajectories)();
|
|
326
|
+
const rejected = loaded.filter(t => t.result === "repair" && t.feedback?.rejected === true && t.violation?.description === uniqueSig);
|
|
327
|
+
(0, vitest_1.expect)(rejected.length).toBe(1);
|
|
328
|
+
(0, vitest_1.expect)(rejected[0].cost?.latency).toBe(7);
|
|
329
|
+
});
|
|
330
|
+
(0, vitest_1.it)("getRepairStats aggregates feedback for P4 Reward Model", async () => {
|
|
331
|
+
(0, failure_corpus_1.recordTrajectory)({
|
|
332
|
+
protocol: "AuthProtocol",
|
|
333
|
+
initialState: ["UNAUTHENTICATED"],
|
|
334
|
+
finalState: ["SESSION_ACTIVE"],
|
|
335
|
+
trajectory: ["verify_password", "generate_jwt", "create_session"],
|
|
336
|
+
result: "repair",
|
|
337
|
+
violationType: "missing_prerequisite",
|
|
338
|
+
violationDesc: "Skipped verification",
|
|
339
|
+
fixPath: ["verify_password"],
|
|
340
|
+
successRate: 1.0,
|
|
341
|
+
source: "planner",
|
|
342
|
+
feedback: { accepted: true, rejected: false },
|
|
343
|
+
cost: { latency: 25, actions: 3 },
|
|
344
|
+
});
|
|
345
|
+
await flushWrites();
|
|
346
|
+
const stats = (0, failure_corpus_1.getRepairStats)();
|
|
347
|
+
(0, vitest_1.expect)(stats.totalRepairs).toBeGreaterThanOrEqual(3);
|
|
348
|
+
(0, vitest_1.expect)(stats.acceptedRepairs).toBeGreaterThanOrEqual(2);
|
|
349
|
+
(0, vitest_1.expect)(stats.rejectedRepairs).toBeGreaterThanOrEqual(1);
|
|
350
|
+
(0, vitest_1.expect)(stats.acceptanceRate).toBeGreaterThan(0);
|
|
351
|
+
(0, vitest_1.expect)(stats.acceptanceRate).toBeLessThanOrEqual(1);
|
|
352
|
+
(0, vitest_1.expect)(stats.avgLatency).toBeGreaterThan(0);
|
|
353
|
+
});
|
|
354
|
+
});
|
|
355
|
+
// ════════════════════════════════════════════════════════
|
|
356
|
+
// Test 5: Goal → Repair → Feedback → Corpus closed loop
|
|
357
|
+
// ════════════════════════════════════════════════════════
|
|
358
|
+
// Separate corpus dir for the flywheel test
|
|
359
|
+
const FLYWHEEL_DIR = path.resolve(__dirname, "..", "test-evolution-flywheel");
|
|
360
|
+
fs.mkdirSync(FLYWHEEL_DIR, { recursive: true });
|
|
361
|
+
const flywheelCorpus = path.join(FLYWHEEL_DIR, ".progmune_corpus");
|
|
362
|
+
fs.mkdirSync(flywheelCorpus, { recursive: true });
|
|
363
|
+
fs.mkdirSync(path.join(flywheelCorpus, "trajectories"), { recursive: true });
|
|
364
|
+
(0, vitest_1.describe)("Test 5: Goal → Repair → Feedback → Corpus flywheel", () => {
|
|
365
|
+
(0, vitest_1.it)("accepted repair feeds back into corpus as future evidence", async () => {
|
|
366
|
+
// Point to flywheel corpus for this test
|
|
367
|
+
process.env.PROGMUNE_PROJECT_DIR = FLYWHEEL_DIR;
|
|
368
|
+
const flywheelId = `flywheel-accepted-${Date.now()}`;
|
|
369
|
+
// Step 1: Generate a repair plan via the Planner
|
|
370
|
+
const rules = fileProtocolRules();
|
|
371
|
+
const alts = await (0, counterfactual_engine_1.suggestAlternatives)({
|
|
372
|
+
violation: {
|
|
373
|
+
svl: 4,
|
|
374
|
+
violatedConstraint: "resource_leak",
|
|
375
|
+
actionIndex: 2,
|
|
376
|
+
currentStates: ["FILE_OPEN"],
|
|
377
|
+
requiredStates: [],
|
|
378
|
+
description: "File not closed after write",
|
|
379
|
+
},
|
|
380
|
+
protocol: "_global",
|
|
381
|
+
currentState: ["FILE_OPEN"],
|
|
382
|
+
targetState: [],
|
|
383
|
+
constraints: [],
|
|
384
|
+
rules,
|
|
385
|
+
});
|
|
386
|
+
(0, vitest_1.expect)(alts.length).toBeGreaterThan(0);
|
|
387
|
+
const topRepair = alts[0];
|
|
388
|
+
// Step 2: Simulate user accepting the repair
|
|
389
|
+
(0, failure_corpus_1.recordTrajectory)({
|
|
390
|
+
protocol: "FileProtocol",
|
|
391
|
+
initialState: ["FILE_OPEN"],
|
|
392
|
+
finalState: [],
|
|
393
|
+
trajectory: ["open_file", "write_file", ...topRepair.fixPath],
|
|
394
|
+
result: "repair",
|
|
395
|
+
violationType: "resource_leak",
|
|
396
|
+
violationDesc: flywheelId,
|
|
397
|
+
fixPath: topRepair.fixPath,
|
|
398
|
+
successRate: 1.0,
|
|
399
|
+
source: "planner",
|
|
400
|
+
intent: "safely write config file",
|
|
401
|
+
feedback: { accepted: true, rejected: false },
|
|
402
|
+
cost: { latency: 15, actions: topRepair.fixPath.length + 2 },
|
|
403
|
+
});
|
|
404
|
+
await flushWrites();
|
|
405
|
+
// Step 3: Verify corpus has the accepted repair
|
|
406
|
+
const loaded = (0, failure_corpus_1.loadTrajectories)();
|
|
407
|
+
const repairs = loaded.filter(t => t.result === "repair" && t.violation?.description === flywheelId);
|
|
408
|
+
(0, vitest_1.expect)(repairs.length).toBe(1);
|
|
409
|
+
(0, vitest_1.expect)(repairs[0].feedback?.accepted).toBe(true);
|
|
410
|
+
(0, vitest_1.expect)(repairs[0].metadata.intent).toBe("safely write config file");
|
|
411
|
+
(0, vitest_1.expect)(repairs[0].violation?.fixPath?.length).toBeGreaterThan(0);
|
|
412
|
+
// Step 4: The flywheel is spinning
|
|
413
|
+
// Goal → Planner → Repair → Accepted → Corpus → (future) Planner
|
|
414
|
+
const stats = {
|
|
415
|
+
accepted: repairs.length,
|
|
416
|
+
hasIntent: repairs.filter(r => r.metadata.intent).length,
|
|
417
|
+
hasFixPath: repairs.filter(r => r.violation?.fixPath?.length).length,
|
|
418
|
+
};
|
|
419
|
+
(0, vitest_1.expect)(stats.accepted).toBeGreaterThanOrEqual(1);
|
|
420
|
+
(0, vitest_1.expect)(stats.hasIntent).toBeGreaterThanOrEqual(1);
|
|
421
|
+
(0, vitest_1.expect)(stats.hasFixPath).toBeGreaterThanOrEqual(1);
|
|
422
|
+
});
|
|
423
|
+
(0, vitest_1.it)("rejected repair also feeds the flywheel (negative signal)", async () => {
|
|
424
|
+
process.env.PROGMUNE_PROJECT_DIR = FLYWHEEL_DIR;
|
|
425
|
+
const flywheelId = `flywheel-rejected-${Date.now()}`;
|
|
426
|
+
(0, failure_corpus_1.recordTrajectory)({
|
|
427
|
+
protocol: "FileProtocol",
|
|
428
|
+
initialState: ["FILE_OPEN"],
|
|
429
|
+
finalState: ["FILE_OPEN"], // still open — repair failed
|
|
430
|
+
trajectory: ["open_file", "write_file"],
|
|
431
|
+
result: "repair",
|
|
432
|
+
violationType: "resource_leak",
|
|
433
|
+
violationDesc: flywheelId,
|
|
434
|
+
fixPath: [],
|
|
435
|
+
successRate: 0.0,
|
|
436
|
+
source: "llm",
|
|
437
|
+
intent: "safely write config file",
|
|
438
|
+
feedback: { accepted: false, rejected: true },
|
|
439
|
+
cost: { latency: 8, actions: 2 },
|
|
440
|
+
});
|
|
441
|
+
await flushWrites();
|
|
442
|
+
const loaded = (0, failure_corpus_1.loadTrajectories)();
|
|
443
|
+
const myRecord = loaded.filter(t => t.violation?.description === flywheelId);
|
|
444
|
+
(0, vitest_1.expect)(myRecord.length).toBe(1);
|
|
445
|
+
(0, vitest_1.expect)(myRecord[0].feedback?.accepted).toBe(false);
|
|
446
|
+
(0, vitest_1.expect)(myRecord[0].feedback?.rejected).toBe(true);
|
|
447
|
+
// Both signals present — P4 Reward Model can learn from both
|
|
448
|
+
const allRepairs = loaded.filter(t => t.result === "repair");
|
|
449
|
+
const accepted = allRepairs.filter(t => t.feedback?.accepted === true).length;
|
|
450
|
+
const rejected = allRepairs.filter(t => t.feedback?.rejected === true).length;
|
|
451
|
+
(0, vitest_1.expect)(accepted).toBeGreaterThanOrEqual(1);
|
|
452
|
+
(0, vitest_1.expect)(rejected).toBeGreaterThanOrEqual(1);
|
|
453
|
+
});
|
|
454
|
+
});
|