progmune-runtime 2.1.6 → 3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +108 -468
- package/dist/ablation-study.js +144 -0
- package/dist/ablation-study.test.js +18 -0
- package/dist/action-runtime.js +3 -1
- package/dist/active-learning.js +211 -0
- package/dist/analytics.js +139 -0
- package/dist/asset-factory.js +309 -0
- package/dist/asset-growth.js +244 -0
- package/dist/asset-promotion.js +382 -0
- package/dist/asset-quality.js +550 -0
- package/dist/audit/business-translator.js +285 -0
- package/dist/audit/cli.js +66 -0
- package/dist/audit/formatters/html.js +379 -0
- package/dist/audit/formatters/json.js +11 -0
- package/dist/audit/formatters/markdown.js +192 -0
- package/dist/audit/formatters/terminal.js +189 -0
- package/dist/audit/index.js +25 -0
- package/dist/audit/report-builder.js +318 -0
- package/dist/audit/types.js +8 -0
- package/dist/audit.js +3 -3
- package/dist/auto-benchmark-generator.js +137 -0
- package/dist/auto-benchmark-generator.test.js +45 -0
- package/dist/auto-protocol-synthesizer.js +362 -0
- package/dist/auto-protocol-synthesizer.test.js +82 -0
- package/dist/autonomous-patch.js +175 -0
- package/dist/autonomous-patch.test.js +128 -0
- package/dist/badge/badge-server.js +98 -0
- package/dist/behavior-miner.js +442 -0
- package/dist/belief-layer.js +475 -0
- package/dist/benchmark-count.js +5 -0
- package/dist/benchmark-generator.js +211 -0
- package/dist/benchmark-harness.js +201 -0
- package/dist/benchmark-pass-rate.js +7 -0
- package/dist/benchmark-report.js +8 -3
- package/dist/benchmark-save.js +14 -1
- package/dist/bootstrap-validation.js +197 -0
- package/dist/bootstrap-validation.test.js +51 -0
- package/dist/branch-ledger.js +1 -1
- package/dist/capability-gap.js +130 -0
- package/dist/certify-html.js +351 -0
- package/dist/certify.js +326 -0
- package/dist/check.js +4 -4
- package/dist/compliance-miner.js +447 -0
- package/dist/continuous-benchmark.js +194 -0
- package/dist/continuous-benchmark.test.js +116 -0
- package/dist/corpus-stats.js +173 -0
- package/dist/counterfactual-engine.js +288 -0
- package/dist/coverage-dashboard.js +109 -0
- package/dist/coverage-system.test.js +205 -0
- package/dist/cross-repo-precision.js +352 -0
- package/dist/cve-benchmark.js +180 -0
- package/dist/cve-benchmark.test.js +28 -0
- package/dist/cve-collector.js +73 -0
- package/dist/data-quality.js +141 -0
- package/dist/decision-engine.js +388 -0
- package/dist/derive-metadata.js +250 -0
- package/dist/difficulty-active.test.js +198 -0
- package/dist/difficulty-map.js +244 -0
- package/dist/discovery-analytics.js +125 -0
- package/dist/discovery-model.js +149 -0
- package/dist/discovery-optimize.test.js +199 -0
- package/dist/discovery-trace.js +276 -0
- package/dist/discovery-trace.test.js +97 -0
- package/dist/emitter.js +83 -1
- package/dist/enterprise-dashboard.js +405 -0
- package/dist/eval-hardening.js +297 -0
- package/dist/eval-hardening.test.js +85 -0
- package/dist/evaluation-campaign.js +359 -0
- package/dist/evaluation-campaign.test.js +181 -0
- package/dist/evidence-growth.js +143 -0
- package/dist/evidence-repository.js +209 -0
- package/dist/evidence-system.js +441 -0
- package/dist/execute.js +15 -7
- package/dist/experimental/software-physics.js +291 -0
- package/dist/experimental/state-inference.js +516 -0
- package/dist/experimental/unsupervised-physics.js +230 -0
- package/dist/extract-ir-python.js +54 -7
- package/dist/extract-ir.js +376 -12
- package/dist/failure-collector.js +2 -2
- package/dist/failure-corpus.js +322 -9
- package/dist/feedback.js +16 -5
- package/dist/feedback.test.js +49 -0
- package/dist/file-lock.js +1 -1
- package/dist/flywheel-batch.js +292 -0
- package/dist/frameworks/express-cli.js +237 -0
- package/dist/frameworks/express-detector.js +445 -0
- package/dist/frameworks/express-detector.test.js +206 -0
- package/dist/frameworks/index.js +30 -0
- package/dist/frameworks/nestjs-detector.js +302 -0
- package/dist/frameworks/trpc-detector.js +161 -0
- package/dist/frameworks/version-awareness.js +179 -0
- package/dist/function-synonyms.js +164 -0
- package/dist/function-synonyms.test.js +68 -0
- package/dist/generalization.test.js +352 -0
- package/dist/goal-annotator.js +113 -0
- package/dist/goal-planner.js +563 -0
- package/dist/gold-cve.js +164 -0
- package/dist/gold-cve.test.js +104 -0
- package/dist/gold-quality.js +206 -0
- package/dist/gold-tiers.js +241 -0
- package/dist/governance-dashboard.js +327 -0
- package/dist/graph-viz.js +240 -0
- package/dist/guided-frontier.js +195 -0
- package/dist/hierarchical-planner.js +148 -0
- package/dist/identifier-parser.js +260 -0
- package/dist/immune-metrics.js +93 -0
- package/dist/immune-receiver.js +158 -0
- package/dist/immune-reporter.js +1 -1
- package/dist/improvement-orchestrator.js +206 -0
- package/dist/inject-p0-vocabulary.js +300 -0
- package/dist/intent-parser.js +218 -0
- package/dist/invariant-algebra.js +476 -0
- package/dist/invariant-calculus.js +533 -0
- package/dist/ir-utils.js +70 -0
- package/dist/ir-utils.test.js +50 -0
- package/dist/knowledge-api.js +312 -0
- package/dist/knowledge-evolution.js +452 -0
- package/dist/knowledge-explorer.js +506 -0
- package/dist/knowledge-flywheel.js +274 -0
- package/dist/knowledge-governance.js +338 -0
- package/dist/knowledge-governance.test.js +150 -0
- package/dist/knowledge-graph.js +181 -0
- package/dist/knowledge-guided-synth.js +246 -0
- package/dist/knowledge-loop.test.js +77 -0
- package/dist/knowledge-object.js +316 -0
- package/dist/knowledge-package.js +98 -0
- package/dist/kpi-dashboard.js +561 -0
- package/dist/l3-cross-function.js +280 -0
- package/dist/learning-ranker.js +148 -0
- package/dist/learning-ranker.test.js +291 -0
- package/dist/ledger/accountability.js +322 -0
- package/dist/ledger/chain-builder.js +185 -0
- package/dist/ledger/cli.js +222 -0
- package/dist/ledger/index.js +13 -0
- package/dist/ledger/signatures.js +193 -0
- package/dist/ledger/types.js +9 -0
- package/dist/llm.js +74 -3
- package/dist/load-benchmarks.js +8 -3
- package/dist/logger.js +66 -0
- package/dist/logger.test.js +37 -0
- package/dist/logistic-reward.js +339 -0
- package/dist/logistic-reward.test.js +180 -0
- package/dist/macro-graph.js +193 -0
- package/dist/macro-repair.js +183 -0
- package/dist/mcp-server.mjs +1202 -483
- package/dist/memory-layer.js +42 -5
- package/dist/multi-repo-precision.js +422 -0
- package/dist/name-free-protocol.js +425 -0
- package/dist/name-free-protocol.test.js +170 -0
- package/dist/name-scrambling.js +138 -0
- package/dist/name-scrambling.test.js +16 -0
- package/dist/p3-observability.test.js +281 -0
- package/dist/p5-orchestrator.test.js +225 -0
- package/dist/pairwise-preference.js +294 -0
- package/dist/pairwise-preference.test.js +140 -0
- package/dist/planner-constraints.js +104 -0
- package/dist/planner-prompts.js +155 -0
- package/dist/planner-telemetry.js +415 -0
- package/dist/planner-trace.js +214 -0
- package/dist/planner.js +162 -167
- package/dist/plsb/artifact.js +116 -0
- package/dist/plsb/cli.js +71 -0
- package/dist/plsb/index.js +19 -0
- package/dist/plsb/leaderboard.js +249 -0
- package/dist/plsb/report-md.js +156 -0
- package/dist/plsb/schema.js +179 -0
- package/dist/plsb-benchmark.js +284 -0
- package/dist/plsb-benchmark.test.js +119 -0
- package/dist/policy/cli.js +134 -0
- package/dist/policy/engine.js +333 -0
- package/dist/policy/index.js +12 -0
- package/dist/policy/types.js +59 -0
- package/dist/policy-miner.js +505 -0
- package/dist/precision-analyze.js +229 -0
- package/dist/precision-benchmark.js +147 -0
- package/dist/precision-label-c.js +134 -0
- package/dist/precision-label.js +193 -0
- package/dist/precision-report-c.js +149 -0
- package/dist/precision-report.js +246 -0
- package/dist/progmune-status.js +108 -0
- package/dist/proof-engine.js +479 -0
- package/dist/proof-provenance.js +315 -0
- package/dist/protocol-coverage.js +294 -0
- package/dist/protocol-detector.js +1189 -0
- package/dist/protocol-embedding-expanded.js +297 -0
- package/dist/protocol-embedding-expanded.test.js +97 -0
- package/dist/protocol-embedding.js +195 -0
- package/dist/protocol-embedding.test.js +82 -0
- package/dist/protocol-extractor-v2.js +354 -0
- package/dist/protocol-extractor-v2.test.js +140 -0
- package/dist/protocol-extractor.js +310 -0
- package/dist/protocol-extractor.test.js +113 -0
- package/dist/protocol-foundation.js +322 -0
- package/dist/protocol-foundation.test.js +163 -0
- package/dist/protocol-frontier.js +243 -0
- package/dist/protocol-frontier.test.js +92 -0
- package/dist/protocol-gap-analyzer.js +228 -0
- package/dist/protocol-gap-analyzer.test.js +49 -0
- package/dist/protocol-invariants.js +276 -0
- package/dist/protocol-invariants.test.js +111 -0
- package/dist/protocol-knowledge.js +464 -0
- package/dist/protocol-miner.js +343 -0
- package/dist/protocol-mining.js +207 -0
- package/dist/protocol-mining.test.js +37 -0
- package/dist/protocol-registry.js +1 -1
- package/dist/protocol-security-benchmark.js +222 -0
- package/dist/protocol-vulnerability.js +257 -0
- package/dist/protocol-vulnerability.test.js +60 -0
- package/dist/python-benchmark.js +120 -0
- package/dist/python-emitter.js +163 -45
- package/dist/python-protocol-extractor.js +187 -0
- package/dist/python-protocol-extractor.test.js +116 -0
- package/dist/realworld-benchmark.js +646 -0
- package/dist/realworld-benchmark.test.js +36 -0
- package/dist/repair-arch.test.js +411 -0
- package/dist/repair-evolution.test.js +454 -0
- package/dist/repair-executor.js +719 -0
- package/dist/repair-proposal.js +4 -4
- package/dist/repair-ranker.js +141 -0
- package/dist/repair-strategies.js +419 -0
- package/dist/repair-taxonomy.js +234 -0
- package/dist/repair-types.js +12 -0
- package/dist/repo-evaluator.js +250 -0
- package/dist/repo-evaluator.test.js +128 -0
- package/dist/resource-abstraction.js +242 -0
- package/dist/resource-detector.js +211 -0
- package/dist/result.test.js +43 -0
- package/dist/reward-system.js +411 -0
- package/dist/reward-system.test.js +175 -0
- package/dist/risk-model.js +215 -0
- package/dist/rule-miner.js +234 -7
- package/dist/rule-specificity.js +254 -0
- package/dist/runtime-types.js +27 -0
- package/dist/scaffold.js +208 -0
- package/dist/scale-collector.test.js +101 -0
- package/dist/scale-trajectory-collector.js +128 -0
- package/dist/sdk.js +250 -0
- package/dist/search-planner.js +4 -41
- package/dist/semantic-snapshot.js +1 -1
- package/dist/semantic-topology.js +121 -0
- package/dist/semantic-trace.js +310 -317
- package/dist/sequence-extractor.js +343 -0
- package/dist/skill-library.js +245 -0
- package/dist/skill-planner.test.js +189 -0
- package/dist/software-physics.js +291 -0
- package/dist/software-physics.test.js +81 -0
- package/dist/ssg-precision.js +478 -0
- package/dist/ssg-validator.js +71 -21
- package/dist/state-inference-doubleblind.test.js +160 -0
- package/dist/state-inference.js +516 -0
- package/dist/state-inference.test.js +115 -0
- package/dist/state-machine-fingerprint.js +345 -0
- package/dist/state-machine-fingerprint.test.js +120 -0
- package/dist/state-miner.js +386 -0
- package/dist/state-name-inference.js +213 -0
- package/dist/state-name-inference.test.js +69 -0
- package/dist/strategy-planner.js +262 -96
- package/dist/strategy-planner.test.js +135 -0
- package/dist/telemetry-analytics.test.js +402 -0
- package/dist/terminal-format.js +68 -0
- package/dist/terminal-format.test.js +83 -0
- package/dist/topology-factory.js +196 -0
- package/dist/topology-representation.js +242 -0
- package/dist/topology-representation.test.js +27 -0
- package/dist/trajectory-augmentation.js +254 -0
- package/dist/trajectory-augmentation.test.js +63 -0
- package/dist/trajectory-corpus.js +440 -0
- package/dist/trajectory-corpus.test.js +32 -0
- package/dist/trajectory-feedback.test.js +116 -0
- package/dist/transition-synthesizer.js +286 -0
- package/dist/transition-synthesizer.test.js +123 -0
- package/dist/trust/api-semantic-mapper.js +809 -0
- package/dist/trust/call-graph-propagator.js +225 -0
- package/dist/trust/cli.js +122 -0
- package/dist/trust/compliance-scorer.js +283 -0
- package/dist/trust/confidence-calculator.js +261 -0
- package/dist/trust/engine.js +1145 -0
- package/dist/trust/explainability.js +85 -0
- package/dist/trust/formatters/ci.js +42 -0
- package/dist/trust/formatters/json.js +11 -0
- package/dist/trust/formatters/terminal.js +152 -0
- package/dist/trust/index.js +39 -0
- package/dist/trust/phase1-verify.js +171 -0
- package/dist/trust/protocol-domain-validator.js +697 -0
- package/dist/trust/score-calculator.js +282 -0
- package/dist/trust/ssg-bridge.js +641 -0
- package/dist/trust/ssg-bridge.test.js +269 -0
- package/dist/trust/types.js +67 -0
- package/dist/trust/violation-trace.js +335 -0
- package/dist/trust-api.js +179 -0
- package/dist/trust-calibration.js +279 -0
- package/dist/unknown-protocol-discovery.js +339 -0
- package/dist/unknown-protocol-discovery.test.js +102 -0
- package/dist/unsupervised-physics.js +230 -0
- package/dist/unsupervised-physics.test.js +95 -0
- package/dist/utils.test.js +37 -0
- package/dist/validator.js +187 -10
- package/dist/verification-intelligence.js +475 -0
- package/dist/verify-api.js +432 -0
- package/dist/vi-impact-report.js +293 -0
- package/dist/wl-fingerprint.js +162 -0
- package/dist/wl-fingerprint.test.js +130 -0
- package/dist/zeroshot-strategy.js +139 -0
- package/docs/Progmune_/346/212/225/350/265/204/344/272/272/347/231/275/347/232/256/344/271/246_v2.0.html +576 -0
- package/docs/Progmune_/351/241/271/347/233/256/345/205/250/350/247/243.html +710 -0
- package/package.json +74 -7
- package/protocols.json +1956 -50
- package/.dockerignore +0 -14
- package/.mcp.json +0 -11
- package/.progmune_allowlist +0 -50
- package/.test_report/test_report.md +0 -87
- package/Dockerfile +0 -9
- package/FAQ.md +0 -167
- package/WHITEPAPER.md +0 -540
- package/demo-project/auth.ts +0 -55
- package/demo-project/tsconfig.json +0 -8
- package/dist/acl-breakdown.js +0 -13
- package/dist/all-sessions.js +0 -11
- package/dist/antibody-stats.js +0 -11
- package/dist/branch-tree-count.js +0 -14
- package/dist/common-fixpath.js +0 -12
- package/dist/constraint-types.js +0 -12
- package/dist/exec-metrics.js +0 -11
- package/dist/failure-report.js +0 -11
- package/dist/fast-path-hits.js +0 -13
- package/dist/fingerprint-list.js +0 -15
- package/dist/gen-history-log.js +0 -13
- package/dist/heatmap-data.js +0 -11
- package/dist/recent-session.js +0 -12
- package/dist/svl-distribution.js +0 -11
- package/dist/terminal-status.js +0 -11
- package/dist/token-savings.js +0 -11
- package/dist/total-repairs.js +0 -12
- package/dist/unresolved-count.js +0 -12
- package/dist/valid-fingerprints.js +0 -13
- package/dist/verify-ledgers.js +0 -11
- package/docs/whitepaper-style.css +0 -77
- package/docs/whitepaper-v2.1.md +0 -609
- package/docs/whitepaper-v2.2.md +0 -1064
- package/docs/whitepaper-v2.2.pdf +0 -0
- package/fly.toml +0 -31
- package/public/dashboard.html +0 -119
- package/server/hub.js +0 -116
- package/test/replay-golden/sess_1780063202050_mgeld.json +0 -9
- package/test/replay-golden/sess_1780064032560_gocld.json +0 -354
- package/test/replay-golden/sess_1780064413331_s2709.json +0 -606
- package/test/replay-golden/sess_1780064792710_y3avo.json +0 -614
- package/test/replay-golden.ts +0 -84
- package/test_benchmark.js +0 -165
- package/test_comprehensive.mjs +0 -638
- package/test_concurrency.js +0 -129
- package/test_ir_robustness.js +0 -85
- package/test_semantic_contracts.js +0 -269
- package/test_ssg_stress.js +0 -156
- package/test_svl3.js +0 -58
- package/tsconfig.json +0 -17
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* P3.21-23: Knowledge Governance Tests
|
|
4
|
+
*/
|
|
5
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
8
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
9
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
10
|
+
}
|
|
11
|
+
Object.defineProperty(o, k2, desc);
|
|
12
|
+
}) : (function(o, m, k, k2) {
|
|
13
|
+
if (k2 === undefined) k2 = k;
|
|
14
|
+
o[k2] = m[k];
|
|
15
|
+
}));
|
|
16
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
17
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
18
|
+
}) : function(o, v) {
|
|
19
|
+
o["default"] = v;
|
|
20
|
+
});
|
|
21
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
22
|
+
var ownKeys = function(o) {
|
|
23
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
24
|
+
var ar = [];
|
|
25
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
26
|
+
return ar;
|
|
27
|
+
};
|
|
28
|
+
return ownKeys(o);
|
|
29
|
+
};
|
|
30
|
+
return function (mod) {
|
|
31
|
+
if (mod && mod.__esModule) return mod;
|
|
32
|
+
var result = {};
|
|
33
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
34
|
+
__setModuleDefault(result, mod);
|
|
35
|
+
return result;
|
|
36
|
+
};
|
|
37
|
+
})();
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
const vitest_1 = require("vitest");
|
|
40
|
+
const fs = __importStar(require("fs"));
|
|
41
|
+
const path = __importStar(require("path"));
|
|
42
|
+
const knowledge_governance_1 = require("./knowledge-governance");
|
|
43
|
+
const GOV_DIR = path.resolve(__dirname, "..", "test-knowledge-gov");
|
|
44
|
+
process.env.PROGMUNE_PROJECT_DIR = GOV_DIR;
|
|
45
|
+
fs.mkdirSync(GOV_DIR, { recursive: true });
|
|
46
|
+
fs.mkdirSync(path.join(GOV_DIR, ".progmune_corpus", "knowledge"), { recursive: true });
|
|
47
|
+
function makeBaseRules() {
|
|
48
|
+
return new Map([
|
|
49
|
+
["open_file", { pre_states: [], post_states: ["FILE_OPEN"] }],
|
|
50
|
+
["write_file", { pre_states: ["FILE_OPEN"], post_states: ["FILE_DIRTY"] }],
|
|
51
|
+
["close_file", { pre_states: ["FILE_OPEN", "FILE_DIRTY"], post_states: [], invalidate: ["FILE_OPEN", "FILE_DIRTY"] }],
|
|
52
|
+
]);
|
|
53
|
+
}
|
|
54
|
+
(0, vitest_1.describe)("Inference Validator", () => {
|
|
55
|
+
(0, vitest_1.it)("classifies inferences as proposed/verified/rejected", () => {
|
|
56
|
+
const inferences = [
|
|
57
|
+
{ from: "FILE_OPEN", to: "FILE_DIRTY", action: "open_file → flush_file", protocol: "FileProtocol", confidence: 1.0, evidenceCount: 1, examples: ["test"] },
|
|
58
|
+
{ from: "FILE_OPEN", to: "FILE_DIRTY", action: "open_file → flush_file", protocol: "FileProtocol", confidence: 1.0, evidenceCount: 3, examples: ["a", "b", "c"] },
|
|
59
|
+
];
|
|
60
|
+
const validated = (0, knowledge_governance_1.validateInferences)(inferences, 5); // 5 trajectory support
|
|
61
|
+
// First: only 1 benchmark → proposed
|
|
62
|
+
(0, vitest_1.expect)(validated[0].validation.status).toBe("proposed");
|
|
63
|
+
(0, vitest_1.expect)(validated[0].validation.benchmarkSupport).toBe(1);
|
|
64
|
+
(0, vitest_1.expect)(validated[0].validation.trajectorySupport).toBe(5);
|
|
65
|
+
// Second: 3 benchmarks + 5 trajectories → verified
|
|
66
|
+
(0, vitest_1.expect)(validated[1].validation.status).toBe("verified");
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
(0, vitest_1.describe)("Knowledge Patch Store", () => {
|
|
70
|
+
(0, vitest_1.it)("proposes, approves, rejects, and rolls back patches", () => {
|
|
71
|
+
const store = new knowledge_governance_1.KnowledgePatchStore(path.join(GOV_DIR, ".progmune_corpus", "knowledge", `test-${Date.now()}.json`));
|
|
72
|
+
const inference = {
|
|
73
|
+
from: "FILE_OPEN", to: "FILE_DIRTY", action: "open_file → flush_file",
|
|
74
|
+
protocol: "FileProtocol", confidence: 1.0, evidenceCount: 3, examples: ["a", "b", "c"],
|
|
75
|
+
validation: { benchmarkSupport: 3, trajectorySupport: 5, contradictionCount: 0, status: "verified" },
|
|
76
|
+
};
|
|
77
|
+
// Propose
|
|
78
|
+
const patch = store.propose(inference);
|
|
79
|
+
(0, vitest_1.expect)(patch.status).toBe("proposed");
|
|
80
|
+
(0, vitest_1.expect)(patch.id).toMatch(/^KP-/);
|
|
81
|
+
(0, vitest_1.expect)(store.proposed.length).toBe(1);
|
|
82
|
+
// Approve
|
|
83
|
+
const ok = store.approve(patch.id, { top1Before: 0.5, top1After: 0.55, top3Before: 0.7, top3After: 0.75 });
|
|
84
|
+
(0, vitest_1.expect)(ok).toBe(true);
|
|
85
|
+
(0, vitest_1.expect)(store.approved.length).toBe(1);
|
|
86
|
+
(0, vitest_1.expect)(store.approved[0].approvalMetrics?.top1After).toBe(0.55);
|
|
87
|
+
// Rollback
|
|
88
|
+
const rb = store.rollback(patch.id);
|
|
89
|
+
(0, vitest_1.expect)(rb).toBe(true);
|
|
90
|
+
(0, vitest_1.expect)(store.approved.length).toBe(0);
|
|
91
|
+
// Reject a new one
|
|
92
|
+
const p2 = store.propose(inference);
|
|
93
|
+
store.reject(p2.id);
|
|
94
|
+
(0, vitest_1.expect)(store.all.filter(p => p.status === "rejected").length).toBe(1);
|
|
95
|
+
});
|
|
96
|
+
(0, vitest_1.it)("builds augmented rules from approved patches", () => {
|
|
97
|
+
const store = new knowledge_governance_1.KnowledgePatchStore(path.join(GOV_DIR, ".progmune_corpus", "knowledge", `aug-${Date.now()}.json`));
|
|
98
|
+
const inference = {
|
|
99
|
+
from: "FILE_OPEN", to: "FILE_DIRTY", action: "open_file → flush_file",
|
|
100
|
+
protocol: "FileProtocol", confidence: 1.0, evidenceCount: 3, examples: ["a"],
|
|
101
|
+
validation: { benchmarkSupport: 3, trajectorySupport: 5, contradictionCount: 0, status: "verified" },
|
|
102
|
+
};
|
|
103
|
+
const patch = store.propose(inference);
|
|
104
|
+
store.approve(patch.id, { top1Before: 0.5, top1After: 0.6, top3Before: 0.7, top3After: 0.8 });
|
|
105
|
+
const baseRules = makeBaseRules();
|
|
106
|
+
const augmented = store.buildAugmentedRules(baseRules);
|
|
107
|
+
// Should have base rules + 1 patch bridge
|
|
108
|
+
(0, vitest_1.expect)(augmented.size).toBe(baseRules.size + 1);
|
|
109
|
+
const hasBridge = [...augmented.keys()].some(k => k.startsWith("_patch_"));
|
|
110
|
+
(0, vitest_1.expect)(hasBridge).toBe(true);
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
(0, vitest_1.describe)("Regression Test", () => {
|
|
114
|
+
(0, vitest_1.it)("auto-approves if Top-1/Top-3 improves", () => {
|
|
115
|
+
const store = new knowledge_governance_1.KnowledgePatchStore(path.join(GOV_DIR, ".progmune_corpus", "knowledge", `reg-${Date.now()}.json`));
|
|
116
|
+
const patch = store.propose({
|
|
117
|
+
from: "FILE_OPEN", to: "FILE_DIRTY", action: "open_file → flush_file",
|
|
118
|
+
protocol: "FileProtocol", confidence: 1.0, evidenceCount: 3, examples: ["a", "b", "c"],
|
|
119
|
+
validation: { benchmarkSupport: 3, trajectorySupport: 5, contradictionCount: 0, status: "verified" },
|
|
120
|
+
});
|
|
121
|
+
const baseRules = makeBaseRules();
|
|
122
|
+
// Test case: from FILE_OPEN to FILE_DIRTY — this path doesn't exist in base rules (open→write exists, but open→flush is missing)
|
|
123
|
+
const testCases = [
|
|
124
|
+
{ currentState: ["FILE_OPEN"], targetState: ["FILE_DIRTY"] },
|
|
125
|
+
];
|
|
126
|
+
const result = (0, knowledge_governance_1.autoApprovePatch)(patch, baseRules, testCases, store);
|
|
127
|
+
// With augmented rules, the patch adds open_file→flush_file bridge
|
|
128
|
+
// This should improve Top-1 (found paths increase)
|
|
129
|
+
(0, vitest_1.expect)(result.passed).toBe(true);
|
|
130
|
+
(0, vitest_1.expect)(result.top1After).toBeGreaterThanOrEqual(result.top1Before);
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
(0, vitest_1.describe)("Full Governance Pipeline", () => {
|
|
134
|
+
(0, vitest_1.it)("runs synthesize → validate → propose → regression → approve", () => {
|
|
135
|
+
// revoke_token produces UNAUTHENTICATED, create_session needs TOKEN_ISSUED
|
|
136
|
+
// These are NOT connected (UNAUTHENTICATED ≠ TOKEN_ISSUED) → genuine gap
|
|
137
|
+
// Both functions exist in AuthProtocol (protocols.json)
|
|
138
|
+
const failures = [
|
|
139
|
+
{ goal: "revoke then create session", protocol: "AuthProtocol", expectedRepair: ["revoke_token", "create_session"] },
|
|
140
|
+
{ goal: "revoke then create session v2", protocol: "AuthProtocol", expectedRepair: ["revoke_token", "create_session"] },
|
|
141
|
+
];
|
|
142
|
+
const testCases = [
|
|
143
|
+
{ currentState: ["FILE_OPEN"], targetState: ["FILE_DIRTY"] },
|
|
144
|
+
];
|
|
145
|
+
const store = new knowledge_governance_1.KnowledgePatchStore(path.join(GOV_DIR, ".progmune_corpus", "knowledge", `full-${Date.now()}.json`));
|
|
146
|
+
const report = (0, knowledge_governance_1.runKnowledgeGovernance)(failures, testCases, store);
|
|
147
|
+
(0, vitest_1.expect)(report.proposed).toBeGreaterThanOrEqual(1);
|
|
148
|
+
(0, knowledge_governance_1.printGovernanceReport)(report);
|
|
149
|
+
});
|
|
150
|
+
});
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Knowledge Network — Cross-protocol reference graph
|
|
4
|
+
*
|
|
5
|
+
* Transforms flat Knowledge Units into an interconnected graph.
|
|
6
|
+
* Protocols reference each other: TLS depends_on TCP, HTTP/2 extends HTTP, etc.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* npx ts-node src/knowledge-graph.ts
|
|
10
|
+
* npx ts-node src/knowledge-graph.ts --tree
|
|
11
|
+
* npx ts-node src/knowledge-graph.ts --dependents TLS
|
|
12
|
+
*/
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
exports.buildKnowledgeGraph = buildKnowledgeGraph;
|
|
15
|
+
exports.getDependents = getDependents;
|
|
16
|
+
exports.getDependencies = getDependencies;
|
|
17
|
+
const protocol_knowledge_1 = require("./protocol-knowledge");
|
|
18
|
+
// Cross-protocol relations that go beyond existing unit.relations
|
|
19
|
+
const CROSS_PROTOCOL_EDGES = [
|
|
20
|
+
// Transport layer
|
|
21
|
+
{ from: "PROTO-TLS", to: "PROTO-CONN", type: "depends_on", description: "TLS handshake runs over a TCP connection" },
|
|
22
|
+
{ from: "PROTO-QUIC", to: "PROTO-CONN", type: "depends_on", description: "QUIC runs over UDP connection" },
|
|
23
|
+
// HTTP stack
|
|
24
|
+
{ from: "PROTO-H2", to: "PROTO-HTTP", type: "extends", description: "HTTP/2 extends HTTP/1.1 request semantics" },
|
|
25
|
+
{ from: "PROTO-TLS-ALPN", to: "PROTO-TLS", type: "extends", description: "ALPN negotiation extends TLS handshake" },
|
|
26
|
+
{ from: "PROTO-TLS-CERT", to: "PROTO-TLS", type: "extends", description: "Certificate validation extends TLS handshake" },
|
|
27
|
+
{ from: "PROTO-TLS-SESS", to: "PROTO-TLS", type: "depends_on", description: "Session resumption requires completed handshake" },
|
|
28
|
+
// Auth
|
|
29
|
+
{ from: "PROTO-SSH", to: "PROTO-AUTH", type: "depends_on", description: "SSH requires authentication" },
|
|
30
|
+
{ from: "PROTO-HTTP", to: "PROTO-AUTH", type: "compatible_with", description: "HTTP can use authentication headers" },
|
|
31
|
+
// Cross-domain
|
|
32
|
+
{ from: "PROTO-TLS", to: "PROTO-AUTH", type: "compatible_with", description: "TLS can carry client certificates for authentication" },
|
|
33
|
+
{ from: "PROTO-SSH", to: "PROTO-CONN", type: "depends_on", description: "SSH runs over TCP connection" },
|
|
34
|
+
];
|
|
35
|
+
function buildKnowledgeGraph() {
|
|
36
|
+
const kb = (0, protocol_knowledge_1.buildKnowledgeBase)();
|
|
37
|
+
const nodes = kb.units.map(u => ({
|
|
38
|
+
id: u.id, name: u.name, domain: u.domain, maturity: u.maturity, confidence: u.confidence,
|
|
39
|
+
}));
|
|
40
|
+
// Collect all edges: both intra-unit relations and cross-protocol relations
|
|
41
|
+
const edges = [...CROSS_PROTOCOL_EDGES];
|
|
42
|
+
// Add intra-unit relations
|
|
43
|
+
for (const u of kb.units) {
|
|
44
|
+
for (const r of u.relations || []) {
|
|
45
|
+
edges.push({ from: u.id, to: r.targetId, type: r.type, description: r.description });
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
// Build adjacency
|
|
49
|
+
const adj = {};
|
|
50
|
+
const inDeg = {};
|
|
51
|
+
const outDeg = {};
|
|
52
|
+
for (const n of nodes) {
|
|
53
|
+
adj[n.id] = [];
|
|
54
|
+
inDeg[n.id] = 0;
|
|
55
|
+
outDeg[n.id] = 0;
|
|
56
|
+
}
|
|
57
|
+
for (const e of edges) {
|
|
58
|
+
if (!adj[e.from])
|
|
59
|
+
adj[e.from] = [];
|
|
60
|
+
if (!adj[e.to])
|
|
61
|
+
adj[e.to] = [];
|
|
62
|
+
adj[e.from].push(e.to);
|
|
63
|
+
outDeg[e.from] = (outDeg[e.from] || 0) + 1;
|
|
64
|
+
inDeg[e.to] = (inDeg[e.to] || 0) + 1;
|
|
65
|
+
}
|
|
66
|
+
return { nodes, edges, adjacency: adj, inDegree: inDeg, outDegree: outDeg };
|
|
67
|
+
}
|
|
68
|
+
// ═══════════════════════════════════════════════════════════════
|
|
69
|
+
// Queries
|
|
70
|
+
// ═══════════════════════════════════════════════════════════════
|
|
71
|
+
function getDependents(graph, nodeId) {
|
|
72
|
+
const ids = graph.edges.filter(e => e.to === nodeId).map(e => e.from);
|
|
73
|
+
return graph.nodes.filter(n => ids.includes(n.id));
|
|
74
|
+
}
|
|
75
|
+
function getDependencies(graph, nodeId) {
|
|
76
|
+
const ids = graph.edges.filter(e => e.from === nodeId).map(e => e.to);
|
|
77
|
+
return graph.nodes.filter(n => ids.includes(n.id));
|
|
78
|
+
}
|
|
79
|
+
// ═══════════════════════════════════════════════════════════════
|
|
80
|
+
// Formatters
|
|
81
|
+
// ═══════════════════════════════════════════════════════════════
|
|
82
|
+
function formatTree(graph) {
|
|
83
|
+
const C = { r: "\x1b[0m", b: "\x1b[1m", d: "\x1b[2m", g: "\x1b[32m", y: "\x1b[33m", r2: "\x1b[31m", c: "\x1b[36m", m: "\x1b[35m" };
|
|
84
|
+
const l = [];
|
|
85
|
+
l.push(`\n${C.b}${C.c}Protocol Knowledge Graph${C.r}\n`);
|
|
86
|
+
// Find root nodes (no incoming edges from other protocols)
|
|
87
|
+
const roots = graph.nodes.filter(n => graph.inDegree[n.id] === 0 || (graph.inDegree[n.id] <= 1 && graph.outDegree[n.id] >= 2));
|
|
88
|
+
const visited = new Set();
|
|
89
|
+
function renderNode(id, prefix, isLast) {
|
|
90
|
+
if (visited.has(id))
|
|
91
|
+
return;
|
|
92
|
+
visited.add(id);
|
|
93
|
+
const n = graph.nodes.find(x => x.id === id);
|
|
94
|
+
if (!n)
|
|
95
|
+
return;
|
|
96
|
+
const connector = isLast ? "└── " : "├── ";
|
|
97
|
+
const matIcon = n.maturity === "stable" ? C.g + "★" + C.r : n.maturity === "validated" ? C.y + "◉" + C.r : C.r2 + "●" + C.r;
|
|
98
|
+
l.push(`${prefix}${connector}${matIcon} ${C.b}${n.name}${C.r} ${C.d}(${n.domain}, ${n.confidence}%)${C.r}`);
|
|
99
|
+
const children = graph.edges.filter(e => e.from === id);
|
|
100
|
+
const childPrefix = prefix + (isLast ? " " : "│ ");
|
|
101
|
+
children.forEach((e, i) => {
|
|
102
|
+
l.push(`${childPrefix}${i === children.length - 1 ? "└── " : "├── "}${C.d}${e.type}${C.r} → ${e.description.slice(0, 50)}`);
|
|
103
|
+
});
|
|
104
|
+
// Don't recurse into children to avoid cycles — just show direct edges
|
|
105
|
+
}
|
|
106
|
+
// Render starting from connection/transport layer (roots)
|
|
107
|
+
const transportRoots = graph.nodes.filter(n => n.domain === "Connection" || n.domain === "QUIC");
|
|
108
|
+
for (const r of transportRoots) {
|
|
109
|
+
renderNode(r.id, "", true);
|
|
110
|
+
}
|
|
111
|
+
// Then TLS, SSH, HTTP
|
|
112
|
+
const appRoots = graph.nodes.filter(n => ["TLS", "SSH", "HTTP"].includes(n.domain) && !transportRoots.includes(n));
|
|
113
|
+
for (const r of appRoots) {
|
|
114
|
+
if (!visited.has(r.id))
|
|
115
|
+
renderNode(r.id, "", true);
|
|
116
|
+
}
|
|
117
|
+
return l.join("\n") + "\n";
|
|
118
|
+
}
|
|
119
|
+
function formatMatrix(graph) {
|
|
120
|
+
const C = { r: "\x1b[0m", b: "\x1b[1m", d: "\x1b[2m", g: "\x1b[32m" };
|
|
121
|
+
const l = [];
|
|
122
|
+
l.push(`\n${C.b}Cross-Reference Matrix${C.r}\n`);
|
|
123
|
+
l.push(`${C.d}Rows point TO columns (row depends_on / extends column)${C.r}\n`);
|
|
124
|
+
const ids = graph.nodes.map(n => n.id);
|
|
125
|
+
const names = graph.nodes.map(n => n.name.slice(0, 8));
|
|
126
|
+
l.push(` ${names.join(" ")}`);
|
|
127
|
+
l.push(` ${names.map(() => "──").join(" ")}`);
|
|
128
|
+
for (const n of graph.nodes) {
|
|
129
|
+
const row = ids.map(targetId => {
|
|
130
|
+
const edge = graph.edges.find(e => e.from === n.id && e.to === targetId);
|
|
131
|
+
return edge ? (edge.type === "depends_on" ? "↓ " : edge.type === "extends" ? "↗ " : "· ") : " ";
|
|
132
|
+
}).join(" ");
|
|
133
|
+
l.push(`${n.name.slice(0, 8).padEnd(8)} ${row}`);
|
|
134
|
+
}
|
|
135
|
+
return l.join("\n") + "\n";
|
|
136
|
+
}
|
|
137
|
+
// ═══════════════════════════════════════════════════════════════
|
|
138
|
+
// CLI
|
|
139
|
+
// ═══════════════════════════════════════════════════════════════
|
|
140
|
+
if (require.main === module) {
|
|
141
|
+
const g = buildKnowledgeGraph();
|
|
142
|
+
const args = process.argv.slice(2);
|
|
143
|
+
const C = { r: "\x1b[0m", b: "\x1b[1m", d: "\x1b[2m", g: "\x1b[32m", c: "\x1b[36m" };
|
|
144
|
+
if (args.includes("--tree")) {
|
|
145
|
+
console.log(formatTree(g));
|
|
146
|
+
}
|
|
147
|
+
else if (args.includes("--matrix")) {
|
|
148
|
+
console.log(formatMatrix(g));
|
|
149
|
+
}
|
|
150
|
+
else if (args.includes("--dependents") && args[1]) {
|
|
151
|
+
const deps = getDependents(g, args[1]);
|
|
152
|
+
console.log(`\nNodes that depend on ${args[1]}:`);
|
|
153
|
+
deps.forEach(d => console.log(` ${d.name} (${d.domain}, ${d.maturity})`));
|
|
154
|
+
}
|
|
155
|
+
else if (args.includes("--dependencies") && args[1]) {
|
|
156
|
+
const deps = getDependencies(g, args[1]);
|
|
157
|
+
console.log(`\nNodes that ${args[1]} depends on:`);
|
|
158
|
+
deps.forEach(d => console.log(` ${d.name} (${d.domain}, ${d.maturity})`));
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
// Default: summary
|
|
162
|
+
console.log(`\n${C.b}${C.c}Knowledge Network${C.r}`);
|
|
163
|
+
console.log(`${C.d}${g.nodes.length} nodes, ${g.edges.length} edges${C.r}`);
|
|
164
|
+
// Top nodes by connections
|
|
165
|
+
const ranked = g.nodes.map(n => ({
|
|
166
|
+
name: n.name, domain: n.domain, maturity: n.maturity,
|
|
167
|
+
total: (g.inDegree[n.id] || 0) + (g.outDegree[n.id] || 0),
|
|
168
|
+
in: g.inDegree[n.id] || 0, out: g.outDegree[n.id] || 0,
|
|
169
|
+
})).sort((a, b) => b.total - a.total);
|
|
170
|
+
console.log(`\n Node Domain In Out Total`);
|
|
171
|
+
for (const r of ranked.slice(0, 8)) {
|
|
172
|
+
console.log(` ${r.name.padEnd(20)} ${r.domain.padEnd(10)} ${String(r.in).padStart(2)} ${String(r.out).padStart(2)} ${r.total}`);
|
|
173
|
+
}
|
|
174
|
+
// Cross-references
|
|
175
|
+
console.log(`\n Cross-protocol edges:`);
|
|
176
|
+
for (const e of g.edges) {
|
|
177
|
+
console.log(` ${e.from.padEnd(14)} ${e.type.padEnd(14)} → ${e.to.padEnd(14)} ${C.d}${e.description.slice(0, 50)}${C.r}`);
|
|
178
|
+
}
|
|
179
|
+
console.log("");
|
|
180
|
+
}
|
|
181
|
+
}
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* P6: Knowledge-Guided Rule Synthesis
|
|
4
|
+
*
|
|
5
|
+
* The existing synthesizer generates too many rules (452 from 61 sequences)
|
|
6
|
+
* because it blindly clusters ALL observed patterns. This module adds
|
|
7
|
+
* knowledge-based filtering to produce fewer, higher-quality rules.
|
|
8
|
+
*
|
|
9
|
+
* Three filters:
|
|
10
|
+
* 1. DOMAIN_FILTER — Only generate rules for protocol-relevant functions
|
|
11
|
+
* 2. SPECIFICITY_FILTER — Require minimum pre/post state specificity
|
|
12
|
+
* 3. FREQUENCY_FILTER — Require pattern observed in ≥N sequences
|
|
13
|
+
*
|
|
14
|
+
* Target: 452 rules → ~50 high-quality rules (89% reduction)
|
|
15
|
+
*/
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.synthesizeWithKnowledge = synthesizeWithKnowledge;
|
|
18
|
+
exports.formatKGSynthesisStats = formatKGSynthesisStats;
|
|
19
|
+
const auto_protocol_synthesizer_1 = require("./auto-protocol-synthesizer");
|
|
20
|
+
// ═══════════════════════════════════════════════════════════════
|
|
21
|
+
// Knowledge Base — Protocol-Relevant Function Patterns
|
|
22
|
+
// ═══════════════════════════════════════════════════════════════
|
|
23
|
+
/**
|
|
24
|
+
* Protocol domain patterns — functions matching these patterns
|
|
25
|
+
* are likely to be part of real protocols (TLS, SSH, HTTP, File, Auth).
|
|
26
|
+
*
|
|
27
|
+
* Functions NOT matching any pattern are likely utilities, helpers,
|
|
28
|
+
* or internal functions that should be excluded from rule generation.
|
|
29
|
+
*/
|
|
30
|
+
const PROTOCOL_DOMAINS = [
|
|
31
|
+
{
|
|
32
|
+
domain: "TLS/SSL",
|
|
33
|
+
patterns: [
|
|
34
|
+
/ssl/i, /tls/i, /handshake/i, /cipher/i, /cert/i, /verify/i,
|
|
35
|
+
/encrypt/i, /decrypt/i, /key/i, /x509/i, /pki/i,
|
|
36
|
+
/SSL_/i, /TLS_/i, /ossl_/i,
|
|
37
|
+
],
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
domain: "SSH",
|
|
41
|
+
patterns: [
|
|
42
|
+
/ssh_/i, /sftp/i, /scp/i, /auth_/i, /kex/i, /hostkey/i,
|
|
43
|
+
/SSH_/i, /ssh_/i,
|
|
44
|
+
],
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
domain: "HTTP",
|
|
48
|
+
patterns: [
|
|
49
|
+
/http/i, /request/i, /response/i, /header/i, /cookie/i,
|
|
50
|
+
/session/i, /url/i, /uri/i, /CURL/i, /curl_/i, /ngx_http/i,
|
|
51
|
+
],
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
domain: "File I/O",
|
|
55
|
+
patterns: [
|
|
56
|
+
/open_/i, /close_/i, /read_/i, /write_/i, /file_/i,
|
|
57
|
+
/fopen/i, /fclose/i, /fread/i, /fwrite/i, /fd_/i,
|
|
58
|
+
],
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
domain: "Auth",
|
|
62
|
+
patterns: [
|
|
63
|
+
/auth/i, /login/i, /logout/i, /password/i, /token/i,
|
|
64
|
+
/verify_/i, /credential/i, /oauth/i, /jwt/i,
|
|
65
|
+
],
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
domain: "Connection",
|
|
69
|
+
patterns: [
|
|
70
|
+
/connect/i, /disconnect/i, /bind/i, /listen/i, /accept/i,
|
|
71
|
+
/socket/i, /resolve/i, /dns/i,
|
|
72
|
+
],
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
domain: "Memory/Resource",
|
|
76
|
+
patterns: [
|
|
77
|
+
/alloc/i, /free/i, /init/i, /cleanup/i, /destroy/i,
|
|
78
|
+
/create_/i, /delete_/i, /new_/i, /release/i, /acquire/i,
|
|
79
|
+
],
|
|
80
|
+
},
|
|
81
|
+
];
|
|
82
|
+
/**
|
|
83
|
+
* Generic utility functions that are NOT protocol-relevant.
|
|
84
|
+
* Rules generated from these functions are almost always false positives.
|
|
85
|
+
*/
|
|
86
|
+
const GENERIC_FUNCTIONS = new Set([
|
|
87
|
+
// Standard library
|
|
88
|
+
"memset", "memcpy", "memmove", "memcmp", "strlen", "strcmp", "strcasecmp",
|
|
89
|
+
"strdup", "strcpy", "strncpy", "strcat", "sprintf", "snprintf",
|
|
90
|
+
"malloc", "calloc", "realloc", "free",
|
|
91
|
+
"printf", "fprintf", "assert", "abort", "exit",
|
|
92
|
+
// Preprocessor / compiler
|
|
93
|
+
"defined", "UNUSED", "FALLTHROUGH", "GOOD_MULTI_HANDLE",
|
|
94
|
+
// Data structures
|
|
95
|
+
"STACK_OF", "ERR_clear_error", "curlx_dyn_init",
|
|
96
|
+
// Generic utility
|
|
97
|
+
"time", "delay", "sleep", "usleep",
|
|
98
|
+
"buffer", "files", "multi_now", "scheme",
|
|
99
|
+
"curl_socket", "curl_dynhds_init", "curl_global_trace",
|
|
100
|
+
"is_pkcs11_uri", "ossl_do_file_type",
|
|
101
|
+
// One-off internal helpers
|
|
102
|
+
"init_telnet", "rfc2228", "myssh_to_error",
|
|
103
|
+
"libssh2_sftp_stat_ex",
|
|
104
|
+
]);
|
|
105
|
+
const DEFAULT_KG_OPTIONS = {
|
|
106
|
+
minFrequency: 3, // Cluster must have ≥3 sequences
|
|
107
|
+
minSpecificity: 1,
|
|
108
|
+
filterGenerics: true,
|
|
109
|
+
requireDomain: false,
|
|
110
|
+
};
|
|
111
|
+
/**
|
|
112
|
+
* Check if a function name matches any known protocol domain.
|
|
113
|
+
*/
|
|
114
|
+
function matchesDomain(fnName) {
|
|
115
|
+
for (const domain of PROTOCOL_DOMAINS) {
|
|
116
|
+
if (domain.patterns.some(p => p.test(fnName))) {
|
|
117
|
+
return domain.domain;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
function classifySemanticRole(fnName, preStates, postStates, invalidate) {
|
|
123
|
+
const fn = fnName.toLowerCase();
|
|
124
|
+
// Init: creates/acquires resources — empty pre_states, produces post_states
|
|
125
|
+
if (preStates.length === 0 && postStates.length > 0)
|
|
126
|
+
return "init";
|
|
127
|
+
// Cleanup: releases/invalidates resources
|
|
128
|
+
if (invalidate && invalidate.length > 0)
|
|
129
|
+
return "cleanup";
|
|
130
|
+
// Use: requires pre_states, may produce post_states, no invalidation
|
|
131
|
+
if (preStates.length > 0)
|
|
132
|
+
return "use";
|
|
133
|
+
return "unknown";
|
|
134
|
+
}
|
|
135
|
+
function synthesizeWithKnowledge(sequences, options = {}) {
|
|
136
|
+
const opts = { ...DEFAULT_KG_OPTIONS, ...options };
|
|
137
|
+
const stats = {
|
|
138
|
+
inputSequences: sequences.length,
|
|
139
|
+
filteredSequences: sequences.length, // Don't filter sequences — filter rules instead
|
|
140
|
+
rawProtocols: 0,
|
|
141
|
+
rawRules: 0,
|
|
142
|
+
filteredProtocols: 0,
|
|
143
|
+
filteredRules: 0,
|
|
144
|
+
byFilter: { domain: 0, generic: 0, frequency: 0, specificity: 0 },
|
|
145
|
+
domainBreakdown: {},
|
|
146
|
+
};
|
|
147
|
+
// Step 1: Run the existing synthesizer on ALL sequences (don't pre-filter)
|
|
148
|
+
const rawProtocols = (0, auto_protocol_synthesizer_1.synthesizeProtocols)(sequences);
|
|
149
|
+
stats.rawProtocols = rawProtocols.length;
|
|
150
|
+
let totalRawRules = 0;
|
|
151
|
+
for (const p of rawProtocols)
|
|
152
|
+
totalRawRules += p.rules.length;
|
|
153
|
+
stats.rawRules = totalRawRules;
|
|
154
|
+
// Step 2: Filter synthesized rules by quality
|
|
155
|
+
const rules = new Map();
|
|
156
|
+
const namespaces = new Set();
|
|
157
|
+
// Count function frequency across ALL sequences
|
|
158
|
+
const fnFrequency = new Map();
|
|
159
|
+
for (const seq of sequences) {
|
|
160
|
+
const seen = new Set();
|
|
161
|
+
for (const fn of seq) {
|
|
162
|
+
if (!seen.has(fn)) {
|
|
163
|
+
fnFrequency.set(fn, (fnFrequency.get(fn) || 0) + 1);
|
|
164
|
+
seen.add(fn);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
for (const proto of rawProtocols) {
|
|
169
|
+
// Frequency/confidence filter: cluster must have sufficient confidence
|
|
170
|
+
// (closedLoopRate from clustering — higher = stronger pattern)
|
|
171
|
+
if (proto.confidence < 0.3 && proto.prototype.length < 5) {
|
|
172
|
+
stats.byFilter.frequency++;
|
|
173
|
+
continue;
|
|
174
|
+
}
|
|
175
|
+
let keptRules = 0;
|
|
176
|
+
for (const r of proto.rules) {
|
|
177
|
+
// Filter 1: Generic/utility functions — these match everywhere, always FP
|
|
178
|
+
if (opts.filterGenerics && GENERIC_FUNCTIONS.has(r.function)) {
|
|
179
|
+
stats.byFilter.generic++;
|
|
180
|
+
continue;
|
|
181
|
+
}
|
|
182
|
+
// Filter 2: Frequency — function must appear in ≥minFrequency sequences
|
|
183
|
+
const freq = fnFrequency.get(r.function) || 0;
|
|
184
|
+
if (freq < opts.minFrequency) {
|
|
185
|
+
stats.byFilter.frequency++;
|
|
186
|
+
continue;
|
|
187
|
+
}
|
|
188
|
+
// Filter 3: Semantic role
|
|
189
|
+
const role = classifySemanticRole(r.function, r.pre_states, r.post_states, r.invalidate);
|
|
190
|
+
if (role === "unknown") {
|
|
191
|
+
stats.byFilter.specificity++;
|
|
192
|
+
continue;
|
|
193
|
+
}
|
|
194
|
+
// Filter 4: Domain annotation
|
|
195
|
+
const domain = matchesDomain(r.function);
|
|
196
|
+
const ns = domain || proto.inferredPattern || "discovered";
|
|
197
|
+
namespaces.add(ns);
|
|
198
|
+
stats.domainBreakdown[domain || "unknown"] =
|
|
199
|
+
(stats.domainBreakdown[domain || "unknown"] || 0) + 1;
|
|
200
|
+
rules.set(r.function, {
|
|
201
|
+
pre_states: r.pre_states,
|
|
202
|
+
post_states: r.post_states,
|
|
203
|
+
invalidate: r.invalidate,
|
|
204
|
+
namespace: ns,
|
|
205
|
+
});
|
|
206
|
+
keptRules++;
|
|
207
|
+
}
|
|
208
|
+
if (keptRules > 0) {
|
|
209
|
+
stats.filteredProtocols++;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
stats.filteredRules = rules.size;
|
|
213
|
+
// Build namespace initial states
|
|
214
|
+
const nsInit = new Map();
|
|
215
|
+
nsInit.set("_global", "INIT");
|
|
216
|
+
for (const ns of namespaces) {
|
|
217
|
+
nsInit.set(ns, "INIT");
|
|
218
|
+
}
|
|
219
|
+
return { rules, nsInit, stats };
|
|
220
|
+
}
|
|
221
|
+
function formatKGSynthesisStats(stats) {
|
|
222
|
+
const lines = [];
|
|
223
|
+
const reduction = stats.rawRules > 0
|
|
224
|
+
? ((1 - stats.filteredRules / stats.rawRules) * 100).toFixed(0)
|
|
225
|
+
: "0";
|
|
226
|
+
lines.push("");
|
|
227
|
+
lines.push("── Knowledge-Guided Synthesis ──");
|
|
228
|
+
lines.push(` Input sequences: ${stats.inputSequences}`);
|
|
229
|
+
lines.push(` After domain filter: ${stats.filteredSequences} (${stats.byFilter.domain} removed by domain, ${stats.byFilter.generic} generics)`);
|
|
230
|
+
lines.push(` Raw protocols: ${stats.rawProtocols}`);
|
|
231
|
+
lines.push(` Raw rules: ${stats.rawRules}`);
|
|
232
|
+
lines.push(` Filtered rules: ${stats.filteredRules} (${reduction}% reduction)`);
|
|
233
|
+
lines.push("");
|
|
234
|
+
lines.push(" ── Filter breakdown ──");
|
|
235
|
+
lines.push(` Domain mismatch: ${stats.byFilter.domain}`);
|
|
236
|
+
lines.push(` Generic function: ${stats.byFilter.generic}`);
|
|
237
|
+
lines.push(` Low frequency: ${stats.byFilter.frequency}`);
|
|
238
|
+
lines.push(` Low specificity: ${stats.byFilter.specificity}`);
|
|
239
|
+
lines.push("");
|
|
240
|
+
lines.push(" ── Domain distribution ──");
|
|
241
|
+
for (const [domain, count] of Object.entries(stats.domainBreakdown).sort((a, b) => b[1] - a[1])) {
|
|
242
|
+
lines.push(` ${domain.padEnd(20)} ${count} rules`);
|
|
243
|
+
}
|
|
244
|
+
lines.push("");
|
|
245
|
+
return lines.join("\n");
|
|
246
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
/**
|
|
4
|
+
* Knowledge loop integration test.
|
|
5
|
+
*
|
|
6
|
+
* Verifies the full feedback loop end-to-end:
|
|
7
|
+
* Failure → Record → Aggregate → Antibody → L1 Hint / L2 Fast Path / L3 Credit
|
|
8
|
+
*
|
|
9
|
+
* Tests run against real feedback.json and .progmune_corpus data on disk.
|
|
10
|
+
*/
|
|
11
|
+
const vitest_1 = require("vitest");
|
|
12
|
+
const failure_corpus_1 = require("./failure-corpus");
|
|
13
|
+
const feedback_1 = require("./feedback");
|
|
14
|
+
const logger_1 = require("./logger");
|
|
15
|
+
// ── L3: Credit scoring works with real data ──
|
|
16
|
+
(0, vitest_1.describe)("L3: Credit scoring", () => {
|
|
17
|
+
(0, vitest_1.it)("getFailureAdjustedCredit returns Laplace-smoothed value for unknown function", () => {
|
|
18
|
+
const credit = (0, feedback_1.getFailureAdjustedCredit)("__nonexistent_xyz__");
|
|
19
|
+
(0, vitest_1.expect)(credit).toBe(0.5);
|
|
20
|
+
});
|
|
21
|
+
(0, vitest_1.it)("getFailureAdjustedCredit for known functions is between 0.3 and 1.0", () => {
|
|
22
|
+
// Test a few functions that may or may not have history
|
|
23
|
+
for (const fn of ["generateJWT", "validatePassword", "loadIR", "plan"]) {
|
|
24
|
+
const credit = (0, feedback_1.getFailureAdjustedCredit)(fn);
|
|
25
|
+
(0, vitest_1.expect)(credit).toBeGreaterThanOrEqual(0.3);
|
|
26
|
+
(0, vitest_1.expect)(credit).toBeLessThanOrEqual(1.0);
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
(0, vitest_1.it)("getFunctionSuccessRate returns 0.5 for cold start", () => {
|
|
30
|
+
(0, vitest_1.expect)((0, feedback_1.getFunctionSuccessRate)("__never_called__")).toBe(0.5);
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
// ── L1/L2: Antibody generation ──
|
|
34
|
+
(0, vitest_1.describe)("L1/L2: Antibody pipeline", () => {
|
|
35
|
+
(0, vitest_1.it)("getLearnedPatterns returns a valid structure", () => {
|
|
36
|
+
const result = (0, failure_corpus_1.getLearnedPatterns)();
|
|
37
|
+
(0, vitest_1.expect)(result).toHaveProperty("failureToFix");
|
|
38
|
+
(0, vitest_1.expect)(Array.isArray(result.failureToFix)).toBe(true);
|
|
39
|
+
});
|
|
40
|
+
(0, vitest_1.it)("getFailureGenome returns summary statistics", () => {
|
|
41
|
+
const genome = (0, failure_corpus_1.getFailureGenome)();
|
|
42
|
+
(0, vitest_1.expect)(genome).toHaveProperty("totalFailures");
|
|
43
|
+
(0, vitest_1.expect)(genome).toHaveProperty("bySVL");
|
|
44
|
+
(0, vitest_1.expect)(genome).toHaveProperty("averageRetriesToSuccess");
|
|
45
|
+
(0, vitest_1.expect)(typeof genome.totalFailures).toBe("number");
|
|
46
|
+
});
|
|
47
|
+
(0, vitest_1.it)("getTopFailurePatterns returns sorted patterns", () => {
|
|
48
|
+
const patterns = (0, failure_corpus_1.getTopFailurePatterns)(5);
|
|
49
|
+
(0, vitest_1.expect)(Array.isArray(patterns)).toBe(true);
|
|
50
|
+
// Verify sorted by count descending
|
|
51
|
+
for (let i = 1; i < patterns.length; i++) {
|
|
52
|
+
(0, vitest_1.expect)(patterns[i].count).toBeLessThanOrEqual(patterns[i - 1].count);
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
(0, vitest_1.it)("queryAntibodies returns ACL-3+ matches", () => {
|
|
56
|
+
const antibodies = (0, failure_corpus_1.queryAntibodies)("test intent", "ACL-3");
|
|
57
|
+
(0, vitest_1.expect)(Array.isArray(antibodies)).toBe(true);
|
|
58
|
+
// All returned antibodies should be ACL-3 or ACL-4
|
|
59
|
+
for (const ab of antibodies) {
|
|
60
|
+
(0, vitest_1.expect)(["ACL-3", "ACL-4"]).toContain(ab.antibodyLevel);
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
(0, vitest_1.it)("queryAntibodies returns results sorted by relevance", () => {
|
|
64
|
+
const antibodies = (0, failure_corpus_1.queryAntibodies)("authenticate user password", "ACL-3");
|
|
65
|
+
for (let i = 1; i < antibodies.length; i++) {
|
|
66
|
+
(0, vitest_1.expect)(antibodies[i]._score).toBeLessThanOrEqual(antibodies[i - 1]._score);
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
// ── Logger integration ──
|
|
71
|
+
(0, vitest_1.describe)("Structured logger", () => {
|
|
72
|
+
(0, vitest_1.it)("createLogger produces distinguishable module names", () => {
|
|
73
|
+
const plan = (0, logger_1.createLogger)("planner");
|
|
74
|
+
const val = (0, logger_1.createLogger)("validator");
|
|
75
|
+
(0, vitest_1.expect)(plan).not.toBe(val);
|
|
76
|
+
});
|
|
77
|
+
});
|