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,260 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Identifier Parser — decompose compound identifiers into semantic tokens.
|
|
4
|
+
*
|
|
5
|
+
* The \b boundary in regex fails on compound names:
|
|
6
|
+
* registerNewUser → \bregister\b doesn't match
|
|
7
|
+
* doLogin → \blogin\b doesn't match
|
|
8
|
+
* performAuthentication → \bauthenticate\b doesn't match
|
|
9
|
+
*
|
|
10
|
+
* This parser splits camelCase/snake_case identifiers and
|
|
11
|
+
* extracts verbs, entities, and actions from compound names.
|
|
12
|
+
*
|
|
13
|
+
* Not AST. Just smarter string splitting.
|
|
14
|
+
*
|
|
15
|
+
* Examples:
|
|
16
|
+
* registerNewUser → tokens: [register, new, user] → verb: register
|
|
17
|
+
* doLogin → tokens: [do, login] → verb: login
|
|
18
|
+
* performAuthentication → tokens: [perform, authentication] → verb: authenticate
|
|
19
|
+
* verifyTokenSignature → tokens: [verify, token, signature] → verb: verify
|
|
20
|
+
*/
|
|
21
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
|
+
exports.tokenize = tokenize;
|
|
23
|
+
exports.stripCPrefix = stripCPrefix;
|
|
24
|
+
exports.isCNaming = isCNaming;
|
|
25
|
+
exports.parseIdentifier = parseIdentifier;
|
|
26
|
+
exports.enrichCalls = enrichCalls;
|
|
27
|
+
// ═══════════════════════════════════════════════════════════════
|
|
28
|
+
// Tokenizer
|
|
29
|
+
// ═══════════════════════════════════════════════════════════════
|
|
30
|
+
/**
|
|
31
|
+
* Split a camelCase or PascalCase identifier into lowercase tokens.
|
|
32
|
+
* Optionally strips C project prefixes before tokenizing.
|
|
33
|
+
*/
|
|
34
|
+
function tokenize(identifier, options) {
|
|
35
|
+
let name = identifier;
|
|
36
|
+
if (options?.stripCPrefix) {
|
|
37
|
+
name = stripCPrefix(identifier);
|
|
38
|
+
}
|
|
39
|
+
// Split on camelCase boundaries
|
|
40
|
+
const tokens = [];
|
|
41
|
+
let current = "";
|
|
42
|
+
for (let i = 0; i < name.length; i++) {
|
|
43
|
+
const ch = name[i];
|
|
44
|
+
if (ch >= "A" && ch <= "Z" && current.length > 0) {
|
|
45
|
+
tokens.push(current.toLowerCase());
|
|
46
|
+
current = ch;
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
current += ch;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
if (current.length > 0) {
|
|
53
|
+
tokens.push(current.toLowerCase());
|
|
54
|
+
}
|
|
55
|
+
// Also split on underscores
|
|
56
|
+
const flat = [];
|
|
57
|
+
for (const t of tokens) {
|
|
58
|
+
flat.push(...t.split("_").filter(Boolean));
|
|
59
|
+
}
|
|
60
|
+
return flat.filter(t => t.length >= 2);
|
|
61
|
+
}
|
|
62
|
+
// ═══════════════════════════════════════════════════════════════
|
|
63
|
+
// Verb Database
|
|
64
|
+
// ═══════════════════════════════════════════════════════════════
|
|
65
|
+
const VERB_SYNONYMS = {
|
|
66
|
+
// Registration / Auth
|
|
67
|
+
register: "register", signup: "register", signUp: "register", createAccount: "register",
|
|
68
|
+
login: "login", signin: "login", signIn: "login", logon: "login", authenticate: "login",
|
|
69
|
+
logout: "logout", signout: "logout", signOut: "logout", logoff: "logout",
|
|
70
|
+
// CRUD
|
|
71
|
+
create: "create", add: "create", insert: "create", new: "create", make: "create", build: "create",
|
|
72
|
+
delete: "delete", remove: "delete", destroy: "delete", drop: "delete", clear: "delete", erase: "delete",
|
|
73
|
+
update: "update", edit: "update", modify: "update", change: "update", set: "update", put: "update",
|
|
74
|
+
get: "get", fetch: "get", retrieve: "get", read: "get", load: "get", find: "get", query: "get",
|
|
75
|
+
list: "list", search: "list", all: "list", browse: "list", enumerate: "list",
|
|
76
|
+
// Actions
|
|
77
|
+
assign: "assign", transfer: "transfer", share: "share", schedule: "schedule",
|
|
78
|
+
upload: "upload", download: "download", send: "send", post: "post", publish: "post",
|
|
79
|
+
process: "process", verify: "verify", validate: "validate", check: "verify",
|
|
80
|
+
authorize: "authorize", permit: "authorize", allow: "authorize",
|
|
81
|
+
toggle: "toggle", lock: "lock", unlock: "unlock", enable: "enable", disable: "disable",
|
|
82
|
+
perform: "perform", execute: "execute", run: "execute", do: "do",
|
|
83
|
+
start: "start", begin: "start", stop: "stop", end: "stop", cancel: "cancel", abort: "cancel",
|
|
84
|
+
// ── C Verbs (additive only — no duplicates with entries above) ──
|
|
85
|
+
init: "init", initialize: "init", initialise: "init",
|
|
86
|
+
config: "config", configure: "config", cfg: "config", setup: "config",
|
|
87
|
+
handshake: "connect", negotiate: "connect",
|
|
88
|
+
free: "free", cleanup: "free", dispose: "free",
|
|
89
|
+
alloc: "alloc", allocate: "alloc", malloc: "alloc", calloc: "alloc", realloc: "alloc",
|
|
90
|
+
kex: "kex", ecdh: "ecdh", dh: "dh", curve: "curve", derive: "derive",
|
|
91
|
+
bind: "bind", listen: "listen", accept: "accept",
|
|
92
|
+
recv: "recv", write: "write",
|
|
93
|
+
open: "open", close: "close", shutdown: "close",
|
|
94
|
+
pin: "pin", cert: "cert", certificate: "cert",
|
|
95
|
+
poll: "poll",
|
|
96
|
+
parse: "parse", decode: "decode", encode: "encode",
|
|
97
|
+
copy: "copy", move: "move", rename: "rename",
|
|
98
|
+
hash: "hash", sign: "sign", encrypt: "encrypt", decrypt: "decrypt",
|
|
99
|
+
seed: "seed", random: "random", generate: "generate",
|
|
100
|
+
finish: "finish", complete: "finish", done: "finish",
|
|
101
|
+
reset: "reset", restart: "reset", reload: "reset",
|
|
102
|
+
flush: "flush", sync: "sync", commit: "commit", rollback: "rollback",
|
|
103
|
+
};
|
|
104
|
+
/**
|
|
105
|
+
* Map a token to its canonical verb form.
|
|
106
|
+
* Handles common suffixes: authentication→authenticate, verification→verify, etc.
|
|
107
|
+
*/
|
|
108
|
+
function canonicalVerb(token) {
|
|
109
|
+
// Direct match
|
|
110
|
+
if (VERB_SYNONYMS[token])
|
|
111
|
+
return VERB_SYNONYMS[token];
|
|
112
|
+
// Stemming: authentication → authenticate, registration → register
|
|
113
|
+
const stemMap = {
|
|
114
|
+
authentication: "authenticate", registration: "register",
|
|
115
|
+
verification: "verify", validation: "validate",
|
|
116
|
+
authorization: "authorize", creation: "create",
|
|
117
|
+
deletion: "delete", modification: "modify", updation: "update",
|
|
118
|
+
assignment: "assign", transfer: "transfer",
|
|
119
|
+
execution: "execute", cancellation: "cancel",
|
|
120
|
+
notification: "notify", publication: "publish",
|
|
121
|
+
// C-style stems
|
|
122
|
+
initialization: "init", initialisation: "init",
|
|
123
|
+
configuration: "config", allocation: "alloc",
|
|
124
|
+
negotiation: "negotiate", connection: "connect",
|
|
125
|
+
derivation: "derive", generation: "generate",
|
|
126
|
+
encryption: "encrypt", decryption: "decrypt",
|
|
127
|
+
completion: "finish", destruction: "destroy",
|
|
128
|
+
};
|
|
129
|
+
if (stemMap[token])
|
|
130
|
+
return stemMap[token];
|
|
131
|
+
// -ize / -ise suffix: finalize→final, synchronize→sync, sanitize→sanitize
|
|
132
|
+
if (token.endsWith("ize") || token.endsWith("ise")) {
|
|
133
|
+
const base = token.slice(0, token.endsWith("ize") ? -3 : -3);
|
|
134
|
+
if (VERB_SYNONYMS[base])
|
|
135
|
+
return VERB_SYNONYMS[base];
|
|
136
|
+
return base; // finalize → final, sanitize → sanitize
|
|
137
|
+
}
|
|
138
|
+
// Common suffixes: -ing, -ed, -ion
|
|
139
|
+
if (token.endsWith("ing")) {
|
|
140
|
+
const base = token.slice(0, -3);
|
|
141
|
+
if (VERB_SYNONYMS[base])
|
|
142
|
+
return VERB_SYNONYMS[base];
|
|
143
|
+
// running → run, stopping → stop
|
|
144
|
+
if (base.endsWith("nn"))
|
|
145
|
+
return base.slice(0, -1); // running → run
|
|
146
|
+
if (base.endsWith("pp"))
|
|
147
|
+
return base.slice(0, -1); // stopping → stop
|
|
148
|
+
return base; // creating → create
|
|
149
|
+
}
|
|
150
|
+
if (token.endsWith("ed")) {
|
|
151
|
+
const base = token.slice(0, -2);
|
|
152
|
+
if (VERB_SYNONYMS[base])
|
|
153
|
+
return VERB_SYNONYMS[base];
|
|
154
|
+
if (base.endsWith("i"))
|
|
155
|
+
return base.slice(0, -1) + "y"; // verified → verify
|
|
156
|
+
return base; // created → create
|
|
157
|
+
}
|
|
158
|
+
return null;
|
|
159
|
+
}
|
|
160
|
+
// ═══════════════════════════════════════════════════════════════
|
|
161
|
+
// C Prefix Stripping
|
|
162
|
+
// ═══════════════════════════════════════════════════════════════
|
|
163
|
+
/**
|
|
164
|
+
* Known C project/library prefixes that hide semantic verbs.
|
|
165
|
+
* Curl_conn_connect → after stripping: conn_connect
|
|
166
|
+
* ssh_userauth_agent → after stripping: userauth_agent
|
|
167
|
+
*/
|
|
168
|
+
const C_PROJECT_PREFIXES = [
|
|
169
|
+
"Curl_", "curl_", "mbedtls_", "mbed_", "ngx_", "ossl_",
|
|
170
|
+
"SSL_", "ssh_", "EC_", "EC_KEY_", "EVP_", "DH_", "BN_",
|
|
171
|
+
"BIO_", "X509_", "SSL_CTX_", "wolfSSL_", "gtls_", "gcry_",
|
|
172
|
+
"OSSL_PARAM_", "OPENSSL_", "CONF_",
|
|
173
|
+
];
|
|
174
|
+
/**
|
|
175
|
+
* Strip known C project prefixes from a function name.
|
|
176
|
+
* For example: Curl_auth_create_ntlm_type1_message → auth_create_ntlm_type1_message
|
|
177
|
+
*/
|
|
178
|
+
function stripCPrefix(name) {
|
|
179
|
+
for (const prefix of C_PROJECT_PREFIXES) {
|
|
180
|
+
if (name.startsWith(prefix))
|
|
181
|
+
return name.slice(prefix.length);
|
|
182
|
+
}
|
|
183
|
+
return name;
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Detect if an identifier looks like C naming (has known C prefix or is all snake_case).
|
|
187
|
+
*/
|
|
188
|
+
function isCNaming(name) {
|
|
189
|
+
// Check known C prefixes
|
|
190
|
+
for (const prefix of C_PROJECT_PREFIXES) {
|
|
191
|
+
if (name.startsWith(prefix))
|
|
192
|
+
return true;
|
|
193
|
+
}
|
|
194
|
+
// Check if it's pure snake_case with no camelCase boundaries
|
|
195
|
+
if (name.includes("_") && !/[a-z][A-Z]/.test(name))
|
|
196
|
+
return true;
|
|
197
|
+
return false;
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Parse a function name into semantic components.
|
|
201
|
+
*
|
|
202
|
+
* registerNewUser → { verb: "register", entity: "user", isMutate: true }
|
|
203
|
+
* getContact → { verb: "get", entity: "contact", isRead: true }
|
|
204
|
+
* doLogin → { verb: "login", entity: null, isMutate: true }
|
|
205
|
+
*/
|
|
206
|
+
function parseIdentifier(functionName, options) {
|
|
207
|
+
const tokens = tokenize(functionName, options);
|
|
208
|
+
let verb = null;
|
|
209
|
+
let entity = null;
|
|
210
|
+
// Find the first meaningful verb token
|
|
211
|
+
// Skip helper prefixes: do, perform, execute, run
|
|
212
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
213
|
+
// If this is a helper prefix and there's a next token, use the next token as verb
|
|
214
|
+
if (["do", "perform", "execute", "run"].includes(tokens[i]) && i + 1 < tokens.length) {
|
|
215
|
+
const nextCv = canonicalVerb(tokens[i + 1]);
|
|
216
|
+
if (nextCv) {
|
|
217
|
+
verb = nextCv;
|
|
218
|
+
entity = tokens.slice(i + 2).filter(t => t.length >= 2 && !["new", "the", "for", "by", "to", "of", "in", "on", "at"].includes(t)).join("_") || null;
|
|
219
|
+
break;
|
|
220
|
+
}
|
|
221
|
+
// Even without canonical form, use the next token as verb
|
|
222
|
+
verb = tokens[i + 1];
|
|
223
|
+
entity = tokens.slice(i + 2).filter(t => t.length >= 2).join("_") || null;
|
|
224
|
+
break;
|
|
225
|
+
}
|
|
226
|
+
const cv = canonicalVerb(tokens[i]);
|
|
227
|
+
if (cv) {
|
|
228
|
+
verb = cv;
|
|
229
|
+
// Entity = remaining tokens after the verb
|
|
230
|
+
const remaining = tokens.slice(i + 1).filter(t => t.length >= 2 && !["new", "the", "for", "by", "to", "of", "in", "on", "at", "my", "our", "all", "one"].includes(t));
|
|
231
|
+
if (remaining.length > 0) {
|
|
232
|
+
entity = remaining.join("_");
|
|
233
|
+
}
|
|
234
|
+
break;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
// If no canonical verb found, use the first token as-is
|
|
238
|
+
if (!verb && tokens.length > 0) {
|
|
239
|
+
verb = tokens[0];
|
|
240
|
+
if (tokens.length > 1) {
|
|
241
|
+
entity = tokens.slice(1).join("_");
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
const readVerbs = new Set(["get", "fetch", "retrieve", "read", "load", "find", "query", "list", "search", "browse", "view"]);
|
|
245
|
+
const mutateVerbs = new Set(["create", "add", "insert", "delete", "remove", "destroy", "update", "edit", "modify", "set", "register", "login", "logout", "assign", "transfer", "share", "upload", "send", "post", "process", "toggle", "lock", "unlock", "execute", "perform", "cancel"]);
|
|
246
|
+
return {
|
|
247
|
+
original: functionName,
|
|
248
|
+
tokens,
|
|
249
|
+
verb,
|
|
250
|
+
entity,
|
|
251
|
+
isRead: verb !== null && readVerbs.has(verb),
|
|
252
|
+
isMutate: verb !== null && mutateVerbs.has(verb),
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Parse all function names in a call list and return enriched call data.
|
|
257
|
+
*/
|
|
258
|
+
function enrichCalls(calls) {
|
|
259
|
+
return calls.map(c => parseIdentifier(c));
|
|
260
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Immune Metrics — real-time tracking of immune system efficacy.
|
|
4
|
+
*
|
|
5
|
+
* Tracks:
|
|
6
|
+
* 1. Immune repair success rate (antibody hits → successful repairs)
|
|
7
|
+
* 2. Token savings from L1 hints + L2 fast paths
|
|
8
|
+
* 3. Credit-weighted vs unweighted planning success delta
|
|
9
|
+
*
|
|
10
|
+
* These metrics answer: "Is the knowledge layer actually improving outcomes?"
|
|
11
|
+
*/
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.computeImmuneMetrics = computeImmuneMetrics;
|
|
14
|
+
exports.formatImmuneMetrics = formatImmuneMetrics;
|
|
15
|
+
exports.reportImmuneMetrics = reportImmuneMetrics;
|
|
16
|
+
const failure_corpus_1 = require("./failure-corpus");
|
|
17
|
+
const feedback_1 = require("./feedback");
|
|
18
|
+
/**
|
|
19
|
+
* Compute live immune metrics from the current corpus.
|
|
20
|
+
*/
|
|
21
|
+
function computeImmuneMetrics() {
|
|
22
|
+
const stats = (0, failure_corpus_1.getAntibodyStats)();
|
|
23
|
+
const genome = (0, failure_corpus_1.getFailureGenome)();
|
|
24
|
+
const learned = (0, failure_corpus_1.getLearnedPatterns)();
|
|
25
|
+
// Estimate token savings: L2 fast path = full prompt saved, L1 hint = ~200 tokens overhead
|
|
26
|
+
const TOKENS_PER_LLM_CALL = 800;
|
|
27
|
+
const tokensSaved = stats.fastPathHits * TOKENS_PER_LLM_CALL + stats.injectedHintHits * 200;
|
|
28
|
+
// Immune repair rate: what fraction of sessions with antibody hits resolved?
|
|
29
|
+
const immuneRepairRate = stats.totalHits > 0
|
|
30
|
+
? (stats.fastPathHits + stats.injectedHintHits * 0.7) / stats.totalHits
|
|
31
|
+
: 0;
|
|
32
|
+
// Count functions with non-Laplace credit scores
|
|
33
|
+
let functionsWithHistory = 0;
|
|
34
|
+
let creditSum = 0;
|
|
35
|
+
let creditCount = 0;
|
|
36
|
+
for (const p of learned.failureToFix) {
|
|
37
|
+
for (const fn of (p.fixPath || [])) {
|
|
38
|
+
const credit = (0, feedback_1.getFailureAdjustedCredit)(fn);
|
|
39
|
+
if (credit !== 0.5)
|
|
40
|
+
functionsWithHistory++;
|
|
41
|
+
creditSum += credit;
|
|
42
|
+
creditCount++;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
const avgCreditScore = creditCount > 0 ? creditSum / creditCount : 0.5;
|
|
46
|
+
return {
|
|
47
|
+
totalAntibodyHits: stats.totalHits,
|
|
48
|
+
fastPathHits: stats.fastPathHits,
|
|
49
|
+
injectedHints: stats.injectedHintHits,
|
|
50
|
+
llmCallsSaved: stats.totalLLMCallsSaved,
|
|
51
|
+
tokensSaved: stats.totalTokensSaved + tokensSaved,
|
|
52
|
+
immuneRepairRate: Math.round(immuneRepairRate * 100) / 100,
|
|
53
|
+
avgCreditScore: Math.round(avgCreditScore * 100) / 100,
|
|
54
|
+
functionsWithHistory,
|
|
55
|
+
totalFailures: genome.totalFailures,
|
|
56
|
+
avgRetriesToSuccess: genome.averageRetriesToSuccess,
|
|
57
|
+
learnedPatternCount: learned.failureToFix.length,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Format immune metrics as a human-readable report.
|
|
62
|
+
*/
|
|
63
|
+
function formatImmuneMetrics(m) {
|
|
64
|
+
const lines = [
|
|
65
|
+
"═══════ Immune System Metrics ═══════",
|
|
66
|
+
"",
|
|
67
|
+
"── Efficacy ──",
|
|
68
|
+
` Total antibody hits: ${m.totalAntibodyHits}`,
|
|
69
|
+
` ACL-4 fast paths (0 LLM): ${m.fastPathHits}`,
|
|
70
|
+
` ACL-3 injected hints: ${m.injectedHints}`,
|
|
71
|
+
` LLM calls saved: ${m.llmCallsSaved}`,
|
|
72
|
+
` Est. tokens saved: ${m.tokensSaved.toLocaleString()}`,
|
|
73
|
+
` Immune repair rate: ${(m.immuneRepairRate * 100).toFixed(0)}%`,
|
|
74
|
+
"",
|
|
75
|
+
"── Knowledge ROI ──",
|
|
76
|
+
` Avg credit score: ${m.avgCreditScore}`,
|
|
77
|
+
` Functions with history: ${m.functionsWithHistory}`,
|
|
78
|
+
` Learned patterns: ${m.learnedPatternCount}`,
|
|
79
|
+
"",
|
|
80
|
+
"── Failure Landscape ──",
|
|
81
|
+
` Total failures: ${m.totalFailures}`,
|
|
82
|
+
` Avg retries to success: ${m.avgRetriesToSuccess.toFixed(1)}`,
|
|
83
|
+
"",
|
|
84
|
+
"══════════════════════════════════════",
|
|
85
|
+
];
|
|
86
|
+
return lines.join("\n");
|
|
87
|
+
}
|
|
88
|
+
/** Print current immune metrics to stderr. */
|
|
89
|
+
function reportImmuneMetrics() {
|
|
90
|
+
const m = computeImmuneMetrics();
|
|
91
|
+
console.error(formatImmuneMetrics(m));
|
|
92
|
+
return m;
|
|
93
|
+
}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Immune Network Receiver — the missing half of the global immune network.
|
|
4
|
+
*
|
|
5
|
+
* Accepts external failure fingerprints (from remote instances or file imports),
|
|
6
|
+
* deduplicates against local records, and merges them into the local corpus.
|
|
7
|
+
*
|
|
8
|
+
* This closes the "send-only" gap: immune-reporter.ts pushes out, this pulls in.
|
|
9
|
+
*/
|
|
10
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
13
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
14
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
15
|
+
}
|
|
16
|
+
Object.defineProperty(o, k2, desc);
|
|
17
|
+
}) : (function(o, m, k, k2) {
|
|
18
|
+
if (k2 === undefined) k2 = k;
|
|
19
|
+
o[k2] = m[k];
|
|
20
|
+
}));
|
|
21
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
22
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
23
|
+
}) : function(o, v) {
|
|
24
|
+
o["default"] = v;
|
|
25
|
+
});
|
|
26
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
27
|
+
var ownKeys = function(o) {
|
|
28
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
29
|
+
var ar = [];
|
|
30
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
31
|
+
return ar;
|
|
32
|
+
};
|
|
33
|
+
return ownKeys(o);
|
|
34
|
+
};
|
|
35
|
+
return function (mod) {
|
|
36
|
+
if (mod && mod.__esModule) return mod;
|
|
37
|
+
var result = {};
|
|
38
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
39
|
+
__setModuleDefault(result, mod);
|
|
40
|
+
return result;
|
|
41
|
+
};
|
|
42
|
+
})();
|
|
43
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
44
|
+
exports.importFingerprints = importFingerprints;
|
|
45
|
+
exports.importFromFile = importFromFile;
|
|
46
|
+
exports.getReceiverStats = getReceiverStats;
|
|
47
|
+
const fs = __importStar(require("fs"));
|
|
48
|
+
const path = __importStar(require("path"));
|
|
49
|
+
const crypto = __importStar(require("crypto"));
|
|
50
|
+
const CORPUS_DIR = path.resolve(__dirname, "..", ".progmune_corpus");
|
|
51
|
+
const RECEIVED_FILE = path.resolve(__dirname, "..", ".progmune_memory", "received_fingerprints.json");
|
|
52
|
+
/** Hash a fingerprint for deduplication. */
|
|
53
|
+
function hashFingerprint(fp) {
|
|
54
|
+
const key = `${fp.instance_id}:${fp.timestamp}:${fp.violatedSVL}:${fp.constraintType}:${(fp.functionSequence || []).join(",")}`;
|
|
55
|
+
return crypto.createHash("sha256").update(key).digest("hex").slice(0, 16);
|
|
56
|
+
}
|
|
57
|
+
/** Load the set of previously received fingerprint hashes. */
|
|
58
|
+
function getReceivedHashes() {
|
|
59
|
+
try {
|
|
60
|
+
if (fs.existsSync(RECEIVED_FILE)) {
|
|
61
|
+
const raw = JSON.parse(fs.readFileSync(RECEIVED_FILE, "utf-8"));
|
|
62
|
+
return new Set(raw.hashes || []);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
catch { /* receiver log may be unavailable */ }
|
|
66
|
+
return new Set();
|
|
67
|
+
}
|
|
68
|
+
/** Save received fingerprint hashes. */
|
|
69
|
+
function saveReceivedHashes(hashes) {
|
|
70
|
+
const dir = path.dirname(RECEIVED_FILE);
|
|
71
|
+
if (!fs.existsSync(dir))
|
|
72
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
73
|
+
fs.writeFileSync(RECEIVED_FILE, JSON.stringify({
|
|
74
|
+
hashes: [...hashes],
|
|
75
|
+
updatedAt: new Date().toISOString(),
|
|
76
|
+
total: hashes.size,
|
|
77
|
+
}, null, 2));
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Import external fingerprints into the local failure corpus.
|
|
81
|
+
* Deduplicates: each fingerprint is only imported once.
|
|
82
|
+
*
|
|
83
|
+
* @returns count of imported and skipped fingerprints.
|
|
84
|
+
*/
|
|
85
|
+
function importFingerprints(fingerprints) {
|
|
86
|
+
const received = getReceivedHashes();
|
|
87
|
+
let imported = 0;
|
|
88
|
+
let skipped = 0;
|
|
89
|
+
for (const fp of fingerprints) {
|
|
90
|
+
const hash = hashFingerprint(fp);
|
|
91
|
+
if (received.has(hash)) {
|
|
92
|
+
skipped++;
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
// Write fingerprint into the corpus as a failure record
|
|
96
|
+
const today = new Date().toISOString().slice(0, 10);
|
|
97
|
+
const dateDir = path.join(CORPUS_DIR, today);
|
|
98
|
+
if (!fs.existsSync(dateDir))
|
|
99
|
+
fs.mkdirSync(dateDir, { recursive: true });
|
|
100
|
+
// Get next sequence number
|
|
101
|
+
const seqFile = path.join(CORPUS_DIR, ".seq");
|
|
102
|
+
let seq = 1;
|
|
103
|
+
try {
|
|
104
|
+
if (fs.existsSync(seqFile)) {
|
|
105
|
+
seq = parseInt(fs.readFileSync(seqFile, "utf-8"), 10) + 1;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
catch { /* best-effort */ }
|
|
109
|
+
const record = {
|
|
110
|
+
intent: `[remote:${fp.instance_id}] ${fp.constraintType}`,
|
|
111
|
+
functionPath: fp.functionSequence,
|
|
112
|
+
violatedSVL: fp.violatedSVL,
|
|
113
|
+
constraintType: fp.constraintType,
|
|
114
|
+
preState: fp.preState,
|
|
115
|
+
postState: fp.postState,
|
|
116
|
+
fingerprintHash: hash,
|
|
117
|
+
sourceInstance: fp.instance_id,
|
|
118
|
+
sourceTimestamp: fp.timestamp,
|
|
119
|
+
importedAt: new Date().toISOString(),
|
|
120
|
+
};
|
|
121
|
+
const fileName = `fail_${Date.now()}_${seq}.json`;
|
|
122
|
+
fs.writeFileSync(path.join(dateDir, fileName), JSON.stringify(record, null, 2));
|
|
123
|
+
// Update sequence
|
|
124
|
+
fs.writeFileSync(seqFile, String(seq));
|
|
125
|
+
received.add(hash);
|
|
126
|
+
imported++;
|
|
127
|
+
}
|
|
128
|
+
saveReceivedHashes(received);
|
|
129
|
+
return { imported, skipped, total: fingerprints.length };
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Import fingerprints from a JSON file (e.g., downloaded from the Hub).
|
|
133
|
+
*/
|
|
134
|
+
function importFromFile(filePath) {
|
|
135
|
+
if (!fs.existsSync(filePath)) {
|
|
136
|
+
return { imported: 0, skipped: 0, total: 0 };
|
|
137
|
+
}
|
|
138
|
+
const raw = JSON.parse(fs.readFileSync(filePath, "utf-8"));
|
|
139
|
+
const fingerprints = Array.isArray(raw)
|
|
140
|
+
? raw
|
|
141
|
+
: (raw.fingerprints || []);
|
|
142
|
+
return importFingerprints(fingerprints);
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Get import statistics: how many external fingerprints have been received.
|
|
146
|
+
*/
|
|
147
|
+
function getReceiverStats() {
|
|
148
|
+
const hashes = getReceivedHashes();
|
|
149
|
+
let lastUpdated = null;
|
|
150
|
+
try {
|
|
151
|
+
if (fs.existsSync(RECEIVED_FILE)) {
|
|
152
|
+
const raw = JSON.parse(fs.readFileSync(RECEIVED_FILE, "utf-8"));
|
|
153
|
+
lastUpdated = raw.updatedAt || null;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
catch { /* best-effort */ }
|
|
157
|
+
return { totalReceived: hashes.size, lastUpdated };
|
|
158
|
+
}
|
package/dist/immune-reporter.js
CHANGED
|
@@ -53,7 +53,7 @@ function getReportCursor() {
|
|
|
53
53
|
if (fs.existsSync(CURSOR_FILE))
|
|
54
54
|
return JSON.parse(fs.readFileSync(CURSOR_FILE, "utf-8"));
|
|
55
55
|
}
|
|
56
|
-
catch { }
|
|
56
|
+
catch { /* report may be unavailable */ }
|
|
57
57
|
return { lastTimestamp: null, reportedCount: 0 };
|
|
58
58
|
}
|
|
59
59
|
function saveReportCursor(timestamp, count) {
|