@fairfox/polly 0.1.1 → 0.1.3
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/cli/polly.ts +9 -3
- package/package.json +2 -2
- package/vendor/analysis/src/extract/adr.ts +212 -0
- package/vendor/analysis/src/extract/architecture.ts +160 -0
- package/vendor/analysis/src/extract/contexts.ts +298 -0
- package/vendor/analysis/src/extract/flows.ts +309 -0
- package/vendor/analysis/src/extract/handlers.ts +321 -0
- package/vendor/analysis/src/extract/index.ts +9 -0
- package/vendor/analysis/src/extract/integrations.ts +329 -0
- package/vendor/analysis/src/extract/manifest.ts +298 -0
- package/vendor/analysis/src/extract/types.ts +389 -0
- package/vendor/analysis/src/index.ts +7 -0
- package/vendor/analysis/src/types/adr.ts +53 -0
- package/vendor/analysis/src/types/architecture.ts +245 -0
- package/vendor/analysis/src/types/core.ts +210 -0
- package/vendor/analysis/src/types/index.ts +18 -0
- package/vendor/verify/src/adapters/base.ts +164 -0
- package/vendor/verify/src/adapters/detection.ts +281 -0
- package/vendor/verify/src/adapters/event-bus/index.ts +480 -0
- package/vendor/verify/src/adapters/web-extension/index.ts +508 -0
- package/vendor/verify/src/adapters/websocket/index.ts +486 -0
- package/vendor/verify/src/cli.ts +430 -0
- package/vendor/verify/src/codegen/config.ts +354 -0
- package/vendor/verify/src/codegen/tla.ts +719 -0
- package/vendor/verify/src/config/parser.ts +303 -0
- package/vendor/verify/src/config/types.ts +113 -0
- package/vendor/verify/src/core/model.ts +267 -0
- package/vendor/verify/src/core/primitives.ts +106 -0
- package/vendor/verify/src/extract/handlers.ts +2 -0
- package/vendor/verify/src/extract/types.ts +2 -0
- package/vendor/verify/src/index.ts +150 -0
- package/vendor/verify/src/primitives/index.ts +102 -0
- package/vendor/verify/src/runner/docker.ts +283 -0
- package/vendor/verify/src/types.ts +51 -0
- package/vendor/visualize/src/cli.ts +365 -0
- package/vendor/visualize/src/codegen/structurizr.ts +770 -0
- package/vendor/visualize/src/index.ts +13 -0
- package/vendor/visualize/src/runner/export.ts +235 -0
- package/vendor/visualize/src/viewer/server.ts +485 -0
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
// Architecture Decision Record types
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Architecture Decision Record
|
|
5
|
+
* Based on Michael Nygard's ADR format
|
|
6
|
+
*/
|
|
7
|
+
export type ADR = {
|
|
8
|
+
/** ADR number/ID */
|
|
9
|
+
id: string;
|
|
10
|
+
|
|
11
|
+
/** Decision title */
|
|
12
|
+
title: string;
|
|
13
|
+
|
|
14
|
+
/** Status: proposed, accepted, deprecated, superseded */
|
|
15
|
+
status: ADRStatus;
|
|
16
|
+
|
|
17
|
+
/** Date of decision */
|
|
18
|
+
date: string;
|
|
19
|
+
|
|
20
|
+
/** Context - what is the issue motivating this decision */
|
|
21
|
+
context: string;
|
|
22
|
+
|
|
23
|
+
/** Decision - what is the change we're proposing */
|
|
24
|
+
decision: string;
|
|
25
|
+
|
|
26
|
+
/** Consequences - what becomes easier or more difficult */
|
|
27
|
+
consequences: string;
|
|
28
|
+
|
|
29
|
+
/** Optional: Alternatives considered */
|
|
30
|
+
alternatives?: string[];
|
|
31
|
+
|
|
32
|
+
/** Optional: Links to superseding/superseded ADRs */
|
|
33
|
+
links?: ADRLink[];
|
|
34
|
+
|
|
35
|
+
/** Source file path */
|
|
36
|
+
source: string;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export type ADRStatus = "proposed" | "accepted" | "deprecated" | "superseded";
|
|
40
|
+
|
|
41
|
+
export type ADRLink = {
|
|
42
|
+
type: "supersedes" | "superseded-by" | "related-to";
|
|
43
|
+
adrId: string;
|
|
44
|
+
title?: string;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Collection of ADRs
|
|
49
|
+
*/
|
|
50
|
+
export type ADRCollection = {
|
|
51
|
+
adrs: ADR[];
|
|
52
|
+
directory: string;
|
|
53
|
+
};
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
// Types for architecture analysis (used by visualize)
|
|
2
|
+
|
|
3
|
+
import type { MessageHandler } from "./core";
|
|
4
|
+
|
|
5
|
+
// ─────────────────────────────────────────────────────────────────
|
|
6
|
+
// Context Information
|
|
7
|
+
// ─────────────────────────────────────────────────────────────────
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Information about an execution context (background, content, popup, etc.)
|
|
11
|
+
*/
|
|
12
|
+
export type ContextInfo = {
|
|
13
|
+
/** Type of context */
|
|
14
|
+
type: string;
|
|
15
|
+
|
|
16
|
+
/** Entry point file path */
|
|
17
|
+
entryPoint: string;
|
|
18
|
+
|
|
19
|
+
/** Message handlers defined in this context */
|
|
20
|
+
handlers: MessageHandler[];
|
|
21
|
+
|
|
22
|
+
/** Chrome APIs used in this context */
|
|
23
|
+
chromeAPIs: string[];
|
|
24
|
+
|
|
25
|
+
/** External APIs called from this context */
|
|
26
|
+
externalAPIs: ExternalAPICall[];
|
|
27
|
+
|
|
28
|
+
/** UI components rendered (for popup/options/devtools) */
|
|
29
|
+
components?: ComponentInfo[];
|
|
30
|
+
|
|
31
|
+
/** Dependencies/imports */
|
|
32
|
+
dependencies: string[];
|
|
33
|
+
|
|
34
|
+
/** JSDoc description if available */
|
|
35
|
+
description?: string;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Component information (for UI contexts)
|
|
40
|
+
*/
|
|
41
|
+
export type ComponentInfo = {
|
|
42
|
+
name: string;
|
|
43
|
+
type: "function" | "class";
|
|
44
|
+
filePath: string;
|
|
45
|
+
line: number;
|
|
46
|
+
props?: string[];
|
|
47
|
+
description?: string;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
// ─────────────────────────────────────────────────────────────────
|
|
51
|
+
// Message Flow Analysis
|
|
52
|
+
// ─────────────────────────────────────────────────────────────────
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Represents a message flow between contexts
|
|
56
|
+
*/
|
|
57
|
+
export type MessageFlow = {
|
|
58
|
+
/** Message type identifier */
|
|
59
|
+
messageType: string;
|
|
60
|
+
|
|
61
|
+
/** Source context */
|
|
62
|
+
from: string;
|
|
63
|
+
|
|
64
|
+
/** Destination context(s) */
|
|
65
|
+
to: string[];
|
|
66
|
+
|
|
67
|
+
/** What triggers this flow (user action, event, etc.) */
|
|
68
|
+
trigger?: string;
|
|
69
|
+
|
|
70
|
+
/** Sequence of steps in this flow */
|
|
71
|
+
sequence: MessageStep[];
|
|
72
|
+
|
|
73
|
+
/** Flow name (from @flow annotation or inferred) */
|
|
74
|
+
flowName?: string;
|
|
75
|
+
|
|
76
|
+
/** Description (from JSDoc) */
|
|
77
|
+
description?: string;
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* A step in a message flow sequence
|
|
82
|
+
*/
|
|
83
|
+
export type MessageStep = {
|
|
84
|
+
/** Step number in sequence */
|
|
85
|
+
step: number;
|
|
86
|
+
|
|
87
|
+
/** Action description */
|
|
88
|
+
action: string;
|
|
89
|
+
|
|
90
|
+
/** Context where this step occurs */
|
|
91
|
+
context: string;
|
|
92
|
+
|
|
93
|
+
/** Source location */
|
|
94
|
+
location?: {
|
|
95
|
+
file: string;
|
|
96
|
+
line: number;
|
|
97
|
+
};
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
// ─────────────────────────────────────────────────────────────────
|
|
101
|
+
// External Integrations
|
|
102
|
+
// ─────────────────────────────────────────────────────────────────
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* External system integration
|
|
106
|
+
*/
|
|
107
|
+
export type ExternalIntegration = {
|
|
108
|
+
/** Type of integration */
|
|
109
|
+
type: "api" | "storage" | "browser-api" | "external-script" | "websocket";
|
|
110
|
+
|
|
111
|
+
/** Name/identifier */
|
|
112
|
+
name: string;
|
|
113
|
+
|
|
114
|
+
/** Technology/protocol */
|
|
115
|
+
technology?: string;
|
|
116
|
+
|
|
117
|
+
/** Base URL or endpoint */
|
|
118
|
+
url?: string;
|
|
119
|
+
|
|
120
|
+
/** Where it's used (file paths) */
|
|
121
|
+
usedIn: string[];
|
|
122
|
+
|
|
123
|
+
/** Description (from JSDoc or inferred) */
|
|
124
|
+
description?: string;
|
|
125
|
+
|
|
126
|
+
/** Specific API calls made */
|
|
127
|
+
calls?: ExternalAPICall[];
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* A specific API call
|
|
132
|
+
*/
|
|
133
|
+
export type ExternalAPICall = {
|
|
134
|
+
/** HTTP method or API method name */
|
|
135
|
+
method: string;
|
|
136
|
+
|
|
137
|
+
/** Endpoint or resource */
|
|
138
|
+
endpoint: string;
|
|
139
|
+
|
|
140
|
+
/** Where this call is made */
|
|
141
|
+
location: {
|
|
142
|
+
file: string;
|
|
143
|
+
line: number;
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
/** Description */
|
|
147
|
+
description?: string;
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
// ─────────────────────────────────────────────────────────────────
|
|
151
|
+
// Manifest Analysis
|
|
152
|
+
// ─────────────────────────────────────────────────────────────────
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Parsed manifest.json information
|
|
156
|
+
*/
|
|
157
|
+
export type ManifestInfo = {
|
|
158
|
+
/** Extension name */
|
|
159
|
+
name: string;
|
|
160
|
+
|
|
161
|
+
/** Version */
|
|
162
|
+
version: string;
|
|
163
|
+
|
|
164
|
+
/** Description */
|
|
165
|
+
description?: string;
|
|
166
|
+
|
|
167
|
+
/** Manifest version (2 or 3) */
|
|
168
|
+
manifestVersion: number;
|
|
169
|
+
|
|
170
|
+
/** Background script/service worker */
|
|
171
|
+
background?: {
|
|
172
|
+
type: "script" | "service_worker";
|
|
173
|
+
files: string[];
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
/** Content scripts */
|
|
177
|
+
contentScripts?: Array<{
|
|
178
|
+
matches: string[];
|
|
179
|
+
js: string[];
|
|
180
|
+
css?: string[];
|
|
181
|
+
}>;
|
|
182
|
+
|
|
183
|
+
/** Popup */
|
|
184
|
+
popup?: {
|
|
185
|
+
html: string;
|
|
186
|
+
default?: boolean;
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
/** Options page */
|
|
190
|
+
options?: {
|
|
191
|
+
page: string;
|
|
192
|
+
openInTab?: boolean;
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
/** DevTools page */
|
|
196
|
+
devtools?: {
|
|
197
|
+
page: string;
|
|
198
|
+
};
|
|
199
|
+
|
|
200
|
+
/** Permissions */
|
|
201
|
+
permissions?: string[];
|
|
202
|
+
|
|
203
|
+
/** Host permissions */
|
|
204
|
+
hostPermissions?: string[];
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
// ─────────────────────────────────────────────────────────────────
|
|
208
|
+
// Complete Architecture Analysis
|
|
209
|
+
// ─────────────────────────────────────────────────────────────────
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Complete architecture analysis result
|
|
213
|
+
*/
|
|
214
|
+
export type ArchitectureAnalysis = {
|
|
215
|
+
/** Basic system information */
|
|
216
|
+
system: {
|
|
217
|
+
name: string;
|
|
218
|
+
version: string;
|
|
219
|
+
description?: string;
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
/** Manifest information */
|
|
223
|
+
manifest?: ManifestInfo;
|
|
224
|
+
|
|
225
|
+
/** All contexts found in the system */
|
|
226
|
+
contexts: Record<string, ContextInfo>;
|
|
227
|
+
|
|
228
|
+
/** Message flows between contexts */
|
|
229
|
+
messageFlows: MessageFlow[];
|
|
230
|
+
|
|
231
|
+
/** External integrations */
|
|
232
|
+
integrations: ExternalIntegration[];
|
|
233
|
+
|
|
234
|
+
/** Architecture Decision Records */
|
|
235
|
+
adrs?: ADRCollection;
|
|
236
|
+
|
|
237
|
+
/** Repository information */
|
|
238
|
+
repository?: {
|
|
239
|
+
url: string;
|
|
240
|
+
type: string;
|
|
241
|
+
};
|
|
242
|
+
};
|
|
243
|
+
|
|
244
|
+
// Import ADR types
|
|
245
|
+
import type { ADRCollection } from "./adr";
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
// ═══════════════════════════════════════════════════════════════
|
|
2
|
+
// Core Analysis Model (Domain-Agnostic)
|
|
3
|
+
// ═══════════════════════════════════════════════════════════════
|
|
4
|
+
//
|
|
5
|
+
// This module defines abstract types for analyzing message-passing systems.
|
|
6
|
+
// These types are independent of the specific domain (web extensions,
|
|
7
|
+
// actors, event buses, etc.).
|
|
8
|
+
|
|
9
|
+
// ─────────────────────────────────────────────────────────────────
|
|
10
|
+
// Type System (Universal)
|
|
11
|
+
// ─────────────────────────────────────────────────────────────────
|
|
12
|
+
|
|
13
|
+
export type TypeKind =
|
|
14
|
+
| "boolean"
|
|
15
|
+
| "string"
|
|
16
|
+
| "number"
|
|
17
|
+
| "enum"
|
|
18
|
+
| "array"
|
|
19
|
+
| "object"
|
|
20
|
+
| "map"
|
|
21
|
+
| "set"
|
|
22
|
+
| "union"
|
|
23
|
+
| "null"
|
|
24
|
+
| "unknown";
|
|
25
|
+
|
|
26
|
+
export type TypeInfo = {
|
|
27
|
+
name: string;
|
|
28
|
+
kind: TypeKind;
|
|
29
|
+
nullable: boolean;
|
|
30
|
+
elementType?: TypeInfo; // For arrays, sets
|
|
31
|
+
valueType?: TypeInfo; // For maps
|
|
32
|
+
properties?: Record<string, TypeInfo>; // For objects
|
|
33
|
+
enumValues?: string[]; // For enums
|
|
34
|
+
unionTypes?: TypeInfo[]; // For unions
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
// ─────────────────────────────────────────────────────────────────
|
|
38
|
+
// Node System (Abstract)
|
|
39
|
+
// ─────────────────────────────────────────────────────────────────
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* A node represents an entity in the system that can send/receive messages.
|
|
43
|
+
*
|
|
44
|
+
* Examples:
|
|
45
|
+
* - Web extension: "background", "content", "popup"
|
|
46
|
+
* - Actor system: Individual actor instances
|
|
47
|
+
* - Event bus: Emitters/listeners
|
|
48
|
+
* - Worker threads: Main thread + worker instances
|
|
49
|
+
*/
|
|
50
|
+
export type NodeDefinition = {
|
|
51
|
+
/** Unique identifier for this node */
|
|
52
|
+
id: string;
|
|
53
|
+
|
|
54
|
+
/** Type of node (adapter-specific) */
|
|
55
|
+
type: string;
|
|
56
|
+
|
|
57
|
+
/** Which nodes can this send messages to? */
|
|
58
|
+
canSendTo: string[];
|
|
59
|
+
|
|
60
|
+
/** Which nodes can send messages to this? */
|
|
61
|
+
canReceiveFrom: string[];
|
|
62
|
+
|
|
63
|
+
/** Optional: Additional metadata */
|
|
64
|
+
metadata?: Record<string, unknown>;
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
// ─────────────────────────────────────────────────────────────────
|
|
68
|
+
// Message Types (Abstract)
|
|
69
|
+
// ─────────────────────────────────────────────────────────────────
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Defines a type of message that flows through the system
|
|
73
|
+
*/
|
|
74
|
+
export type MessageTypeDefinition = {
|
|
75
|
+
/** Name/identifier of the message type */
|
|
76
|
+
name: string;
|
|
77
|
+
|
|
78
|
+
/** Schema of the message payload */
|
|
79
|
+
payload: TypeInfo;
|
|
80
|
+
|
|
81
|
+
/** Routing constraints */
|
|
82
|
+
routing: {
|
|
83
|
+
/** Which node types can send this message? */
|
|
84
|
+
from: string[];
|
|
85
|
+
|
|
86
|
+
/** Which node types can receive this message? */
|
|
87
|
+
to: string[];
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
/** Optional: Expected response type */
|
|
91
|
+
response?: TypeInfo;
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
// ─────────────────────────────────────────────────────────────────
|
|
95
|
+
// State Schema (Abstract)
|
|
96
|
+
// ─────────────────────────────────────────────────────────────────
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Configuration for a state field
|
|
100
|
+
*/
|
|
101
|
+
export type FieldConfig =
|
|
102
|
+
| { maxLength: number | null }
|
|
103
|
+
| { min: number | null; max: number | null }
|
|
104
|
+
| { type: "enum"; values: string[] }
|
|
105
|
+
| { values: string[] | null; abstract?: boolean }
|
|
106
|
+
| { maxSize: number | null; valueType?: unknown }
|
|
107
|
+
| { abstract: boolean };
|
|
108
|
+
|
|
109
|
+
export type StateSchema = Record<string, FieldConfig>;
|
|
110
|
+
|
|
111
|
+
// ─────────────────────────────────────────────────────────────────
|
|
112
|
+
// State Mutations (Abstract)
|
|
113
|
+
// ─────────────────────────────────────────────────────────────────
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Represents an assignment to a state field
|
|
117
|
+
*/
|
|
118
|
+
export type StateAssignment = {
|
|
119
|
+
/** Field path (e.g., "user.loggedIn") */
|
|
120
|
+
field: string;
|
|
121
|
+
|
|
122
|
+
/** The assigned value */
|
|
123
|
+
value: string | boolean | number | null;
|
|
124
|
+
|
|
125
|
+
/** Optional condition guard */
|
|
126
|
+
conditional?: string;
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
// ─────────────────────────────────────────────────────────────────
|
|
130
|
+
// Verification Conditions (Abstract)
|
|
131
|
+
// ─────────────────────────────────────────────────────────────────
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* A verification condition (precondition or postcondition)
|
|
135
|
+
*/
|
|
136
|
+
export type VerificationCondition = {
|
|
137
|
+
/** The condition expression as a string */
|
|
138
|
+
expression: string;
|
|
139
|
+
|
|
140
|
+
/** Optional error message */
|
|
141
|
+
message?: string;
|
|
142
|
+
|
|
143
|
+
/** Source location */
|
|
144
|
+
location: {
|
|
145
|
+
line: number;
|
|
146
|
+
column: number;
|
|
147
|
+
};
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
// ─────────────────────────────────────────────────────────────────
|
|
151
|
+
// Message Handler (Abstract)
|
|
152
|
+
// ─────────────────────────────────────────────────────────────────
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Represents a message handler extracted from code
|
|
156
|
+
*/
|
|
157
|
+
export type MessageHandler = {
|
|
158
|
+
/** Which message type does this handle? */
|
|
159
|
+
messageType: string;
|
|
160
|
+
|
|
161
|
+
/** Which node handles this message? */
|
|
162
|
+
node: string;
|
|
163
|
+
|
|
164
|
+
/** State assignments made by this handler */
|
|
165
|
+
assignments: StateAssignment[];
|
|
166
|
+
|
|
167
|
+
/** Preconditions (requires() calls) */
|
|
168
|
+
preconditions: VerificationCondition[];
|
|
169
|
+
|
|
170
|
+
/** Postconditions (ensures() calls) */
|
|
171
|
+
postconditions: VerificationCondition[];
|
|
172
|
+
|
|
173
|
+
/** Source location */
|
|
174
|
+
location: {
|
|
175
|
+
file: string;
|
|
176
|
+
line: number;
|
|
177
|
+
};
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
// ─────────────────────────────────────────────────────────────────
|
|
181
|
+
// Confidence Levels (Universal)
|
|
182
|
+
// ─────────────────────────────────────────────────────────────────
|
|
183
|
+
|
|
184
|
+
export type Confidence = "high" | "medium" | "low";
|
|
185
|
+
|
|
186
|
+
export type FieldAnalysis = {
|
|
187
|
+
path: string;
|
|
188
|
+
type: TypeInfo;
|
|
189
|
+
confidence: Confidence;
|
|
190
|
+
evidence: string[];
|
|
191
|
+
suggestions: string[];
|
|
192
|
+
bounds?: {
|
|
193
|
+
min?: number;
|
|
194
|
+
max?: number;
|
|
195
|
+
maxLength?: number;
|
|
196
|
+
maxSize?: number;
|
|
197
|
+
values?: string[];
|
|
198
|
+
};
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
// ─────────────────────────────────────────────────────────────────
|
|
202
|
+
// Codebase Analysis Result
|
|
203
|
+
// ─────────────────────────────────────────────────────────────────
|
|
204
|
+
|
|
205
|
+
export type CodebaseAnalysis = {
|
|
206
|
+
stateType: TypeInfo | null;
|
|
207
|
+
messageTypes: string[];
|
|
208
|
+
fields: FieldAnalysis[];
|
|
209
|
+
handlers: MessageHandler[];
|
|
210
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// Export all core types
|
|
2
|
+
export * from "./core";
|
|
3
|
+
|
|
4
|
+
// Export architecture types
|
|
5
|
+
export * from "./architecture";
|
|
6
|
+
|
|
7
|
+
// Export ADR types
|
|
8
|
+
export * from "./adr";
|
|
9
|
+
|
|
10
|
+
// Extension-specific context types
|
|
11
|
+
export type Context =
|
|
12
|
+
| "background"
|
|
13
|
+
| "content"
|
|
14
|
+
| "popup"
|
|
15
|
+
| "devtools"
|
|
16
|
+
| "options"
|
|
17
|
+
| "offscreen"
|
|
18
|
+
| "sidepanel";
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
// ═══════════════════════════════════════════════════════════════
|
|
2
|
+
// Routing Adapter Interface
|
|
3
|
+
// ═══════════════════════════════════════════════════════════════
|
|
4
|
+
//
|
|
5
|
+
// Adapters translate domain-specific code into the core verification model.
|
|
6
|
+
// Each adapter implements pattern matching and extraction logic for a
|
|
7
|
+
// specific messaging paradigm.
|
|
8
|
+
|
|
9
|
+
import type { Node } from "ts-morph";
|
|
10
|
+
import type {
|
|
11
|
+
CoreVerificationModel,
|
|
12
|
+
MessageHandler,
|
|
13
|
+
StateAssignment,
|
|
14
|
+
VerificationCondition,
|
|
15
|
+
CodebaseAnalysis,
|
|
16
|
+
} from "../core/model";
|
|
17
|
+
|
|
18
|
+
// ─────────────────────────────────────────────────────────────────
|
|
19
|
+
// Adapter Configuration
|
|
20
|
+
// ─────────────────────────────────────────────────────────────────
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Base configuration for all adapters
|
|
24
|
+
*/
|
|
25
|
+
export type AdapterConfig = {
|
|
26
|
+
/** Root directory to analyze */
|
|
27
|
+
rootDir?: string;
|
|
28
|
+
|
|
29
|
+
/** TypeScript config path */
|
|
30
|
+
tsConfigPath: string;
|
|
31
|
+
|
|
32
|
+
/** Adapter-specific options */
|
|
33
|
+
[key: string]: unknown;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
// ─────────────────────────────────────────────────────────────────
|
|
37
|
+
// Adapter Interface
|
|
38
|
+
// ─────────────────────────────────────────────────────────────────
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Base interface that all routing adapters must implement.
|
|
42
|
+
*
|
|
43
|
+
* Adapters are responsible for:
|
|
44
|
+
* 1. Extracting the abstract model from domain-specific code
|
|
45
|
+
* 2. Recognizing domain-specific patterns (how messages are sent/received)
|
|
46
|
+
* 3. Mapping domain concepts to abstract model concepts
|
|
47
|
+
*/
|
|
48
|
+
export interface RoutingAdapter<TConfig extends AdapterConfig = AdapterConfig> {
|
|
49
|
+
/** Unique name for this adapter */
|
|
50
|
+
readonly name: string;
|
|
51
|
+
|
|
52
|
+
/** Configuration */
|
|
53
|
+
readonly config: TConfig;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Extract the complete abstract model from a codebase
|
|
57
|
+
*
|
|
58
|
+
* This is the main entry point for the adapter. It should:
|
|
59
|
+
* 1. Discover nodes in the system
|
|
60
|
+
* 2. Extract message types
|
|
61
|
+
* 3. Infer routing rules
|
|
62
|
+
* 4. Extract message handlers and state mutations
|
|
63
|
+
* 5. Return a complete CoreVerificationModel
|
|
64
|
+
*/
|
|
65
|
+
extractModel(): CoreVerificationModel;
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Recognize if an AST node is a message handler registration
|
|
69
|
+
*
|
|
70
|
+
* @param node - TypeScript AST node to analyze
|
|
71
|
+
* @returns MessageHandler if recognized, null otherwise
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
* // Web extension adapter recognizes:
|
|
75
|
+
* bus.on("USER_LOGIN", (payload) => { ... })
|
|
76
|
+
*
|
|
77
|
+
* // Actor adapter recognizes:
|
|
78
|
+
* actor.receive((msg) => { if (msg.type === "USER_LOGIN") { ... } })
|
|
79
|
+
*/
|
|
80
|
+
recognizeMessageHandler(node: Node): MessageHandler | null;
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Recognize if an AST node is a state mutation
|
|
84
|
+
*
|
|
85
|
+
* @param node - TypeScript AST node to analyze
|
|
86
|
+
* @returns StateAssignment if recognized, null otherwise
|
|
87
|
+
*
|
|
88
|
+
* @example
|
|
89
|
+
* // Most adapters recognize:
|
|
90
|
+
* state.user.loggedIn = true
|
|
91
|
+
*/
|
|
92
|
+
recognizeStateUpdate(node: Node): StateAssignment | null;
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Recognize if an AST node is a verification condition
|
|
96
|
+
*
|
|
97
|
+
* @param node - TypeScript AST node to analyze
|
|
98
|
+
* @param type - "precondition" or "postcondition"
|
|
99
|
+
* @returns VerificationCondition if recognized, null otherwise
|
|
100
|
+
*
|
|
101
|
+
* @example
|
|
102
|
+
* // All adapters should recognize:
|
|
103
|
+
* requires(state.user.loggedIn === false, "Must not be logged in")
|
|
104
|
+
* ensures(state.user.loggedIn === true, "Must be logged in")
|
|
105
|
+
*/
|
|
106
|
+
recognizeVerificationCondition(
|
|
107
|
+
node: Node,
|
|
108
|
+
type: "precondition" | "postcondition"
|
|
109
|
+
): VerificationCondition | null;
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Optional: Provide custom TLA+ invariants specific to this domain
|
|
113
|
+
*
|
|
114
|
+
* @example
|
|
115
|
+
* // Actor adapter might add:
|
|
116
|
+
* ["ActorMailboxBounded", "\\A actor \\in Actors : Len(mailbox[actor]) <= MaxMailboxSize"]
|
|
117
|
+
*/
|
|
118
|
+
customInvariants?(): Array<[name: string, tlaExpression: string]>;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// ─────────────────────────────────────────────────────────────────
|
|
122
|
+
// Helper: Base Adapter Class
|
|
123
|
+
// ─────────────────────────────────────────────────────────────────
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Base class providing common extraction logic that adapters can extend.
|
|
127
|
+
* This reduces boilerplate in adapter implementations.
|
|
128
|
+
*/
|
|
129
|
+
export abstract class BaseRoutingAdapter<TConfig extends AdapterConfig = AdapterConfig>
|
|
130
|
+
implements RoutingAdapter<TConfig>
|
|
131
|
+
{
|
|
132
|
+
abstract readonly name: string;
|
|
133
|
+
abstract readonly config: TConfig;
|
|
134
|
+
|
|
135
|
+
abstract extractModel(): CoreVerificationModel;
|
|
136
|
+
abstract recognizeMessageHandler(node: Node): MessageHandler | null;
|
|
137
|
+
abstract recognizeStateUpdate(node: Node): StateAssignment | null;
|
|
138
|
+
abstract recognizeVerificationCondition(
|
|
139
|
+
node: Node,
|
|
140
|
+
type: "precondition" | "postcondition"
|
|
141
|
+
): VerificationCondition | null;
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Common pattern: Extract verification conditions from requires()/ensures() calls
|
|
145
|
+
*
|
|
146
|
+
* Subclasses can use this helper to avoid duplicating condition extraction logic.
|
|
147
|
+
*/
|
|
148
|
+
protected extractConditionFromCall(
|
|
149
|
+
callNode: Node,
|
|
150
|
+
expectedFunctionName: string
|
|
151
|
+
): VerificationCondition | null {
|
|
152
|
+
// Shared implementation for requires()/ensures() extraction
|
|
153
|
+
// This will be implemented when we refactor the existing handler extraction
|
|
154
|
+
return null;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Common pattern: Extract state assignments from binary expressions
|
|
159
|
+
*/
|
|
160
|
+
protected extractAssignmentFromBinaryExpr(binaryNode: Node): StateAssignment | null {
|
|
161
|
+
// Shared implementation for state.field = value extraction
|
|
162
|
+
return null;
|
|
163
|
+
}
|
|
164
|
+
}
|