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
package/dist/python-emitter.js
CHANGED
|
@@ -35,37 +35,48 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.emitPython = emitPython;
|
|
37
37
|
const fs = __importStar(require("fs"));
|
|
38
|
+
const BASIC_TYPES = new Set([
|
|
39
|
+
"str", "int", "float", "bool", "list", "dict", "tuple", "bytes",
|
|
40
|
+
"string", "number", "boolean", "any", "void", "None",
|
|
41
|
+
]);
|
|
38
42
|
function toPythonModule(filePath) {
|
|
39
43
|
let module = filePath.replace(/\.py$/, "").replace(/\//g, ".");
|
|
40
44
|
module = module.replace(/\.$/, "").replace(/\.__init__$/, "");
|
|
41
45
|
return module;
|
|
42
46
|
}
|
|
43
47
|
function pythonValue(val) {
|
|
44
|
-
if (typeof val ===
|
|
48
|
+
if (typeof val === "string")
|
|
45
49
|
return JSON.stringify(val);
|
|
46
|
-
if (typeof val ===
|
|
50
|
+
if (typeof val === "number" || typeof val === "boolean")
|
|
47
51
|
return String(val);
|
|
48
52
|
if (val === null || val === undefined)
|
|
49
|
-
return
|
|
50
|
-
if (typeof val ===
|
|
53
|
+
return "None";
|
|
54
|
+
if (typeof val === "object") {
|
|
51
55
|
const entries = Object.entries(val).map(([k, v]) => `${JSON.stringify(k)}: ${pythonValue(v)}`);
|
|
52
|
-
return `{${entries.join(
|
|
56
|
+
return `{${entries.join(", ")}}`;
|
|
53
57
|
}
|
|
54
|
-
return
|
|
58
|
+
return "None";
|
|
55
59
|
}
|
|
56
|
-
|
|
57
|
-
|
|
60
|
+
const STRING_ENUMS = {
|
|
61
|
+
SVL: '"SVL-4"', RootCause: '"F01"', BranchReason: '"repair_attempt"',
|
|
62
|
+
RepairStrategy: '"insert"', ConstraintType: '"protocol"',
|
|
63
|
+
};
|
|
64
|
+
function emitPython(actions, meta) {
|
|
65
|
+
const irRaw = JSON.parse(fs.readFileSync("ir.json", "utf-8"));
|
|
66
|
+
const ir = irRaw.functions || irRaw;
|
|
58
67
|
const funcToFile = new Map();
|
|
59
|
-
const
|
|
68
|
+
const fnMeta = new Map();
|
|
60
69
|
for (const f of ir) {
|
|
61
70
|
funcToFile.set(f.name, f.file);
|
|
62
|
-
|
|
71
|
+
fnMeta.set(f.name, f);
|
|
63
72
|
}
|
|
73
|
+
// ── Collect imports ──
|
|
64
74
|
const imports = new Map();
|
|
65
75
|
const collectImports = (action) => {
|
|
66
76
|
if (action.kind === "call" && action.function) {
|
|
67
77
|
const file = funcToFile.get(action.function);
|
|
68
|
-
|
|
78
|
+
const meta = fnMeta.get(action.function);
|
|
79
|
+
if (file && file !== "(external)" && meta?.exported !== false) {
|
|
69
80
|
const mod = toPythonModule(file);
|
|
70
81
|
if (!imports.has(mod))
|
|
71
82
|
imports.set(mod, new Set());
|
|
@@ -76,74 +87,181 @@ function emitPython(actions) {
|
|
|
76
87
|
(action.thenActions || []).forEach(collectImports);
|
|
77
88
|
(action.elseActions || []).forEach(collectImports);
|
|
78
89
|
}
|
|
90
|
+
else if (action.kind === "for") {
|
|
91
|
+
(action.bodyActions || []).forEach(collectImports);
|
|
92
|
+
}
|
|
79
93
|
};
|
|
80
94
|
for (const a of actions)
|
|
81
95
|
collectImports(a);
|
|
96
|
+
// ── Variable flow: scan all actions to find inputs ──
|
|
97
|
+
const declared = new Set();
|
|
98
|
+
const referenced = new Set();
|
|
99
|
+
const scanAction = (action) => {
|
|
100
|
+
if (action.kind === "call" && action.assignTo)
|
|
101
|
+
declared.add(action.assignTo);
|
|
102
|
+
else if (action.kind === "assign" && action.target)
|
|
103
|
+
declared.add(action.target);
|
|
104
|
+
else if (action.kind === "for" && action.variable)
|
|
105
|
+
declared.add(action.variable);
|
|
106
|
+
if (action.kind === "call" && action.args) {
|
|
107
|
+
for (const arg of action.args) {
|
|
108
|
+
const v = typeof arg === "object" ? arg?.value : arg;
|
|
109
|
+
if (typeof v === "string" && /^[a-zA-Z_]\w*$/.test(v) && v !== "")
|
|
110
|
+
referenced.add(v);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
if (action.kind === "if") {
|
|
114
|
+
(action.thenActions || []).forEach(scanAction);
|
|
115
|
+
(action.elseActions || []).forEach(scanAction);
|
|
116
|
+
}
|
|
117
|
+
else if (action.kind === "for") {
|
|
118
|
+
(action.bodyActions || []).forEach(scanAction);
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
for (const action of actions)
|
|
122
|
+
scanAction(action);
|
|
123
|
+
const rawInputs = [...referenced].filter(v => !declared.has(v) && v !== "");
|
|
124
|
+
// Resolve types from args
|
|
125
|
+
const inputTypes = new Map();
|
|
126
|
+
for (const action of actions) {
|
|
127
|
+
if (action.kind === "call" && action.args) {
|
|
128
|
+
for (const arg of action.args) {
|
|
129
|
+
const v = typeof arg === "object" ? arg?.value : arg;
|
|
130
|
+
const t = typeof arg === "object" ? arg?.type : "str";
|
|
131
|
+
if (typeof v === "string" && rawInputs.includes(v))
|
|
132
|
+
inputTypes.set(v, t);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
// ── Parameter bloat guard ──
|
|
137
|
+
const MAX_PARAMS = 10;
|
|
138
|
+
if (rawInputs.length > MAX_PARAMS) {
|
|
139
|
+
return `# REFINEMENT_NEEDED: ${rawInputs.length} params detected (max ${MAX_PARAMS}). Split into smaller functions.`;
|
|
140
|
+
}
|
|
141
|
+
// ── Build code ──
|
|
82
142
|
let code = "";
|
|
143
|
+
// Generation marker
|
|
144
|
+
if (meta?.sessionId) {
|
|
145
|
+
code += `# @progmune-generated session=${meta.sessionId} timestamp=${new Date().toISOString()}`;
|
|
146
|
+
if (meta.ruleHash)
|
|
147
|
+
code += ` ruleHash=${meta.ruleHash}`;
|
|
148
|
+
code += "\n";
|
|
149
|
+
const funcs = meta.irFunctionCount ?? ir.length;
|
|
150
|
+
const rules = meta.protocolRuleCount ?? 0;
|
|
151
|
+
code += `# Generated with IR constraint: ${funcs} functions`;
|
|
152
|
+
if (rules > 0)
|
|
153
|
+
code += `, ${rules} protocol rules`;
|
|
154
|
+
code += "\n";
|
|
155
|
+
}
|
|
83
156
|
for (const [mod, funcs] of imports) {
|
|
84
157
|
code += `from ${mod} import ${Array.from(funcs).join(", ")}\n`;
|
|
85
158
|
}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
const
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
return
|
|
159
|
+
const paramList = rawInputs.map(v => `${v}: ${inputTypes.get(v) || "str"}`).join(", ");
|
|
160
|
+
code += `\n\ndef main(${paramList}):\n`;
|
|
161
|
+
const argToPython = (action, i, a, meta) => {
|
|
162
|
+
const paramType = meta?.params?.[i]?.type || "str";
|
|
163
|
+
const val = a?.value;
|
|
164
|
+
// Variable reference
|
|
165
|
+
if (typeof val === "string" && declared.has(val))
|
|
166
|
+
return val;
|
|
167
|
+
if (typeof val === "string" && /^[a-zA-Z_]\w*$/.test(val) && val !== "")
|
|
168
|
+
return val;
|
|
169
|
+
// Empty default → use parameter name
|
|
170
|
+
const isEmpty = (v) => v === "" || v === 0 || v === false || v === null;
|
|
171
|
+
if (isEmpty(val) && a?.name) {
|
|
172
|
+
if (rawInputs.includes(a.name)) {
|
|
173
|
+
declared.add(a.name);
|
|
174
|
+
return a.name;
|
|
175
|
+
}
|
|
94
176
|
}
|
|
177
|
+
// String enums
|
|
178
|
+
if (STRING_ENUMS[paramType])
|
|
179
|
+
return STRING_ENUMS[paramType];
|
|
180
|
+
// Basic type defaults
|
|
181
|
+
if (paramType === "string" || paramType === "str")
|
|
182
|
+
return '""';
|
|
183
|
+
if (paramType === "number" || paramType === "int" || paramType === "float")
|
|
184
|
+
return "0";
|
|
185
|
+
if (paramType === "boolean" || paramType === "bool")
|
|
186
|
+
return "False";
|
|
187
|
+
if (paramType.endsWith("[]") || paramType === "list")
|
|
188
|
+
return "[]";
|
|
189
|
+
if (paramType.startsWith("Map<") || paramType === "dict")
|
|
190
|
+
return "{}";
|
|
191
|
+
if (paramType.startsWith("Set<"))
|
|
192
|
+
return "set()";
|
|
95
193
|
return pythonValue(val);
|
|
96
194
|
};
|
|
97
|
-
|
|
195
|
+
let counter = 0;
|
|
98
196
|
const convertLines = (action, indentLevel) => {
|
|
99
197
|
const indent = " ".repeat(indentLevel);
|
|
100
198
|
if (!action || !action.kind)
|
|
101
199
|
return [];
|
|
102
200
|
if (action.kind === "call") {
|
|
103
|
-
const
|
|
104
|
-
const args = (action.args || []).map((a) => argToPython(a
|
|
105
|
-
const resultVar = action.assignTo || `_res`;
|
|
106
|
-
|
|
107
|
-
return [`${indent}${resultVar} = ${
|
|
201
|
+
const meta = fnMeta.get(action.function || "");
|
|
202
|
+
const args = (action.args || []).map((a, i) => argToPython(action, i, a, meta)).join(", ");
|
|
203
|
+
const resultVar = action.assignTo || `_res${counter++}`;
|
|
204
|
+
declared.add(resultVar);
|
|
205
|
+
return [`${indent}${resultVar} = ${action.function}(${args})`];
|
|
108
206
|
}
|
|
109
207
|
if (action.kind === "if") {
|
|
110
|
-
const lines = [];
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
const elseActions = action.elseActions || [];
|
|
114
|
-
if (thenActions.length > 0) {
|
|
115
|
-
for (const a of thenActions) {
|
|
208
|
+
const lines = [`${indent}if ${action.condition}:`];
|
|
209
|
+
if ((action.thenActions || []).length > 0) {
|
|
210
|
+
for (const a of action.thenActions)
|
|
116
211
|
lines.push(...convertLines(a, indentLevel + 1));
|
|
117
|
-
}
|
|
118
212
|
}
|
|
119
213
|
else {
|
|
120
|
-
// 防止空块
|
|
121
214
|
lines.push(`${indent} pass`);
|
|
122
215
|
}
|
|
123
|
-
if (elseActions.length > 0) {
|
|
216
|
+
if ((action.elseActions || []).length > 0) {
|
|
124
217
|
lines.push(`${indent}else:`);
|
|
125
|
-
for (const a of elseActions)
|
|
218
|
+
for (const a of action.elseActions)
|
|
126
219
|
lines.push(...convertLines(a, indentLevel + 1));
|
|
127
|
-
}
|
|
128
220
|
}
|
|
129
221
|
return lines;
|
|
130
222
|
}
|
|
223
|
+
if (action.kind === "for") {
|
|
224
|
+
declared.add(action.variable);
|
|
225
|
+
const lines = [`${indent}for ${action.variable} in ${action.iterable}:`];
|
|
226
|
+
for (const a of (action.bodyActions || []))
|
|
227
|
+
lines.push(...convertLines(a, indentLevel + 1));
|
|
228
|
+
return lines;
|
|
229
|
+
}
|
|
230
|
+
if (action.kind === "assign") {
|
|
231
|
+
const val = typeof action.value === "string"
|
|
232
|
+
? (declared.has(action.value) ? action.value : JSON.stringify(action.value))
|
|
233
|
+
: pythonValue(action.value);
|
|
234
|
+
if (action.target)
|
|
235
|
+
declared.add(action.target);
|
|
236
|
+
return [`${indent}${action.target} = ${val}`];
|
|
237
|
+
}
|
|
131
238
|
if (action.kind === "return") {
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
return [`${indent}return ${JSON.stringify(val)}`];
|
|
239
|
+
if (typeof action.value === "string") {
|
|
240
|
+
if (declared.has(action.value))
|
|
241
|
+
return [`${indent}return ${action.value}`];
|
|
242
|
+
return [`${indent}return ${JSON.stringify(action.value)}`];
|
|
137
243
|
}
|
|
138
|
-
return [`${indent}return ${pythonValue(
|
|
244
|
+
return [`${indent}return ${pythonValue(action.value)}`];
|
|
139
245
|
}
|
|
140
246
|
return [];
|
|
141
247
|
};
|
|
142
248
|
const lines = [];
|
|
143
|
-
for (const a of actions)
|
|
249
|
+
for (const a of actions)
|
|
144
250
|
lines.push(...convertLines(a, 1));
|
|
145
|
-
}
|
|
146
251
|
code += lines.join("\n") + "\n";
|
|
147
|
-
|
|
252
|
+
// Auto-return injection: if LLM forgot to return
|
|
253
|
+
const lastAction = actions[actions.length - 1];
|
|
254
|
+
if (lastAction && lastAction.kind !== "return") {
|
|
255
|
+
const allCalls = actions.filter(a => a.kind === "call" && a.assignTo);
|
|
256
|
+
if (allCalls.length === 1) {
|
|
257
|
+
const c = allCalls[0];
|
|
258
|
+
code += ` return ${c.assignTo}\n`;
|
|
259
|
+
}
|
|
260
|
+
else if (allCalls.length > 1) {
|
|
261
|
+
const vars = allCalls.map(c => c.assignTo).join(", ");
|
|
262
|
+
code += ` return { ${vars} }\n`;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
code += `\nif __name__ == "__main__":\n main()\n`;
|
|
148
266
|
return code;
|
|
149
267
|
}
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* P8.3: Python Protocol Extractor
|
|
4
|
+
*
|
|
5
|
+
* Extracts protocol state machines from Python IR by analyzing call
|
|
6
|
+
* sequences and decorator-based protocol annotations. Bridges the
|
|
7
|
+
* gap between Python IR (tools/extract_ir.py) and the Progmune
|
|
8
|
+
* protocol discovery pipeline (P6).
|
|
9
|
+
*
|
|
10
|
+
* Two modes:
|
|
11
|
+
* 1. Annotation-based: reads @progmune decorators from IR
|
|
12
|
+
* 2. Sequence-based: infers protocol from call co-occurrence patterns
|
|
13
|
+
*
|
|
14
|
+
* Both modes produce SSG-compatible StateAnnotation maps.
|
|
15
|
+
*/
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.extractProtocolFromAnnotations = extractProtocolFromAnnotations;
|
|
18
|
+
exports.extractCallSequencesFromIR = extractCallSequencesFromIR;
|
|
19
|
+
exports.inferProtocolFromSequences = inferProtocolFromSequences;
|
|
20
|
+
exports.discoverPythonProtocols = discoverPythonProtocols;
|
|
21
|
+
exports.printPythonDiscoveryResult = printPythonDiscoveryResult;
|
|
22
|
+
const auto_protocol_synthesizer_1 = require("./auto-protocol-synthesizer");
|
|
23
|
+
// ═══════════════════════════════════════════════════════════════
|
|
24
|
+
// Annotation-based extraction
|
|
25
|
+
// ═══════════════════════════════════════════════════════════════
|
|
26
|
+
/**
|
|
27
|
+
* Extract protocol rules from Python IR using @progmune decorators.
|
|
28
|
+
*
|
|
29
|
+
* Each Python function with a @progmune decorator becomes a protocol
|
|
30
|
+
* rule with pre_states, post_states, and optional invalidate states.
|
|
31
|
+
*/
|
|
32
|
+
function extractProtocolFromAnnotations(ir) {
|
|
33
|
+
const rules = new Map();
|
|
34
|
+
for (const fn of ir) {
|
|
35
|
+
const proto = fn.protocol;
|
|
36
|
+
if (!proto)
|
|
37
|
+
continue;
|
|
38
|
+
const pre_states = Array.isArray(proto.pre_states) ? proto.pre_states : [];
|
|
39
|
+
const post_states = Array.isArray(proto.post_states) ? proto.post_states : [];
|
|
40
|
+
const invRaw = proto.invalidate;
|
|
41
|
+
const invalidate = Array.isArray(invRaw) && invRaw.length > 0
|
|
42
|
+
? invRaw : undefined;
|
|
43
|
+
rules.set(fn.name, {
|
|
44
|
+
pre_states,
|
|
45
|
+
post_states,
|
|
46
|
+
invalidate,
|
|
47
|
+
namespace: proto.namespace || "python",
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
return rules;
|
|
51
|
+
}
|
|
52
|
+
// ═══════════════════════════════════════════════════════════════
|
|
53
|
+
// Sequence-based inference
|
|
54
|
+
// ═══════════════════════════════════════════════════════════════
|
|
55
|
+
/**
|
|
56
|
+
* Extract call sequences from Python IR.
|
|
57
|
+
*
|
|
58
|
+
* Builds ordered sequences of function calls by analyzing the call
|
|
59
|
+
* graph. For each function that calls others, the called functions
|
|
60
|
+
* form a sequence in source order (approximated by IR order).
|
|
61
|
+
*/
|
|
62
|
+
function extractCallSequencesFromIR(ir) {
|
|
63
|
+
const sequences = [];
|
|
64
|
+
// Method 1: Functions that call other functions form natural sequences
|
|
65
|
+
for (const fn of ir) {
|
|
66
|
+
const calls = fn.calls || [];
|
|
67
|
+
if (calls.length >= 2) {
|
|
68
|
+
sequences.push([...calls]);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
// Method 2: Build sequences from cross-function call patterns
|
|
72
|
+
// If fnA calls fnB and fnB calls fnC, we get [fnB, fnC]
|
|
73
|
+
const fnMap = new Map();
|
|
74
|
+
for (const fn of ir)
|
|
75
|
+
fnMap.set(fn.name, fn);
|
|
76
|
+
// Build adjacency: which functions are called by which
|
|
77
|
+
const calledBy = new Map();
|
|
78
|
+
for (const fn of ir) {
|
|
79
|
+
for (const call of (fn.calls || [])) {
|
|
80
|
+
if (!calledBy.has(call))
|
|
81
|
+
calledBy.set(call, []);
|
|
82
|
+
calledBy.get(call).push(fn.name);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
// Method 3: Topological sort of call graph
|
|
86
|
+
// Functions with no callers = entry points → follow call chain
|
|
87
|
+
const entryPoints = ir.filter(fn => !calledBy.has(fn.name) || calledBy.get(fn.name).length === 0);
|
|
88
|
+
for (const entry of entryPoints) {
|
|
89
|
+
const seq = [entry.name];
|
|
90
|
+
const visited = new Set([entry.name]);
|
|
91
|
+
let current = entry;
|
|
92
|
+
// Follow calls until we hit a function that calls nothing new
|
|
93
|
+
for (let depth = 0; depth < 10; depth++) {
|
|
94
|
+
const next = (current.calls || []).find(c => !visited.has(c) && fnMap.has(c));
|
|
95
|
+
if (!next)
|
|
96
|
+
break;
|
|
97
|
+
seq.push(next);
|
|
98
|
+
visited.add(next);
|
|
99
|
+
current = fnMap.get(next);
|
|
100
|
+
}
|
|
101
|
+
if (seq.length >= 2)
|
|
102
|
+
sequences.push(seq);
|
|
103
|
+
}
|
|
104
|
+
return sequences;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Infer protocol rules from call sequences using the auto-protocol-synthesizer.
|
|
108
|
+
*/
|
|
109
|
+
function inferProtocolFromSequences(sequences) {
|
|
110
|
+
const synthesized = (0, auto_protocol_synthesizer_1.synthesizeProtocols)(sequences);
|
|
111
|
+
const rules = new Map();
|
|
112
|
+
for (const proto of synthesized) {
|
|
113
|
+
for (const r of proto.rules) {
|
|
114
|
+
rules.set(r.function, {
|
|
115
|
+
pre_states: r.pre_states,
|
|
116
|
+
post_states: r.post_states,
|
|
117
|
+
invalidate: r.invalidate,
|
|
118
|
+
namespace: "python_inferred",
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return rules;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Run the full Python protocol discovery pipeline on a set of IR functions.
|
|
126
|
+
*
|
|
127
|
+
* 1. Extract protocol annotations from @progmune decorators
|
|
128
|
+
* 2. Extract call sequences from the call graph
|
|
129
|
+
* 3. Infer additional protocols from call sequences
|
|
130
|
+
* 4. Merge annotation and inferred rules
|
|
131
|
+
*/
|
|
132
|
+
function discoverPythonProtocols(ir) {
|
|
133
|
+
// 1. Annotation-based
|
|
134
|
+
const annotationRules = extractProtocolFromAnnotations(ir);
|
|
135
|
+
const annotationCount = annotationRules.size;
|
|
136
|
+
// 2. Sequence extraction
|
|
137
|
+
const callSequences = extractCallSequencesFromIR(ir);
|
|
138
|
+
const sequenceCount = callSequences.length;
|
|
139
|
+
// 3. Inference-based
|
|
140
|
+
const inferredRules = inferProtocolFromSequences(callSequences);
|
|
141
|
+
const inferredCount = inferredRules.size;
|
|
142
|
+
// 4. Merge (annotation rules take precedence)
|
|
143
|
+
const combinedRules = new Map(inferredRules);
|
|
144
|
+
for (const [fn, rule] of annotationRules) {
|
|
145
|
+
combinedRules.set(fn, rule);
|
|
146
|
+
}
|
|
147
|
+
return {
|
|
148
|
+
annotationRules,
|
|
149
|
+
annotationCount,
|
|
150
|
+
callSequences,
|
|
151
|
+
sequenceCount,
|
|
152
|
+
inferredRules,
|
|
153
|
+
inferredCount,
|
|
154
|
+
combinedRules,
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
function printPythonDiscoveryResult(result) {
|
|
158
|
+
console.log("\n─── Python Protocol Discovery ───");
|
|
159
|
+
console.log(` Annotation rules: ${result.annotationCount}`);
|
|
160
|
+
console.log(` Call sequences: ${result.sequenceCount}`);
|
|
161
|
+
console.log(` Inferred rules: ${result.inferredCount}`);
|
|
162
|
+
console.log(` Combined rules: ${result.combinedRules.size}`);
|
|
163
|
+
console.log();
|
|
164
|
+
if (result.annotationCount > 0) {
|
|
165
|
+
console.log(" ── Annotation-based protocols ──");
|
|
166
|
+
for (const [fn, rule] of result.annotationRules) {
|
|
167
|
+
const inv = rule.invalidate ? ` [inv: ${rule.invalidate.join(",")}]` : "";
|
|
168
|
+
console.log(` ${fn}: [${rule.pre_states.join(",")}] → [${rule.post_states.join(",")}]${inv} (${rule.namespace})`);
|
|
169
|
+
}
|
|
170
|
+
console.log();
|
|
171
|
+
}
|
|
172
|
+
if (result.sequenceCount > 0) {
|
|
173
|
+
console.log(" ── Top call sequences ──");
|
|
174
|
+
for (const seq of result.callSequences.slice(0, 10)) {
|
|
175
|
+
console.log(` ${seq.join(" → ")}`);
|
|
176
|
+
}
|
|
177
|
+
console.log();
|
|
178
|
+
}
|
|
179
|
+
if (result.inferredCount > 0) {
|
|
180
|
+
console.log(" ── Inferred protocols ──");
|
|
181
|
+
for (const [fn, rule] of result.inferredRules) {
|
|
182
|
+
const inv = rule.invalidate ? ` [inv: ${rule.invalidate.join(",")}]` : "";
|
|
183
|
+
console.log(` ${fn}: [${rule.pre_states.join(",")}] → [${rule.post_states.join(",")}]${inv}`);
|
|
184
|
+
}
|
|
185
|
+
console.log();
|
|
186
|
+
}
|
|
187
|
+
}
|
|
@@ -0,0 +1,116 @@
|
|
|
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
|
+
/**
|
|
37
|
+
* P8.3: Python Protocol Discovery — End-to-End Tests
|
|
38
|
+
*
|
|
39
|
+
* Verifies the full pipeline from Python IR extraction through
|
|
40
|
+
* protocol annotation parsing to SSG-compatible rule generation.
|
|
41
|
+
*/
|
|
42
|
+
const vitest_1 = require("vitest");
|
|
43
|
+
const path = __importStar(require("path"));
|
|
44
|
+
const extract_ir_python_1 = require("./extract-ir-python");
|
|
45
|
+
const python_protocol_extractor_1 = require("./python-protocol-extractor");
|
|
46
|
+
const state_machine_fingerprint_1 = require("./state-machine-fingerprint");
|
|
47
|
+
const topology_factory_1 = require("./topology-factory");
|
|
48
|
+
const PYTHON_FIXTURE = path.resolve(__dirname, "..", "test-python-protocol");
|
|
49
|
+
(0, vitest_1.describe)("Python Protocol Discovery Pipeline", () => {
|
|
50
|
+
(0, vitest_1.it)("extracts IR from Python project with protocol annotations", () => {
|
|
51
|
+
const ir = (0, extract_ir_python_1.extractIRPython)(PYTHON_FIXTURE);
|
|
52
|
+
(0, vitest_1.expect)(ir.length).toBeGreaterThanOrEqual(8);
|
|
53
|
+
// Verify FunctionInfo-compatible output
|
|
54
|
+
for (const fn of ir) {
|
|
55
|
+
(0, vitest_1.expect)(fn.name).toBeTruthy();
|
|
56
|
+
(0, vitest_1.expect)(Array.isArray(fn.params)).toBe(true);
|
|
57
|
+
(0, vitest_1.expect)(Array.isArray(fn.calls)).toBe(true);
|
|
58
|
+
(0, vitest_1.expect)(typeof fn.exported).toBe("boolean");
|
|
59
|
+
(0, vitest_1.expect)(typeof fn.file).toBe("string");
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
(0, vitest_1.it)("extracts protocol annotations from @progmune decorators", () => {
|
|
63
|
+
const ir = (0, extract_ir_python_1.extractIRPython)(PYTHON_FIXTURE);
|
|
64
|
+
const rules = (0, python_protocol_extractor_1.extractProtocolFromAnnotations)(ir);
|
|
65
|
+
// Should find all 8 annotated functions
|
|
66
|
+
(0, vitest_1.expect)(rules.size).toBeGreaterThanOrEqual(8);
|
|
67
|
+
// Auth protocol
|
|
68
|
+
(0, vitest_1.expect)(rules.has("verify_password")).toBe(true);
|
|
69
|
+
(0, vitest_1.expect)(rules.get("verify_password").namespace).toBe("auth");
|
|
70
|
+
(0, vitest_1.expect)(rules.get("verify_password").pre_states).toEqual(["UNAUTHENTICATED"]);
|
|
71
|
+
(0, vitest_1.expect)(rules.get("verify_password").post_states).toEqual(["PASSWORD_VERIFIED"]);
|
|
72
|
+
// generate_jwt has invalidate
|
|
73
|
+
(0, vitest_1.expect)(rules.has("generate_jwt")).toBe(true);
|
|
74
|
+
(0, vitest_1.expect)(rules.get("generate_jwt").invalidate).toEqual(["PASSWORD_VERIFIED"]);
|
|
75
|
+
// File protocol
|
|
76
|
+
(0, vitest_1.expect)(rules.has("open_config")).toBe(true);
|
|
77
|
+
(0, vitest_1.expect)(rules.get("open_config").namespace).toBe("file");
|
|
78
|
+
// Stateless functions should NOT have protocol rules
|
|
79
|
+
(0, vitest_1.expect)(rules.has("compute_hash")).toBe(false);
|
|
80
|
+
(0, vitest_1.expect)(rules.has("validate_input")).toBe(false);
|
|
81
|
+
});
|
|
82
|
+
(0, vitest_1.it)("extracts call sequences from Python call graph", () => {
|
|
83
|
+
const ir = (0, extract_ir_python_1.extractIRPython)(PYTHON_FIXTURE);
|
|
84
|
+
const sequences = (0, python_protocol_extractor_1.extractCallSequencesFromIR)(ir);
|
|
85
|
+
(0, vitest_1.expect)(sequences.length).toBeGreaterThan(0);
|
|
86
|
+
// authenticate_and_open calls: verify_password, create_session, open_config,
|
|
87
|
+
// read_config, close_config, logout
|
|
88
|
+
const crossSeq = sequences.find(s => s.includes("open_config"));
|
|
89
|
+
(0, vitest_1.expect)(crossSeq).toBeTruthy();
|
|
90
|
+
});
|
|
91
|
+
(0, vitest_1.it)("runs full discovery pipeline and produces combined rules", () => {
|
|
92
|
+
const ir = (0, extract_ir_python_1.extractIRPython)(PYTHON_FIXTURE);
|
|
93
|
+
const result = (0, python_protocol_extractor_1.discoverPythonProtocols)(ir);
|
|
94
|
+
(0, python_protocol_extractor_1.printPythonDiscoveryResult)(result);
|
|
95
|
+
// Annotation rules
|
|
96
|
+
(0, vitest_1.expect)(result.annotationCount).toBeGreaterThanOrEqual(8);
|
|
97
|
+
// Call sequences
|
|
98
|
+
(0, vitest_1.expect)(result.sequenceCount).toBeGreaterThan(0);
|
|
99
|
+
// Combined rules should contain all annotation rules
|
|
100
|
+
(0, vitest_1.expect)(result.combinedRules.size).toBeGreaterThanOrEqual(result.annotationCount);
|
|
101
|
+
for (const [fn, rule] of result.annotationRules) {
|
|
102
|
+
(0, vitest_1.expect)(result.combinedRules.has(fn)).toBe(true);
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
(0, vitest_1.it)("Python protocol state machine matches hand-written TypeScript equivalent", () => {
|
|
106
|
+
const ir = (0, extract_ir_python_1.extractIRPython)(PYTHON_FIXTURE);
|
|
107
|
+
const pythonRules = (0, python_protocol_extractor_1.extractProtocolFromAnnotations)(ir);
|
|
108
|
+
// Build TypeScript-equivalent auth protocol using topology factory
|
|
109
|
+
const tsAuthRules = (0, topology_factory_1.createProtocolForTopology)("linear", 4); // has similar shape
|
|
110
|
+
const pythonFp = (0, state_machine_fingerprint_1.extractStateMachine)(pythonRules);
|
|
111
|
+
const tsFp = (0, state_machine_fingerprint_1.extractStateMachine)(tsAuthRules);
|
|
112
|
+
const comp = (0, state_machine_fingerprint_1.compareStateMachines)(pythonFp, tsFp);
|
|
113
|
+
console.log(`\n Python auth ↔ TypeScript linear: ${(comp.similarity * 100).toFixed(0)}%`);
|
|
114
|
+
(0, vitest_1.expect)(comp.similarity).toBeGreaterThan(0);
|
|
115
|
+
});
|
|
116
|
+
});
|