glamsterdam-compat-lab 0.2.2

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 (96) hide show
  1. package/CONTRIBUTING.md +59 -0
  2. package/LICENSE +21 -0
  3. package/README.md +187 -0
  4. package/ROADMAP.md +76 -0
  5. package/SECURITY.md +19 -0
  6. package/data/client-compat/clients.example.json +42 -0
  7. package/data/detectors/thresholds.ci.json +33 -0
  8. package/data/detectors/thresholds.json +33 -0
  9. package/data/detectors/thresholds.research.json +33 -0
  10. package/data/eips/glamsterdam.json +85 -0
  11. package/dist/cli.d.ts +2 -0
  12. package/dist/cli.js +163 -0
  13. package/dist/cli.js.map +1 -0
  14. package/dist/detectors/balDetectors.d.ts +3 -0
  15. package/dist/detectors/balDetectors.js +26 -0
  16. package/dist/detectors/balDetectors.js.map +1 -0
  17. package/dist/detectors/contractSizeDetectors.d.ts +3 -0
  18. package/dist/detectors/contractSizeDetectors.js +37 -0
  19. package/dist/detectors/contractSizeDetectors.js.map +1 -0
  20. package/dist/detectors/epbsDetectors.d.ts +7 -0
  21. package/dist/detectors/epbsDetectors.js +33 -0
  22. package/dist/detectors/epbsDetectors.js.map +1 -0
  23. package/dist/detectors/gasRepricingDetectors.d.ts +4 -0
  24. package/dist/detectors/gasRepricingDetectors.js +135 -0
  25. package/dist/detectors/gasRepricingDetectors.js.map +1 -0
  26. package/dist/detectors/nativeEthTransferLogDetectors.d.ts +8 -0
  27. package/dist/detectors/nativeEthTransferLogDetectors.js +54 -0
  28. package/dist/detectors/nativeEthTransferLogDetectors.js.map +1 -0
  29. package/dist/detectors/stateCreationDetectors.d.ts +4 -0
  30. package/dist/detectors/stateCreationDetectors.js +46 -0
  31. package/dist/detectors/stateCreationDetectors.js.map +1 -0
  32. package/dist/detectors/thresholds.d.ts +34 -0
  33. package/dist/detectors/thresholds.js +45 -0
  34. package/dist/detectors/thresholds.js.map +1 -0
  35. package/dist/detectors/types.d.ts +15 -0
  36. package/dist/detectors/types.js +23 -0
  37. package/dist/detectors/types.js.map +1 -0
  38. package/dist/index.d.ts +16 -0
  39. package/dist/index.js +13 -0
  40. package/dist/index.js.map +1 -0
  41. package/dist/registry/eipRegistry.d.ts +6 -0
  42. package/dist/registry/eipRegistry.js +30 -0
  43. package/dist/registry/eipRegistry.js.map +1 -0
  44. package/dist/registry/schemas.d.ts +76 -0
  45. package/dist/registry/schemas.js +34 -0
  46. package/dist/registry/schemas.js.map +1 -0
  47. package/dist/reports/jsonReporter.d.ts +2 -0
  48. package/dist/reports/jsonReporter.js +5 -0
  49. package/dist/reports/jsonReporter.js.map +1 -0
  50. package/dist/reports/markdownReporter.d.ts +2 -0
  51. package/dist/reports/markdownReporter.js +75 -0
  52. package/dist/reports/markdownReporter.js.map +1 -0
  53. package/dist/reports/reportTypes.d.ts +150 -0
  54. package/dist/reports/reportTypes.js +111 -0
  55. package/dist/reports/reportTypes.js.map +1 -0
  56. package/dist/scanners/bytecodeScanner.d.ts +11 -0
  57. package/dist/scanners/bytecodeScanner.js +107 -0
  58. package/dist/scanners/bytecodeScanner.js.map +1 -0
  59. package/dist/scanners/indexerScanner.d.ts +13 -0
  60. package/dist/scanners/indexerScanner.js +129 -0
  61. package/dist/scanners/indexerScanner.js.map +1 -0
  62. package/dist/scanners/rpcTraceScanner.d.ts +40 -0
  63. package/dist/scanners/rpcTraceScanner.js +121 -0
  64. package/dist/scanners/rpcTraceScanner.js.map +1 -0
  65. package/dist/scanners/traceScanner.d.ts +24 -0
  66. package/dist/scanners/traceScanner.js +272 -0
  67. package/dist/scanners/traceScanner.js.map +1 -0
  68. package/dist/scanners/validatorScanner.d.ts +40 -0
  69. package/dist/scanners/validatorScanner.js +210 -0
  70. package/dist/scanners/validatorScanner.js.map +1 -0
  71. package/dist/utils/bytecode.d.ts +11 -0
  72. package/dist/utils/bytecode.js +140 -0
  73. package/dist/utils/bytecode.js.map +1 -0
  74. package/dist/utils/files.d.ts +10 -0
  75. package/dist/utils/files.js +51 -0
  76. package/dist/utils/files.js.map +1 -0
  77. package/dist/utils/severity.d.ts +2 -0
  78. package/dist/utils/severity.js +13 -0
  79. package/dist/utils/severity.js.map +1 -0
  80. package/docs/fixtures.md +60 -0
  81. package/docs/release.md +132 -0
  82. package/examples/storage-heavy-bytecode.md +57 -0
  83. package/fixtures/bytecode/storage-heavy.hex +1 -0
  84. package/fixtures/indexers/balance-diff-indexer.json +15 -0
  85. package/fixtures/indexers/subgraph.yaml +24 -0
  86. package/fixtures/traces/besu-debug-structlogs.json +18 -0
  87. package/fixtures/traces/call-tracer-tree.json +27 -0
  88. package/fixtures/traces/drpc-call-tracer-real.json +373 -0
  89. package/fixtures/traces/erigon-action-trace.json +29 -0
  90. package/fixtures/traces/foundry-json-trace.json +19 -0
  91. package/fixtures/traces/geth-json-rpc-structlogs.json +16 -0
  92. package/fixtures/traces/hardhat-debug-trace.json +13 -0
  93. package/fixtures/traces/nethermind-debug-structlogs.json +17 -0
  94. package/fixtures/traces/storage-heavy-trace.json +25 -0
  95. package/fixtures/validator/operator-config.yaml +15 -0
  96. package/package.json +80 -0
@@ -0,0 +1,45 @@
1
+ import { existsSync, readFileSync } from "node:fs";
2
+ import { dirname, resolve } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ import { z } from "zod";
5
+ const moduleDir = dirname(fileURLToPath(import.meta.url));
6
+ export const detectorThresholdsSchema = z.object({
7
+ schemaVersion: z.number().int().positive(),
8
+ profile: z.string().min(1).optional(),
9
+ lastUpdated: z.string().min(1),
10
+ notes: z.array(z.string()).default([]),
11
+ bytecode: z.object({
12
+ contractSize: z.object({
13
+ currentRuntimeLimitBytes: z.number().int().positive(),
14
+ nearCurrentLimitBytes: z.number().int().positive()
15
+ }),
16
+ stateAccountOpcodeExposure: z.object({
17
+ mediumSensitiveOpcodeCount: z.number().int().positive(),
18
+ lowSensitiveOpcodeCount: z.number().int().positive()
19
+ }),
20
+ storagePattern: z.object({
21
+ mediumStorageOpcodeCount: z.number().int().positive()
22
+ })
23
+ }),
24
+ trace: z.object({
25
+ stateHeavyExecution: z.object({
26
+ highStorageOps: z.number().int().positive(),
27
+ highSensitiveOpcodeCount: z.number().int().positive(),
28
+ mediumStorageOps: z.number().int().positive(),
29
+ mediumSensitiveOpcodeCount: z.number().int().positive()
30
+ }),
31
+ calldataHeavy: z.object({
32
+ mediumCalldataBytes: z.number().int().positive()
33
+ })
34
+ })
35
+ });
36
+ export function defaultThresholdsPath() {
37
+ return resolve(moduleDir, "../../data/detectors/thresholds.json");
38
+ }
39
+ export function loadDetectorThresholds(thresholdsPath = defaultThresholdsPath()) {
40
+ if (!existsSync(thresholdsPath)) {
41
+ throw new Error(`Detector thresholds not found: ${thresholdsPath}`);
42
+ }
43
+ return detectorThresholdsSchema.parse(JSON.parse(readFileSync(thresholdsPath, "utf8")));
44
+ }
45
+ //# sourceMappingURL=thresholds.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"thresholds.js","sourceRoot":"","sources":["../../src/detectors/thresholds.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAE1D,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC/C,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;IAC1C,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IACrC,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC9B,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;IACtC,QAAQ,EAAE,CAAC,CAAC,MAAM,CAAC;QACjB,YAAY,EAAE,CAAC,CAAC,MAAM,CAAC;YACrB,wBAAwB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;YACrD,qBAAqB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;SACnD,CAAC;QACF,0BAA0B,EAAE,CAAC,CAAC,MAAM,CAAC;YACnC,0BAA0B,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;YACvD,uBAAuB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;SACrD,CAAC;QACF,cAAc,EAAE,CAAC,CAAC,MAAM,CAAC;YACvB,wBAAwB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;SACtD,CAAC;KACH,CAAC;IACF,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC;QACd,mBAAmB,EAAE,CAAC,CAAC,MAAM,CAAC;YAC5B,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;YAC3C,wBAAwB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;YACrD,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;YAC7C,0BAA0B,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;SACxD,CAAC;QACF,aAAa,EAAE,CAAC,CAAC,MAAM,CAAC;YACtB,mBAAmB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;SACjD,CAAC;KACH,CAAC;CACH,CAAC,CAAC;AAIH,MAAM,UAAU,qBAAqB;IACnC,OAAO,OAAO,CAAC,SAAS,EAAE,sCAAsC,CAAC,CAAC;AACpE,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,cAAc,GAAG,qBAAqB,EAAE;IAC7E,IAAI,CAAC,UAAU,CAAC,cAAc,CAAC,EAAE,CAAC;QAChC,MAAM,IAAI,KAAK,CAAC,kCAAkC,cAAc,EAAE,CAAC,CAAC;IACtE,CAAC;IAED,OAAO,wBAAwB,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;AAC1F,CAAC"}
@@ -0,0 +1,15 @@
1
+ import type { EipRegistry } from "../registry/schemas.js";
2
+ import type { CompatibilityFinding, ReportDomain } from "../reports/reportTypes.js";
3
+ import type { DetectorThresholds } from "./thresholds.js";
4
+ export type FindingInput = Omit<CompatibilityFinding, "relatedEips" | "evidence"> & {
5
+ relatedEips?: string[];
6
+ evidence?: unknown[] | unknown;
7
+ };
8
+ export interface DetectorContext {
9
+ registry: EipRegistry;
10
+ targetName: string;
11
+ thresholds: DetectorThresholds;
12
+ }
13
+ export declare function relatedEipsForDetector(registry: EipRegistry, detectorName: string, preferredIds?: string[]): string[];
14
+ export declare function makeFinding(input: FindingInput): CompatibilityFinding;
15
+ export declare function domains(...domains: ReportDomain[]): ReportDomain[];
@@ -0,0 +1,23 @@
1
+ export function relatedEipsForDetector(registry, detectorName, preferredIds = []) {
2
+ const registryIds = registry.eips
3
+ .filter((entry) => entry.detectors.includes(detectorName))
4
+ .map((entry) => entry.id);
5
+ const knownIds = new Set(registry.eips.map((entry) => entry.id));
6
+ return [...new Set([...preferredIds.filter((id) => knownIds.has(id)), ...registryIds])];
7
+ }
8
+ export function makeFinding(input) {
9
+ const evidence = input.evidence === undefined
10
+ ? []
11
+ : Array.isArray(input.evidence)
12
+ ? input.evidence
13
+ : [input.evidence];
14
+ return {
15
+ ...input,
16
+ evidence,
17
+ relatedEips: input.relatedEips ?? []
18
+ };
19
+ }
20
+ export function domains(...domains) {
21
+ return domains;
22
+ }
23
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/detectors/types.ts"],"names":[],"mappings":"AAeA,MAAM,UAAU,sBAAsB,CACpC,QAAqB,EACrB,YAAoB,EACpB,eAAyB,EAAE;IAE3B,MAAM,WAAW,GAAG,QAAQ,CAAC,IAAI;SAC9B,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;SACzD,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAC5B,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;IACjE,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;AAC1F,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,KAAmB;IAC7C,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,KAAK,SAAS;QAC3C,CAAC,CAAC,EAAE;QACJ,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC;YAC7B,CAAC,CAAC,KAAK,CAAC,QAAQ;YAChB,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAEvB,OAAO;QACL,GAAG,KAAK;QACR,QAAQ;QACR,WAAW,EAAE,KAAK,CAAC,WAAW,IAAI,EAAE;KACrC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,GAAG,OAAuB;IAChD,OAAO,OAAO,CAAC;AACjB,CAAC"}
@@ -0,0 +1,16 @@
1
+ export { loadEipRegistry, defaultRegistryPath } from "./registry/eipRegistry.js";
2
+ export type { EipEntry, EipRegistry, EipStatus, EipDomain } from "./registry/schemas.js";
3
+ export { scanBytecode } from "./scanners/bytecodeScanner.js";
4
+ export { scanTrace, scanTraceFile, normalizeTrace } from "./scanners/traceScanner.js";
5
+ export { fetchAndScanTransactionTrace, fetchDebugTraceTransaction, normalizeTxHash, parseDebugTraceMode, scanFetchedTransactionTrace, scanTransactionTrace } from "./scanners/rpcTraceScanner.js";
6
+ export { writeFetchedTrace } from "./scanners/rpcTraceScanner.js";
7
+ export type { DebugTraceMode, FetchDebugTraceOptions, RpcFetch, ScannedTransactionTrace, ScanTransactionTraceOptions } from "./scanners/rpcTraceScanner.js";
8
+ export { scanIndexer, summarizeHandlers } from "./scanners/indexerScanner.js";
9
+ export { scanValidatorConfig, defaultClientMatrixPath } from "./scanners/validatorScanner.js";
10
+ export { loadDetectorThresholds, defaultThresholdsPath, detectorThresholdsSchema } from "./detectors/thresholds.js";
11
+ export type { DetectorThresholds } from "./detectors/thresholds.js";
12
+ export { compatibilityReportSchema, findingSchema, makeReport, summarizeFindings, validateCompatibilityReport, combineReports } from "./reports/reportTypes.js";
13
+ export type { CompatibilityFinding, CompatibilityReport, Confidence, ReportDomain, Severity, TargetKind } from "./reports/reportTypes.js";
14
+ export { renderJsonReport } from "./reports/jsonReporter.js";
15
+ export { renderMarkdownReport } from "./reports/markdownReporter.js";
16
+ export { normalizeBytecode, disassembleBytecode, countOpcodeNames, byteLength, opcodeCount } from "./utils/bytecode.js";
package/dist/index.js ADDED
@@ -0,0 +1,13 @@
1
+ export { loadEipRegistry, defaultRegistryPath } from "./registry/eipRegistry.js";
2
+ export { scanBytecode } from "./scanners/bytecodeScanner.js";
3
+ export { scanTrace, scanTraceFile, normalizeTrace } from "./scanners/traceScanner.js";
4
+ export { fetchAndScanTransactionTrace, fetchDebugTraceTransaction, normalizeTxHash, parseDebugTraceMode, scanFetchedTransactionTrace, scanTransactionTrace } from "./scanners/rpcTraceScanner.js";
5
+ export { writeFetchedTrace } from "./scanners/rpcTraceScanner.js";
6
+ export { scanIndexer, summarizeHandlers } from "./scanners/indexerScanner.js";
7
+ export { scanValidatorConfig, defaultClientMatrixPath } from "./scanners/validatorScanner.js";
8
+ export { loadDetectorThresholds, defaultThresholdsPath, detectorThresholdsSchema } from "./detectors/thresholds.js";
9
+ export { compatibilityReportSchema, findingSchema, makeReport, summarizeFindings, validateCompatibilityReport, combineReports } from "./reports/reportTypes.js";
10
+ export { renderJsonReport } from "./reports/jsonReporter.js";
11
+ export { renderMarkdownReport } from "./reports/markdownReporter.js";
12
+ export { normalizeBytecode, disassembleBytecode, countOpcodeNames, byteLength, opcodeCount } from "./utils/bytecode.js";
13
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAGjF,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAC7D,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AACtF,OAAO,EACL,4BAA4B,EAC5B,0BAA0B,EAC1B,eAAe,EACf,mBAAmB,EACnB,2BAA2B,EAC3B,oBAAoB,EACrB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAQlE,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AAC9E,OAAO,EAAE,mBAAmB,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAC;AAC9F,OAAO,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AAGpH,OAAO,EACL,yBAAyB,EACzB,aAAa,EACb,UAAU,EACV,iBAAiB,EACjB,2BAA2B,EAC3B,cAAc,EACf,MAAM,0BAA0B,CAAC;AAUlC,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAC7D,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAErE,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EACnB,gBAAgB,EAChB,UAAU,EACV,WAAW,EACZ,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,6 @@
1
+ import { type EipEntry, type EipRegistry } from "./schemas.js";
2
+ export declare function defaultRegistryPath(): string;
3
+ export declare function loadEipRegistry(registryPath?: string): EipRegistry;
4
+ export declare function eipsForDetector(registry: EipRegistry, detectorName: string): EipEntry[];
5
+ export declare function findEip(registry: EipRegistry, id: string): EipEntry | undefined;
6
+ export declare function activeOrConsideredEipIds(registry: EipRegistry, ids: string[]): string[];
@@ -0,0 +1,30 @@
1
+ import { existsSync, readFileSync } from "node:fs";
2
+ import { dirname, resolve } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ import { eipRegistrySchema } from "./schemas.js";
5
+ const moduleDir = dirname(fileURLToPath(import.meta.url));
6
+ export function defaultRegistryPath() {
7
+ return resolve(moduleDir, "../../data/eips/glamsterdam.json");
8
+ }
9
+ export function loadEipRegistry(registryPath = defaultRegistryPath()) {
10
+ if (!existsSync(registryPath)) {
11
+ throw new Error(`EIP registry not found: ${registryPath}`);
12
+ }
13
+ const raw = readFileSync(registryPath, "utf8");
14
+ const parsed = JSON.parse(raw);
15
+ return eipRegistrySchema.parse(parsed);
16
+ }
17
+ export function eipsForDetector(registry, detectorName) {
18
+ return registry.eips.filter((entry) => entry.detectors.includes(detectorName));
19
+ }
20
+ export function findEip(registry, id) {
21
+ return registry.eips.find((entry) => entry.id === id);
22
+ }
23
+ export function activeOrConsideredEipIds(registry, ids) {
24
+ const usableStatuses = new Set(["scheduled", "considered"]);
25
+ return ids.filter((id) => {
26
+ const entry = findEip(registry, id);
27
+ return entry ? usableStatuses.has(entry.status) : false;
28
+ });
29
+ }
30
+ //# sourceMappingURL=eipRegistry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"eipRegistry.js","sourceRoot":"","sources":["../../src/registry/eipRegistry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,iBAAiB,EAAmC,MAAM,cAAc,CAAC;AAElF,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAE1D,MAAM,UAAU,mBAAmB;IACjC,OAAO,OAAO,CAAC,SAAS,EAAE,kCAAkC,CAAC,CAAC;AAChE,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,YAAY,GAAG,mBAAmB,EAAE;IAClE,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,2BAA2B,YAAY,EAAE,CAAC,CAAC;IAC7D,CAAC;IAED,MAAM,GAAG,GAAG,YAAY,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;IAC/C,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC/B,OAAO,iBAAiB,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,QAAqB,EAAE,YAAoB;IACzE,OAAO,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAC;AACjF,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,QAAqB,EAAE,EAAU;IACvD,OAAO,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;AACxD,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAC,QAAqB,EAAE,GAAa;IAC3E,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC,CAAC;IAC5D,OAAO,GAAG,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE;QACvB,MAAM,KAAK,GAAG,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;QACpC,OAAO,KAAK,CAAC,CAAC,CAAC,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IAC1D,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,76 @@
1
+ import { z } from "zod";
2
+ export declare const eipStatusSchema: z.ZodEnum<{
3
+ scheduled: "scheduled";
4
+ considered: "considered";
5
+ declined: "declined";
6
+ superseded: "superseded";
7
+ unknown: "unknown";
8
+ }>;
9
+ export declare const eipDomainSchema: z.ZodEnum<{
10
+ execution: "execution";
11
+ consensus: "consensus";
12
+ networking: "networking";
13
+ tooling: "tooling";
14
+ monitoring: "monitoring";
15
+ indexer: "indexer";
16
+ validator: "validator";
17
+ builder: "builder";
18
+ contracts: "contracts";
19
+ }>;
20
+ export declare const eipEntrySchema: z.ZodObject<{
21
+ id: z.ZodString;
22
+ name: z.ZodString;
23
+ status: z.ZodEnum<{
24
+ scheduled: "scheduled";
25
+ considered: "considered";
26
+ declined: "declined";
27
+ superseded: "superseded";
28
+ unknown: "unknown";
29
+ }>;
30
+ domain: z.ZodArray<z.ZodEnum<{
31
+ execution: "execution";
32
+ consensus: "consensus";
33
+ networking: "networking";
34
+ tooling: "tooling";
35
+ monitoring: "monitoring";
36
+ indexer: "indexer";
37
+ validator: "validator";
38
+ builder: "builder";
39
+ contracts: "contracts";
40
+ }>>;
41
+ detectors: z.ZodDefault<z.ZodArray<z.ZodString>>;
42
+ notes: z.ZodOptional<z.ZodString>;
43
+ }, z.core.$strip>;
44
+ export declare const eipRegistrySchema: z.ZodObject<{
45
+ fork: z.ZodString;
46
+ lastUpdated: z.ZodString;
47
+ sources: z.ZodDefault<z.ZodArray<z.ZodString>>;
48
+ eips: z.ZodArray<z.ZodObject<{
49
+ id: z.ZodString;
50
+ name: z.ZodString;
51
+ status: z.ZodEnum<{
52
+ scheduled: "scheduled";
53
+ considered: "considered";
54
+ declined: "declined";
55
+ superseded: "superseded";
56
+ unknown: "unknown";
57
+ }>;
58
+ domain: z.ZodArray<z.ZodEnum<{
59
+ execution: "execution";
60
+ consensus: "consensus";
61
+ networking: "networking";
62
+ tooling: "tooling";
63
+ monitoring: "monitoring";
64
+ indexer: "indexer";
65
+ validator: "validator";
66
+ builder: "builder";
67
+ contracts: "contracts";
68
+ }>>;
69
+ detectors: z.ZodDefault<z.ZodArray<z.ZodString>>;
70
+ notes: z.ZodOptional<z.ZodString>;
71
+ }, z.core.$strip>>;
72
+ }, z.core.$strip>;
73
+ export type EipStatus = z.infer<typeof eipStatusSchema>;
74
+ export type EipDomain = z.infer<typeof eipDomainSchema>;
75
+ export type EipEntry = z.infer<typeof eipEntrySchema>;
76
+ export type EipRegistry = z.infer<typeof eipRegistrySchema>;
@@ -0,0 +1,34 @@
1
+ import { z } from "zod";
2
+ export const eipStatusSchema = z.enum([
3
+ "scheduled",
4
+ "considered",
5
+ "declined",
6
+ "superseded",
7
+ "unknown"
8
+ ]);
9
+ export const eipDomainSchema = z.enum([
10
+ "execution",
11
+ "consensus",
12
+ "networking",
13
+ "tooling",
14
+ "monitoring",
15
+ "indexer",
16
+ "validator",
17
+ "builder",
18
+ "contracts"
19
+ ]);
20
+ export const eipEntrySchema = z.object({
21
+ id: z.string().min(1),
22
+ name: z.string().min(1),
23
+ status: eipStatusSchema,
24
+ domain: z.array(eipDomainSchema).min(1),
25
+ detectors: z.array(z.string()).default([]),
26
+ notes: z.string().optional()
27
+ });
28
+ export const eipRegistrySchema = z.object({
29
+ fork: z.string().min(1),
30
+ lastUpdated: z.string().min(1),
31
+ sources: z.array(z.string().url()).default([]),
32
+ eips: z.array(eipEntrySchema)
33
+ });
34
+ //# sourceMappingURL=schemas.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schemas.js","sourceRoot":"","sources":["../../src/registry/schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,CAAC,IAAI,CAAC;IACpC,WAAW;IACX,YAAY;IACZ,UAAU;IACV,YAAY;IACZ,SAAS;CACV,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,CAAC,IAAI,CAAC;IACpC,WAAW;IACX,WAAW;IACX,YAAY;IACZ,SAAS;IACT,YAAY;IACZ,SAAS;IACT,WAAW;IACX,SAAS;IACT,WAAW;CACZ,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC,MAAM,CAAC;IACrC,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACrB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACvB,MAAM,EAAE,eAAe;IACvB,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IACvC,SAAS,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;IAC1C,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAC7B,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC;IACxC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACvB,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC9B,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;IAC9C,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,cAAc,CAAC;CAC9B,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ import { type CompatibilityReport } from "./reportTypes.js";
2
+ export declare function renderJsonReport(report: CompatibilityReport): string;
@@ -0,0 +1,5 @@
1
+ import { compatibilityReportSchema } from "./reportTypes.js";
2
+ export function renderJsonReport(report) {
3
+ return `${JSON.stringify(compatibilityReportSchema.parse(report), null, 2)}\n`;
4
+ }
5
+ //# sourceMappingURL=jsonReporter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsonReporter.js","sourceRoot":"","sources":["../../src/reports/jsonReporter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAA4B,MAAM,kBAAkB,CAAC;AAEvF,MAAM,UAAU,gBAAgB,CAAC,MAA2B;IAC1D,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,yBAAyB,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC;AACjF,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { CompatibilityReport } from "./reportTypes.js";
2
+ export declare function renderMarkdownReport(report: CompatibilityReport): string;
@@ -0,0 +1,75 @@
1
+ export function renderMarkdownReport(report) {
2
+ const lines = [];
3
+ lines.push("# Glamsterdam Compatibility Report");
4
+ lines.push("");
5
+ lines.push(`Target: ${report.target.kind} ${report.target.name}`);
6
+ lines.push(`Tool version: ${report.toolVersion}`);
7
+ lines.push(`Fork registry: ${report.fork}`);
8
+ lines.push("");
9
+ lines.push("## Summary");
10
+ lines.push("");
11
+ lines.push(`Overall risk: ${formatInlineSeverity(report.summary.risk)}`);
12
+ lines.push(`Findings: ${report.summary.findingCount} total, ${report.summary.highCount} high, ${report.summary.mediumCount} medium, ${report.summary.lowCount} low, ${report.summary.unknownCount} unknown`);
13
+ lines.push("");
14
+ lines.push("## Findings");
15
+ lines.push("");
16
+ if (report.findings.length === 0) {
17
+ lines.push("No findings were produced by this scanner.");
18
+ lines.push("");
19
+ }
20
+ else {
21
+ report.findings.forEach((finding, index) => {
22
+ lines.push(renderFinding(finding, index + 1));
23
+ });
24
+ }
25
+ lines.push("## Assumptions");
26
+ lines.push("");
27
+ pushList(lines, report.assumptions, "No explicit assumptions were recorded.");
28
+ lines.push("");
29
+ lines.push("## Limitations");
30
+ lines.push("");
31
+ pushList(lines, report.limitations, "No limitations were recorded.");
32
+ lines.push("");
33
+ return `${lines.join("\n")}\n`;
34
+ }
35
+ function renderFinding(finding, index) {
36
+ const lines = [];
37
+ lines.push(`### ${index}. ${finding.title}`);
38
+ lines.push("");
39
+ lines.push(`Severity: ${formatInlineSeverity(finding.severity)}`);
40
+ lines.push(`Confidence: ${finding.confidence}`);
41
+ lines.push(`Domains: ${finding.domain.join(", ")}`);
42
+ lines.push(`Related EIPs: ${finding.relatedEips.length > 0 ? finding.relatedEips.join(", ") : "none"}`);
43
+ lines.push("");
44
+ lines.push(finding.description);
45
+ lines.push("");
46
+ if (finding.evidence.length > 0) {
47
+ lines.push("Evidence:");
48
+ for (const item of finding.evidence) {
49
+ lines.push(`- ${formatEvidence(item)}`);
50
+ }
51
+ lines.push("");
52
+ }
53
+ lines.push(`Recommendation: ${finding.recommendation}`);
54
+ lines.push("");
55
+ return lines.join("\n");
56
+ }
57
+ function pushList(lines, items, emptyText) {
58
+ if (items.length === 0) {
59
+ lines.push(emptyText);
60
+ return;
61
+ }
62
+ for (const item of items) {
63
+ lines.push(`- ${item}`);
64
+ }
65
+ }
66
+ function formatEvidence(item) {
67
+ if (typeof item === "string") {
68
+ return item;
69
+ }
70
+ return JSON.stringify(item);
71
+ }
72
+ function formatInlineSeverity(value) {
73
+ return value.toUpperCase();
74
+ }
75
+ //# sourceMappingURL=markdownReporter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markdownReporter.js","sourceRoot":"","sources":["../../src/reports/markdownReporter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,150 @@
1
+ import { z } from "zod";
2
+ export declare const TOOL_VERSION = "0.2.2";
3
+ export declare const severitySchema: z.ZodEnum<{
4
+ unknown: "unknown";
5
+ low: "low";
6
+ medium: "medium";
7
+ high: "high";
8
+ }>;
9
+ export declare const confidenceSchema: z.ZodEnum<{
10
+ low: "low";
11
+ medium: "medium";
12
+ high: "high";
13
+ }>;
14
+ export declare const reportDomainSchema: z.ZodEnum<{
15
+ execution: "execution";
16
+ consensus: "consensus";
17
+ networking: "networking";
18
+ tooling: "tooling";
19
+ monitoring: "monitoring";
20
+ indexer: "indexer";
21
+ validator: "validator";
22
+ builder: "builder";
23
+ contracts: "contracts";
24
+ }>;
25
+ export declare const targetKindSchema: z.ZodEnum<{
26
+ indexer: "indexer";
27
+ validator: "validator";
28
+ bytecode: "bytecode";
29
+ trace: "trace";
30
+ combined: "combined";
31
+ }>;
32
+ export declare const findingSchema: z.ZodObject<{
33
+ id: z.ZodString;
34
+ title: z.ZodString;
35
+ severity: z.ZodEnum<{
36
+ unknown: "unknown";
37
+ low: "low";
38
+ medium: "medium";
39
+ high: "high";
40
+ }>;
41
+ confidence: z.ZodEnum<{
42
+ low: "low";
43
+ medium: "medium";
44
+ high: "high";
45
+ }>;
46
+ domain: z.ZodArray<z.ZodEnum<{
47
+ execution: "execution";
48
+ consensus: "consensus";
49
+ networking: "networking";
50
+ tooling: "tooling";
51
+ monitoring: "monitoring";
52
+ indexer: "indexer";
53
+ validator: "validator";
54
+ builder: "builder";
55
+ contracts: "contracts";
56
+ }>>;
57
+ relatedEips: z.ZodDefault<z.ZodArray<z.ZodString>>;
58
+ description: z.ZodString;
59
+ evidence: z.ZodDefault<z.ZodArray<z.ZodUnknown>>;
60
+ recommendation: z.ZodString;
61
+ }, z.core.$strip>;
62
+ export declare const reportSummarySchema: z.ZodObject<{
63
+ risk: z.ZodEnum<{
64
+ unknown: "unknown";
65
+ low: "low";
66
+ medium: "medium";
67
+ high: "high";
68
+ }>;
69
+ findingCount: z.ZodNumber;
70
+ highCount: z.ZodNumber;
71
+ mediumCount: z.ZodNumber;
72
+ lowCount: z.ZodNumber;
73
+ unknownCount: z.ZodNumber;
74
+ }, z.core.$strip>;
75
+ export declare const compatibilityReportSchema: z.ZodObject<{
76
+ toolVersion: z.ZodString;
77
+ fork: z.ZodString;
78
+ target: z.ZodObject<{
79
+ kind: z.ZodEnum<{
80
+ indexer: "indexer";
81
+ validator: "validator";
82
+ bytecode: "bytecode";
83
+ trace: "trace";
84
+ combined: "combined";
85
+ }>;
86
+ name: z.ZodString;
87
+ }, z.core.$strip>;
88
+ summary: z.ZodObject<{
89
+ risk: z.ZodEnum<{
90
+ unknown: "unknown";
91
+ low: "low";
92
+ medium: "medium";
93
+ high: "high";
94
+ }>;
95
+ findingCount: z.ZodNumber;
96
+ highCount: z.ZodNumber;
97
+ mediumCount: z.ZodNumber;
98
+ lowCount: z.ZodNumber;
99
+ unknownCount: z.ZodNumber;
100
+ }, z.core.$strip>;
101
+ findings: z.ZodArray<z.ZodObject<{
102
+ id: z.ZodString;
103
+ title: z.ZodString;
104
+ severity: z.ZodEnum<{
105
+ unknown: "unknown";
106
+ low: "low";
107
+ medium: "medium";
108
+ high: "high";
109
+ }>;
110
+ confidence: z.ZodEnum<{
111
+ low: "low";
112
+ medium: "medium";
113
+ high: "high";
114
+ }>;
115
+ domain: z.ZodArray<z.ZodEnum<{
116
+ execution: "execution";
117
+ consensus: "consensus";
118
+ networking: "networking";
119
+ tooling: "tooling";
120
+ monitoring: "monitoring";
121
+ indexer: "indexer";
122
+ validator: "validator";
123
+ builder: "builder";
124
+ contracts: "contracts";
125
+ }>>;
126
+ relatedEips: z.ZodDefault<z.ZodArray<z.ZodString>>;
127
+ description: z.ZodString;
128
+ evidence: z.ZodDefault<z.ZodArray<z.ZodUnknown>>;
129
+ recommendation: z.ZodString;
130
+ }, z.core.$strip>>;
131
+ assumptions: z.ZodDefault<z.ZodArray<z.ZodString>>;
132
+ limitations: z.ZodDefault<z.ZodArray<z.ZodString>>;
133
+ }, z.core.$strip>;
134
+ export type Severity = z.infer<typeof severitySchema>;
135
+ export type Confidence = z.infer<typeof confidenceSchema>;
136
+ export type ReportDomain = z.infer<typeof reportDomainSchema>;
137
+ export type TargetKind = z.infer<typeof targetKindSchema>;
138
+ export type CompatibilityFinding = z.infer<typeof findingSchema>;
139
+ export type CompatibilityReport = z.infer<typeof compatibilityReportSchema>;
140
+ export interface MakeReportInput {
141
+ fork?: string;
142
+ target: CompatibilityReport["target"];
143
+ findings: CompatibilityFinding[];
144
+ assumptions?: string[];
145
+ limitations?: string[];
146
+ }
147
+ export declare function summarizeFindings(findings: CompatibilityFinding[]): CompatibilityReport["summary"];
148
+ export declare function makeReport(input: MakeReportInput): CompatibilityReport;
149
+ export declare function validateCompatibilityReport(value: unknown): CompatibilityReport;
150
+ export declare function combineReports(reports: CompatibilityReport[]): CompatibilityReport;
@@ -0,0 +1,111 @@
1
+ import { z } from "zod";
2
+ export const TOOL_VERSION = "0.2.2";
3
+ export const severitySchema = z.enum(["low", "medium", "high", "unknown"]);
4
+ export const confidenceSchema = z.enum(["low", "medium", "high"]);
5
+ export const reportDomainSchema = z.enum([
6
+ "contracts",
7
+ "indexer",
8
+ "validator",
9
+ "monitoring",
10
+ "execution",
11
+ "consensus",
12
+ "networking",
13
+ "builder",
14
+ "tooling"
15
+ ]);
16
+ export const targetKindSchema = z.enum([
17
+ "bytecode",
18
+ "trace",
19
+ "indexer",
20
+ "validator",
21
+ "combined"
22
+ ]);
23
+ export const findingSchema = z.object({
24
+ id: z.string().min(1),
25
+ title: z.string().min(1),
26
+ severity: severitySchema,
27
+ confidence: confidenceSchema,
28
+ domain: z.array(reportDomainSchema).min(1),
29
+ relatedEips: z.array(z.string()).default([]),
30
+ description: z.string().min(1),
31
+ evidence: z.array(z.unknown()).default([]),
32
+ recommendation: z.string().min(1)
33
+ });
34
+ export const reportSummarySchema = z.object({
35
+ risk: severitySchema,
36
+ findingCount: z.number().int().nonnegative(),
37
+ highCount: z.number().int().nonnegative(),
38
+ mediumCount: z.number().int().nonnegative(),
39
+ lowCount: z.number().int().nonnegative(),
40
+ unknownCount: z.number().int().nonnegative()
41
+ });
42
+ export const compatibilityReportSchema = z.object({
43
+ toolVersion: z.string().min(1),
44
+ fork: z.string().min(1),
45
+ target: z.object({
46
+ kind: targetKindSchema,
47
+ name: z.string().min(1)
48
+ }),
49
+ summary: reportSummarySchema,
50
+ findings: z.array(findingSchema),
51
+ assumptions: z.array(z.string()).default([]),
52
+ limitations: z.array(z.string()).default([])
53
+ });
54
+ export function summarizeFindings(findings) {
55
+ const highCount = findings.filter((finding) => finding.severity === "high").length;
56
+ const mediumCount = findings.filter((finding) => finding.severity === "medium").length;
57
+ const lowCount = findings.filter((finding) => finding.severity === "low").length;
58
+ const unknownCount = findings.filter((finding) => finding.severity === "unknown").length;
59
+ const risk = highCount > 0
60
+ ? "high"
61
+ : mediumCount > 0
62
+ ? "medium"
63
+ : lowCount > 0
64
+ ? "low"
65
+ : unknownCount > 0
66
+ ? "unknown"
67
+ : "low";
68
+ return {
69
+ risk,
70
+ findingCount: findings.length,
71
+ highCount,
72
+ mediumCount,
73
+ lowCount,
74
+ unknownCount
75
+ };
76
+ }
77
+ export function makeReport(input) {
78
+ return compatibilityReportSchema.parse({
79
+ toolVersion: TOOL_VERSION,
80
+ fork: input.fork ?? "glamsterdam",
81
+ target: input.target,
82
+ summary: summarizeFindings(input.findings),
83
+ findings: input.findings,
84
+ assumptions: input.assumptions ?? [],
85
+ limitations: input.limitations ?? []
86
+ });
87
+ }
88
+ export function validateCompatibilityReport(value) {
89
+ return compatibilityReportSchema.parse(value);
90
+ }
91
+ export function combineReports(reports) {
92
+ const findings = reports.flatMap((report) => report.findings.map((finding) => ({
93
+ ...finding,
94
+ id: `${report.target.kind}.${finding.id}`,
95
+ evidence: [`Source report: ${report.target.kind} ${report.target.name}`, ...finding.evidence]
96
+ })));
97
+ return makeReport({
98
+ fork: reports[0]?.fork ?? "glamsterdam",
99
+ target: {
100
+ kind: "combined",
101
+ name: `${reports.length} report${reports.length === 1 ? "" : "s"}`
102
+ },
103
+ findings,
104
+ assumptions: dedupe(reports.flatMap((report) => report.assumptions)),
105
+ limitations: dedupe(reports.flatMap((report) => report.limitations))
106
+ });
107
+ }
108
+ function dedupe(values) {
109
+ return [...new Set(values)];
110
+ }
111
+ //# sourceMappingURL=reportTypes.js.map