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,343 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.extractSequences = extractSequences;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
const child_process_1 = require("child_process");
|
|
40
|
+
// Python stdlib and built-in names to exclude from call sequences
|
|
41
|
+
const PYTHON_EXCLUDED = new Set([
|
|
42
|
+
'if', 'for', 'while', 'return', 'print', 'assert', 'raise', 'lambda',
|
|
43
|
+
'len', 'str', 'int', 'float', 'bool', 'list', 'dict', 'tuple', 'set',
|
|
44
|
+
'range', 'enumerate', 'zip', 'map', 'filter', 'sorted', 'reversed',
|
|
45
|
+
'min', 'max', 'sum', 'abs', 'round', 'type', 'isinstance', 'issubclass',
|
|
46
|
+
'hasattr', 'getattr', 'setattr', 'delattr',
|
|
47
|
+
'open', 'close', 'read', 'write', 'super',
|
|
48
|
+
'hexdigest', 'encode', 'decode', 'upper', 'lower', 'strip', 'split',
|
|
49
|
+
'append', 'extend', 'pop', 'remove', 'insert', 'index', 'count', 'sort', 'reverse',
|
|
50
|
+
'keys', 'values', 'items', 'get', 'update', 'popitem',
|
|
51
|
+
'format', 'join', 'replace', 'find', 'startswith', 'endswith',
|
|
52
|
+
'def', 'class', 'pass', 'del', 'self', 'cls',
|
|
53
|
+
'None', 'True', 'False', 'Ellipsis', 'NotImplemented',
|
|
54
|
+
]);
|
|
55
|
+
function extractSequences(repoPath, options = {}) {
|
|
56
|
+
const { include = /\.(c|h|ts|js|py)$/, exclude = /(test|vendor|node_modules|build|dist|\.git|__pycache__)/, maxBodyLines = 200 } = options;
|
|
57
|
+
if (options.useCflow && isCProject(repoPath)) {
|
|
58
|
+
return extractWithCflow(repoPath);
|
|
59
|
+
}
|
|
60
|
+
const sequences = [];
|
|
61
|
+
const files = findFiles(repoPath, include, exclude);
|
|
62
|
+
for (const file of files) {
|
|
63
|
+
const ext = path.extname(file);
|
|
64
|
+
if (['.c', '.h'].includes(ext)) {
|
|
65
|
+
sequences.push(...extractFromCFile(file, maxBodyLines));
|
|
66
|
+
}
|
|
67
|
+
else if (['.ts', '.js'].includes(ext)) {
|
|
68
|
+
sequences.push(...extractFromTSFile(file, maxBodyLines));
|
|
69
|
+
}
|
|
70
|
+
else if (['.py'].includes(ext)) {
|
|
71
|
+
sequences.push(...extractFromPythonFile(file, maxBodyLines));
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return sequences;
|
|
75
|
+
}
|
|
76
|
+
function extractWithCflow(repoPath) {
|
|
77
|
+
const sequences = [];
|
|
78
|
+
try {
|
|
79
|
+
const output = (0, child_process_1.execSync)(`cflow --format=posix ${repoPath}/*.c 2>/dev/null || true`, {
|
|
80
|
+
encoding: 'utf-8',
|
|
81
|
+
maxBuffer: 50 * 1024 * 1024,
|
|
82
|
+
});
|
|
83
|
+
const lines = output.split('\n');
|
|
84
|
+
let currentFunc = '';
|
|
85
|
+
let calls = [];
|
|
86
|
+
for (const line of lines) {
|
|
87
|
+
if (line.startsWith(' ')) {
|
|
88
|
+
const match = line.match(/\s+(\w+)/);
|
|
89
|
+
if (match)
|
|
90
|
+
calls.push(match[1]);
|
|
91
|
+
}
|
|
92
|
+
else if (line.trim()) {
|
|
93
|
+
if (currentFunc && calls.length > 0) {
|
|
94
|
+
sequences.push({
|
|
95
|
+
functionName: currentFunc,
|
|
96
|
+
filePath: 'unknown',
|
|
97
|
+
lineNumber: 0,
|
|
98
|
+
calls: calls,
|
|
99
|
+
bodyLength: 0,
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
const match = line.match(/^(\w+)/);
|
|
103
|
+
currentFunc = match ? match[1] : '';
|
|
104
|
+
calls = [];
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
console.warn('cflow not available, falling back to regex parser');
|
|
110
|
+
}
|
|
111
|
+
return sequences;
|
|
112
|
+
}
|
|
113
|
+
function extractFromCFile(filePath, maxBodyLines) {
|
|
114
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
115
|
+
const lines = content.split('\n');
|
|
116
|
+
const sequences = [];
|
|
117
|
+
// v2: Multi-line function signature matching.
|
|
118
|
+
// Handles: Type *func(...) {, static Type\nfunc(...) {, MACRO\nType func(...) {
|
|
119
|
+
// Strategy: scan for identifier(...) { pattern, then backtrack for return type.
|
|
120
|
+
const C_KEYWORDS = new Set([
|
|
121
|
+
'if', 'for', 'while', 'switch', 'return', 'sizeof', 'typeof',
|
|
122
|
+
'goto', 'break', 'continue', 'case', 'default', 'do', 'else',
|
|
123
|
+
'struct', 'union', 'enum', 'typedef', 'extern', 'volatile', 'const',
|
|
124
|
+
]);
|
|
125
|
+
let i = 0;
|
|
126
|
+
while (i < lines.length) {
|
|
127
|
+
// Build a multi-line buffer: join consecutive lines until we see '{' or ';'
|
|
128
|
+
let buf = '';
|
|
129
|
+
let bufStart = i;
|
|
130
|
+
while (i < lines.length) {
|
|
131
|
+
const line = lines[i].trim();
|
|
132
|
+
buf += (buf ? ' ' : '') + line;
|
|
133
|
+
if (line.includes('{') || line.includes(';'))
|
|
134
|
+
break;
|
|
135
|
+
i++;
|
|
136
|
+
}
|
|
137
|
+
if (i >= lines.length)
|
|
138
|
+
break;
|
|
139
|
+
// Skip preprocessor directives, comments, and declarations (lines ending with ;)
|
|
140
|
+
if (buf.trim().startsWith('#') || buf.trim().startsWith('//') || buf.trim().startsWith('/*')) {
|
|
141
|
+
i++;
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
// v2 regex: handles pointer types, struct types, multi-word return types
|
|
145
|
+
// Matches: [static] [inline] [attributes] ReturnType [*] funcName(params) {
|
|
146
|
+
const funcMatch = buf.match(/(?:^|\s)(?:static\s+)?(?:inline\s+)?(?:__attribute__\s*\([^)]*\)\s*)?(?:OSSL_DEPRECATEDIN\S*\s*)?(?:[a-zA-Z_][a-zA-Z0-9_]*\s+(?:\*\s*)?)*?([a-zA-Z_][a-zA-Z0-9_]*)\s*\(([^;]*?)\)\s*\{/);
|
|
147
|
+
if (funcMatch && !C_KEYWORDS.has(funcMatch[1]) && !funcMatch[1].startsWith('__')) {
|
|
148
|
+
const funcName = funcMatch[1];
|
|
149
|
+
const startLine = bufStart;
|
|
150
|
+
let braceCount = 0;
|
|
151
|
+
const calls = [];
|
|
152
|
+
// Find the opening brace position
|
|
153
|
+
const braceIdx = buf.indexOf('{', funcMatch.index + funcMatch[0].length - 1);
|
|
154
|
+
if (braceIdx >= 0)
|
|
155
|
+
braceCount = 1;
|
|
156
|
+
// Advance i past the current line if it's been consumed in buf
|
|
157
|
+
i++;
|
|
158
|
+
let bodyLines = 0;
|
|
159
|
+
while (i < lines.length && braceCount > 0) {
|
|
160
|
+
const currentLine = lines[i];
|
|
161
|
+
for (const char of currentLine) {
|
|
162
|
+
if (char === '{')
|
|
163
|
+
braceCount++;
|
|
164
|
+
else if (char === '}')
|
|
165
|
+
braceCount--;
|
|
166
|
+
}
|
|
167
|
+
if (braceCount > 0) {
|
|
168
|
+
bodyLines++;
|
|
169
|
+
if (bodyLines <= maxBodyLines) {
|
|
170
|
+
const callMatches = currentLine.matchAll(/\b([a-zA-Z_][a-zA-Z0-9_]*)\s*\(/g);
|
|
171
|
+
for (const cm of callMatches) {
|
|
172
|
+
const called = cm[1];
|
|
173
|
+
if (!C_KEYWORDS.has(called) && !called.startsWith('__')) {
|
|
174
|
+
calls.push(called);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
// Capture goto targets as synthetic calls (goto cleanup → "goto_cleanup")
|
|
178
|
+
const gotoMatches = currentLine.matchAll(/\bgoto\s+([a-zA-Z_][a-zA-Z0-9_]*)\b/g);
|
|
179
|
+
for (const gm of gotoMatches) {
|
|
180
|
+
calls.push(`goto_${gm[1]}`);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
i++;
|
|
185
|
+
}
|
|
186
|
+
if (bodyLines <= maxBodyLines && calls.length > 0) {
|
|
187
|
+
sequences.push({
|
|
188
|
+
functionName: funcName,
|
|
189
|
+
filePath,
|
|
190
|
+
lineNumber: startLine + 1,
|
|
191
|
+
calls,
|
|
192
|
+
bodyLength: bodyLines,
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
else {
|
|
197
|
+
i++;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
return sequences;
|
|
201
|
+
}
|
|
202
|
+
function extractFromTSFile(filePath, maxBodyLines) {
|
|
203
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
204
|
+
const lines = content.split('\n');
|
|
205
|
+
const sequences = [];
|
|
206
|
+
const funcRegex = /(?:function\s+|(?:const|let|var)\s+)([a-zA-Z_$][a-zA-Z0-9_$]*)\s*(?:=)?\s*(?:\([^)]*\)\s*=>|\([^)]*\)\s*\{)/;
|
|
207
|
+
let i = 0;
|
|
208
|
+
while (i < lines.length) {
|
|
209
|
+
const line = lines[i];
|
|
210
|
+
const match = line.match(funcRegex);
|
|
211
|
+
if (match) {
|
|
212
|
+
const funcName = match[1];
|
|
213
|
+
const startLine = i;
|
|
214
|
+
let braceCount = line.includes('{') ? 1 : 0;
|
|
215
|
+
let bodyLines = 0;
|
|
216
|
+
const calls = [];
|
|
217
|
+
i++;
|
|
218
|
+
while (i < lines.length && braceCount > 0) {
|
|
219
|
+
const currentLine = lines[i];
|
|
220
|
+
for (const char of currentLine) {
|
|
221
|
+
if (char === '{')
|
|
222
|
+
braceCount++;
|
|
223
|
+
else if (char === '}')
|
|
224
|
+
braceCount--;
|
|
225
|
+
}
|
|
226
|
+
if (braceCount > 0) {
|
|
227
|
+
bodyLines++;
|
|
228
|
+
const callMatches = currentLine.matchAll(/\b([a-zA-Z_$][a-zA-Z0-9_$]*)\s*\(/g);
|
|
229
|
+
for (const cm of callMatches) {
|
|
230
|
+
const called = cm[1];
|
|
231
|
+
if (!['if', 'for', 'while', 'switch', 'return', 'console', 'require', 'import'].includes(called)) {
|
|
232
|
+
calls.push(called);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
i++;
|
|
237
|
+
}
|
|
238
|
+
if (bodyLines <= maxBodyLines && calls.length > 0) {
|
|
239
|
+
sequences.push({
|
|
240
|
+
functionName: funcName,
|
|
241
|
+
filePath,
|
|
242
|
+
lineNumber: startLine + 1,
|
|
243
|
+
calls,
|
|
244
|
+
bodyLength: bodyLines,
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
else {
|
|
249
|
+
i++;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
return sequences;
|
|
253
|
+
}
|
|
254
|
+
function extractFromPythonFile(filePath, maxBodyLines) {
|
|
255
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
256
|
+
const lines = content.split('\n');
|
|
257
|
+
const sequences = [];
|
|
258
|
+
const funcRegex = /^\s*def\s+([a-zA-Z_][a-zA-Z0-9_]*)\s*\(/;
|
|
259
|
+
let i = 0;
|
|
260
|
+
while (i < lines.length) {
|
|
261
|
+
const line = lines[i];
|
|
262
|
+
const match = line.match(funcRegex);
|
|
263
|
+
if (match) {
|
|
264
|
+
const funcName = match[1];
|
|
265
|
+
const startLine = i;
|
|
266
|
+
let bodyLines = 0;
|
|
267
|
+
let indentLevel = 0;
|
|
268
|
+
const calls = [];
|
|
269
|
+
i++;
|
|
270
|
+
// Extract decorators above the function definition
|
|
271
|
+
for (let j = startLine - 1; j >= 0; j--) {
|
|
272
|
+
const decLine = lines[j].trim();
|
|
273
|
+
if (decLine.startsWith('@')) {
|
|
274
|
+
const decMatch = decLine.match(/^@(\w+(?:\.\w+)*)/);
|
|
275
|
+
if (decMatch)
|
|
276
|
+
calls.push(`@${decMatch[1]}`);
|
|
277
|
+
}
|
|
278
|
+
else if (decLine !== '') {
|
|
279
|
+
break; // stop at first non-decorator, non-blank line
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
// 找到函数体的缩进级别
|
|
283
|
+
const indentMatch = lines[i].match(/^(\s*)/);
|
|
284
|
+
if (indentMatch) {
|
|
285
|
+
indentLevel = indentMatch[1].length;
|
|
286
|
+
}
|
|
287
|
+
while (i < lines.length) {
|
|
288
|
+
const currentLine = lines[i];
|
|
289
|
+
const currentIndent = currentLine.match(/^(\s*)/);
|
|
290
|
+
const indent = currentIndent ? currentIndent[1].length : 0;
|
|
291
|
+
if (indent <= indentLevel && currentLine.trim() !== '') {
|
|
292
|
+
break;
|
|
293
|
+
}
|
|
294
|
+
bodyLines++;
|
|
295
|
+
const callMatches = currentLine.matchAll(/\b([a-zA-Z_][a-zA-Z0-9_]*)\s*\(/g);
|
|
296
|
+
for (const cm of callMatches) {
|
|
297
|
+
const called = cm[1];
|
|
298
|
+
if (!PYTHON_EXCLUDED.has(called)) {
|
|
299
|
+
calls.push(called);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
i++;
|
|
303
|
+
}
|
|
304
|
+
if (bodyLines <= maxBodyLines && calls.length > 0) {
|
|
305
|
+
sequences.push({
|
|
306
|
+
functionName: funcName,
|
|
307
|
+
filePath,
|
|
308
|
+
lineNumber: startLine + 1,
|
|
309
|
+
calls,
|
|
310
|
+
bodyLength: bodyLines,
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
else {
|
|
315
|
+
i++;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
return sequences;
|
|
319
|
+
}
|
|
320
|
+
function findFiles(dir, include, exclude) {
|
|
321
|
+
const results = [];
|
|
322
|
+
if (!fs.existsSync(dir))
|
|
323
|
+
return results;
|
|
324
|
+
const items = fs.readdirSync(dir, { withFileTypes: true });
|
|
325
|
+
for (const item of items) {
|
|
326
|
+
const fullPath = path.join(dir, item.name);
|
|
327
|
+
if (item.isDirectory()) {
|
|
328
|
+
if (!exclude.test(item.name)) {
|
|
329
|
+
results.push(...findFiles(fullPath, include, exclude));
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
else if (include.test(item.name)) {
|
|
333
|
+
results.push(fullPath);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
return results;
|
|
337
|
+
}
|
|
338
|
+
function isCProject(dir) {
|
|
339
|
+
if (!fs.existsSync(dir))
|
|
340
|
+
return false;
|
|
341
|
+
const files = fs.readdirSync(dir);
|
|
342
|
+
return files.some(f => f.endsWith('.c'));
|
|
343
|
+
}
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* P5.1: Skill Library
|
|
4
|
+
*
|
|
5
|
+
* Formalizes MacroGraph nodes into a queryable, composable skill catalog.
|
|
6
|
+
*
|
|
7
|
+
* A Skill is a named, reusable action sequence with known preconditions,
|
|
8
|
+
* effects, and success metrics. It abstracts the low-level action space
|
|
9
|
+
* into a higher-level skill space, reducing planner search depth.
|
|
10
|
+
*
|
|
11
|
+
* Three-level hierarchy:
|
|
12
|
+
* Goal → Skill → Action
|
|
13
|
+
* (what) (how) (primitive)
|
|
14
|
+
*
|
|
15
|
+
* Example:
|
|
16
|
+
* Goal: "safely write config file"
|
|
17
|
+
* Skill: safe_file_write
|
|
18
|
+
* Macro: [open_file, write_file, close_file]
|
|
19
|
+
* Effect: FILE_OPEN → FILE_DIRTY → FILE_CLOSED
|
|
20
|
+
*/
|
|
21
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
22
|
+
if (k2 === undefined) k2 = k;
|
|
23
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
24
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
25
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
26
|
+
}
|
|
27
|
+
Object.defineProperty(o, k2, desc);
|
|
28
|
+
}) : (function(o, m, k, k2) {
|
|
29
|
+
if (k2 === undefined) k2 = k;
|
|
30
|
+
o[k2] = m[k];
|
|
31
|
+
}));
|
|
32
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
33
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
34
|
+
}) : function(o, v) {
|
|
35
|
+
o["default"] = v;
|
|
36
|
+
});
|
|
37
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
38
|
+
var ownKeys = function(o) {
|
|
39
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
40
|
+
var ar = [];
|
|
41
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
42
|
+
return ar;
|
|
43
|
+
};
|
|
44
|
+
return ownKeys(o);
|
|
45
|
+
};
|
|
46
|
+
return function (mod) {
|
|
47
|
+
if (mod && mod.__esModule) return mod;
|
|
48
|
+
var result = {};
|
|
49
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
50
|
+
__setModuleDefault(result, mod);
|
|
51
|
+
return result;
|
|
52
|
+
};
|
|
53
|
+
})();
|
|
54
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
55
|
+
exports.SkillLibrary = void 0;
|
|
56
|
+
exports.printSkillLibrary = printSkillLibrary;
|
|
57
|
+
const fs = __importStar(require("fs"));
|
|
58
|
+
const path = __importStar(require("path"));
|
|
59
|
+
const macro_graph_1 = require("./macro-graph");
|
|
60
|
+
const SKILL_DIR = path.resolve(process.env.PROGMUNE_PROJECT_DIR || process.cwd(), ".progmune_corpus", "skills");
|
|
61
|
+
function ensureDir(dir) {
|
|
62
|
+
if (!fs.existsSync(dir))
|
|
63
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
64
|
+
}
|
|
65
|
+
// ═══════════════════════════════════════════════════════════════
|
|
66
|
+
// Skill Library
|
|
67
|
+
// ═══════════════════════════════════════════════════════════════
|
|
68
|
+
class SkillLibrary {
|
|
69
|
+
constructor() {
|
|
70
|
+
this.skills = new Map();
|
|
71
|
+
/** Index: effects → skills that produce this effect. */
|
|
72
|
+
this.byEffect = new Map();
|
|
73
|
+
/** Index: preconditions → skills that require this state. */
|
|
74
|
+
this.byPrecond = new Map();
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Learn skills from telemetry via MacroGraph mining.
|
|
78
|
+
*/
|
|
79
|
+
learn(telemetry, rules) {
|
|
80
|
+
const builder = new macro_graph_1.MacroGraphBuilder();
|
|
81
|
+
const graph = builder.learnMacros(telemetry, rules, 0.7, 3);
|
|
82
|
+
for (const [, node] of graph.nodes) {
|
|
83
|
+
this.addSkill(nodeToSkill(node));
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
/** Add a skill to the library, updating indexes. */
|
|
87
|
+
addSkill(skill) {
|
|
88
|
+
this.skills.set(skill.id, skill);
|
|
89
|
+
for (const effect of skill.effects) {
|
|
90
|
+
const list = this.byEffect.get(effect) || [];
|
|
91
|
+
list.push(skill);
|
|
92
|
+
this.byEffect.set(effect, list);
|
|
93
|
+
}
|
|
94
|
+
for (const pre of skill.preconditions) {
|
|
95
|
+
const list = this.byPrecond.get(pre) || [];
|
|
96
|
+
list.push(skill);
|
|
97
|
+
this.byPrecond.set(pre, list);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Find skills whose preconditions are satisfied by current state.
|
|
102
|
+
*/
|
|
103
|
+
findApplicable(currentStates) {
|
|
104
|
+
const currentSet = new Set(currentStates);
|
|
105
|
+
return [...this.skills.values()].filter(s => s.preconditions.length === 0 || s.preconditions.every(p => currentSet.has(p)));
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Find skills that produce a target state (effect match).
|
|
109
|
+
*/
|
|
110
|
+
findProducers(targetState) {
|
|
111
|
+
return this.byEffect.get(targetState) || [];
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Compose a skill chain from current state to goal state.
|
|
115
|
+
*
|
|
116
|
+
* Returns the shortest chain (by skill count) that transforms
|
|
117
|
+
* currentStates into a state set containing targetStates.
|
|
118
|
+
*/
|
|
119
|
+
compose(currentStates, targetStates, maxDepth = 4) {
|
|
120
|
+
const chains = [];
|
|
121
|
+
const currentSet = new Set(currentStates);
|
|
122
|
+
// BFS over skill space
|
|
123
|
+
const visited = new Set();
|
|
124
|
+
const queue = [];
|
|
125
|
+
// Seed: skills that can fire from current state
|
|
126
|
+
const startable = this.findApplicable(currentStates);
|
|
127
|
+
for (const s of startable) {
|
|
128
|
+
const next = new Set(currentStates);
|
|
129
|
+
for (const e of s.effects)
|
|
130
|
+
next.add(e);
|
|
131
|
+
queue.push({ skills: [s], states: next, depth: 1 });
|
|
132
|
+
visited.add(s.id);
|
|
133
|
+
}
|
|
134
|
+
while (queue.length > 0 && chains.length < 10) {
|
|
135
|
+
const { skills, states, depth } = queue.shift();
|
|
136
|
+
if (depth > maxDepth)
|
|
137
|
+
continue;
|
|
138
|
+
// Target reached?
|
|
139
|
+
if (targetStates.length > 0 && targetStates.every(t => states.has(t))) {
|
|
140
|
+
chains.push(skills);
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
// Try the next skill
|
|
144
|
+
const nextSkills = this.findApplicable([...states]);
|
|
145
|
+
for (const ns of nextSkills) {
|
|
146
|
+
if (skills.some(s => s.id === ns.id))
|
|
147
|
+
continue; // no cycles
|
|
148
|
+
const key = skills.map(s => s.id).join("→") + "→" + ns.id;
|
|
149
|
+
if (visited.has(key))
|
|
150
|
+
continue;
|
|
151
|
+
visited.add(key);
|
|
152
|
+
const next = new Set(states);
|
|
153
|
+
for (const e of ns.effects)
|
|
154
|
+
next.add(e);
|
|
155
|
+
queue.push({ skills: [...skills, ns], states: next, depth: depth + 1 });
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
// Sort by success rate (descending)
|
|
159
|
+
chains.sort((a, b) => {
|
|
160
|
+
const rA = a.reduce((s, sk) => s + sk.successRate, 0) / a.length;
|
|
161
|
+
const rB = b.reduce((s, sk) => s + sk.successRate, 0) / b.length;
|
|
162
|
+
return rB - rA;
|
|
163
|
+
});
|
|
164
|
+
return chains;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Expand a skill chain into a flat action sequence.
|
|
168
|
+
*/
|
|
169
|
+
expand(skills) {
|
|
170
|
+
return skills.flatMap(s => s.macro);
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Expand a single skill by name into its action sequence.
|
|
174
|
+
*/
|
|
175
|
+
expandSkill(skillId) {
|
|
176
|
+
const skill = this.skills.get(skillId);
|
|
177
|
+
return skill ? [...skill.macro] : null;
|
|
178
|
+
}
|
|
179
|
+
/** All skills in the library. */
|
|
180
|
+
all() {
|
|
181
|
+
return [...this.skills.values()].sort((a, b) => b.successRate - a.successRate);
|
|
182
|
+
}
|
|
183
|
+
/** Number of skills. */
|
|
184
|
+
get size() { return this.skills.size; }
|
|
185
|
+
// ── Persistence ──
|
|
186
|
+
save(filepath) {
|
|
187
|
+
ensureDir(SKILL_DIR);
|
|
188
|
+
const fp = filepath || path.join(SKILL_DIR, `skills-${new Date().toISOString().slice(0, 10)}.json`);
|
|
189
|
+
fs.writeFileSync(fp, JSON.stringify([...this.skills.values()], null, 2));
|
|
190
|
+
return fp;
|
|
191
|
+
}
|
|
192
|
+
load(filepath) {
|
|
193
|
+
const fp = filepath || path.join(SKILL_DIR, `skills-${new Date().toISOString().slice(0, 10)}.json`);
|
|
194
|
+
if (!fs.existsSync(fp))
|
|
195
|
+
return;
|
|
196
|
+
try {
|
|
197
|
+
const data = JSON.parse(fs.readFileSync(fp, "utf-8"));
|
|
198
|
+
for (const s of data)
|
|
199
|
+
this.addSkill(s);
|
|
200
|
+
}
|
|
201
|
+
catch { /* empty or corrupted */ }
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
exports.SkillLibrary = SkillLibrary;
|
|
205
|
+
// ═══════════════════════════════════════════════════════════════
|
|
206
|
+
// Helpers
|
|
207
|
+
// ═══════════════════════════════════════════════════════════════
|
|
208
|
+
function nodeToSkill(node) {
|
|
209
|
+
// Infer a goal description from the action names
|
|
210
|
+
const goalPattern = node.actions
|
|
211
|
+
.map(fn => fn.replace(/_/g, " "))
|
|
212
|
+
.join(" then ");
|
|
213
|
+
return {
|
|
214
|
+
id: node.id,
|
|
215
|
+
goal: goalPattern,
|
|
216
|
+
protocol: node.protocol,
|
|
217
|
+
preconditions: node.preconditions,
|
|
218
|
+
effects: node.postconditions,
|
|
219
|
+
macro: node.actions,
|
|
220
|
+
successRate: node.reward,
|
|
221
|
+
acceptanceRate: node.reward,
|
|
222
|
+
frequency: node.frequency,
|
|
223
|
+
avgLatencyMs: node.source?.avgLatencyMs || 0,
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
function printSkillLibrary(library) {
|
|
227
|
+
console.log("\n─── Skill Library ───");
|
|
228
|
+
console.log(`Skills: ${library.size}`);
|
|
229
|
+
console.log();
|
|
230
|
+
const skills = library.all();
|
|
231
|
+
if (skills.length === 0) {
|
|
232
|
+
console.log(" No skills learned yet. Collect more feedback data.");
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
console.log("Success Accept Freq Skill");
|
|
236
|
+
console.log("──────────────────────────────────────────────────");
|
|
237
|
+
for (const s of skills.slice(0, 15)) {
|
|
238
|
+
const succ = (s.successRate * 100).toFixed(0).padStart(4);
|
|
239
|
+
const acc = (s.acceptanceRate * 100).toFixed(0).padStart(4);
|
|
240
|
+
const freq = String(s.frequency).padStart(4);
|
|
241
|
+
console.log(` ${succ}% ${acc}% ${freq} ${s.goal}`);
|
|
242
|
+
console.log(` protocol: ${s.protocol.padEnd(12)} pre: [${s.preconditions.join(",") || "none"}] → [${s.effects.join(",") || "none"}]`);
|
|
243
|
+
}
|
|
244
|
+
console.log();
|
|
245
|
+
}
|