progmune-runtime 2.0.2 → 2.1.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.
Files changed (107) hide show
  1. package/.mcp.json +11 -0
  2. package/.progmune_allowlist +50 -0
  3. package/.test_report/test_report.md +87 -0
  4. package/Dockerfile +2 -10
  5. package/FAQ.md +167 -0
  6. package/demo-project/auth.ts +55 -0
  7. package/demo-project/tsconfig.json +8 -0
  8. package/dist/ab-stats.js +11 -0
  9. package/dist/acl-breakdown.js +13 -0
  10. package/dist/all-sessions.js +11 -0
  11. package/dist/antibody-stats.js +11 -0
  12. package/dist/audit.js +218 -0
  13. package/dist/benchmark-count.js +7 -0
  14. package/dist/benchmark-full.js +17 -0
  15. package/dist/benchmark-pass-rate.js +54 -0
  16. package/dist/benchmark-report.js +67 -0
  17. package/dist/benchmark-save.js +62 -0
  18. package/dist/benchmark-status.js +15 -0
  19. package/dist/branch-ledger.js +365 -0
  20. package/dist/branch-tree-count.js +14 -0
  21. package/dist/check.js +506 -0
  22. package/dist/common-fixpath.js +12 -0
  23. package/dist/constraint-types.js +12 -0
  24. package/dist/deterministic-replay.js +277 -0
  25. package/dist/emitter.js +112 -12
  26. package/dist/exec-metrics.js +11 -0
  27. package/dist/execute.js +242 -0
  28. package/dist/extract-ir.js +550 -5
  29. package/dist/failure-collector.js +143 -0
  30. package/dist/failure-corpus.js +481 -35
  31. package/dist/failure-report.js +11 -0
  32. package/dist/failures.js +11 -0
  33. package/dist/fast-path-hits.js +13 -0
  34. package/dist/feedback.js +6 -3
  35. package/dist/file-lock.js +82 -0
  36. package/dist/find-session.js +10 -0
  37. package/dist/fingerprint-list.js +15 -0
  38. package/dist/gen-history-log.js +13 -0
  39. package/dist/generate.js +2 -1
  40. package/dist/generate_500.js +4 -2
  41. package/dist/genome.js +11 -0
  42. package/dist/heatmap-data.js +11 -0
  43. package/dist/heatmap.js +11 -0
  44. package/dist/immune-reporter.js +137 -0
  45. package/dist/learned.js +11 -0
  46. package/dist/ledger-registry.js +241 -0
  47. package/dist/llm.js +43 -2
  48. package/dist/load-benchmarks.js +47 -0
  49. package/dist/main.js +2 -1
  50. package/dist/mcp-server.mjs +446 -34
  51. package/dist/memory-layer.js +51 -13
  52. package/dist/metrics.js +11 -0
  53. package/dist/obs-web.js +561 -0
  54. package/dist/p0_ssg_demo.js +255 -40
  55. package/dist/planner.js +933 -65
  56. package/dist/protocol-registry.js +105 -0
  57. package/dist/recent-session.js +12 -0
  58. package/dist/repair-proposal.js +353 -0
  59. package/dist/report.js +32 -0
  60. package/dist/runtime-invariants.js +161 -0
  61. package/dist/runtime-types.js +117 -0
  62. package/dist/search-planner.js +38 -9
  63. package/dist/semantic-snapshot.js +155 -0
  64. package/dist/semantic-trace.js +1497 -0
  65. package/dist/semantic-validator.js +3 -2
  66. package/dist/semantic_guard_test.js +2 -1
  67. package/dist/sessions.js +11 -0
  68. package/dist/ssg-validator.js +658 -20
  69. package/dist/svl-distribution.js +11 -0
  70. package/dist/terminal-status.js +11 -0
  71. package/dist/test_failure_corpus.js +3 -1
  72. package/dist/token-savings.js +11 -0
  73. package/dist/total-repairs.js +12 -0
  74. package/dist/unresolved-count.js +12 -0
  75. package/dist/valid-fingerprints.js +13 -0
  76. package/dist/validator.js +116 -60
  77. package/dist/verify-fps.js +11 -0
  78. package/dist/verify-ledgers.js +11 -0
  79. package/docs/whitepaper-style.css +77 -0
  80. package/docs/whitepaper-v2.1.md +609 -0
  81. package/docs/whitepaper-v2.2.md +1064 -0
  82. package/docs/whitepaper-v2.2.pdf +0 -0
  83. package/fly.toml +1 -1
  84. package/package.json +13 -4
  85. package/protocols.json +136 -0
  86. package/public/dashboard.html +119 -0
  87. package/readme.md +829 -0
  88. package/server/hub.js +84 -12
  89. package/test/replay-golden/sess_1780063202050_mgeld.json +9 -0
  90. package/test/replay-golden/sess_1780064032560_gocld.json +354 -0
  91. package/test/replay-golden/sess_1780064413331_s2709.json +606 -0
  92. package/test/replay-golden/sess_1780064792710_y3avo.json +614 -0
  93. package/test/replay-golden.ts +84 -0
  94. package/test_benchmark.js +165 -0
  95. package/test_comprehensive.mjs +638 -0
  96. package/test_concurrency.js +129 -0
  97. package/test_ir_robustness.js +85 -0
  98. package/test_semantic_contracts.js +269 -0
  99. package/test_ssg_stress.js +156 -0
  100. package/test_svl3.js +58 -0
  101. package/tsconfig.json +1 -1
  102. package/.env.example +0 -3
  103. package/.progmune_memory/fingerprints.json +0 -7
  104. package/.progmune_memory/opt_in.json +0 -4
  105. package/README.md +0 -118
  106. package/dist/mcp-server.js +0 -55
  107. package/immune_hub_data/2026-05-14.json +0 -50
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.main = main;
4
+ // @progmune-generated session=sess_1780350938098_h5bts timestamp=2026-06-01T21:55:39.709Z ruleHash=9dec68bc2995e92a
5
+ // Generated with IR constraint: 404 functions, 17 protocol rules
6
+ const load_benchmarks_1 = require("./load-benchmarks");
7
+ const benchmark_count_1 = require("./benchmark-count");
8
+ const benchmark_report_1 = require("./benchmark-report");
9
+ const benchmark_save_1 = require("./benchmark-save");
10
+ function main() {
11
+ const benchmarks = (0, load_benchmarks_1.loadBenchmarks)();
12
+ const count = (0, benchmark_count_1.benchmarkCount)();
13
+ const report = (0, benchmark_report_1.benchmarkReport)();
14
+ const savedPath = (0, benchmark_save_1.benchmarkSave)(report);
15
+ return savedPath;
16
+ }
17
+ main();
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.benchmarkPassRate = benchmarkPassRate;
37
+ const fs = __importStar(require("fs"));
38
+ const path = __importStar(require("path"));
39
+ function benchmarkPassRate() {
40
+ const resultsDir = path.resolve(process.cwd(), "bench");
41
+ if (!fs.existsSync(resultsDir))
42
+ return { total: 0, passed: 0, rate: 0 };
43
+ const files = fs.readdirSync(resultsDir).filter(f => f.startsWith("results-") && f.endsWith(".json"));
44
+ if (files.length === 0)
45
+ return { total: 0, passed: 0, rate: 0 };
46
+ const latest = files.sort().reverse()[0];
47
+ const results = JSON.parse(fs.readFileSync(path.join(resultsDir, latest), "utf-8"));
48
+ const passed = results.filter(r => r.compile_success).length;
49
+ return {
50
+ total: results.length,
51
+ passed,
52
+ rate: results.length > 0 ? passed / results.length : 0,
53
+ };
54
+ }
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.benchmarkReport = benchmarkReport;
37
+ /** Format benchmark results as a readable report
38
+ * @protocol pre_states=["BENCHMARKS_LOADED"] post_states=["REPORT_FORMATTED"]
39
+ */
40
+ const fs = __importStar(require("fs"));
41
+ const path = __importStar(require("path"));
42
+ function benchmarkReport() {
43
+ const resultsDir = path.resolve(process.cwd(), "bench");
44
+ if (!fs.existsSync(resultsDir))
45
+ return "No benchmark results.";
46
+ const files = fs.readdirSync(resultsDir)
47
+ .filter(f => f.startsWith("results-") && f.endsWith(".json"))
48
+ .sort().reverse();
49
+ if (files.length === 0)
50
+ return "No benchmark results.";
51
+ const latest = files[0];
52
+ const results = JSON.parse(fs.readFileSync(path.join(resultsDir, latest), "utf-8"));
53
+ const passed = results.filter(r => r.compile_success).length;
54
+ const repaired = results.filter(r => r.repair_applied).length;
55
+ const lines = [
56
+ `Benchmark: ${results.length} tasks`,
57
+ `Compiled: ${passed}/${results.length} (${((passed / results.length) * 100).toFixed(1)}%)`,
58
+ `Repaired: ${repaired}`,
59
+ "",
60
+ ];
61
+ for (const r of results) {
62
+ const icon = r.compile_success ? "✅" : "❌";
63
+ const repair = r.repair_applied ? " 🔧" : "";
64
+ lines.push(`${icon} ${r.id}: ${r.intent.slice(0, 60)}${repair}`);
65
+ }
66
+ return lines.join("\n");
67
+ }
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.benchmarkSave = benchmarkSave;
37
+ exports.benchmarkLoadLatest = benchmarkLoadLatest;
38
+ /** Save benchmark results to a timestamped file
39
+ * @protocol pre_states=["BENCHMARKS_LOADED"] post_states=["RESULTS_SAVED"]
40
+ */
41
+ const fs = __importStar(require("fs"));
42
+ const path = __importStar(require("path"));
43
+ function benchmarkSave(data) {
44
+ const dir = path.resolve(process.cwd(), "bench");
45
+ if (!fs.existsSync(dir))
46
+ fs.mkdirSync(dir, { recursive: true });
47
+ const ts = Date.now();
48
+ const filePath = path.join(dir, `results-${ts}.json`);
49
+ fs.writeFileSync(filePath, JSON.stringify(data, null, 2), "utf-8");
50
+ return filePath;
51
+ }
52
+ function benchmarkLoadLatest() {
53
+ const dir = path.resolve(process.cwd(), "bench");
54
+ if (!fs.existsSync(dir))
55
+ return null;
56
+ const files = fs.readdirSync(dir)
57
+ .filter(f => f.startsWith("results-") && f.endsWith(".json"))
58
+ .sort().reverse();
59
+ if (files.length === 0)
60
+ return null;
61
+ return JSON.parse(fs.readFileSync(path.join(dir, files[0]), "utf-8"));
62
+ }
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.main = main;
4
+ // @progmune-generated session=sess_1780350835297_stf8a timestamp=2026-06-01T21:53:57.126Z ruleHash=9dec68bc2995e92a
5
+ // Generated with IR constraint: 401 functions, 17 protocol rules
6
+ const load_benchmarks_1 = require("./load-benchmarks");
7
+ const benchmark_count_1 = require("./benchmark-count");
8
+ const benchmark_report_1 = require("./benchmark-report");
9
+ function main() {
10
+ const tasks = (0, load_benchmarks_1.loadBenchmarks)();
11
+ const count = (0, benchmark_count_1.benchmarkCount)();
12
+ const report = (0, benchmark_report_1.benchmarkReport)();
13
+ return report;
14
+ }
15
+ main();
@@ -0,0 +1,365 @@
1
+ "use strict";
2
+ /**
3
+ * Phase 4: Branch Ledger (P1)
4
+ *
5
+ * Upgrades the semantic ledger from linear to tree-structured.
6
+ * Supports fork/merge for future Repair Planner, alternative plans,
7
+ * and counterfactual replay.
8
+ *
9
+ * A Branch is a named sequence of state transitions with a parent reference.
10
+ * The full execution is a tree of branches rooted at a single "root" branch.
11
+ *
12
+ * Backward compatible: existing linear ledgers auto-wrap as single-branch root.
13
+ */
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.generateBranchId = generateBranchId;
16
+ exports.createRootBranch = createRootBranch;
17
+ exports.createBranch = createBranch;
18
+ exports.forkBranch = forkBranch;
19
+ exports.mergeBranches = mergeBranches;
20
+ exports.flattenBranch = flattenBranch;
21
+ exports.getBranchPath = getBranchPath;
22
+ exports.replayBranch = replayBranch;
23
+ exports.buildBranchMap = buildBranchMap;
24
+ exports.findRootBranch = findRootBranch;
25
+ exports.findChildBranches = findChildBranches;
26
+ exports.describeBranchTree = describeBranchTree;
27
+ exports.evaluateBranches = evaluateBranches;
28
+ exports.wrapAsBranch = wrapAsBranch;
29
+ exports.unwrapBranchTree = unwrapBranchTree;
30
+ const ssg_validator_1 = require("./ssg-validator");
31
+ const runtime_invariants_1 = require("./runtime-invariants");
32
+ const protocol_registry_1 = require("./protocol-registry");
33
+ // ── Pure Functions ──
34
+ /** Generate a unique branch ID. */
35
+ function generateBranchId() {
36
+ return `br_${Date.now()}_${Math.random().toString(36).slice(2, 7)}`;
37
+ }
38
+ /** Create the root branch of a new execution tree. */
39
+ function createRootBranch(transitions = []) {
40
+ const id = generateBranchId();
41
+ return {
42
+ id,
43
+ rootId: id,
44
+ transitions,
45
+ reason: "root",
46
+ createdAt: Date.now(),
47
+ };
48
+ }
49
+ /**
50
+ * Create a CHILD branch (parent → child relationship).
51
+ *
52
+ * Tree structure:
53
+ * root
54
+ * └── child (parentId = root.id)
55
+ *
56
+ * The child starts with an independent transition sequence. It does NOT
57
+ * inherit any transitions from the parent — it begins empty or with
58
+ * the given initialTransitions. The parent's state at creation time is
59
+ * the child's implicit starting state; use forkBranch() if you need to
60
+ * share a prefix of transitions.
61
+ *
62
+ * Use createBranch when:
63
+ * - Creating an alternative implementation from scratch
64
+ * - The child has no shared history with the parent beyond the parent's
65
+ * final state
66
+ */
67
+ function createBranch(parent, reason = "alternative", initialTransitions = []) {
68
+ const id = generateBranchId();
69
+ return {
70
+ id,
71
+ parentId: parent.id,
72
+ rootId: parent.rootId,
73
+ transitions: initialTransitions,
74
+ reason,
75
+ createdAt: Date.now(),
76
+ };
77
+ }
78
+ /**
79
+ * Fork a branch at a specific transition index, creating a SIBLING branch.
80
+ *
81
+ * Sibling semantics (NOT child):
82
+ * parent
83
+ * ├── original (branch, truncated at splitIndex, marked "abandoned")
84
+ * └── forked (NEW sibling — same parentId as original, NOT a child of original)
85
+ *
86
+ * Tree structure BEFORE fork:
87
+ * ... → parent → branch
88
+ *
89
+ * Tree structure AFTER fork:
90
+ * ... → parent
91
+ * ├── original (abandoned — only transitions[0..splitIndex])
92
+ * └── forked (repair_attempt — transitions[splitIndex+1..end])
93
+ *
94
+ * Both share the same parent. The forked branch inherits the COMMON PREFIX
95
+ * (transitions 0..splitIndex) implicitly through the tree path — flattenBranch()
96
+ * will walk parent → forked and include parent's + forked's transitions.
97
+ *
98
+ * Use forkBranch when:
99
+ * - A violation is detected at splitIndex and you want to try a fix
100
+ * - The prefix up to splitIndex is valid and should be preserved
101
+ * - You want to keep the original as evidence (abandoned, not deleted)
102
+ *
103
+ * Use createBranch when:
104
+ * - Starting a completely fresh alternative from the parent's final state
105
+ */
106
+ function forkBranch(branch, splitIndex, reason = "repair_attempt") {
107
+ const sharedTransitions = branch.transitions.slice(0, splitIndex + 1);
108
+ const remainingTransitions = branch.transitions.slice(splitIndex + 1);
109
+ const original = {
110
+ ...branch,
111
+ transitions: sharedTransitions,
112
+ outcome: "abandoned",
113
+ };
114
+ const forked = {
115
+ id: generateBranchId(),
116
+ parentId: branch.parentId, // sibling — same parent
117
+ rootId: branch.rootId,
118
+ transitions: remainingTransitions,
119
+ reason,
120
+ createdAt: Date.now(),
121
+ };
122
+ // Ontology: verify all split transitions are internally consistent
123
+ for (const t of [...sharedTransitions, ...remainingTransitions]) {
124
+ if (t.valid)
125
+ try {
126
+ (0, runtime_invariants_1.assertDeltaConsistency)(t);
127
+ }
128
+ catch { }
129
+ }
130
+ return { original, forked };
131
+ }
132
+ /** Merge multiple branches into one.
133
+ * Takes the successful path: concatenates transitions from each branch
134
+ * in the order they appear in the tree path.
135
+ * Returns null if no branches have transitions. */
136
+ function mergeBranches(branches) {
137
+ const validBranches = branches.filter(b => b.transitions.length > 0);
138
+ if (validBranches.length === 0)
139
+ return null;
140
+ // Sort by creation time to preserve causal order
141
+ const sorted = [...validBranches].sort((a, b) => a.createdAt - b.createdAt);
142
+ const first = sorted[0];
143
+ const merged = {
144
+ id: generateBranchId(),
145
+ rootId: first.rootId,
146
+ transitions: [],
147
+ reason: "merge",
148
+ createdAt: Date.now(),
149
+ };
150
+ // Deduplicate transitions by index (keep first occurrence)
151
+ const seenIndices = new Set();
152
+ for (const branch of sorted) {
153
+ for (const t of branch.transitions) {
154
+ if (!seenIndices.has(t.actionIndex)) {
155
+ seenIndices.add(t.actionIndex);
156
+ merged.transitions.push(t);
157
+ }
158
+ }
159
+ }
160
+ // Sort by actionIndex
161
+ merged.transitions.sort((a, b) => a.actionIndex - b.actionIndex);
162
+ return merged;
163
+ }
164
+ /** Flatten a branch and all its ancestors into a single linear transition sequence.
165
+ * This is the bridge between the tree model and existing linear-only consumers
166
+ * (checkLedgerConsistency, hashLedger, etc.). */
167
+ function flattenBranch(branch, allBranches) {
168
+ const path = getBranchPath(branch, allBranches);
169
+ const allTransitions = [];
170
+ const seenIndices = new Set();
171
+ for (const b of path) {
172
+ for (const t of b.transitions) {
173
+ // In case of index collision (forked branches), keep the later branch's version
174
+ if (seenIndices.has(t.actionIndex)) {
175
+ // Replace the earlier transition with this one
176
+ const existingIdx = allTransitions.findIndex(existing => existing.actionIndex === t.actionIndex);
177
+ if (existingIdx >= 0) {
178
+ allTransitions[existingIdx] = t;
179
+ }
180
+ }
181
+ else {
182
+ seenIndices.add(t.actionIndex);
183
+ allTransitions.push(t);
184
+ }
185
+ }
186
+ }
187
+ return allTransitions.sort((a, b) => a.actionIndex - b.actionIndex);
188
+ }
189
+ /** Get the path from root to a given branch (inclusive). */
190
+ function getBranchPath(branch, allBranches) {
191
+ const path = [];
192
+ let current = branch;
193
+ while (current) {
194
+ path.unshift(current);
195
+ if (current.parentId) {
196
+ current = allBranches.get(current.parentId);
197
+ }
198
+ else {
199
+ current = undefined;
200
+ }
201
+ }
202
+ return path;
203
+ }
204
+ /** Replay a branch tree: rebuild state across all ancestor branches
205
+ * and verify every transition is valid. */
206
+ function replayBranch(branch, allBranches, namespaceInitialStates = (0, protocol_registry_1.getNsInit)()) {
207
+ const path = getBranchPath(branch, allBranches);
208
+ const pathIds = path.map(b => b.id);
209
+ // Collect all transitions in tree order
210
+ const allTransitions = flattenBranch(branch, allBranches);
211
+ // Check validity
212
+ let valid = true;
213
+ let violationIndex;
214
+ let violationBranch;
215
+ for (const t of allTransitions) {
216
+ if (!t.valid) {
217
+ valid = false;
218
+ violationIndex = t.actionIndex;
219
+ // Find which branch contains this transition
220
+ for (const b of path) {
221
+ if (b.transitions.some(bt => bt.actionIndex === t.actionIndex)) {
222
+ violationBranch = b.id;
223
+ break;
224
+ }
225
+ }
226
+ break;
227
+ }
228
+ }
229
+ const finalState = allTransitions.length > 0
230
+ ? (0, ssg_validator_1.rebuildState)(allTransitions, namespaceInitialStates)
231
+ : {};
232
+ return {
233
+ branchId: branch.id,
234
+ path: pathIds,
235
+ finalState,
236
+ totalTransitions: allTransitions.length,
237
+ valid,
238
+ violationIndex,
239
+ violationBranch,
240
+ };
241
+ }
242
+ /** Build a branch lookup map from an array of branches. */
243
+ function buildBranchMap(branches) {
244
+ const map = new Map();
245
+ for (const b of branches) {
246
+ map.set(b.id, b);
247
+ }
248
+ return map;
249
+ }
250
+ /** Find the root branch of a tree. */
251
+ function findRootBranch(branches) {
252
+ return branches.find(b => !b.parentId);
253
+ }
254
+ /** Find all child branches of a given parent. */
255
+ function findChildBranches(parent, allBranches) {
256
+ const children = [];
257
+ for (const b of allBranches.values()) {
258
+ if (b.parentId === parent.id) {
259
+ children.push(b);
260
+ }
261
+ }
262
+ return children;
263
+ }
264
+ /** Get the full branch tree as a human-readable structure. */
265
+ function describeBranchTree(root, allBranches, indent = 0) {
266
+ const prefix = " ".repeat(indent);
267
+ let result = `${prefix}${root.id.slice(0, 12)} [${root.reason}] (${root.transitions.length} tx, outcome: ${root.outcome || "open"})\n`;
268
+ const children = findChildBranches(root, allBranches);
269
+ for (const child of children) {
270
+ result += describeBranchTree(child, allBranches, indent + 1);
271
+ }
272
+ return result;
273
+ }
274
+ /** Evaluate all branches in a tree, score them, and return the recommended winner.
275
+ * Scoring: replay +50, zero violations +30, success outcome +20.
276
+ * Highest score wins. Ties go to the smaller branch (fewer transitions). */
277
+ function evaluateBranches(branches, namespaceInitialStates = new Map([["_global", "UNAUTHENTICATED"]])) {
278
+ if (branches.length === 0)
279
+ return { scores: [], winner: null };
280
+ const map = buildBranchMap(branches);
281
+ const scores = [];
282
+ for (const branch of branches) {
283
+ const tx = flattenBranch(branch, map);
284
+ const validCount = tx.filter(t => t.valid).length;
285
+ const invalidCount = tx.filter(t => !t.valid).length;
286
+ let replayPassed = false;
287
+ try {
288
+ const replay = replayBranch(branch, map, namespaceInitialStates);
289
+ replayPassed = replay.valid;
290
+ }
291
+ catch {
292
+ replayPassed = false;
293
+ }
294
+ let score = 0;
295
+ if (replayPassed)
296
+ score += 50;
297
+ if (invalidCount === 0)
298
+ score += 30;
299
+ if (branch.outcome === "success")
300
+ score += 20;
301
+ let recommendation = "";
302
+ if (score >= 90)
303
+ recommendation = "Recommended — clean execution";
304
+ else if (score >= 70)
305
+ recommendation = "Acceptable — minor issues";
306
+ else if (score >= 50)
307
+ recommendation = "Needs review — violations present";
308
+ else
309
+ recommendation = "Rejected — replay failed or significant violations";
310
+ scores.push({
311
+ branchId: branch.id,
312
+ reason: branch.reason,
313
+ outcome: branch.outcome || "open",
314
+ transitionCount: tx.length,
315
+ validCount,
316
+ violationCount: invalidCount,
317
+ replayPassed,
318
+ score,
319
+ recommendation,
320
+ });
321
+ }
322
+ // Sort: highest score first, ties broken by fewer transitions
323
+ scores.sort((a, b) => b.score - a.score || a.transitionCount - b.transitionCount);
324
+ // Winner is the first one that passed replay
325
+ const winner = scores.find(s => s.replayPassed) || scores[0] || null;
326
+ return { scores, winner };
327
+ }
328
+ /** Wrap a linear transition array as a single root branch (backward compat). */
329
+ function wrapAsBranch(transitions) {
330
+ const b = createRootBranch(transitions);
331
+ b.outcome = transitions.length > 0
332
+ ? (transitions.every(t => t.valid) ? "success" : "violation")
333
+ : "success";
334
+ return b;
335
+ }
336
+ /** Unwrap a branch tree to the linear transition list.
337
+ * For backward compatibility: flattens the "winning" path (first successful leaf). */
338
+ function unwrapBranchTree(branches) {
339
+ if (branches.length === 0)
340
+ return [];
341
+ const map = buildBranchMap(branches);
342
+ const root = findRootBranch(branches);
343
+ if (!root)
344
+ return [];
345
+ // Find the first successful leaf
346
+ const successfulLeaf = findSuccessfulLeaf(root, map);
347
+ if (successfulLeaf) {
348
+ return flattenBranch(successfulLeaf, map);
349
+ }
350
+ // Fallback: flatten the root
351
+ return flattenBranch(root, map);
352
+ }
353
+ function findSuccessfulLeaf(branch, allBranches) {
354
+ if (branch.outcome === "success") {
355
+ // Check if any children are also successful (prefer children)
356
+ const children = findChildBranches(branch, allBranches);
357
+ for (const child of children) {
358
+ const leaf = findSuccessfulLeaf(child, allBranches);
359
+ if (leaf)
360
+ return leaf;
361
+ }
362
+ return branch;
363
+ }
364
+ return undefined;
365
+ }
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.main = main;
4
+ // @progmune-generated session=sess_1780343627181_k5xw4 timestamp=2026-06-01T19:53:48.655Z ruleHash=9dec68bc2995e92a
5
+ // Generated with IR constraint: 389 functions, 17 protocol rules
6
+ const failure_corpus_1 = require("./failure-corpus");
7
+ const branch_ledger_1 = require("./branch-ledger");
8
+ function main() {
9
+ const sessions = (0, failure_corpus_1.getAllSessions)();
10
+ const root = (0, branch_ledger_1.findRootBranch)(sessions);
11
+ const children = (0, branch_ledger_1.findChildBranches)(root, {});
12
+ return children;
13
+ }
14
+ main();