@fairfox/polly 0.88.0 → 0.89.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/cli/polly.js +4 -4
- package/dist/cli/polly.js.map +2 -2
- package/dist/gallery/gallery.css +51 -59
- package/dist/gallery/gallery.js +1155 -1047
- package/dist/src/actions/index.js +5 -78
- package/dist/src/actions/index.js.map +2 -2
- package/dist/src/background/index.js +126 -152
- package/dist/src/background/index.js.map +4 -4
- package/dist/src/background/message-router.js +126 -152
- package/dist/src/background/message-router.js.map +4 -4
- package/dist/src/client/index.js +186 -259
- package/dist/src/client/index.js.map +5 -5
- package/dist/src/elysia/index.js +21 -35
- package/dist/src/elysia/index.js.map +2 -2
- package/dist/src/index.js +218 -246
- package/dist/src/index.js.map +10 -10
- package/dist/src/mesh.js +49 -61
- package/dist/src/mesh.js.map +4 -4
- package/dist/src/peer.js +23 -52
- package/dist/src/peer.js.map +2 -2
- package/dist/src/polly-ui/Button.d.ts +7 -0
- package/dist/src/polly-ui/Collapsible.d.ts +3 -1
- package/dist/src/polly-ui/Layout.d.ts +16 -1
- package/dist/src/polly-ui/index.css +47 -59
- package/dist/src/polly-ui/index.js +112 -124
- package/dist/src/polly-ui/index.js.map +13 -13
- package/dist/src/polly-ui/markdown.js +72 -145
- package/dist/src/polly-ui/markdown.js.map +2 -2
- package/dist/src/polly-ui/styles.css +47 -59
- package/dist/src/polly-ui/theme.css +10 -0
- package/dist/src/shared/adapters/index.js +31 -44
- package/dist/src/shared/adapters/index.js.map +2 -2
- package/dist/src/shared/lib/context-helpers.js +126 -152
- package/dist/src/shared/lib/context-helpers.js.map +4 -4
- package/dist/src/shared/lib/errors.js +1 -74
- package/dist/src/shared/lib/errors.js.map +2 -2
- package/dist/src/shared/lib/guards.js +1 -74
- package/dist/src/shared/lib/guards.js.map +2 -2
- package/dist/src/shared/lib/message-bus.js +126 -152
- package/dist/src/shared/lib/message-bus.js.map +4 -4
- package/dist/src/shared/lib/resource.js +16 -27
- package/dist/src/shared/lib/resource.js.map +5 -5
- package/dist/src/shared/lib/state.js +13 -26
- package/dist/src/shared/lib/state.js.map +2 -2
- package/dist/src/shared/lib/test-helpers.js +1 -74
- package/dist/src/shared/lib/test-helpers.js.map +2 -2
- package/dist/src/shared/state/app-state.js +35 -46
- package/dist/src/shared/state/app-state.js.map +5 -5
- package/dist/src/shared/types/messages.js +1 -74
- package/dist/src/shared/types/messages.js.map +2 -2
- package/dist/tools/bdd/src/cli.js +11 -15
- package/dist/tools/bdd/src/cli.js.map +2 -2
- package/dist/tools/bdd/src/index.js +11 -19
- package/dist/tools/bdd/src/index.js.map +2 -2
- package/dist/tools/gallery/src/cli.js +1 -18
- package/dist/tools/gallery/src/cli.js.map +2 -2
- package/dist/tools/init/src/cli.js +1 -18
- package/dist/tools/init/src/cli.js.map +2 -2
- package/dist/tools/mutate/src/cli.js +8 -25
- package/dist/tools/mutate/src/cli.js.map +2 -2
- package/dist/tools/mutate/src/index.js +8 -26
- package/dist/tools/mutate/src/index.js.map +2 -2
- package/dist/tools/quality/src/cli.js +39 -46
- package/dist/tools/quality/src/cli.js.map +3 -3
- package/dist/tools/quality/src/css/check-layout.d.ts +5 -3
- package/dist/tools/quality/src/index.js +39 -47
- package/dist/tools/quality/src/index.js.map +3 -3
- package/dist/tools/test/src/adapters/index.js +4 -77
- package/dist/tools/test/src/adapters/index.js.map +2 -2
- package/dist/tools/test/src/browser/index.js +1 -74
- package/dist/tools/test/src/browser/index.js.map +2 -2
- package/dist/tools/test/src/browser/run.js +5 -22
- package/dist/tools/test/src/browser/run.js.map +2 -2
- package/dist/tools/test/src/contrast/index.js +1 -74
- package/dist/tools/test/src/contrast/index.js.map +2 -2
- package/dist/tools/test/src/coverage-policy/cli.js +13 -25
- package/dist/tools/test/src/coverage-policy/cli.js.map +2 -2
- package/dist/tools/test/src/coverage-policy/index.js +11 -23
- package/dist/tools/test/src/coverage-policy/index.js.map +2 -2
- package/dist/tools/test/src/e2e-mesh/index.js +18 -43
- package/dist/tools/test/src/e2e-mesh/index.js.map +2 -2
- package/dist/tools/test/src/e2e-relay/index.js +615 -623
- package/dist/tools/test/src/e2e-relay/index.js.map +2 -2
- package/dist/tools/test/src/index.js +30 -103
- package/dist/tools/test/src/index.js.map +5 -5
- package/dist/tools/test/src/test-utils.js +1 -74
- package/dist/tools/test/src/test-utils.js.map +2 -2
- package/dist/tools/test/src/tiers/cli.js +1 -18
- package/dist/tools/test/src/tiers/cli.js.map +2 -2
- package/dist/tools/test/src/tiers/worker.js +11 -15
- package/dist/tools/test/src/tiers/worker.js.map +2 -2
- package/dist/tools/test/src/visual/index.js +1112 -1134
- package/dist/tools/test/src/visual/index.js.map +3 -3
- package/dist/tools/verify/src/cli.js +103 -169
- package/dist/tools/verify/src/cli.js.map +2 -2
- package/dist/tools/verify/src/config.js +1 -74
- package/dist/tools/verify/src/config.js.map +2 -2
- package/dist/tools/verify/src/stryker/index.js +1 -19
- package/dist/tools/verify/src/stryker/index.js.map +2 -2
- package/dist/tools/visualize/src/cli.js +69 -85
- package/dist/tools/visualize/src/cli.js.map +2 -2
- package/package.json +1 -1
|
@@ -1,20 +1,16 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
import { createRequire } from "node:module";
|
|
3
|
-
var
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
configurable: true,
|
|
14
|
-
set: __exportSetter.bind(all, name)
|
|
15
|
-
});
|
|
3
|
+
var __esm = (fn, res, err) => () => {
|
|
4
|
+
if (fn)
|
|
5
|
+
try {
|
|
6
|
+
res = fn(fn = 0);
|
|
7
|
+
} catch (e) {
|
|
8
|
+
err = [e];
|
|
9
|
+
}
|
|
10
|
+
if (err)
|
|
11
|
+
throw err[0];
|
|
12
|
+
return res;
|
|
16
13
|
};
|
|
17
|
-
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
18
14
|
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
19
15
|
|
|
20
16
|
// tools/verify/src/analysis/expression-validator.ts
|
|
@@ -250,11 +246,6 @@ var init_expression_validator = __esm(() => {
|
|
|
250
246
|
});
|
|
251
247
|
|
|
252
248
|
// tools/verify/src/analysis/model-coverage.ts
|
|
253
|
-
var exports_model_coverage = {};
|
|
254
|
-
__export(exports_model_coverage, {
|
|
255
|
-
computeModelCoverage: () => computeModelCoverage,
|
|
256
|
-
strictCoverageReasons: () => strictCoverageReasons
|
|
257
|
-
});
|
|
258
249
|
function norm(field) {
|
|
259
250
|
return field.replace(/_/g, ".");
|
|
260
251
|
}
|
|
@@ -344,10 +335,6 @@ function strictCoverageReasons(report, meshFindingCount) {
|
|
|
344
335
|
}
|
|
345
336
|
|
|
346
337
|
// tools/verify/src/analysis/coupled-fields.ts
|
|
347
|
-
var exports_coupled_fields = {};
|
|
348
|
-
__export(exports_coupled_fields, {
|
|
349
|
-
checkCoupledFields: () => checkCoupledFields
|
|
350
|
-
});
|
|
351
338
|
function norm2(field) {
|
|
352
339
|
return field.replace(/_/g, ".");
|
|
353
340
|
}
|
|
@@ -388,10 +375,6 @@ function subsetViolation(group, groupSet, handler) {
|
|
|
388
375
|
}
|
|
389
376
|
|
|
390
377
|
// tools/verify/src/analysis/non-interference.ts
|
|
391
|
-
var exports_non_interference = {};
|
|
392
|
-
__export(exports_non_interference, {
|
|
393
|
-
checkNonInterference: () => checkNonInterference
|
|
394
|
-
});
|
|
395
378
|
function checkNonInterference(subsystems, handlers) {
|
|
396
379
|
const violations = [];
|
|
397
380
|
const fieldOwner = new Map;
|
|
@@ -430,10 +413,6 @@ function checkNonInterference(subsystems, handlers) {
|
|
|
430
413
|
}
|
|
431
414
|
|
|
432
415
|
// tools/verify/src/analysis/precondition-locality.ts
|
|
433
|
-
var exports_precondition_locality = {};
|
|
434
|
-
__export(exports_precondition_locality, {
|
|
435
|
-
checkPreconditionLocality: () => checkPreconditionLocality
|
|
436
|
-
});
|
|
437
416
|
function findOwner(fieldRef, fieldOwner) {
|
|
438
417
|
const candidates = [fieldRef, fieldRef.replace(/\./g, "_"), fieldRef.replace(/_/g, ".")];
|
|
439
418
|
for (const c of candidates) {
|
|
@@ -692,13 +671,6 @@ class TemporalTLAGenerator {
|
|
|
692
671
|
var init_temporal = () => {};
|
|
693
672
|
|
|
694
673
|
// tools/verify/src/codegen/tla.ts
|
|
695
|
-
var exports_tla = {};
|
|
696
|
-
__export(exports_tla, {
|
|
697
|
-
TLAGenerator: () => TLAGenerator,
|
|
698
|
-
TLAValidationError: () => TLAValidationError,
|
|
699
|
-
generateSubsystemTLA: () => generateSubsystemTLA,
|
|
700
|
-
generateTLA: () => generateTLA
|
|
701
|
-
});
|
|
702
674
|
import * as fs2 from "node:fs";
|
|
703
675
|
import * as os from "node:os";
|
|
704
676
|
import * as path2 from "node:path";
|
|
@@ -2083,14 +2055,14 @@ var init_tla = __esm(() => {
|
|
|
2083
2055
|
const peerPrefix = isPrimed ? `contextStates'[${binder}]` : `contextStates[${binder}]`;
|
|
2084
2056
|
let body = scoped.innerBody;
|
|
2085
2057
|
const binderRe1 = new RegExp(`\\b${binder}\\.([a-zA-Z_][a-zA-Z0-9_]*)\\.value\\.([a-zA-Z_][a-zA-Z0-9_.]*)`, "g");
|
|
2086
|
-
body = body.replace(binderRe1, (_m, sig,
|
|
2058
|
+
body = body.replace(binderRe1, (_m, sig, path) => {
|
|
2087
2059
|
const meshDoc = this.meshSignalDocs.get(sig);
|
|
2088
2060
|
if (meshDoc !== undefined) {
|
|
2089
2061
|
const meshPeerPrefix = isPrimed ? `meshState'[${binder}]["${meshDoc}"]` : `meshState[${binder}]["${meshDoc}"]`;
|
|
2090
|
-
const field = this.sanitizeFieldName(String(
|
|
2062
|
+
const field = this.sanitizeFieldName(String(path).replace(/\./g, "_"));
|
|
2091
2063
|
return `${meshPeerPrefix}.${field}`;
|
|
2092
2064
|
}
|
|
2093
|
-
const flat = this.sanitizeFieldName(`${sig}_${String(
|
|
2065
|
+
const flat = this.sanitizeFieldName(`${sig}_${String(path).replace(/\./g, "_")}`);
|
|
2094
2066
|
return `${peerPrefix}.${flat}`;
|
|
2095
2067
|
});
|
|
2096
2068
|
const binderRe2 = new RegExp(`\\b${binder}\\.([a-zA-Z_][a-zA-Z0-9_]*)\\.value\\b(?!\\.)`, "g");
|
|
@@ -2120,14 +2092,14 @@ var init_tla = __esm(() => {
|
|
|
2120
2092
|
return expr;
|
|
2121
2093
|
}
|
|
2122
2094
|
tla = tla.replace(/'([^']+)'/g, '"$1"');
|
|
2123
|
-
tla = tla.replace(/([a-zA-Z_][a-zA-Z0-9_]*)\.value\.([a-zA-Z_][a-zA-Z0-9_.]*)/g, (_match, stateName,
|
|
2095
|
+
tla = tla.replace(/([a-zA-Z_][a-zA-Z0-9_]*)\.value\.([a-zA-Z_][a-zA-Z0-9_.]*)/g, (_match, stateName, path) => {
|
|
2124
2096
|
const meshDoc = this.meshSignalDocs.get(stateName);
|
|
2125
2097
|
if (meshDoc !== undefined) {
|
|
2126
2098
|
const meshPrefix = isPrimed ? `meshState'[ctx]["${meshDoc}"]` : `meshState[ctx]["${meshDoc}"]`;
|
|
2127
|
-
const field = this.sanitizeFieldName(String(
|
|
2099
|
+
const field = this.sanitizeFieldName(String(path).replace(/\./g, "_"));
|
|
2128
2100
|
return `${meshPrefix}.${field}`;
|
|
2129
2101
|
}
|
|
2130
|
-
const fullPath = `${stateName}_${
|
|
2102
|
+
const fullPath = `${stateName}_${path.replace(/\./g, "_")}`;
|
|
2131
2103
|
return `${statePrefix}.${this.sanitizeFieldName(fullPath)}`;
|
|
2132
2104
|
});
|
|
2133
2105
|
tla = tla.replace(/([a-zA-Z_][a-zA-Z0-9_]*)\.value\b(?!\.)/g, (_match, stateName) => {
|
|
@@ -2137,11 +2109,11 @@ var init_tla = __esm(() => {
|
|
|
2137
2109
|
}
|
|
2138
2110
|
return `${statePrefix}.${stateName}`;
|
|
2139
2111
|
});
|
|
2140
|
-
tla = tla.replace(/state\.([a-zA-Z_][a-zA-Z0-9_.]*)/g, (_match,
|
|
2141
|
-
return `${statePrefix}.${this.sanitizeFieldName(
|
|
2112
|
+
tla = tla.replace(/state\.([a-zA-Z_][a-zA-Z0-9_.]*)/g, (_match, path) => {
|
|
2113
|
+
return `${statePrefix}.${this.sanitizeFieldName(path)}`;
|
|
2142
2114
|
});
|
|
2143
|
-
tla = tla.replace(/payload\.([a-zA-Z_][a-zA-Z0-9_.]*)/g, (_match,
|
|
2144
|
-
return `payload.${this.sanitizeFieldName(
|
|
2115
|
+
tla = tla.replace(/payload\.([a-zA-Z_][a-zA-Z0-9_.]*)/g, (_match, path) => {
|
|
2116
|
+
return `payload.${this.sanitizeFieldName(path)}`;
|
|
2145
2117
|
});
|
|
2146
2118
|
tla = tla.replace(/===/g, "=");
|
|
2147
2119
|
tla = tla.replace(/!==/g, "#");
|
|
@@ -2262,8 +2234,8 @@ var init_tla = __esm(() => {
|
|
|
2262
2234
|
});
|
|
2263
2235
|
result = result.replace(/(\w+(?:\.\w+)*)\[(\d+)\]|\]\[(\d+)\]/g, (_match, identPart, index1, index2) => {
|
|
2264
2236
|
if (identPart) {
|
|
2265
|
-
const
|
|
2266
|
-
return `${identPart}[${
|
|
2237
|
+
const newIndex = Number.parseInt(index1, 10) + 1;
|
|
2238
|
+
return `${identPart}[${newIndex}]`;
|
|
2267
2239
|
}
|
|
2268
2240
|
const newIndex = Number.parseInt(index2, 10) + 1;
|
|
2269
2241
|
return `][${newIndex}]`;
|
|
@@ -2425,7 +2397,7 @@ var init_tla = __esm(() => {
|
|
|
2425
2397
|
while (result.includes("?.") && iteration < maxIterations && result !== previousResult) {
|
|
2426
2398
|
previousResult = result;
|
|
2427
2399
|
result = result.replace(/(\w+(?:\.\w+)*)\?\.(\w+)(?!\?\.)/g, (_match, obj, prop) => `IF ${obj} # NULL THEN ${obj}.${prop} ELSE NULL`);
|
|
2428
|
-
result = result.replace(/\(([^)]+)\)\?\.(\w+)/g, (_match,
|
|
2400
|
+
result = result.replace(/\(([^)]+)\)\?\.(\w+)/g, (_match, expr, prop) => `IF (${expr}) # NULL THEN (${expr}).${prop} ELSE NULL`);
|
|
2429
2401
|
result = result.replace(/(\w+(?:\.\w+)*)\?\.\[(\d+)\]/g, (_match, obj, index) => {
|
|
2430
2402
|
const tlaIndex = Number.parseInt(index, 10) + 1;
|
|
2431
2403
|
return `IF ${obj} # NULL THEN ${obj}[${tlaIndex}] ELSE NULL`;
|
|
@@ -3164,9 +3136,9 @@ function parseFeatureText(text, file) {
|
|
|
3164
3136
|
file
|
|
3165
3137
|
};
|
|
3166
3138
|
}
|
|
3167
|
-
async function parseFeatureFile(
|
|
3168
|
-
const text = await Bun.file(
|
|
3169
|
-
return parseFeatureText(text,
|
|
3139
|
+
async function parseFeatureFile(path) {
|
|
3140
|
+
const text = await Bun.file(path).text();
|
|
3141
|
+
return parseFeatureText(text, path);
|
|
3170
3142
|
}
|
|
3171
3143
|
var init_parse = () => {};
|
|
3172
3144
|
|
|
@@ -3212,10 +3184,6 @@ function registeredBindings() {
|
|
|
3212
3184
|
}
|
|
3213
3185
|
|
|
3214
3186
|
// tools/bdd/src/witness.ts
|
|
3215
|
-
var exports_witness = {};
|
|
3216
|
-
__export(exports_witness, {
|
|
3217
|
-
extractWitnesses: () => extractWitnesses
|
|
3218
|
-
});
|
|
3219
3187
|
async function loadStepModules(stepFiles) {
|
|
3220
3188
|
resetRegistry();
|
|
3221
3189
|
for (const file of stepFiles) {
|
|
@@ -3284,22 +3252,6 @@ var init_witness = __esm(() => {
|
|
|
3284
3252
|
});
|
|
3285
3253
|
|
|
3286
3254
|
// tools/verify/src/codegen/witness.ts
|
|
3287
|
-
var exports_witness2 = {};
|
|
3288
|
-
__export(exports_witness2, {
|
|
3289
|
-
WITNESS_INVARIANT: () => WITNESS_INVARIANT,
|
|
3290
|
-
WitnessTranslationError: () => WitnessTranslationError,
|
|
3291
|
-
bareFieldRenderer: () => bareFieldRenderer,
|
|
3292
|
-
bddPredicateToTLA: () => bddPredicateToTLA,
|
|
3293
|
-
buildWitnessCfg: () => buildWitnessCfg,
|
|
3294
|
-
buildWitnessInvariant: () => buildWitnessInvariant,
|
|
3295
|
-
buildWitnessInvariantBare: () => buildWitnessInvariantBare,
|
|
3296
|
-
buildWitnessModule: () => buildWitnessModule,
|
|
3297
|
-
parseModuleName: () => parseModuleName,
|
|
3298
|
-
routeWitness: () => routeWitness,
|
|
3299
|
-
witnessPolarity: () => witnessPolarity,
|
|
3300
|
-
witnessSpecLocation: () => witnessSpecLocation,
|
|
3301
|
-
witnessVerdict: () => witnessVerdict
|
|
3302
|
-
});
|
|
3303
3255
|
import * as path3 from "node:path";
|
|
3304
3256
|
function witnessPolarity(tags) {
|
|
3305
3257
|
return tags.includes("forbidden") ? "forbidden" : "positive";
|
|
@@ -3318,8 +3270,8 @@ function witnessVerdict(polarity, reachable) {
|
|
|
3318
3270
|
message: "the model proves this outcome impossible (the scenario lies)"
|
|
3319
3271
|
};
|
|
3320
3272
|
}
|
|
3321
|
-
function flattenField(
|
|
3322
|
-
return
|
|
3273
|
+
function flattenField(path) {
|
|
3274
|
+
return path.split(".").join("_");
|
|
3323
3275
|
}
|
|
3324
3276
|
function bareFieldRenderer(fields = {}) {
|
|
3325
3277
|
return (fieldPath) => fields[fieldPath] ?? flattenField(fieldPath);
|
|
@@ -3521,13 +3473,6 @@ function sanitizeKind(kind) {
|
|
|
3521
3473
|
var CONTAINER_NAME_PREFIX = "polly-tla-", counter = 0;
|
|
3522
3474
|
|
|
3523
3475
|
// tools/verify/src/runner/docker.ts
|
|
3524
|
-
var exports_docker = {};
|
|
3525
|
-
__export(exports_docker, {
|
|
3526
|
-
DockerRunner: () => DockerRunner,
|
|
3527
|
-
removeContainer: () => removeContainer,
|
|
3528
|
-
sweepOrphanedContainers: () => sweepOrphanedContainers,
|
|
3529
|
-
sweepOrphanedContainersOnce: () => sweepOrphanedContainersOnce
|
|
3530
|
-
});
|
|
3531
3476
|
import { spawn, spawnSync } from "node:child_process";
|
|
3532
3477
|
import * as fs3 from "node:fs";
|
|
3533
3478
|
import * as path4 from "node:path";
|
|
@@ -3709,7 +3654,7 @@ class DockerRunner {
|
|
|
3709
3654
|
return "Unknown error occurred during model checking";
|
|
3710
3655
|
}
|
|
3711
3656
|
runCommand(command, args, options) {
|
|
3712
|
-
return new Promise((
|
|
3657
|
+
return new Promise((resolve, reject) => {
|
|
3713
3658
|
const proc = spawn(command, args);
|
|
3714
3659
|
let stdout = "";
|
|
3715
3660
|
let stderr = "";
|
|
@@ -3730,7 +3675,7 @@ class DockerRunner {
|
|
|
3730
3675
|
proc.on("close", (exitCode) => {
|
|
3731
3676
|
if (timeout)
|
|
3732
3677
|
clearTimeout(timeout);
|
|
3733
|
-
|
|
3678
|
+
resolve({
|
|
3734
3679
|
exitCode: exitCode || 0,
|
|
3735
3680
|
stdout,
|
|
3736
3681
|
stderr
|
|
@@ -3744,7 +3689,7 @@ class DockerRunner {
|
|
|
3744
3689
|
});
|
|
3745
3690
|
}
|
|
3746
3691
|
runCommandStreaming(command, args, onOutput, timeout) {
|
|
3747
|
-
return new Promise((
|
|
3692
|
+
return new Promise((resolve, reject) => {
|
|
3748
3693
|
const proc = spawn(command, args);
|
|
3749
3694
|
const timeoutHandle = timeout && timeout > 0 ? setTimeout(() => {
|
|
3750
3695
|
proc.kill();
|
|
@@ -3776,7 +3721,7 @@ class DockerRunner {
|
|
|
3776
3721
|
if (timeoutHandle)
|
|
3777
3722
|
clearTimeout(timeoutHandle);
|
|
3778
3723
|
if (exitCode === 0) {
|
|
3779
|
-
|
|
3724
|
+
resolve();
|
|
3780
3725
|
} else {
|
|
3781
3726
|
reject(new Error(`Command failed with exit code ${exitCode}`));
|
|
3782
3727
|
}
|
|
@@ -4663,13 +4608,13 @@ class ConfigValidator {
|
|
|
4663
4608
|
this.issues.push(...validateCapabilities(config.capabilities, config.state));
|
|
4664
4609
|
this.issues.push(...validateCoupledFields(config.coupledFields, config.state));
|
|
4665
4610
|
}
|
|
4666
|
-
findNullPlaceholders(obj,
|
|
4611
|
+
findNullPlaceholders(obj, path) {
|
|
4667
4612
|
if (obj === null || obj === undefined) {
|
|
4668
4613
|
this.issues.push({
|
|
4669
4614
|
type: "null_placeholder",
|
|
4670
4615
|
severity: "error",
|
|
4671
|
-
field:
|
|
4672
|
-
message: `Configuration incomplete: ${
|
|
4616
|
+
field: path,
|
|
4617
|
+
message: `Configuration incomplete: ${path}`,
|
|
4673
4618
|
suggestion: "Replace null with a concrete value"
|
|
4674
4619
|
});
|
|
4675
4620
|
return;
|
|
@@ -4678,7 +4623,7 @@ class ConfigValidator {
|
|
|
4678
4623
|
return;
|
|
4679
4624
|
}
|
|
4680
4625
|
for (const [key, value] of Object.entries(obj)) {
|
|
4681
|
-
const fullPath = `${
|
|
4626
|
+
const fullPath = `${path}.${key}`;
|
|
4682
4627
|
if (value === null) {
|
|
4683
4628
|
this.issues.push({
|
|
4684
4629
|
type: "null_placeholder",
|
|
@@ -5161,9 +5106,9 @@ class RelationshipExtractor {
|
|
|
5161
5106
|
return;
|
|
5162
5107
|
}
|
|
5163
5108
|
if (Node.isPropertyAccessExpression(expr)) {
|
|
5164
|
-
const
|
|
5165
|
-
if (
|
|
5166
|
-
relationships.push(
|
|
5109
|
+
const rel = this.extractFromPropertyAccess(expr, handlerName);
|
|
5110
|
+
if (rel) {
|
|
5111
|
+
relationships.push(rel);
|
|
5167
5112
|
return;
|
|
5168
5113
|
}
|
|
5169
5114
|
}
|
|
@@ -6491,9 +6436,9 @@ class HandlerExtractor {
|
|
|
6491
6436
|
return;
|
|
6492
6437
|
}
|
|
6493
6438
|
if (Node2.isIdentifier(initializer)) {
|
|
6494
|
-
const
|
|
6495
|
-
if (this.currentFunctionParams.includes(
|
|
6496
|
-
assignments.push({ field, value: `param:${
|
|
6439
|
+
const paramName = initializer.getText();
|
|
6440
|
+
if (this.currentFunctionParams.includes(paramName)) {
|
|
6441
|
+
assignments.push({ field, value: `param:${paramName}` });
|
|
6497
6442
|
return;
|
|
6498
6443
|
}
|
|
6499
6444
|
}
|
|
@@ -7331,56 +7276,56 @@ class HandlerExtractor {
|
|
|
7331
7276
|
if (filePath.startsWith(pathPrefix))
|
|
7332
7277
|
return context;
|
|
7333
7278
|
}
|
|
7334
|
-
const
|
|
7335
|
-
return this.inferElectronContext(
|
|
7279
|
+
const path = filePath.toLowerCase();
|
|
7280
|
+
return this.inferElectronContext(path) || this.inferWorkerContext(path) || this.inferServerAppContext(path) || this.inferChromeExtensionContext(path) || "unknown";
|
|
7336
7281
|
}
|
|
7337
|
-
inferElectronContext(
|
|
7338
|
-
if (
|
|
7282
|
+
inferElectronContext(path) {
|
|
7283
|
+
if (path.includes("main.ts") || path.includes("main.js") || path.includes("/main/") || path.includes("\\main\\")) {
|
|
7339
7284
|
return "main";
|
|
7340
7285
|
}
|
|
7341
|
-
if (
|
|
7286
|
+
if (path.includes("/renderer/") || path.includes("\\renderer\\") || path.includes("renderer.ts") || path.includes("renderer.js")) {
|
|
7342
7287
|
return "renderer";
|
|
7343
7288
|
}
|
|
7344
|
-
if (
|
|
7289
|
+
if (path.includes("preload.ts") || path.includes("preload.js")) {
|
|
7345
7290
|
return "preload";
|
|
7346
7291
|
}
|
|
7347
7292
|
return null;
|
|
7348
7293
|
}
|
|
7349
|
-
inferWorkerContext(
|
|
7350
|
-
if (
|
|
7294
|
+
inferWorkerContext(path) {
|
|
7295
|
+
if (path.includes("service-worker") || path.includes("sw.ts") || path.includes("sw.js")) {
|
|
7351
7296
|
return "worker";
|
|
7352
7297
|
}
|
|
7353
|
-
if (
|
|
7298
|
+
if (path.includes("/worker/") || path.includes("\\worker\\")) {
|
|
7354
7299
|
return "worker";
|
|
7355
7300
|
}
|
|
7356
7301
|
return null;
|
|
7357
7302
|
}
|
|
7358
|
-
inferServerAppContext(
|
|
7359
|
-
if (
|
|
7303
|
+
inferServerAppContext(path) {
|
|
7304
|
+
if (path.includes("/server/") || path.includes("\\server\\") || path.includes("/server.") || path.includes("server.ts") || path.includes("server.js")) {
|
|
7360
7305
|
return "server";
|
|
7361
7306
|
}
|
|
7362
|
-
if (
|
|
7307
|
+
if (path.includes("/client/") || path.includes("\\client\\") || path.includes("/client.")) {
|
|
7363
7308
|
return "client";
|
|
7364
7309
|
}
|
|
7365
7310
|
return null;
|
|
7366
7311
|
}
|
|
7367
|
-
inferChromeExtensionContext(
|
|
7368
|
-
if (
|
|
7312
|
+
inferChromeExtensionContext(path) {
|
|
7313
|
+
if (path.includes("/background/") || path.includes("\\background\\")) {
|
|
7369
7314
|
return "background";
|
|
7370
7315
|
}
|
|
7371
|
-
if (
|
|
7316
|
+
if (path.includes("/content/") || path.includes("\\content\\")) {
|
|
7372
7317
|
return "content";
|
|
7373
7318
|
}
|
|
7374
|
-
if (
|
|
7319
|
+
if (path.includes("/popup/") || path.includes("\\popup\\")) {
|
|
7375
7320
|
return "popup";
|
|
7376
7321
|
}
|
|
7377
|
-
if (
|
|
7322
|
+
if (path.includes("/devtools/") || path.includes("\\devtools\\")) {
|
|
7378
7323
|
return "devtools";
|
|
7379
7324
|
}
|
|
7380
|
-
if (
|
|
7325
|
+
if (path.includes("/options/") || path.includes("\\options\\")) {
|
|
7381
7326
|
return "options";
|
|
7382
7327
|
}
|
|
7383
|
-
if (
|
|
7328
|
+
if (path.includes("/offscreen/") || path.includes("\\offscreen\\")) {
|
|
7384
7329
|
return "offscreen";
|
|
7385
7330
|
}
|
|
7386
7331
|
return null;
|
|
@@ -7760,9 +7705,9 @@ class HandlerExtractor {
|
|
|
7760
7705
|
const left = node.getLeft();
|
|
7761
7706
|
if (!Node2.isPropertyAccessExpression(left))
|
|
7762
7707
|
return;
|
|
7763
|
-
const
|
|
7708
|
+
const path = this.getPropertyPath(left);
|
|
7764
7709
|
for (const varName of stateVarNames) {
|
|
7765
|
-
if (
|
|
7710
|
+
if (path === `${varName}.value`) {
|
|
7766
7711
|
const right = node.getRight();
|
|
7767
7712
|
if (Node2.isObjectLiteralExpression(right)) {
|
|
7768
7713
|
this.extractObjectLiteralAssignments(right, mutations, varName);
|
|
@@ -7770,8 +7715,8 @@ class HandlerExtractor {
|
|
|
7770
7715
|
break;
|
|
7771
7716
|
}
|
|
7772
7717
|
const fieldPrefix = `${varName}.value.`;
|
|
7773
|
-
if (
|
|
7774
|
-
const fieldName =
|
|
7718
|
+
if (path.startsWith(fieldPrefix)) {
|
|
7719
|
+
const fieldName = path.substring(fieldPrefix.length);
|
|
7775
7720
|
const value = this.extractValue(node.getRight());
|
|
7776
7721
|
mutations.push({ field: `${varName}_${fieldName}`, value: value ?? "@" });
|
|
7777
7722
|
break;
|
|
@@ -7856,13 +7801,13 @@ class HandlerExtractor {
|
|
|
7856
7801
|
return [{ field: match.signal, ...base }];
|
|
7857
7802
|
return fields.map((f) => ({ field: `${match.signal}_${f}`, ...base }));
|
|
7858
7803
|
}
|
|
7859
|
-
matchVerifiedStateWrite(
|
|
7804
|
+
matchVerifiedStateWrite(path, stateVarNames) {
|
|
7860
7805
|
for (const varName of stateVarNames) {
|
|
7861
|
-
if (
|
|
7806
|
+
if (path === `${varName}.value`)
|
|
7862
7807
|
return { signal: varName };
|
|
7863
7808
|
const prefix = `${varName}.value.`;
|
|
7864
|
-
if (
|
|
7865
|
-
return { signal: varName, field:
|
|
7809
|
+
if (path.startsWith(prefix))
|
|
7810
|
+
return { signal: varName, field: path.substring(prefix.length) };
|
|
7866
7811
|
}
|
|
7867
7812
|
return null;
|
|
7868
7813
|
}
|
|
@@ -8377,20 +8322,20 @@ class TypeExtractor {
|
|
|
8377
8322
|
const fields = [];
|
|
8378
8323
|
if (stateType.kind === "object" && stateType.properties) {
|
|
8379
8324
|
for (const [key, propType] of Object.entries(stateType.properties)) {
|
|
8380
|
-
const
|
|
8325
|
+
const path = prefix ? `${prefix}.${key}` : key;
|
|
8381
8326
|
if (propType.kind === "object") {
|
|
8382
|
-
fields.push(...this.analyzeFields(propType,
|
|
8327
|
+
fields.push(...this.analyzeFields(propType, path));
|
|
8383
8328
|
} else {
|
|
8384
|
-
const analysis = this.analyzeField(
|
|
8329
|
+
const analysis = this.analyzeField(path, propType);
|
|
8385
8330
|
fields.push(analysis);
|
|
8386
8331
|
}
|
|
8387
8332
|
}
|
|
8388
8333
|
}
|
|
8389
8334
|
return fields;
|
|
8390
8335
|
}
|
|
8391
|
-
analyzeField(
|
|
8336
|
+
analyzeField(path, type) {
|
|
8392
8337
|
const analysis = {
|
|
8393
|
-
path
|
|
8338
|
+
path,
|
|
8394
8339
|
type,
|
|
8395
8340
|
confidence: "low",
|
|
8396
8341
|
evidence: [],
|
|
@@ -8825,13 +8770,13 @@ function displayModelCoverage(report) {
|
|
|
8825
8770
|
}
|
|
8826
8771
|
}
|
|
8827
8772
|
async function runModelCoverage(typedConfig, typedAnalysis, meshFindingCount) {
|
|
8828
|
-
|
|
8773
|
+
await Promise.resolve();
|
|
8829
8774
|
const stateFields = Object.keys(typedConfig.state ?? {});
|
|
8830
|
-
const coverage =
|
|
8775
|
+
const coverage = computeModelCoverage(stateFields, typedAnalysis.handlers, typedAnalysis.offSurfaceMutations ?? []);
|
|
8831
8776
|
displayModelCoverage(coverage);
|
|
8832
8777
|
if (!isStrictMode())
|
|
8833
8778
|
return;
|
|
8834
|
-
const reasons =
|
|
8779
|
+
const reasons = strictCoverageReasons(coverage, meshFindingCount);
|
|
8835
8780
|
if (reasons.length === 0) {
|
|
8836
8781
|
console.log(color("✓ Strict mode: model coverage complete", COLORS.green));
|
|
8837
8782
|
console.log();
|
|
@@ -8925,8 +8870,8 @@ async function runCoupledFieldsLint(config, analysis) {
|
|
|
8925
8870
|
const groups = config.coupledFields ?? [];
|
|
8926
8871
|
if (groups.length === 0)
|
|
8927
8872
|
return;
|
|
8928
|
-
|
|
8929
|
-
const result =
|
|
8873
|
+
await Promise.resolve();
|
|
8874
|
+
const result = checkCoupledFields(groups, analysis.handlers);
|
|
8930
8875
|
if (result.valid) {
|
|
8931
8876
|
console.log(color("✓ Coupled fields: verified (no partial-subset writes)", COLORS.green));
|
|
8932
8877
|
console.log();
|
|
@@ -9017,8 +8962,8 @@ async function runSubsystemVerification(config, analysis) {
|
|
|
9017
8962
|
const subsystemNames = Object.keys(subsystems);
|
|
9018
8963
|
console.log(color(`Subsystem-scoped verification (${subsystemNames.length} subsystems)
|
|
9019
8964
|
`, COLORS.blue));
|
|
9020
|
-
|
|
9021
|
-
const interference =
|
|
8965
|
+
await Promise.resolve();
|
|
8966
|
+
const interference = checkNonInterference(subsystems, analysis.handlers);
|
|
9022
8967
|
if (interference.valid) {
|
|
9023
8968
|
console.log(color("✓ Non-interference: verified (no cross-subsystem state writes)", COLORS.green));
|
|
9024
8969
|
console.log();
|
|
@@ -9032,8 +8977,8 @@ async function runSubsystemVerification(config, analysis) {
|
|
|
9032
8977
|
console.log(color(" Compositional verification may not be sound. Consider restructuring subsystem boundaries.", COLORS.yellow));
|
|
9033
8978
|
console.log();
|
|
9034
8979
|
}
|
|
9035
|
-
|
|
9036
|
-
const locality =
|
|
8980
|
+
await Promise.resolve().then(() => init_precondition_locality());
|
|
8981
|
+
const locality = checkPreconditionLocality(subsystems, analysis.handlers);
|
|
9037
8982
|
if (locality.valid) {
|
|
9038
8983
|
console.log(color("✓ Precondition locality: verified (no cross-subsystem requires() reads)", COLORS.green));
|
|
9039
8984
|
console.log();
|
|
@@ -9066,7 +9011,7 @@ async function runSubsystemVerification(config, analysis) {
|
|
|
9066
9011
|
const timeoutSeconds = getTimeout(config);
|
|
9067
9012
|
const workers = getWorkers(config);
|
|
9068
9013
|
const maxDepth = getMaxDepth(config);
|
|
9069
|
-
|
|
9014
|
+
await Promise.resolve().then(() => init_tla());
|
|
9070
9015
|
const results = [];
|
|
9071
9016
|
const customTLAPaths = getCustomTLAPaths(config);
|
|
9072
9017
|
for (const name of subsystemNames) {
|
|
@@ -9077,7 +9022,7 @@ async function runSubsystemVerification(config, analysis) {
|
|
|
9077
9022
|
continue;
|
|
9078
9023
|
}
|
|
9079
9024
|
console.log(color(`⚙️ Verifying subsystem: ${name}...`, COLORS.blue));
|
|
9080
|
-
const { spec, cfg } = await
|
|
9025
|
+
const { spec, cfg } = await generateSubsystemTLA(name, sub, config, analysis);
|
|
9081
9026
|
const ensuresCount = (spec.match(/^EnsuresAfter_\w+ ==/gm) ?? []).length;
|
|
9082
9027
|
const specDir = path5.join(process.cwd(), "specs", "tla", "generated", name);
|
|
9083
9028
|
if (!fs4.existsSync(specDir)) {
|
|
@@ -9143,22 +9088,11 @@ async function runWitnessVerification(config) {
|
|
|
9143
9088
|
`, COLORS.gray));
|
|
9144
9089
|
return;
|
|
9145
9090
|
}
|
|
9146
|
-
|
|
9147
|
-
|
|
9148
|
-
bareFieldRenderer: bareFieldRenderer2,
|
|
9149
|
-
bddPredicateToTLA: bddPredicateToTLA2,
|
|
9150
|
-
buildWitnessCfg: buildWitnessCfg2,
|
|
9151
|
-
buildWitnessModule: buildWitnessModule2,
|
|
9152
|
-
parseModuleName: parseModuleName2,
|
|
9153
|
-
routeWitness: routeWitness2,
|
|
9154
|
-
witnessPolarity: witnessPolarity2,
|
|
9155
|
-
witnessSpecLocation: witnessSpecLocation2,
|
|
9156
|
-
witnessVerdict: witnessVerdict2,
|
|
9157
|
-
WITNESS_INVARIANT: WITNESS_INVARIANT2
|
|
9158
|
-
} = await Promise.resolve().then(() => (init_witness2(), exports_witness2));
|
|
9091
|
+
await Promise.resolve().then(() => init_witness());
|
|
9092
|
+
await Promise.resolve().then(() => init_witness2());
|
|
9159
9093
|
const subsystems = config.subsystems;
|
|
9160
9094
|
const customTLAPaths = getCustomTLAPaths(config);
|
|
9161
|
-
const witnesses = await
|
|
9095
|
+
const witnesses = await extractWitnesses(featureFiles, stepFiles);
|
|
9162
9096
|
const docker = await setupDocker();
|
|
9163
9097
|
const timeoutSeconds = getTimeout(config);
|
|
9164
9098
|
const timeout = timeoutSeconds > 0 ? timeoutSeconds * 1000 : DEFAULT_WITNESS_TIMEOUT_MS;
|
|
@@ -9167,7 +9101,7 @@ async function runWitnessVerification(config) {
|
|
|
9167
9101
|
let idx = 0;
|
|
9168
9102
|
for (const w of witnesses) {
|
|
9169
9103
|
const id = `${w.feature} › ${w.scenario}`;
|
|
9170
|
-
const polarity =
|
|
9104
|
+
const polarity = witnessPolarity(w.tags);
|
|
9171
9105
|
if (!w.predicate) {
|
|
9172
9106
|
results.push({
|
|
9173
9107
|
id,
|
|
@@ -9177,7 +9111,7 @@ async function runWitnessVerification(config) {
|
|
|
9177
9111
|
});
|
|
9178
9112
|
continue;
|
|
9179
9113
|
}
|
|
9180
|
-
const subsystem =
|
|
9114
|
+
const subsystem = routeWitness(w.fields, subsystems);
|
|
9181
9115
|
if (!subsystem) {
|
|
9182
9116
|
results.push({
|
|
9183
9117
|
id,
|
|
@@ -9202,7 +9136,7 @@ async function runWitnessVerification(config) {
|
|
|
9202
9136
|
});
|
|
9203
9137
|
continue;
|
|
9204
9138
|
}
|
|
9205
|
-
const module = custom.module ??
|
|
9139
|
+
const module = custom.module ?? parseModuleName(fs4.readFileSync(tlaAbs, "utf8"));
|
|
9206
9140
|
if (!module) {
|
|
9207
9141
|
results.push({
|
|
9208
9142
|
id,
|
|
@@ -9213,9 +9147,9 @@ async function runWitnessVerification(config) {
|
|
|
9213
9147
|
});
|
|
9214
9148
|
continue;
|
|
9215
9149
|
}
|
|
9216
|
-
location =
|
|
9150
|
+
location = witnessSpecLocation(cwd, subsystem, custom, module);
|
|
9217
9151
|
} else {
|
|
9218
|
-
location =
|
|
9152
|
+
location = witnessSpecLocation(cwd, subsystem, undefined, "");
|
|
9219
9153
|
if (!fs4.existsSync(location.tlaPath) || !fs4.existsSync(location.cfgPath)) {
|
|
9220
9154
|
results.push({
|
|
9221
9155
|
id,
|
|
@@ -9229,7 +9163,7 @@ async function runWitnessVerification(config) {
|
|
|
9229
9163
|
}
|
|
9230
9164
|
let tlaPredicate;
|
|
9231
9165
|
try {
|
|
9232
|
-
tlaPredicate = location.custom ?
|
|
9166
|
+
tlaPredicate = location.custom ? bddPredicateToTLA(w.predicate, bareFieldRenderer(custom?.fields)) : bddPredicateToTLA(w.predicate);
|
|
9233
9167
|
} catch (err) {
|
|
9234
9168
|
results.push({
|
|
9235
9169
|
id,
|
|
@@ -9242,8 +9176,8 @@ async function runWitnessVerification(config) {
|
|
|
9242
9176
|
}
|
|
9243
9177
|
const moduleName = `Witness_${subsystem}_${idx++}`;
|
|
9244
9178
|
const witnessTla = path5.join(location.dir, `${moduleName}.tla`);
|
|
9245
|
-
fs4.writeFileSync(witnessTla,
|
|
9246
|
-
fs4.writeFileSync(path5.join(location.dir, `${moduleName}.cfg`),
|
|
9179
|
+
fs4.writeFileSync(witnessTla, buildWitnessModule(moduleName, location.module, tlaPredicate, { bare: location.custom }));
|
|
9180
|
+
fs4.writeFileSync(path5.join(location.dir, `${moduleName}.cfg`), buildWitnessCfg(fs4.readFileSync(location.cfgPath, "utf8")));
|
|
9247
9181
|
const polarityTag = polarity === "forbidden" ? color(" [forbidden — must be unreachable]", COLORS.gray) : "";
|
|
9248
9182
|
console.log(color(`⚙️ ${id}`, COLORS.blue) + polarityTag);
|
|
9249
9183
|
console.log(color(` ${subsystem} ⊨ ${w.predicate}`, COLORS.gray));
|
|
@@ -9263,7 +9197,7 @@ async function runWitnessVerification(config) {
|
|
|
9263
9197
|
console.log(color(" ⚠ inconclusive — TLC did not finish (raise the config timeout)", COLORS.yellow));
|
|
9264
9198
|
continue;
|
|
9265
9199
|
}
|
|
9266
|
-
const reachable = !tlc.success && tlc.violation?.name ===
|
|
9200
|
+
const reachable = !tlc.success && tlc.violation?.name === WITNESS_INVARIANT;
|
|
9267
9201
|
if (!tlc.success && !reachable) {
|
|
9268
9202
|
results.push({
|
|
9269
9203
|
id,
|
|
@@ -9277,7 +9211,7 @@ async function runWitnessVerification(config) {
|
|
|
9277
9211
|
fs4.writeFileSync(path5.join(location.dir, `${moduleName}.tlc-output.log`), tlc.output);
|
|
9278
9212
|
continue;
|
|
9279
9213
|
}
|
|
9280
|
-
const verdict =
|
|
9214
|
+
const verdict = witnessVerdict(polarity, reachable);
|
|
9281
9215
|
const note = reachable ? undefined : `${tlc.stats?.distinctStates ?? 0} distinct states explored`;
|
|
9282
9216
|
results.push({
|
|
9283
9217
|
id,
|
|
@@ -9400,9 +9334,9 @@ async function runCodebaseAnalysis() {
|
|
|
9400
9334
|
return analysis;
|
|
9401
9335
|
}
|
|
9402
9336
|
async function generateAndWriteTLASpecs(config, analysis) {
|
|
9403
|
-
|
|
9337
|
+
await Promise.resolve().then(() => init_tla());
|
|
9404
9338
|
console.log(color("\uD83D\uDCDD Generating TLA+ specification...", COLORS.blue));
|
|
9405
|
-
const { spec, cfg } = await
|
|
9339
|
+
const { spec, cfg } = await generateTLA(config, analysis);
|
|
9406
9340
|
const specDir = path5.join(process.cwd(), "specs", "tla", "generated");
|
|
9407
9341
|
if (!fs4.existsSync(specDir)) {
|
|
9408
9342
|
fs4.mkdirSync(specDir, { recursive: true });
|
|
@@ -9469,9 +9403,9 @@ async function runMeshSeedGuard(docker, specDir, config) {
|
|
|
9469
9403
|
return docker.runTLC(path5.join(specDir, "MeshSeed.tla"), { workers: 1 });
|
|
9470
9404
|
}
|
|
9471
9405
|
async function setupDocker() {
|
|
9472
|
-
|
|
9406
|
+
await Promise.resolve().then(() => init_docker());
|
|
9473
9407
|
console.log(color("\uD83D\uDC33 Checking Docker...", COLORS.blue));
|
|
9474
|
-
const docker = new
|
|
9408
|
+
const docker = new DockerRunner;
|
|
9475
9409
|
try {
|
|
9476
9410
|
if (!await docker.isDockerAvailable()) {
|
|
9477
9411
|
console.log();
|
|
@@ -9640,4 +9574,4 @@ main().catch((error) => {
|
|
|
9640
9574
|
process.exit(1);
|
|
9641
9575
|
});
|
|
9642
9576
|
|
|
9643
|
-
//# debugId=
|
|
9577
|
+
//# debugId=92CAFBFCF98F237564756E2164756E21
|