progmune-runtime 2.1.6 → 3.2.1
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 +119 -461
- 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 +721 -0
- package/package.json +73 -6
- 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,533 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Progmune V5 — Invariant Calculus
|
|
4
|
+
* =================================
|
|
5
|
+
* 将不变量从 JSON 记录提升为可证明、可组合、可验证的数学对象。
|
|
6
|
+
*
|
|
7
|
+
* 核心理念:
|
|
8
|
+
* V4 回答: "能推导出新不变量吗?" → Closure 实现了传递闭包
|
|
9
|
+
* V5 回答: "能证明每个不变量吗?" → 每个不变量携带自己的 Proof Object
|
|
10
|
+
*
|
|
11
|
+
* 新增能力:
|
|
12
|
+
* 1. Proof Objects — 每个不变量附带推导链
|
|
13
|
+
* 2. Minimal Basis — 自动消除冗余规则,只保留生成基
|
|
14
|
+
* 3. Contradiction Detection — 检测逻辑冲突
|
|
15
|
+
* 4. Dependency Graph — 不变量之间的依赖 DAG
|
|
16
|
+
* 5. Counterexample Generation — 验证失败时构造反例
|
|
17
|
+
*/
|
|
18
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
19
|
+
if (k2 === undefined) k2 = k;
|
|
20
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
21
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
22
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
23
|
+
}
|
|
24
|
+
Object.defineProperty(o, k2, desc);
|
|
25
|
+
}) : (function(o, m, k, k2) {
|
|
26
|
+
if (k2 === undefined) k2 = k;
|
|
27
|
+
o[k2] = m[k];
|
|
28
|
+
}));
|
|
29
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
30
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
31
|
+
}) : function(o, v) {
|
|
32
|
+
o["default"] = v;
|
|
33
|
+
});
|
|
34
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
35
|
+
var ownKeys = function(o) {
|
|
36
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
37
|
+
var ar = [];
|
|
38
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
39
|
+
return ar;
|
|
40
|
+
};
|
|
41
|
+
return ownKeys(o);
|
|
42
|
+
};
|
|
43
|
+
return function (mod) {
|
|
44
|
+
if (mod && mod.__esModule) return mod;
|
|
45
|
+
var result = {};
|
|
46
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
47
|
+
__setModuleDefault(result, mod);
|
|
48
|
+
return result;
|
|
49
|
+
};
|
|
50
|
+
})();
|
|
51
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
52
|
+
exports.runCalculus = runCalculus;
|
|
53
|
+
const fs = __importStar(require("fs"));
|
|
54
|
+
const path = __importStar(require("path"));
|
|
55
|
+
// ══════════════════════════════════════════════
|
|
56
|
+
// L0: LOGIC TYPE CLASSIFICATION
|
|
57
|
+
// ══════════════════════════════════════════════
|
|
58
|
+
/**
|
|
59
|
+
* Classify an invariant into its logical type.
|
|
60
|
+
*
|
|
61
|
+
* REQUIRES: "A ⇒ B" — A requires B to have been satisfied before entering A.
|
|
62
|
+
* e.g. "production ⇒ paid" = must have paid before production.
|
|
63
|
+
* Transitive: if A⇒B and B⇒C, then A⇒C.
|
|
64
|
+
*
|
|
65
|
+
* FORBIDS: "¬(A → B)" — cannot directly transition from A to B.
|
|
66
|
+
* e.g. "¬(shipped → pending)" = cannot go backwards.
|
|
67
|
+
* NOT transitive. A forbidding B and B forbidding C does NOT
|
|
68
|
+
* imply A forbids C. These are local edge constraints.
|
|
69
|
+
*
|
|
70
|
+
* TERMINAL: "A ⇒ ¬∃ next" — once in A, no further transitions exist.
|
|
71
|
+
* e.g. "completed is terminal" = cannot leave completed state.
|
|
72
|
+
*
|
|
73
|
+
* UNIQUE: "|payments| ≤ 1" — cardinality constraint.
|
|
74
|
+
*
|
|
75
|
+
* INITIAL: "∀ entity: initial_state = A" — only one valid starting state.
|
|
76
|
+
*/
|
|
77
|
+
function classifyLogicType(inv) {
|
|
78
|
+
const pred = (inv.rawPredicate || inv.predicate || "").toLowerCase();
|
|
79
|
+
const desc = (inv.description || "").toLowerCase();
|
|
80
|
+
if (pred.includes("¬∃ next") || pred.includes("terminal") || desc.includes("终态")) {
|
|
81
|
+
return "TERMINAL";
|
|
82
|
+
}
|
|
83
|
+
if (pred.includes("¬(") && pred.includes("→")) {
|
|
84
|
+
return "FORBIDS";
|
|
85
|
+
}
|
|
86
|
+
if (pred.includes("≤ 1") || pred.includes("unique") || pred.includes("at most one") || desc.includes("唯一")) {
|
|
87
|
+
return "UNIQUE";
|
|
88
|
+
}
|
|
89
|
+
if (pred.includes("initial_state") || desc.includes("起始") || desc.includes("初始")) {
|
|
90
|
+
return "INITIAL";
|
|
91
|
+
}
|
|
92
|
+
// Default: "A ⇒ B" with actual different atoms = prerequisite
|
|
93
|
+
return "REQUIRES";
|
|
94
|
+
}
|
|
95
|
+
// ══════════════════════════════════════════════
|
|
96
|
+
// L1: PROOF OBJECT CONSTRUCTION
|
|
97
|
+
// ══════════════════════════════════════════════
|
|
98
|
+
/**
|
|
99
|
+
* Build a proof object for each invariant.
|
|
100
|
+
*
|
|
101
|
+
* A proof is a derivation chain from premises to conclusion.
|
|
102
|
+
* - Axioms (premises): invariants that were mined directly from code/state machines.
|
|
103
|
+
* They have no derivation — they are assumed true based on evidence.
|
|
104
|
+
* - Derived invariants: those obtained by applying inference rules to axioms.
|
|
105
|
+
* Their proof references the premises and the rule used.
|
|
106
|
+
*/
|
|
107
|
+
function buildProofObjects(invariants, closures) {
|
|
108
|
+
const certified = [];
|
|
109
|
+
const idCounter = { value: 10000 };
|
|
110
|
+
// ── Step 1: Mark all mined invariants as axioms ──
|
|
111
|
+
for (const inv of invariants) {
|
|
112
|
+
const logicType = classifyLogicType(inv);
|
|
113
|
+
const proof = {
|
|
114
|
+
invariantId: inv.id,
|
|
115
|
+
statement: inv.rawPredicate || inv.predicate,
|
|
116
|
+
steps: [{
|
|
117
|
+
rule: "premise",
|
|
118
|
+
from: [],
|
|
119
|
+
to: inv.id,
|
|
120
|
+
description: `Mined from ${inv.source || "code analysis"} [type: ${logicType}]`,
|
|
121
|
+
}],
|
|
122
|
+
premises: [inv.id],
|
|
123
|
+
isAxiom: true,
|
|
124
|
+
confidence: inv.confidence || 50,
|
|
125
|
+
logicType,
|
|
126
|
+
};
|
|
127
|
+
certified.push({
|
|
128
|
+
id: inv.id,
|
|
129
|
+
description: inv.description,
|
|
130
|
+
predicate: inv.rawPredicate || inv.predicate,
|
|
131
|
+
domain: inv.domain || "unknown",
|
|
132
|
+
confidence: inv.confidence || 50,
|
|
133
|
+
proof,
|
|
134
|
+
dependsOn: [],
|
|
135
|
+
dependedOnBy: [],
|
|
136
|
+
logicType,
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
// ── Step 2: Mark closure-derived invariants with their derivation chain ──
|
|
140
|
+
for (const closureInv of closures) {
|
|
141
|
+
const sourceDesc = closureInv.source || "";
|
|
142
|
+
// Parse premises from source string like "closure: pending⇒production + production⇒paid"
|
|
143
|
+
const premiseMatch = sourceDesc.match(/closure:\s*(\w+⇒\w+)\s*\+\s*(\w+⇒\w+)/);
|
|
144
|
+
// Closure-derived invariants inherit REQUIRES type (transitivity only applies to prerequisites)
|
|
145
|
+
const proof = {
|
|
146
|
+
invariantId: closureInv.id,
|
|
147
|
+
statement: closureInv.rawPredicate || closureInv.predicate || "",
|
|
148
|
+
steps: [{
|
|
149
|
+
rule: "transitivity",
|
|
150
|
+
from: premiseMatch
|
|
151
|
+
? [findInvariantId(certified, premiseMatch[1]), findInvariantId(certified, premiseMatch[2])].filter(Boolean)
|
|
152
|
+
: [],
|
|
153
|
+
to: closureInv.id,
|
|
154
|
+
description: closureInv.description || `Derived via transitive closure`,
|
|
155
|
+
}],
|
|
156
|
+
premises: premiseMatch
|
|
157
|
+
? [findInvariantId(certified, premiseMatch[1]), findInvariantId(certified, premiseMatch[2])].filter(Boolean)
|
|
158
|
+
: [],
|
|
159
|
+
isAxiom: false,
|
|
160
|
+
confidence: closureInv.confidence || 50,
|
|
161
|
+
logicType: "REQUIRES", // Closure only derives REQUIRES invariants
|
|
162
|
+
};
|
|
163
|
+
const certInv = {
|
|
164
|
+
id: closureInv.id,
|
|
165
|
+
description: closureInv.description || "",
|
|
166
|
+
predicate: closureInv.rawPredicate || closureInv.predicate || "",
|
|
167
|
+
domain: closureInv.domain || "unknown",
|
|
168
|
+
confidence: closureInv.confidence || 50,
|
|
169
|
+
proof,
|
|
170
|
+
dependsOn: proof.premises,
|
|
171
|
+
dependedOnBy: [],
|
|
172
|
+
logicType: "REQUIRES",
|
|
173
|
+
};
|
|
174
|
+
certified.push(certInv);
|
|
175
|
+
// Update dependedOnBy on premises
|
|
176
|
+
for (const premId of proof.premises) {
|
|
177
|
+
const prem = certified.find(c => c.id === premId);
|
|
178
|
+
if (prem && !prem.dependedOnBy.includes(certInv.id)) {
|
|
179
|
+
prem.dependedOnBy.push(certInv.id);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
return certified;
|
|
184
|
+
}
|
|
185
|
+
/** Find an invariant ID by its predicate string */
|
|
186
|
+
function findInvariantId(invariants, predicate) {
|
|
187
|
+
const norm = (s) => s.replace(/\s+/g, "").toLowerCase();
|
|
188
|
+
const target = norm(predicate);
|
|
189
|
+
for (const inv of invariants) {
|
|
190
|
+
if (norm(inv.predicate) === target || norm(inv.predicate).includes(target)) {
|
|
191
|
+
return inv.id;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
return null;
|
|
195
|
+
}
|
|
196
|
+
// ══════════════════════════════════════════════
|
|
197
|
+
// L2: DEPENDENCY GRAPH
|
|
198
|
+
// ══════════════════════════════════════════════
|
|
199
|
+
/**
|
|
200
|
+
* Build the dependency DAG from certified invariants.
|
|
201
|
+
* If B depends on A, and A changes, B must be re-verified.
|
|
202
|
+
*/
|
|
203
|
+
function buildDependencyGraph(certified) {
|
|
204
|
+
return certified.map(inv => ({
|
|
205
|
+
id: inv.id,
|
|
206
|
+
dependsOn: inv.dependsOn,
|
|
207
|
+
dependedOnBy: inv.dependedOnBy,
|
|
208
|
+
}));
|
|
209
|
+
}
|
|
210
|
+
// ══════════════════════════════════════════════
|
|
211
|
+
// L3: CONSISTENCY CHECK (Contradiction Detection)
|
|
212
|
+
// ══════════════════════════════════════════════
|
|
213
|
+
/**
|
|
214
|
+
* Detect contradictions in the invariant set.
|
|
215
|
+
* A contradiction exists when we have both A⇒B and A⇒¬B
|
|
216
|
+
* (or equivalently, A⇒B and an invalid transition ¬(A→B)).
|
|
217
|
+
*
|
|
218
|
+
* Also detects: A⇒B and B⇒A simultaneously (cycle in strict partial order)
|
|
219
|
+
*/
|
|
220
|
+
function checkConsistency(certified) {
|
|
221
|
+
const contradictions = [];
|
|
222
|
+
// Separate by logic type — different types don't conflict
|
|
223
|
+
const requires = new Map(); // REQUIRES: A ⇒ B
|
|
224
|
+
const forbids = new Map(); // FORBIDS: ¬(A → B)
|
|
225
|
+
const terminals = new Set(); // TERMINAL: A has no next state
|
|
226
|
+
for (const inv of certified) {
|
|
227
|
+
const pred = inv.predicate;
|
|
228
|
+
if (inv.logicType === "REQUIRES") {
|
|
229
|
+
const impliesMatch = pred.match(/(\w+)\s*⇒\s*(\w+)/);
|
|
230
|
+
if (impliesMatch) {
|
|
231
|
+
const a = impliesMatch[1].toLowerCase();
|
|
232
|
+
const b = impliesMatch[2].toLowerCase();
|
|
233
|
+
if (a !== b) {
|
|
234
|
+
if (!requires.has(a))
|
|
235
|
+
requires.set(a, []);
|
|
236
|
+
if (!requires.get(a).includes(b))
|
|
237
|
+
requires.get(a).push(b);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
if (inv.logicType === "FORBIDS") {
|
|
242
|
+
const notImpliesMatch = pred.match(/¬\((\w+)\s*→\s*(\w+)\)/);
|
|
243
|
+
if (notImpliesMatch) {
|
|
244
|
+
const a = notImpliesMatch[1].toLowerCase();
|
|
245
|
+
const b = notImpliesMatch[2].toLowerCase();
|
|
246
|
+
if (!forbids.has(a))
|
|
247
|
+
forbids.set(a, []);
|
|
248
|
+
if (!forbids.get(a).includes(b))
|
|
249
|
+
forbids.get(a).push(b);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
if (inv.logicType === "TERMINAL") {
|
|
253
|
+
const termMatch = pred.match(/(\w+)/);
|
|
254
|
+
if (termMatch)
|
|
255
|
+
terminals.add(termMatch[1].toLowerCase());
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
// ── Only check WITHIN each type ──
|
|
259
|
+
// REQUIRES internal: A⇒B and B⇒A (cycle in strict partial order)
|
|
260
|
+
for (const [a, deps] of requires) {
|
|
261
|
+
for (const b of deps) {
|
|
262
|
+
const bDeps = requires.get(b) || [];
|
|
263
|
+
if (bDeps.includes(a) && a < b) { // a < b to avoid double-counting
|
|
264
|
+
contradictions.push({
|
|
265
|
+
a: `${a}⇒${b}`,
|
|
266
|
+
b: `${b}⇒${a}`,
|
|
267
|
+
description: `REQUIRES 循环: ${a}⇒${b} 且 ${b}⇒${a} —— 违反严格偏序`,
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
// REQUIRES + TERMINAL conflict: A is terminal but also requires B (can't transition to B if terminal)
|
|
273
|
+
for (const a of terminals) {
|
|
274
|
+
const deps = requires.get(a) || [];
|
|
275
|
+
if (deps.length > 0) {
|
|
276
|
+
// Being terminal AND requiring something is suspicious
|
|
277
|
+
// (terminal means no outgoing transitions, but REQUIRES implies a dependency chain)
|
|
278
|
+
// This is NOT necessarily a contradiction — terminal just means no FURTHER states
|
|
279
|
+
// We'll skip this check for now
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
// FORBIDS internal: A forbids B and also forbids B twice (redundant, not contradiction)
|
|
283
|
+
// NOTE: REQUIRES vs FORBIDS are NOT contradictions.
|
|
284
|
+
// "shipped ⇒ production" (REQUIRES: must have passed through production)
|
|
285
|
+
// and "¬(shipped → production)" (FORBIDS: cannot transition back to production)
|
|
286
|
+
// are CONSISTENT. One is about history, the other about future transitions.
|
|
287
|
+
return {
|
|
288
|
+
isConsistent: contradictions.length === 0,
|
|
289
|
+
contradictions,
|
|
290
|
+
minimalBasis: { generators: [], consequences: [], removedRedundant: [] },
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
// ══════════════════════════════════════════════
|
|
294
|
+
// L4: MINIMAL BASIS (Redundancy Elimination)
|
|
295
|
+
// ══════════════════════════════════════════════
|
|
296
|
+
/**
|
|
297
|
+
* Compute the minimal generating basis.
|
|
298
|
+
*
|
|
299
|
+
* An invariant is REDUNDANT if it can be derived from other invariants
|
|
300
|
+
* via transitivity. Example:
|
|
301
|
+
* A⇒B, B⇒C, A⇒C → A⇒C is redundant (derivable from the first two)
|
|
302
|
+
*
|
|
303
|
+
* The minimal basis contains only the axioms that cannot be derived.
|
|
304
|
+
* All consequences are derivable from the basis.
|
|
305
|
+
*/
|
|
306
|
+
function computeMinimalBasis(certified) {
|
|
307
|
+
const axioms = certified.filter(inv => inv.proof.isAxiom);
|
|
308
|
+
const derived = certified.filter(inv => !inv.proof.isAxiom);
|
|
309
|
+
// For now: all axioms are generators, all derived are consequences.
|
|
310
|
+
// A more sophisticated version would find transitive reducibility among axioms.
|
|
311
|
+
// e.g., if A⇒B and B⇒C are both axioms, we could remove A⇒C from generators
|
|
312
|
+
// (but we only generate A⇒C via closure, so it's already in derived).
|
|
313
|
+
const redundant = [];
|
|
314
|
+
// Check: are any axioms actually derivable from other axioms?
|
|
315
|
+
// If axiom A⇒C is also in the transitive closure of other axioms, it's redundant.
|
|
316
|
+
for (let i = 0; i < axioms.length; i++) {
|
|
317
|
+
for (let j = 0; j < axioms.length; j++) {
|
|
318
|
+
if (i === j)
|
|
319
|
+
continue;
|
|
320
|
+
// Check if axioms[i] is transitively implied by axioms[j] + some chain
|
|
321
|
+
// This is a simplified check: same predicate means redundant
|
|
322
|
+
if (axioms[i].predicate === axioms[j].predicate && i > j) {
|
|
323
|
+
redundant.push(axioms[i].id);
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
const generators = axioms.filter(a => !redundant.includes(a.id));
|
|
328
|
+
return {
|
|
329
|
+
generators,
|
|
330
|
+
consequences: derived,
|
|
331
|
+
removedRedundant: redundant,
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
// ══════════════════════════════════════════════
|
|
335
|
+
// L5: COUNTEREXAMPLE GENERATION
|
|
336
|
+
// ══════════════════════════════════════════════
|
|
337
|
+
/**
|
|
338
|
+
* Generate counterexamples for violated invariants.
|
|
339
|
+
*
|
|
340
|
+
* Given a state machine and an invariant A⇒B:
|
|
341
|
+
* - Find a path where A is true but B has not been satisfied yet.
|
|
342
|
+
* - The shortest such path is the counterexample.
|
|
343
|
+
*/
|
|
344
|
+
function generateCounterexamples(certified, stateMachines) {
|
|
345
|
+
const counterexamples = [];
|
|
346
|
+
for (const machine of stateMachines) {
|
|
347
|
+
const states = machine.states || [];
|
|
348
|
+
const validTransitions = new Set(machine.validTransitions || []);
|
|
349
|
+
const invalidTransitions = machine.invalidTransitions || [];
|
|
350
|
+
// For each safety invariant (¬(A→B)), construct the violating path
|
|
351
|
+
for (const invId of invalidTransitions) {
|
|
352
|
+
const [from, to] = invId.split("→");
|
|
353
|
+
if (!from || !to)
|
|
354
|
+
continue;
|
|
355
|
+
// Find the corresponding certified invariant
|
|
356
|
+
const certInv = certified.find(c => c.predicate.includes(from) && c.predicate.includes(to) && c.predicate.includes("¬"));
|
|
357
|
+
if (certInv) {
|
|
358
|
+
// Construct the shortest violating path
|
|
359
|
+
const path = [from, to];
|
|
360
|
+
counterexamples.push({
|
|
361
|
+
invariantId: certInv.id,
|
|
362
|
+
invariantStatement: certInv.predicate,
|
|
363
|
+
path,
|
|
364
|
+
atStep: 1,
|
|
365
|
+
explanation: `状态机允许从 ${from} 直接跳转到 ${to}。违反了不变量: ${certInv.predicate}`,
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
// For prerequisite invariants (A⇒B), check if there's a path from initial to A that skips B
|
|
370
|
+
for (const certInv of certified) {
|
|
371
|
+
const impliesMatch = certInv.predicate.match(/(\w+)\s*⇒\s*(\w+)/);
|
|
372
|
+
if (!impliesMatch)
|
|
373
|
+
continue;
|
|
374
|
+
const a = impliesMatch[1].toLowerCase();
|
|
375
|
+
const b = impliesMatch[2].toLowerCase();
|
|
376
|
+
// Check: does any path from initial state reach 'a' without passing through 'b'?
|
|
377
|
+
const initialState = machine.initialState?.toLowerCase();
|
|
378
|
+
if (initialState && states.map((s) => s.toLowerCase()).includes(a)) {
|
|
379
|
+
// If there's a direct transition from initial to 'a' that skips 'b', that's a violation
|
|
380
|
+
const directPath = `${initialState}→${a}`;
|
|
381
|
+
if (!validTransitions.has(directPath) && initialState !== a) {
|
|
382
|
+
// This means the state machine already blocks this path — invariant is satisfied
|
|
383
|
+
// If the path IS valid, it's a violation
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
// Simpler check: if 'a' can be reached without 'b' in the state list before it
|
|
387
|
+
const aIdx = states.findIndex((s) => s.toLowerCase() === a);
|
|
388
|
+
const bIdx = states.findIndex((s) => s.toLowerCase() === b);
|
|
389
|
+
if (aIdx >= 0 && bIdx >= 0 && aIdx < bIdx) {
|
|
390
|
+
// 'a' appears before 'b' in state ordering — potential violation
|
|
391
|
+
// This means the state can be entered without satisfying the prerequisite
|
|
392
|
+
counterexamples.push({
|
|
393
|
+
invariantId: certInv.id,
|
|
394
|
+
invariantStatement: certInv.predicate,
|
|
395
|
+
path: [states[aIdx], states[bIdx]],
|
|
396
|
+
atStep: aIdx,
|
|
397
|
+
explanation: `在状态序列中,${states[aIdx]} 出现在 ${states[bIdx]} 之前。可能违反: ${certInv.predicate}`,
|
|
398
|
+
});
|
|
399
|
+
break; // One counterexample per invariant is sufficient
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
return counterexamples;
|
|
404
|
+
}
|
|
405
|
+
function runCalculus(input) {
|
|
406
|
+
console.log("🔬 Progmune Invariant Calculus — V5");
|
|
407
|
+
// Collect all invariants and closures
|
|
408
|
+
const allInvariants = [];
|
|
409
|
+
for (const proto of input.protocols || []) {
|
|
410
|
+
for (const inv of proto.invariants || []) {
|
|
411
|
+
allInvariants.push(inv);
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
const allClosures = [];
|
|
415
|
+
for (const proto of input.protocols || []) {
|
|
416
|
+
for (const inv of proto.closure || []) {
|
|
417
|
+
allClosures.push(inv);
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
console.log(` Input: ${allInvariants.length} invariants, ${allClosures.length} closure-derived`);
|
|
421
|
+
// ── L1: Proof Objects ──
|
|
422
|
+
console.log("\nL1 · Proof Object Construction...");
|
|
423
|
+
const certified = buildProofObjects(allInvariants, allClosures);
|
|
424
|
+
const axioms = certified.filter(c => c.proof.isAxiom);
|
|
425
|
+
const derived = certified.filter(c => !c.proof.isAxiom);
|
|
426
|
+
const typeCounts = {};
|
|
427
|
+
for (const c of certified) {
|
|
428
|
+
typeCounts[c.logicType] = (typeCounts[c.logicType] || 0) + 1;
|
|
429
|
+
}
|
|
430
|
+
console.log(` ${certified.length} certified: ${axioms.length} axioms, ${derived.length} derived`);
|
|
431
|
+
console.log(` By type: REQUIRES=${typeCounts["REQUIRES"] || 0} FORBIDS=${typeCounts["FORBIDS"] || 0} TERMINAL=${typeCounts["TERMINAL"] || 0} UNIQUE=${typeCounts["UNIQUE"] || 0} INITIAL=${typeCounts["INITIAL"] || 0}`);
|
|
432
|
+
// Show derivation chains
|
|
433
|
+
for (const d of derived.slice(0, 3)) {
|
|
434
|
+
const premises = d.proof.premises.join(", ");
|
|
435
|
+
console.log(` ⊢ ${d.predicate} [from: ${premises}]`);
|
|
436
|
+
}
|
|
437
|
+
// ── L2: Dependency Graph ──
|
|
438
|
+
console.log("\nL2 · Dependency Graph...");
|
|
439
|
+
const depGraph = buildDependencyGraph(certified);
|
|
440
|
+
const withDeps = depGraph.filter(d => d.dependedOnBy.length > 0);
|
|
441
|
+
console.log(` ${withDeps.length} invariants with dependents`);
|
|
442
|
+
for (const d of withDeps.slice(0, 3)) {
|
|
443
|
+
console.log(` ${d.id} is depended on by: ${d.dependedOnBy.join(", ")}`);
|
|
444
|
+
}
|
|
445
|
+
// ── L3: Consistency Check ──
|
|
446
|
+
console.log("\nL3 · Consistency Check...");
|
|
447
|
+
const consistency = checkConsistency(certified);
|
|
448
|
+
if (consistency.isConsistent) {
|
|
449
|
+
console.log(" ✅ No contradictions found");
|
|
450
|
+
}
|
|
451
|
+
else {
|
|
452
|
+
console.log(` ❌ ${consistency.contradictions.length} contradictions found`);
|
|
453
|
+
for (const c of consistency.contradictions.slice(0, 3)) {
|
|
454
|
+
console.log(` ${c.description}`);
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
// ── L4: Minimal Basis ──
|
|
458
|
+
console.log("\nL4 · Minimal Basis...");
|
|
459
|
+
const minimalBasis = computeMinimalBasis(certified);
|
|
460
|
+
// Update consistency with the computed basis
|
|
461
|
+
consistency.minimalBasis = minimalBasis;
|
|
462
|
+
console.log(` Generators: ${minimalBasis.generators.length}`);
|
|
463
|
+
console.log(` Consequences: ${minimalBasis.consequences.length}`);
|
|
464
|
+
console.log(` Redundant: ${minimalBasis.removedRedundant.length}`);
|
|
465
|
+
if (minimalBasis.removedRedundant.length > 0) {
|
|
466
|
+
console.log(` Removed: ${minimalBasis.removedRedundant.join(", ")}`);
|
|
467
|
+
}
|
|
468
|
+
// ── L5: Counterexample Generation ──
|
|
469
|
+
console.log(`\nL5 · Counterexample Generation (FORBIDS type only)...`);
|
|
470
|
+
// Only FORBIDS invariants can have counterexamples (invalid transitions)
|
|
471
|
+
const forbidsInvariants = certified.filter(c => c.logicType === "FORBIDS");
|
|
472
|
+
const counterexamples = generateCounterexamples(forbidsInvariants, input.stateMachines || []);
|
|
473
|
+
console.log(` ${counterexamples.length} counterexamples`);
|
|
474
|
+
for (const ce of counterexamples.slice(0, 3)) {
|
|
475
|
+
console.log(` ❌ ${ce.invariantStatement}`);
|
|
476
|
+
console.log(` Path: ${ce.path.join(" → ")}`);
|
|
477
|
+
console.log(` ${ce.explanation}`);
|
|
478
|
+
}
|
|
479
|
+
const report = {
|
|
480
|
+
timestamp: new Date().toISOString(),
|
|
481
|
+
certifiedInvariants: certified,
|
|
482
|
+
dependencyGraph: depGraph,
|
|
483
|
+
minimalBasis,
|
|
484
|
+
consistency,
|
|
485
|
+
counterexamples,
|
|
486
|
+
summary: {
|
|
487
|
+
totalInvariants: certified.length,
|
|
488
|
+
axioms: axioms.length,
|
|
489
|
+
derived: derived.length,
|
|
490
|
+
redundant: minimalBasis.removedRedundant.length,
|
|
491
|
+
contradictions: consistency.contradictions.length,
|
|
492
|
+
counterexamples: counterexamples.length,
|
|
493
|
+
},
|
|
494
|
+
};
|
|
495
|
+
return report;
|
|
496
|
+
}
|
|
497
|
+
// ══════════════════════════════════════════════
|
|
498
|
+
// CLI
|
|
499
|
+
// ══════════════════════════════════════════════
|
|
500
|
+
if (require.main === module) {
|
|
501
|
+
const targetProject = process.argv[2];
|
|
502
|
+
if (!targetProject) {
|
|
503
|
+
console.error("Usage: npx ts-node src/invariant-calculus.ts <project-path>");
|
|
504
|
+
process.exit(1);
|
|
505
|
+
}
|
|
506
|
+
const protoPath = path.join(targetProject, ".progmune_protocols.json");
|
|
507
|
+
const algebraPath = path.join(targetProject, ".progmune_algebra.json");
|
|
508
|
+
const statePath = path.join(targetProject, ".progmune_state_machines.json");
|
|
509
|
+
if (!fs.existsSync(protoPath)) {
|
|
510
|
+
console.error("Run V3.4 first: npx ts-node src/protocol-miner.ts");
|
|
511
|
+
process.exit(1);
|
|
512
|
+
}
|
|
513
|
+
const protocols = JSON.parse(fs.readFileSync(protoPath, "utf-8"));
|
|
514
|
+
const algebra = fs.existsSync(algebraPath) ? JSON.parse(fs.readFileSync(algebraPath, "utf-8")) : { protocols: [] };
|
|
515
|
+
const states = fs.existsSync(statePath) ? JSON.parse(fs.readFileSync(statePath, "utf-8")) : { machines: [] };
|
|
516
|
+
const input = {
|
|
517
|
+
protocols: protocols.protocols || [],
|
|
518
|
+
closures: algebra.protocols?.flatMap((p) => p.closure || []) || [],
|
|
519
|
+
stateMachines: states.machines || [],
|
|
520
|
+
};
|
|
521
|
+
const report = runCalculus(input);
|
|
522
|
+
const outputPath = path.join(targetProject, ".progmune_calculus.json");
|
|
523
|
+
fs.writeFileSync(outputPath, JSON.stringify(report, null, 2));
|
|
524
|
+
console.log(`\n✅ Calculus report saved to: ${outputPath}`);
|
|
525
|
+
console.log("\n═══ Invariant Calculus Summary ═══");
|
|
526
|
+
console.log(` Total: ${report.summary.totalInvariants}`);
|
|
527
|
+
console.log(` Axioms: ${report.summary.axioms}`);
|
|
528
|
+
console.log(` Derived: ${report.summary.derived}`);
|
|
529
|
+
console.log(` Redundant: ${report.summary.redundant}`);
|
|
530
|
+
console.log(` Contradictions:${report.summary.contradictions}`);
|
|
531
|
+
console.log(` Counterexamples:${report.summary.counterexamples}`);
|
|
532
|
+
console.log();
|
|
533
|
+
}
|
package/dist/ir-utils.js
CHANGED
|
@@ -1,7 +1,57 @@
|
|
|
1
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
|
+
})();
|
|
2
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.loadIR = loadIR;
|
|
3
37
|
exports.countExported = countExported;
|
|
4
38
|
exports.mergeResults = mergeResults;
|
|
39
|
+
exports.getExportedDeclarations = getExportedDeclarations;
|
|
40
|
+
const fs = __importStar(require("fs"));
|
|
41
|
+
const path = __importStar(require("path"));
|
|
42
|
+
/**
|
|
43
|
+
* Load IR (Intermediate Representation) from disk.
|
|
44
|
+
* Centralised loader — used by validator, planner, and search modules.
|
|
45
|
+
* Returns the flat function array regardless of whether the on-disk format
|
|
46
|
+
* is a bare array or an object with a `functions` key.
|
|
47
|
+
*/
|
|
48
|
+
function loadIR(filePath) {
|
|
49
|
+
const irPath = filePath || path.resolve(__dirname, "../ir.json");
|
|
50
|
+
if (!fs.existsSync(irPath))
|
|
51
|
+
return [];
|
|
52
|
+
const raw = JSON.parse(fs.readFileSync(irPath, "utf-8"));
|
|
53
|
+
return Array.isArray(raw) ? raw : (raw.functions || []);
|
|
54
|
+
}
|
|
5
55
|
/** Count exported functions in an IR function list.
|
|
6
56
|
* @requires IR_FUNCTIONS @produces EXPORT_COUNT
|
|
7
57
|
* @tags ir, count, export
|
|
@@ -16,3 +66,23 @@ function countExported(ir) {
|
|
|
16
66
|
function mergeResults(a, b) {
|
|
17
67
|
return { first: a, second: b };
|
|
18
68
|
}
|
|
69
|
+
/**
|
|
70
|
+
* Get all exported function declarations with capability metadata.
|
|
71
|
+
* @requires IR_FUNCTIONS @produces EXPORTED_DECLARATIONS
|
|
72
|
+
* @purpose Return exported functions with their purpose, requires, and produces
|
|
73
|
+
* @tags ir, export, catalog
|
|
74
|
+
* @useWhen building capability catalogs, listing available functions
|
|
75
|
+
*/
|
|
76
|
+
function getExportedDeclarations() {
|
|
77
|
+
const allFuncs = loadIR();
|
|
78
|
+
return allFuncs
|
|
79
|
+
.filter((f) => f.exported)
|
|
80
|
+
.map((f) => ({
|
|
81
|
+
name: f.name,
|
|
82
|
+
purpose: f.purpose || "",
|
|
83
|
+
requires: f.requires || [],
|
|
84
|
+
produces: f.produces || [],
|
|
85
|
+
tags: f.tags || [],
|
|
86
|
+
file: f.file,
|
|
87
|
+
}));
|
|
88
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
/**
|
|
4
|
+
* Unit tests for ir-utils.ts — IR helper functions.
|
|
5
|
+
*/
|
|
6
|
+
const vitest_1 = require("vitest");
|
|
7
|
+
const ir_utils_1 = require("./ir-utils");
|
|
8
|
+
(0, vitest_1.describe)("countExported", () => {
|
|
9
|
+
(0, vitest_1.it)("returns 0 for empty array", () => {
|
|
10
|
+
(0, vitest_1.expect)((0, ir_utils_1.countExported)([])).toBe(0);
|
|
11
|
+
});
|
|
12
|
+
(0, vitest_1.it)("counts only exported functions", () => {
|
|
13
|
+
const ir = [
|
|
14
|
+
{ name: "a", exported: true },
|
|
15
|
+
{ name: "b", exported: false },
|
|
16
|
+
{ name: "c", exported: true },
|
|
17
|
+
{ name: "d" }, // no exported field → falsy
|
|
18
|
+
];
|
|
19
|
+
(0, vitest_1.expect)((0, ir_utils_1.countExported)(ir)).toBe(2);
|
|
20
|
+
});
|
|
21
|
+
(0, vitest_1.it)("returns 0 if all are internal", () => {
|
|
22
|
+
(0, vitest_1.expect)((0, ir_utils_1.countExported)([
|
|
23
|
+
{ name: "x", exported: false },
|
|
24
|
+
{ name: "y", exported: false },
|
|
25
|
+
])).toBe(0);
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
(0, vitest_1.describe)("mergeResults", () => {
|
|
29
|
+
(0, vitest_1.it)("returns object with first and second", () => {
|
|
30
|
+
const r = (0, ir_utils_1.mergeResults)({ a: 1 }, { b: 2 });
|
|
31
|
+
(0, vitest_1.expect)(r.first).toEqual({ a: 1 });
|
|
32
|
+
(0, vitest_1.expect)(r.second).toEqual({ b: 2 });
|
|
33
|
+
});
|
|
34
|
+
(0, vitest_1.it)("works with primitives", () => {
|
|
35
|
+
const r = (0, ir_utils_1.mergeResults)(42, "hello");
|
|
36
|
+
(0, vitest_1.expect)(r.first).toBe(42);
|
|
37
|
+
(0, vitest_1.expect)(r.second).toBe("hello");
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
(0, vitest_1.describe)("loadIR", () => {
|
|
41
|
+
(0, vitest_1.it)("returns empty array for non-existent file", () => {
|
|
42
|
+
const result = (0, ir_utils_1.loadIR)("/nonexistent/path/ir.json");
|
|
43
|
+
(0, vitest_1.expect)(result).toEqual([]);
|
|
44
|
+
});
|
|
45
|
+
(0, vitest_1.it)("returns empty array when no path matches", () => {
|
|
46
|
+
// loadIR without a valid ir.json returns [] (file doesn't exist in test)
|
|
47
|
+
const result = (0, ir_utils_1.loadIR)("/tmp/no-ir-here.json");
|
|
48
|
+
(0, vitest_1.expect)(Array.isArray(result)).toBe(true);
|
|
49
|
+
});
|
|
50
|
+
});
|