@plures/praxis 1.4.0 → 2.0.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/dist/browser/{chunk-N63K4KWS.js → chunk-4IRUGWR3.js} +1 -1
- package/dist/browser/chunk-6MVRT7CK.js +363 -0
- package/dist/browser/chunk-6SJ44Q64.js +473 -0
- package/dist/browser/chunk-BQOYZBWA.js +282 -0
- package/dist/browser/chunk-IG5BJ2MT.js +91 -0
- package/dist/browser/{chunk-MJK3IYTJ.js → chunk-JZDJU2DO.js} +4 -84
- package/dist/browser/chunk-ZEW4LJAJ.js +353 -0
- package/dist/browser/{engine-YIEGSX7U.js → engine-3B5WJPGT.js} +2 -1
- package/dist/browser/expectations/index.d.ts +180 -0
- package/dist/browser/expectations/index.js +14 -0
- package/dist/browser/factory/index.d.ts +150 -0
- package/dist/browser/factory/index.js +15 -0
- package/dist/browser/index.d.ts +277 -3
- package/dist/browser/index.js +425 -60
- package/dist/browser/integrations/svelte.d.ts +4 -2
- package/dist/browser/integrations/svelte.js +3 -2
- package/dist/browser/project/index.d.ts +177 -0
- package/dist/browser/project/index.js +19 -0
- package/dist/browser/reactive-engine.svelte-BwWadvAW.d.ts +224 -0
- package/dist/browser/rule-result-DcXWe9tn.d.ts +206 -0
- package/dist/browser/rules-BaWMqxuG.d.ts +277 -0
- package/dist/browser/unified/index.d.ts +239 -0
- package/dist/browser/unified/index.js +20 -0
- package/dist/node/chunk-6MVRT7CK.js +363 -0
- package/dist/node/chunk-AZLNISFI.js +1690 -0
- package/dist/node/chunk-IG5BJ2MT.js +91 -0
- package/dist/node/{chunk-KMJWAFZV.js → chunk-JZDJU2DO.js} +4 -89
- package/dist/node/{chunk-7M3HV4XR.js → chunk-WFRHXZBP.js} +3 -3
- package/dist/node/cli/index.cjs +48 -0
- package/dist/node/cli/index.js +2 -2
- package/dist/node/{engine-FEN5IYZ5.js → engine-VFHCIEM4.js} +2 -1
- package/dist/node/index.cjs +2114 -0
- package/dist/node/index.d.cts +964 -280
- package/dist/node/index.d.ts +964 -280
- package/dist/node/index.js +575 -10
- package/dist/node/integrations/svelte.d.cts +3 -2
- package/dist/node/integrations/svelte.d.ts +3 -2
- package/dist/node/integrations/svelte.js +3 -2
- package/dist/node/{reactive-engine.svelte-DekxqFu0.d.ts → reactive-engine.svelte-BBZLMzus.d.ts} +3 -79
- package/dist/node/{reactive-engine.svelte-Cg0Yc2Hs.d.cts → reactive-engine.svelte-Cbq_V20o.d.cts} +3 -79
- package/dist/node/rule-result-B9GMivAn.d.cts +80 -0
- package/dist/node/rule-result-Bo3sFMmN.d.ts +80 -0
- package/dist/node/{server-SYZPDULV.js → server-FKLVY57V.js} +4 -2
- package/dist/node/unified/index.cjs +484 -0
- package/dist/node/unified/index.d.cts +240 -0
- package/dist/node/unified/index.d.ts +240 -0
- package/dist/node/unified/index.js +21 -0
- package/dist/node/{validate-TQGVIG7G.js → validate-BY7JNY7H.js} +2 -1
- package/package.json +38 -11
- package/src/__tests__/chronos-project.test.ts +799 -0
- package/src/__tests__/decision-ledger.test.ts +857 -402
- package/src/chronos/diff.ts +336 -0
- package/src/chronos/hooks.ts +227 -0
- package/src/chronos/index.ts +83 -0
- package/src/chronos/project-chronicle.ts +198 -0
- package/src/chronos/timeline.ts +152 -0
- package/src/decision-ledger/analyzer-types.ts +280 -0
- package/src/decision-ledger/analyzer.ts +518 -0
- package/src/decision-ledger/contract-verification.ts +456 -0
- package/src/decision-ledger/derivation.ts +158 -0
- package/src/decision-ledger/index.ts +59 -0
- package/src/decision-ledger/report.ts +378 -0
- package/src/decision-ledger/suggestions.ts +287 -0
- package/src/index.browser.ts +103 -0
- package/src/index.ts +98 -0
- package/src/unified/__tests__/unified.test.ts +396 -0
- package/src/unified/core.ts +517 -0
- package/src/unified/index.ts +32 -0
- package/src/unified/rules.ts +66 -0
- package/src/unified/types.ts +148 -0
- package/dist/browser/reactive-engine.svelte-DjynI82A.d.ts +0 -688
- package/dist/node/chunk-FWOXU4MM.js +0 -487
|
@@ -1,487 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
getContractFromDescriptor
|
|
3
|
-
} from "./chunk-PGVSB6NR.js";
|
|
4
|
-
|
|
5
|
-
// src/dsl/index.ts
|
|
6
|
-
function defineFact(tag) {
|
|
7
|
-
return {
|
|
8
|
-
tag,
|
|
9
|
-
create(payload) {
|
|
10
|
-
return { tag, payload };
|
|
11
|
-
},
|
|
12
|
-
is(fact) {
|
|
13
|
-
return fact.tag === tag;
|
|
14
|
-
}
|
|
15
|
-
};
|
|
16
|
-
}
|
|
17
|
-
function defineEvent(tag) {
|
|
18
|
-
return {
|
|
19
|
-
tag,
|
|
20
|
-
create(payload) {
|
|
21
|
-
return { tag, payload };
|
|
22
|
-
},
|
|
23
|
-
is(event) {
|
|
24
|
-
return event.tag === tag;
|
|
25
|
-
}
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
|
-
function defineRule(options) {
|
|
29
|
-
const contract = options.contract ?? options.meta?.contract;
|
|
30
|
-
const meta = contract ? { ...options.meta ?? {}, contract } : options.meta;
|
|
31
|
-
return {
|
|
32
|
-
id: options.id,
|
|
33
|
-
description: options.description,
|
|
34
|
-
impl: options.impl,
|
|
35
|
-
eventTypes: options.eventTypes,
|
|
36
|
-
contract,
|
|
37
|
-
meta
|
|
38
|
-
};
|
|
39
|
-
}
|
|
40
|
-
function defineConstraint(options) {
|
|
41
|
-
const contract = options.contract ?? options.meta?.contract;
|
|
42
|
-
const meta = contract ? { ...options.meta ?? {}, contract } : options.meta;
|
|
43
|
-
return {
|
|
44
|
-
id: options.id,
|
|
45
|
-
description: options.description,
|
|
46
|
-
impl: options.impl,
|
|
47
|
-
contract,
|
|
48
|
-
meta
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
function defineModule(options) {
|
|
52
|
-
return {
|
|
53
|
-
rules: options.rules ?? [],
|
|
54
|
-
constraints: options.constraints ?? [],
|
|
55
|
-
meta: options.meta
|
|
56
|
-
};
|
|
57
|
-
}
|
|
58
|
-
function filterEvents(events, definition) {
|
|
59
|
-
return events.filter(definition.is);
|
|
60
|
-
}
|
|
61
|
-
function filterFacts(facts, definition) {
|
|
62
|
-
return facts.filter(definition.is);
|
|
63
|
-
}
|
|
64
|
-
function findEvent(events, definition) {
|
|
65
|
-
return events.find(definition.is);
|
|
66
|
-
}
|
|
67
|
-
function findFact(facts, definition) {
|
|
68
|
-
return facts.find(definition.is);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
// src/decision-ledger/facts-events.ts
|
|
72
|
-
var ContractMissing = defineFact("ContractMissing");
|
|
73
|
-
var ContractValidated = defineFact("ContractValidated");
|
|
74
|
-
var AcknowledgeContractGap = defineEvent("ACKNOWLEDGE_CONTRACT_GAP");
|
|
75
|
-
var ValidateContracts = defineEvent("VALIDATE_CONTRACTS");
|
|
76
|
-
var ContractGapAcknowledged = defineFact("ContractGapAcknowledged");
|
|
77
|
-
var ContractAdded = defineEvent("CONTRACT_ADDED");
|
|
78
|
-
var ContractUpdated = defineEvent("CONTRACT_UPDATED");
|
|
79
|
-
var ContractGapEmitted = defineEvent("CONTRACT_GAP_EMITTED");
|
|
80
|
-
|
|
81
|
-
// src/decision-ledger/validation.ts
|
|
82
|
-
function validateContracts(registry, options = {}) {
|
|
83
|
-
const {
|
|
84
|
-
incompleteSeverity = "warning",
|
|
85
|
-
requiredFields = ["behavior", "examples"],
|
|
86
|
-
artifactIndex
|
|
87
|
-
} = options;
|
|
88
|
-
const complete = [];
|
|
89
|
-
const incomplete = [];
|
|
90
|
-
const missing = [];
|
|
91
|
-
for (const rule of registry.getAllRules()) {
|
|
92
|
-
const contract = getContractFromDescriptor(rule);
|
|
93
|
-
if (!contract) {
|
|
94
|
-
missing.push(rule.id);
|
|
95
|
-
if (options.missingSeverity) {
|
|
96
|
-
incomplete.push({
|
|
97
|
-
ruleId: rule.id,
|
|
98
|
-
missing: ["contract"],
|
|
99
|
-
severity: options.missingSeverity,
|
|
100
|
-
message: `Rule '${rule.id}' has no contract`
|
|
101
|
-
});
|
|
102
|
-
}
|
|
103
|
-
continue;
|
|
104
|
-
}
|
|
105
|
-
const gaps = validateContract(contract, requiredFields, artifactIndex);
|
|
106
|
-
if (gaps.length > 0) {
|
|
107
|
-
incomplete.push({
|
|
108
|
-
ruleId: rule.id,
|
|
109
|
-
missing: gaps,
|
|
110
|
-
severity: incompleteSeverity,
|
|
111
|
-
message: `Rule '${rule.id}' contract is incomplete: missing ${gaps.join(", ")}`
|
|
112
|
-
});
|
|
113
|
-
} else {
|
|
114
|
-
complete.push({ ruleId: rule.id, contract });
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
for (const constraint of registry.getAllConstraints()) {
|
|
118
|
-
const contract = getContractFromDescriptor(constraint);
|
|
119
|
-
if (!contract) {
|
|
120
|
-
missing.push(constraint.id);
|
|
121
|
-
if (options.missingSeverity) {
|
|
122
|
-
incomplete.push({
|
|
123
|
-
ruleId: constraint.id,
|
|
124
|
-
missing: ["contract"],
|
|
125
|
-
severity: options.missingSeverity,
|
|
126
|
-
message: `Constraint '${constraint.id}' has no contract`
|
|
127
|
-
});
|
|
128
|
-
}
|
|
129
|
-
continue;
|
|
130
|
-
}
|
|
131
|
-
const gaps = validateContract(contract, requiredFields, artifactIndex);
|
|
132
|
-
if (gaps.length > 0) {
|
|
133
|
-
incomplete.push({
|
|
134
|
-
ruleId: constraint.id,
|
|
135
|
-
missing: gaps,
|
|
136
|
-
severity: incompleteSeverity,
|
|
137
|
-
message: `Constraint '${constraint.id}' contract is incomplete: missing ${gaps.join(", ")}`
|
|
138
|
-
});
|
|
139
|
-
} else {
|
|
140
|
-
complete.push({ ruleId: constraint.id, contract });
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
const total = registry.getAllRules().length + registry.getAllConstraints().length;
|
|
144
|
-
return {
|
|
145
|
-
complete,
|
|
146
|
-
incomplete,
|
|
147
|
-
missing,
|
|
148
|
-
total,
|
|
149
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
150
|
-
};
|
|
151
|
-
}
|
|
152
|
-
function validateContract(contract, requiredFields, artifactIndex) {
|
|
153
|
-
const missing = [];
|
|
154
|
-
if (requiredFields.includes("behavior") && isFieldEmpty(contract.behavior)) {
|
|
155
|
-
missing.push("behavior");
|
|
156
|
-
}
|
|
157
|
-
if (requiredFields.includes("examples") && (!contract.examples || contract.examples.length === 0)) {
|
|
158
|
-
missing.push("examples");
|
|
159
|
-
}
|
|
160
|
-
if (requiredFields.includes("invariants") && (!contract.invariants || contract.invariants.length === 0)) {
|
|
161
|
-
missing.push("invariants");
|
|
162
|
-
}
|
|
163
|
-
if (artifactIndex?.tests && !artifactIndex.tests.has(contract.ruleId)) {
|
|
164
|
-
missing.push("tests");
|
|
165
|
-
}
|
|
166
|
-
if (artifactIndex?.spec && !artifactIndex.spec.has(contract.ruleId)) {
|
|
167
|
-
missing.push("spec");
|
|
168
|
-
}
|
|
169
|
-
return missing;
|
|
170
|
-
}
|
|
171
|
-
function isFieldEmpty(value) {
|
|
172
|
-
return !value || value.trim() === "";
|
|
173
|
-
}
|
|
174
|
-
function formatValidationReport(report) {
|
|
175
|
-
const lines = [];
|
|
176
|
-
lines.push("Contract Validation Report");
|
|
177
|
-
lines.push("=".repeat(50));
|
|
178
|
-
lines.push("");
|
|
179
|
-
lines.push(`Total: ${report.total}`);
|
|
180
|
-
lines.push(`Complete: ${report.complete.length}`);
|
|
181
|
-
lines.push(`Incomplete: ${report.incomplete.length}`);
|
|
182
|
-
lines.push(`Missing: ${report.missing.length}`);
|
|
183
|
-
lines.push("");
|
|
184
|
-
if (report.complete.length > 0) {
|
|
185
|
-
lines.push("\u2713 Complete Contracts:");
|
|
186
|
-
for (const { ruleId, contract } of report.complete) {
|
|
187
|
-
lines.push(` \u2713 ${ruleId} (v${contract.version || "1.0.0"})`);
|
|
188
|
-
}
|
|
189
|
-
lines.push("");
|
|
190
|
-
}
|
|
191
|
-
if (report.incomplete.length > 0) {
|
|
192
|
-
lines.push("\u2717 Incomplete Contracts:");
|
|
193
|
-
for (const gap of report.incomplete) {
|
|
194
|
-
const icon = gap.severity === "error" ? "\u2717" : gap.severity === "warning" ? "\u26A0" : "\u2139";
|
|
195
|
-
lines.push(` ${icon} ${gap.ruleId} - Missing: ${gap.missing.join(", ")}`);
|
|
196
|
-
if (gap.message) {
|
|
197
|
-
lines.push(` ${gap.message}`);
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
lines.push("");
|
|
201
|
-
}
|
|
202
|
-
if (report.missing.length > 0) {
|
|
203
|
-
lines.push("\u2717 No Contract:");
|
|
204
|
-
for (const ruleId of report.missing) {
|
|
205
|
-
lines.push(` \u2717 ${ruleId}`);
|
|
206
|
-
}
|
|
207
|
-
lines.push("");
|
|
208
|
-
}
|
|
209
|
-
lines.push(`Validated at: ${report.timestamp}`);
|
|
210
|
-
return lines.join("\n");
|
|
211
|
-
}
|
|
212
|
-
function formatValidationReportJSON(report) {
|
|
213
|
-
return JSON.stringify(report, null, 2);
|
|
214
|
-
}
|
|
215
|
-
function formatValidationReportSARIF(report) {
|
|
216
|
-
const results = report.incomplete.map((gap) => {
|
|
217
|
-
const primaryMissing = gap.missing.length > 0 ? gap.missing[0] : "contract";
|
|
218
|
-
return {
|
|
219
|
-
ruleId: `decision-ledger/${primaryMissing}`,
|
|
220
|
-
level: gap.severity === "error" ? "error" : gap.severity === "warning" ? "warning" : "note",
|
|
221
|
-
message: {
|
|
222
|
-
text: gap.message || `Missing: ${gap.missing.join(", ")}`
|
|
223
|
-
},
|
|
224
|
-
locations: [
|
|
225
|
-
{
|
|
226
|
-
physicalLocation: {
|
|
227
|
-
artifactLocation: {
|
|
228
|
-
uri: "registry"
|
|
229
|
-
},
|
|
230
|
-
region: {
|
|
231
|
-
startLine: 1
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
],
|
|
236
|
-
properties: {
|
|
237
|
-
ruleId: gap.ruleId,
|
|
238
|
-
missing: gap.missing
|
|
239
|
-
}
|
|
240
|
-
};
|
|
241
|
-
});
|
|
242
|
-
const sarif = {
|
|
243
|
-
version: "2.1.0",
|
|
244
|
-
$schema: "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json",
|
|
245
|
-
runs: [
|
|
246
|
-
{
|
|
247
|
-
tool: {
|
|
248
|
-
driver: {
|
|
249
|
-
name: "Praxis Decision Ledger",
|
|
250
|
-
version: "1.0.0",
|
|
251
|
-
informationUri: "https://github.com/plures/praxis",
|
|
252
|
-
rules: [
|
|
253
|
-
{
|
|
254
|
-
id: "decision-ledger/contract",
|
|
255
|
-
shortDescription: {
|
|
256
|
-
text: "Rule or constraint missing contract"
|
|
257
|
-
}
|
|
258
|
-
},
|
|
259
|
-
{
|
|
260
|
-
id: "decision-ledger/behavior",
|
|
261
|
-
shortDescription: {
|
|
262
|
-
text: "Contract missing behavior description"
|
|
263
|
-
}
|
|
264
|
-
},
|
|
265
|
-
{
|
|
266
|
-
id: "decision-ledger/examples",
|
|
267
|
-
shortDescription: {
|
|
268
|
-
text: "Contract missing examples"
|
|
269
|
-
}
|
|
270
|
-
},
|
|
271
|
-
{
|
|
272
|
-
id: "decision-ledger/invariants",
|
|
273
|
-
shortDescription: {
|
|
274
|
-
text: "Contract missing invariants"
|
|
275
|
-
}
|
|
276
|
-
},
|
|
277
|
-
{
|
|
278
|
-
id: "decision-ledger/tests",
|
|
279
|
-
shortDescription: {
|
|
280
|
-
text: "Contract missing tests"
|
|
281
|
-
}
|
|
282
|
-
},
|
|
283
|
-
{
|
|
284
|
-
id: "decision-ledger/spec",
|
|
285
|
-
shortDescription: {
|
|
286
|
-
text: "Contract missing spec"
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
]
|
|
290
|
-
}
|
|
291
|
-
},
|
|
292
|
-
results
|
|
293
|
-
}
|
|
294
|
-
]
|
|
295
|
-
};
|
|
296
|
-
return JSON.stringify(sarif, null, 2);
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
// src/decision-ledger/ledger.ts
|
|
300
|
-
var BehaviorLedger = class _BehaviorLedger {
|
|
301
|
-
entries = [];
|
|
302
|
-
entryMap = /* @__PURE__ */ new Map();
|
|
303
|
-
/**
|
|
304
|
-
* Append a new entry to the ledger.
|
|
305
|
-
*
|
|
306
|
-
* @param entry The entry to append
|
|
307
|
-
* @throws Error if entry ID already exists
|
|
308
|
-
*/
|
|
309
|
-
append(entry) {
|
|
310
|
-
if (this.entryMap.has(entry.id)) {
|
|
311
|
-
throw new Error(`Ledger entry with ID '${entry.id}' already exists`);
|
|
312
|
-
}
|
|
313
|
-
if (entry.supersedes) {
|
|
314
|
-
const superseded = this.entryMap.get(entry.supersedes);
|
|
315
|
-
if (superseded && superseded.status === "active") {
|
|
316
|
-
const updatedEntry = {
|
|
317
|
-
...superseded,
|
|
318
|
-
status: "superseded"
|
|
319
|
-
};
|
|
320
|
-
this.entryMap.set(entry.supersedes, updatedEntry);
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
this.entries.push(entry);
|
|
324
|
-
this.entryMap.set(entry.id, entry);
|
|
325
|
-
}
|
|
326
|
-
/**
|
|
327
|
-
* Get an entry by ID.
|
|
328
|
-
*
|
|
329
|
-
* @param id The entry ID
|
|
330
|
-
* @returns The entry, or undefined if not found
|
|
331
|
-
*/
|
|
332
|
-
getEntry(id) {
|
|
333
|
-
return this.entryMap.get(id);
|
|
334
|
-
}
|
|
335
|
-
/**
|
|
336
|
-
* Get all entries (in order of append) with current status.
|
|
337
|
-
*
|
|
338
|
-
* @returns Array of all entries with current status from the map
|
|
339
|
-
*/
|
|
340
|
-
getAllEntries() {
|
|
341
|
-
return this.entries.map((entry) => this.entryMap.get(entry.id));
|
|
342
|
-
}
|
|
343
|
-
/**
|
|
344
|
-
* Get entries for a specific rule ID.
|
|
345
|
-
*
|
|
346
|
-
* @param ruleId The rule ID
|
|
347
|
-
* @returns Array of entries for this rule with current status
|
|
348
|
-
*/
|
|
349
|
-
getEntriesForRule(ruleId) {
|
|
350
|
-
return this.entries.map((entry) => this.entryMap.get(entry.id)).filter((entry) => entry.contract.ruleId === ruleId);
|
|
351
|
-
}
|
|
352
|
-
/**
|
|
353
|
-
* Get the latest active entry for a rule.
|
|
354
|
-
*
|
|
355
|
-
* @param ruleId The rule ID
|
|
356
|
-
* @returns The latest active entry, or undefined if none
|
|
357
|
-
*/
|
|
358
|
-
getLatestEntry(ruleId) {
|
|
359
|
-
const entries = this.getEntriesForRule(ruleId);
|
|
360
|
-
const activeEntries = entries.filter((entry) => entry.status === "active");
|
|
361
|
-
if (activeEntries.length === 0) {
|
|
362
|
-
return void 0;
|
|
363
|
-
}
|
|
364
|
-
return activeEntries[activeEntries.length - 1];
|
|
365
|
-
}
|
|
366
|
-
/**
|
|
367
|
-
* Get all active assumptions across all entries.
|
|
368
|
-
*
|
|
369
|
-
* @returns Map of assumption ID to assumption
|
|
370
|
-
*/
|
|
371
|
-
getActiveAssumptions() {
|
|
372
|
-
const assumptions = /* @__PURE__ */ new Map();
|
|
373
|
-
for (const entry of this.entries) {
|
|
374
|
-
const currentEntry = this.entryMap.get(entry.id);
|
|
375
|
-
if (currentEntry.status !== "active") {
|
|
376
|
-
continue;
|
|
377
|
-
}
|
|
378
|
-
for (const assumption of currentEntry.contract.assumptions || []) {
|
|
379
|
-
if (assumption.status === "active") {
|
|
380
|
-
assumptions.set(assumption.id, assumption);
|
|
381
|
-
}
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
return assumptions;
|
|
385
|
-
}
|
|
386
|
-
/**
|
|
387
|
-
* Find assumptions that impact a specific artifact type.
|
|
388
|
-
*
|
|
389
|
-
* @param impactType The artifact type ('spec', 'tests', 'code')
|
|
390
|
-
* @returns Array of assumptions
|
|
391
|
-
*/
|
|
392
|
-
findAssumptionsByImpact(impactType) {
|
|
393
|
-
const assumptions = [];
|
|
394
|
-
for (const entry of this.entries) {
|
|
395
|
-
const currentEntry = this.entryMap.get(entry.id);
|
|
396
|
-
if (currentEntry.status !== "active") {
|
|
397
|
-
continue;
|
|
398
|
-
}
|
|
399
|
-
for (const assumption of currentEntry.contract.assumptions || []) {
|
|
400
|
-
if (assumption.status === "active" && assumption.impacts.includes(impactType)) {
|
|
401
|
-
assumptions.push(assumption);
|
|
402
|
-
}
|
|
403
|
-
}
|
|
404
|
-
}
|
|
405
|
-
return assumptions;
|
|
406
|
-
}
|
|
407
|
-
/**
|
|
408
|
-
* Get ledger statistics.
|
|
409
|
-
*/
|
|
410
|
-
getStats() {
|
|
411
|
-
const currentEntries = this.entries.map((e) => this.entryMap.get(e.id));
|
|
412
|
-
const active = currentEntries.filter((e) => e.status === "active").length;
|
|
413
|
-
const superseded = currentEntries.filter((e) => e.status === "superseded").length;
|
|
414
|
-
const deprecated = currentEntries.filter((e) => e.status === "deprecated").length;
|
|
415
|
-
const uniqueRules = new Set(currentEntries.map((e) => e.contract.ruleId)).size;
|
|
416
|
-
return {
|
|
417
|
-
totalEntries: this.entries.length,
|
|
418
|
-
activeEntries: active,
|
|
419
|
-
supersededEntries: superseded,
|
|
420
|
-
deprecatedEntries: deprecated,
|
|
421
|
-
uniqueRules
|
|
422
|
-
};
|
|
423
|
-
}
|
|
424
|
-
/**
|
|
425
|
-
* Export ledger as JSON.
|
|
426
|
-
*
|
|
427
|
-
* @returns JSON string with current entry status
|
|
428
|
-
*/
|
|
429
|
-
toJSON() {
|
|
430
|
-
return JSON.stringify(
|
|
431
|
-
{
|
|
432
|
-
version: "1.0.0",
|
|
433
|
-
// Export entries with current status from the map
|
|
434
|
-
entries: this.entries.map((entry) => this.entryMap.get(entry.id)),
|
|
435
|
-
stats: this.getStats()
|
|
436
|
-
},
|
|
437
|
-
null,
|
|
438
|
-
2
|
|
439
|
-
);
|
|
440
|
-
}
|
|
441
|
-
/**
|
|
442
|
-
* Import ledger from JSON.
|
|
443
|
-
*
|
|
444
|
-
* Note: The JSON must contain entries in the order they were originally appended.
|
|
445
|
-
* If a superseding entry appears before the entry it supersedes, the superseding
|
|
446
|
-
* logic will not work correctly. The toJSON method preserves this order.
|
|
447
|
-
*
|
|
448
|
-
* @param json The JSON string
|
|
449
|
-
* @returns A new BehaviorLedger instance
|
|
450
|
-
*/
|
|
451
|
-
static fromJSON(json) {
|
|
452
|
-
const data = JSON.parse(json);
|
|
453
|
-
const ledger = new _BehaviorLedger();
|
|
454
|
-
for (const entry of data.entries || []) {
|
|
455
|
-
ledger.append(entry);
|
|
456
|
-
}
|
|
457
|
-
return ledger;
|
|
458
|
-
}
|
|
459
|
-
};
|
|
460
|
-
function createBehaviorLedger() {
|
|
461
|
-
return new BehaviorLedger();
|
|
462
|
-
}
|
|
463
|
-
|
|
464
|
-
export {
|
|
465
|
-
defineFact,
|
|
466
|
-
defineEvent,
|
|
467
|
-
defineRule,
|
|
468
|
-
defineConstraint,
|
|
469
|
-
defineModule,
|
|
470
|
-
filterEvents,
|
|
471
|
-
filterFacts,
|
|
472
|
-
findEvent,
|
|
473
|
-
findFact,
|
|
474
|
-
ContractMissing,
|
|
475
|
-
ContractValidated,
|
|
476
|
-
AcknowledgeContractGap,
|
|
477
|
-
ValidateContracts,
|
|
478
|
-
ContractGapAcknowledged,
|
|
479
|
-
ContractAdded,
|
|
480
|
-
ContractUpdated,
|
|
481
|
-
validateContracts,
|
|
482
|
-
formatValidationReport,
|
|
483
|
-
formatValidationReportJSON,
|
|
484
|
-
formatValidationReportSARIF,
|
|
485
|
-
BehaviorLedger,
|
|
486
|
-
createBehaviorLedger
|
|
487
|
-
};
|