@atlassian/chippy 0.0.0-stage → 0.0.1-beta.1
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/LICENSE +201 -0
- package/README.md +188 -2
- package/bin/chippy.mjs +134 -0
- package/bin/pack.mjs +184 -0
- package/lib/avalanche.js +2570 -0
- package/lib/avalanche.js.map +7 -0
- package/lib/bootstrap.d.ts +1 -0
- package/lib/bootstrap.js +51 -0
- package/lib/bootstrap.js.map +7 -0
- package/lib/browser.js +15 -0
- package/lib/browser.js.map +7 -0
- package/lib/extension/avalanche.es.js +5396 -0
- package/lib/extension/avalanche.es.js.map +1 -0
- package/lib/extension/chippy-page-bridge.js +1833 -0
- package/lib/extension/inspect-react.js +216 -0
- package/lib/extension/layout-lab.js +1453 -0
- package/lib/extension/panel-dom.js +90 -0
- package/lib/extension/resolve-probes.js +342 -0
- package/lib/mcp-skill/LICENSE +201 -0
- package/lib/mcp-skill/README.md +150 -0
- package/lib/mcp-skill/SKILL.md +330 -0
- package/lib/mcp-skill/browser-scripts/playwright-probes.js +368 -0
- package/lib/mcp-skill/browser-scripts/playwright-session.js +114 -0
- package/lib/mcp-skill/extension/avalanche.es.js +5396 -0
- package/lib/mcp-skill/extension/avalanche.es.js.map +1 -0
- package/lib/mcp-skill/extension/avalanche.iife.js +5397 -0
- package/lib/mcp-skill/extension/avalanche.iife.js.map +1 -0
- package/lib/mcp-skill/extension/background.js +323 -0
- package/lib/mcp-skill/extension/chippy-page-bridge.js +1833 -0
- package/lib/mcp-skill/extension/content-script.js +167 -0
- package/lib/mcp-skill/extension/devtools-hook-shim.js +68 -0
- package/lib/mcp-skill/extension/early-bootstrap.js +47 -0
- package/lib/mcp-skill/extension/icon-128.png +0 -0
- package/lib/mcp-skill/extension/icon-16.png +0 -0
- package/lib/mcp-skill/extension/icon-32.png +0 -0
- package/lib/mcp-skill/extension/icon-48.png +0 -0
- package/lib/mcp-skill/extension/inspect-react.js +216 -0
- package/lib/mcp-skill/extension/layout-lab.js +1453 -0
- package/lib/mcp-skill/extension/logo.svg +14 -0
- package/lib/mcp-skill/extension/manifest.json +69 -0
- package/lib/mcp-skill/extension/panel-dom.js +90 -0
- package/lib/mcp-skill/extension/panel-settings.js +191 -0
- package/lib/mcp-skill/extension/popup.html +41 -0
- package/lib/mcp-skill/extension/popup.js +80 -0
- package/lib/mcp-skill/extension/probe-descriptor.js +241 -0
- package/lib/mcp-skill/extension/resolve-probes.js +342 -0
- package/lib/mcp-skill/package.json +1 -0
- package/lib/mcp-skill/references/README.md +56 -0
- package/lib/mcp-skill/references/active-stimulus.md +85 -0
- package/lib/mcp-skill/references/avalanche-detector.md +731 -0
- package/lib/mcp-skill/references/bdd-router.md +310 -0
- package/lib/mcp-skill/references/browser-runtime-api.md +193 -0
- package/lib/mcp-skill/references/command-output-formats.md +1075 -0
- package/lib/mcp-skill/references/command-surface.md +183 -0
- package/lib/mcp-skill/references/cynefin.md +99 -0
- package/lib/mcp-skill/references/debug-hook.md +161 -0
- package/lib/mcp-skill/references/fixing-performance.md +490 -0
- package/lib/mcp-skill/references/hook-metrics.md +199 -0
- package/lib/mcp-skill/references/hooks-inspection.md +61 -0
- package/lib/mcp-skill/references/jira-taxonomy.md +81 -0
- package/lib/mcp-skill/references/mcp.md +122 -0
- package/lib/mcp-skill/references/mode-a-injection.md +68 -0
- package/lib/mcp-skill/references/operating-model.md +128 -0
- package/lib/mcp-skill/references/playwright-cli-setup.md +105 -0
- package/lib/mcp-skill/references/playwright-probes.md +205 -0
- package/lib/mcp-skill/references/procedures.md +545 -0
- package/lib/mcp-skill/references/recipes.txt +114 -0
- package/lib/mcp-skill/references/stability-render.md +428 -0
- package/lib/mcp-skill/references/test-mode-playbook.md +193 -0
- package/lib/mcp-skill/references/troubleshooting.md +54 -0
- package/lib/mcp-skill/scripts/avalanche-analyze.cjs +495 -0
- package/lib/mcp-skill/scripts/build-avalanche-command.js +34 -0
- package/lib/mcp-skill/scripts/build-fiber-state-command.js +19 -0
- package/lib/mcp-skill/scripts/chippy-helper-server.js +1710 -0
- package/lib/mcp-skill/scripts/chippy-mcp.cjs +273 -0
- package/lib/mcp-skill/scripts/chippy.sh +1218 -0
- package/lib/mcp-skill/scripts/format-probe-result.js +34 -0
- package/lib/mcp-skill/scripts/helper-access.js +144 -0
- package/lib/mcp-skill/scripts/probe-annotation-channel.js +116 -0
- package/lib/mcp-skill/scripts/search-recipes.js +248 -0
- package/lib/mcp-skill/snippets/README.md +89 -0
- package/lib/mcp-skill/snippets/count-context-consumers.js +40 -0
- package/lib/mcp-skill/snippets/find-context-providers.js +38 -0
- package/lib/mcp-skill/snippets/find-legacy-context.js +47 -0
- package/lib/mcp-skill/snippets/find-prop.js +83 -0
- package/lib/mcp-skill/snippets/hook-metrics-sample.js +69 -0
- package/lib/mcp-skill/snippets/hook-metrics.js +60 -0
- package/lib/mcp-skill/snippets/hook-tracker.js +198 -0
- package/lib/mcp-skill/snippets/stability-nudge.js +101 -0
- package/lib/package.json +1 -0
- package/lib/plugin.js +119 -0
- package/lib/plugin.js.map +7 -0
- package/lib/storybook/avalanche-panel-model.js +79 -0
- package/lib/storybook/brand.jsx +6 -0
- package/lib/storybook/connection-fallback.jsx +47 -0
- package/lib/storybook/constants.js +15 -0
- package/lib/storybook/context-card.jsx +171 -0
- package/lib/storybook/manager.jsx +403 -0
- package/lib/storybook/preset.js +7 -0
- package/lib/storybook/preview.js +263 -0
- package/lib/storybook/probe-annotation-editor.jsx +52 -0
- package/lib/storybook/probe-intent.js +23 -0
- package/lib/storybook/setup.js +93 -0
- package/lib/types/avalanche/commit-metrics-adapter.d.ts +76 -0
- package/lib/types/avalanche/commit-stats-indices.d.ts +41 -0
- package/lib/types/avalanche/commit-surface-ownership.d.ts +9 -0
- package/lib/types/avalanche/detector.d.ts +183 -0
- package/lib/types/avalanche/interaction-capture.d.ts +25 -0
- package/lib/types/avalanche/internals.d.ts +189 -0
- package/lib/types/avalanche/report-serializer.d.ts +283 -0
- package/lib/types/avalanche/reporter.d.ts +610 -0
- package/lib/types/chippy-bridge/fiber-source.d.ts +37 -0
- package/lib/types/chippy-bridge/react-renderer.d.ts +49 -0
- package/lib/types/chippy-bridge/source-map.d.ts +30 -0
- package/lib/types/debug-render/core.d.ts +72 -0
- package/lib/types/layout-lab/fiber-boundaries.d.ts +51 -0
- package/lib/types/layout-lab/fiber-walk.d.ts +131 -0
- package/lib/types/layout-lab/marker-context.d.ts +94 -0
- package/lib/types/package/avalanche.d.ts +6 -0
- package/lib/types/package/browser.d.ts +10 -0
- package/lib/types/package/plugin.d.ts +15 -0
- package/lib/types/plugins/atl/commit-metrics-adapter.d.ts +65 -0
- package/lib/types/plugins/atl/metrics-slot.d.ts +37 -0
- package/lib/types/plugins/index.d.ts +49 -0
- package/lib/types/plugins/jira/context-provider.d.ts +36 -0
- package/package.json +104 -4
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
export type ComponentType = Function | symbol | {
|
|
2
|
+
$$typeof?: symbol;
|
|
3
|
+
render?: Function;
|
|
4
|
+
displayName?: string;
|
|
5
|
+
name?: string;
|
|
6
|
+
};
|
|
7
|
+
interface StoreCheck {
|
|
8
|
+
getSnapshot: () => unknown;
|
|
9
|
+
value: unknown;
|
|
10
|
+
}
|
|
11
|
+
export interface Fiber {
|
|
12
|
+
tag: number;
|
|
13
|
+
type: ComponentType;
|
|
14
|
+
alternate: Fiber | null;
|
|
15
|
+
return: Fiber | null;
|
|
16
|
+
child: Fiber | null;
|
|
17
|
+
sibling: Fiber | null;
|
|
18
|
+
flags: number;
|
|
19
|
+
subtreeFlags: number;
|
|
20
|
+
lanes: number;
|
|
21
|
+
memoizedState: Hook | null;
|
|
22
|
+
memoizedProps?: unknown;
|
|
23
|
+
pendingProps?: unknown;
|
|
24
|
+
updateQueue: {
|
|
25
|
+
stores: StoreCheck[] | null;
|
|
26
|
+
} | null;
|
|
27
|
+
/**
|
|
28
|
+
* React populates this array during the render phase with fibers that will be
|
|
29
|
+
* deleted in the commit phase. Present when subtreeFlags & ChildDeletion !== 0.
|
|
30
|
+
* Only available in React 18+ (replaces the older effectList pattern).
|
|
31
|
+
*/
|
|
32
|
+
deletions?: Fiber[] | null;
|
|
33
|
+
elementType?: unknown;
|
|
34
|
+
_debugSource?: {
|
|
35
|
+
fileName: string;
|
|
36
|
+
lineNumber: number;
|
|
37
|
+
};
|
|
38
|
+
_debugStack?: unknown;
|
|
39
|
+
_debugHookTypes?: string[];
|
|
40
|
+
}
|
|
41
|
+
export interface Hook {
|
|
42
|
+
memoizedState: unknown;
|
|
43
|
+
baseState: unknown;
|
|
44
|
+
baseQueue: unknown;
|
|
45
|
+
queue: HookQueue | null;
|
|
46
|
+
next: Hook | null;
|
|
47
|
+
}
|
|
48
|
+
interface HookQueue {
|
|
49
|
+
dispatch?: Function;
|
|
50
|
+
value?: unknown;
|
|
51
|
+
getSnapshot?: Function;
|
|
52
|
+
lastRenderedState?: unknown;
|
|
53
|
+
}
|
|
54
|
+
export interface DepOrigin {
|
|
55
|
+
type: ComponentType;
|
|
56
|
+
hookIndex: number;
|
|
57
|
+
depth: number;
|
|
58
|
+
hookType: 'useCallback' | 'useMemo';
|
|
59
|
+
}
|
|
60
|
+
export interface ThrashInfo {
|
|
61
|
+
hookIndex: number;
|
|
62
|
+
hookType: 'effect' | 'callback' | 'memo';
|
|
63
|
+
deps: unknown[];
|
|
64
|
+
changedDepIndices: number[];
|
|
65
|
+
changedDepOrigins: (DepOrigin | null)[];
|
|
66
|
+
effectTag?: number;
|
|
67
|
+
memoValue?: unknown;
|
|
68
|
+
/** The hook body function (for useCallback) or memoized value (for useMemo) */
|
|
69
|
+
hookBody?: Function | unknown;
|
|
70
|
+
}
|
|
71
|
+
export type ChangedHook = {
|
|
72
|
+
prevValue: unknown;
|
|
73
|
+
currentValue: unknown;
|
|
74
|
+
info?: string;
|
|
75
|
+
} | 'repeat';
|
|
76
|
+
export interface StateChangeResult {
|
|
77
|
+
hasChange: boolean;
|
|
78
|
+
actionable: boolean;
|
|
79
|
+
changedIndices: number[];
|
|
80
|
+
changedHooks: ChangedHook[];
|
|
81
|
+
/** True if any of the changes came from useSyncExternalStore */
|
|
82
|
+
hasExternalStoreChange: boolean;
|
|
83
|
+
}
|
|
84
|
+
export interface ThrashingResult {
|
|
85
|
+
effects: ThrashInfo[];
|
|
86
|
+
callbacks: ThrashInfo[];
|
|
87
|
+
memos: ThrashInfo[];
|
|
88
|
+
}
|
|
89
|
+
export declare const PerformedWork = 1;
|
|
90
|
+
export declare const Placement = 2;
|
|
91
|
+
export declare const Hydrating = 4096;
|
|
92
|
+
export declare const SuspenseTag = 13;
|
|
93
|
+
export declare const ChildDeletion = 16;
|
|
94
|
+
export declare const Update = 4;
|
|
95
|
+
export declare const DidCapture = 128;
|
|
96
|
+
export declare function isComponentFiber(tag: number): boolean;
|
|
97
|
+
export declare function isContextProviderFiber(tag: number): boolean;
|
|
98
|
+
export declare function isSuspenseFiber(tag: number): boolean;
|
|
99
|
+
/**
|
|
100
|
+
* Detect whether a Suspense boundary transitioned between suspended/unsuspended states.
|
|
101
|
+
*
|
|
102
|
+
* Suspense memoizedState is:
|
|
103
|
+
* null → primary content is showing (not suspended)
|
|
104
|
+
* non-null (object) → boundary is showing the fallback (suspended/dehydrated)
|
|
105
|
+
*
|
|
106
|
+
* Returns:
|
|
107
|
+
* { entered: true } — boundary just entered fallback
|
|
108
|
+
* - null → non-null (update path)
|
|
109
|
+
* - no alternate + memoizedState non-null (first render directly to fallback)
|
|
110
|
+
* { left: true } — boundary just left fallback / revealed primary (non-null → null)
|
|
111
|
+
* null — no state change (both null, both non-null, or first render not suspended)
|
|
112
|
+
*
|
|
113
|
+
* A Suspense that renders without delay never enters fallback, so memoizedState stays
|
|
114
|
+
* null → returns null → correctly ignored by the detector.
|
|
115
|
+
*/
|
|
116
|
+
export declare function didSuspenseStateChange(fiber: Fiber): {
|
|
117
|
+
entered: boolean;
|
|
118
|
+
left: boolean;
|
|
119
|
+
} | null;
|
|
120
|
+
/**
|
|
121
|
+
* Check if a Context Provider's value changed.
|
|
122
|
+
*/
|
|
123
|
+
export declare function didContextValueChange(fiber: Fiber): boolean;
|
|
124
|
+
export declare function isReactInternalComponentType(type: ComponentType): boolean;
|
|
125
|
+
export declare function getComponentName(fiber: Fiber): string;
|
|
126
|
+
/**
|
|
127
|
+
* Check if hook is a state hook (useState/useReducer/useSyncExternalStore).
|
|
128
|
+
*
|
|
129
|
+
* All hooks share a base shape. The reliable differentiators:
|
|
130
|
+
* - useState/useReducer: queue.dispatch is a function
|
|
131
|
+
* - useSyncExternalStore: queue has 'value' and 'getSnapshot' properties
|
|
132
|
+
*/
|
|
133
|
+
export declare function isStateHook(hook: Hook): boolean;
|
|
134
|
+
/** True if the hook is a useSyncExternalStore-like hook. */
|
|
135
|
+
export declare function isExternalStoreHook(hook: Hook): boolean;
|
|
136
|
+
/**
|
|
137
|
+
* Compare hook chains to detect state changes.
|
|
138
|
+
*
|
|
139
|
+
* IMPORTANT: Hook indices are React internal memoizedState indices, NOT code order.
|
|
140
|
+
* `useContext` hooks are not in memoizedState, causing index misalignment.
|
|
141
|
+
*/
|
|
142
|
+
export declare function detectHookStateChanges(prevHookChain: Hook | null, currentHookChain: Hook | null): StateChangeResult;
|
|
143
|
+
/**
|
|
144
|
+
* Detect thrashing for hooks with deps: useEffect/useLayoutEffect/useInsertionEffect,
|
|
145
|
+
* useCallback and useMemo.
|
|
146
|
+
*/
|
|
147
|
+
export declare function detectHookThrashing(prevHookChain: Hook | null, currentHookChain: Hook | null, mode?: 'non-primitive' | 'all', valueProvenance?: WeakMap<object | Function, DepOrigin> | null): ThrashingResult;
|
|
148
|
+
export declare function didFiberUpdate(fiber: Fiber): boolean;
|
|
149
|
+
/**
|
|
150
|
+
* Detect if fiber has actionable hook state changes by comparing with fiber.alternate.
|
|
151
|
+
*
|
|
152
|
+
* ┌─────────────────────────────────────────────────────────────────────────────┐
|
|
153
|
+
* │ ⚠️ WARNING: fiber.alternate COMPARISON IS UNRELIABLE │
|
|
154
|
+
* └─────────────────────────────────────────────────────────────────────────────┘
|
|
155
|
+
*
|
|
156
|
+
* This function compares fiber.memoizedState vs fiber.alternate.memoizedState.
|
|
157
|
+
*
|
|
158
|
+
* THE PROBLEM:
|
|
159
|
+
* fiber.alternate is NOT always "state from the previous commit".
|
|
160
|
+
* It's "state from last time this fiber was used as work-in-progress".
|
|
161
|
+
*
|
|
162
|
+
* If a component re-renders due to parent/context changes (not self-update),
|
|
163
|
+
* its alternate may be stale - from 1 commit ago, or 100 commits ago!
|
|
164
|
+
*
|
|
165
|
+
* This causes FALSE POSITIVES: we detect "state changed" when it didn't
|
|
166
|
+
* change in THIS commit - it changed in some PAST commit.
|
|
167
|
+
*
|
|
168
|
+
* WHEN THIS FUNCTION IS RELIABLE:
|
|
169
|
+
* ✓ Component called setState (it IS the initiator)
|
|
170
|
+
* ✓ Component has useSyncExternalStore that just triggered
|
|
171
|
+
* ✓ Used alongside memoizedUpdaters validation
|
|
172
|
+
*
|
|
173
|
+
* WHEN THIS FUNCTION IS UNRELIABLE:
|
|
174
|
+
* ✗ Component re-rendered due to parent update
|
|
175
|
+
* ✗ Component re-rendered due to context change
|
|
176
|
+
* ✗ Component was memoized and skipped N commits
|
|
177
|
+
* ✗ Any scenario where alternate wasn't recently updated
|
|
178
|
+
*
|
|
179
|
+
* RECOMMENDED USAGE:
|
|
180
|
+
* - In development: Use memoizedUpdaters to verify component is an initiator,
|
|
181
|
+
* THEN use this function to get hook change details.
|
|
182
|
+
* - In production: Use lastSeenHookState tracking (see detector.tsx)
|
|
183
|
+
* instead of relying on fiber.alternate.
|
|
184
|
+
*
|
|
185
|
+
* See detector.tsx for the full explanation of the "swap" problem and solution.
|
|
186
|
+
*/
|
|
187
|
+
export declare function didFiberSelfUpdate(fiber: Fiber): StateChangeResult | null;
|
|
188
|
+
export declare function isDevelopment(): boolean;
|
|
189
|
+
export {};
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Report Serializer - Converts Report to serializable DTO.
|
|
3
|
+
*
|
|
4
|
+
* PROBLEM:
|
|
5
|
+
* The Report interface contains non-serializable data (Fiber references, ComponentType functions)
|
|
6
|
+
* which makes it unsuitable for JSON.stringify(), IPC, or network transmission.
|
|
7
|
+
*
|
|
8
|
+
* SOLUTION:
|
|
9
|
+
* Strip non-serializable fields (fiber, type). Keep only what's needed:
|
|
10
|
+
* - sourceId already contains component name (e.g., "MyComponent#1@5")
|
|
11
|
+
* - Metrics and numerical data
|
|
12
|
+
* - No need to convert anything - just omit problematic fields
|
|
13
|
+
*
|
|
14
|
+
* USAGE:
|
|
15
|
+
* ```typescript
|
|
16
|
+
* const report = detector.report(50);
|
|
17
|
+
* const dto = serializeReport(report);
|
|
18
|
+
*
|
|
19
|
+
* // Now safe to serialize
|
|
20
|
+
* const json = JSON.stringify(dto);
|
|
21
|
+
*
|
|
22
|
+
* // Send over IPC/network
|
|
23
|
+
* postMessage({ type: 'report', data: dto });
|
|
24
|
+
* ```
|
|
25
|
+
*
|
|
26
|
+
* DESIGN:
|
|
27
|
+
* - Minimal DTO - only what you need for metrics/analysis
|
|
28
|
+
* - sourceId already has component name - no conversion needed
|
|
29
|
+
* - Drop fiber and type fields completely
|
|
30
|
+
*
|
|
31
|
+
* The serializer is also the trust boundary between page-side React objects
|
|
32
|
+
* and helper/offline consumers. A DTO must remain stable after the page is
|
|
33
|
+
* gone, so it carries evidence and summaries rather than live object identity.
|
|
34
|
+
*/
|
|
35
|
+
import type { CommitMetricsDelta, IntegrationMode } from './commit-metrics-adapter.js';
|
|
36
|
+
/**
|
|
37
|
+
* Commit stats tuple: [collateral, sources, restarts, performedWork, effects, memos, callbacks,
|
|
38
|
+
* contextUpdates, unmountedComponents, unmountedSubtrees]. Mirrors CommitStats in reporter.tsx.
|
|
39
|
+
*/
|
|
40
|
+
export type CommitStatsDTO = [
|
|
41
|
+
collateral: number,
|
|
42
|
+
sources: number,
|
|
43
|
+
restarts: number,
|
|
44
|
+
performedWork: number,
|
|
45
|
+
effects: number,
|
|
46
|
+
memos: number,
|
|
47
|
+
callbacks: number,
|
|
48
|
+
contextUpdates: number,
|
|
49
|
+
unmountedComponents: number,
|
|
50
|
+
unmountedSubtrees: number
|
|
51
|
+
];
|
|
52
|
+
/**
|
|
53
|
+
* Per-commit counter deltas from the commit metrics adapter, keyed by counter
|
|
54
|
+
* name. The counters depend on the adapter (see `meta.metricsAdapter`).
|
|
55
|
+
*/
|
|
56
|
+
export type CommitMetricsDeltaDTO = CommitMetricsDelta;
|
|
57
|
+
/** @deprecated Use CommitMetricsDeltaDTO. Kept for one release. */
|
|
58
|
+
export type ATLCommitDeltaDTO = CommitMetricsDeltaDTO;
|
|
59
|
+
/**
|
|
60
|
+
* Commit timing data - measures React commit duration and detector overhead.
|
|
61
|
+
*/
|
|
62
|
+
export interface CommitTimingDTO {
|
|
63
|
+
timeSinceLastCommit: number;
|
|
64
|
+
detectorOverhead: number;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Report metadata - profiling context and overhead metrics.
|
|
68
|
+
*/
|
|
69
|
+
export interface ReportMetaDTO {
|
|
70
|
+
version: number;
|
|
71
|
+
commits: number;
|
|
72
|
+
config: {
|
|
73
|
+
detectionLevel: 'stats' | 'sources' | 'amplifierMetrics' | 'amplifiers' | 'full';
|
|
74
|
+
effectThrashMode: 'non-primitive' | 'all';
|
|
75
|
+
captureFibers: boolean;
|
|
76
|
+
historySize: number;
|
|
77
|
+
};
|
|
78
|
+
memoizedUpdatersSupport: {
|
|
79
|
+
available: boolean;
|
|
80
|
+
commitsWithData: number;
|
|
81
|
+
coverage: string;
|
|
82
|
+
};
|
|
83
|
+
/** Commit-hook integration model; older reports used `'atl'` for `'adapter:atl'`. */
|
|
84
|
+
integrationMode?: IntegrationMode | 'atl';
|
|
85
|
+
/** Id of the commit metrics adapter that drove the report, or null. */
|
|
86
|
+
metricsAdapter?: string | null;
|
|
87
|
+
/** Per-field availability for commitStats indices and metricsByCommit. */
|
|
88
|
+
dataAvailability?: Record<string, boolean>;
|
|
89
|
+
amplifiersMetrics?: {
|
|
90
|
+
totalHookThrashes: number;
|
|
91
|
+
affectedComponentCount: number;
|
|
92
|
+
};
|
|
93
|
+
timing: {
|
|
94
|
+
totalDetectorOverhead: number;
|
|
95
|
+
avgDetectorOverhead: number;
|
|
96
|
+
totalTimeSpan: number;
|
|
97
|
+
avgTimeBetweenCommits: number;
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Minimal serializable source - just the metrics, no functions/fibers.
|
|
102
|
+
* sourceId already contains component name (e.g., "MyComponent#1@5")
|
|
103
|
+
*/
|
|
104
|
+
export interface SourceDTO {
|
|
105
|
+
sourceId: string;
|
|
106
|
+
depth: number;
|
|
107
|
+
collateralUpdates: number;
|
|
108
|
+
maxCollateralUpdates: number;
|
|
109
|
+
maxPenetrationDepth: number;
|
|
110
|
+
causedUpdates: number;
|
|
111
|
+
restartWaste?: number;
|
|
112
|
+
maxRestartWaste?: number;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Source entry in sourcesByCommit - which sources fired in each commit.
|
|
116
|
+
*/
|
|
117
|
+
export interface SourceByCommitDTO {
|
|
118
|
+
sourceId: string;
|
|
119
|
+
depth: number;
|
|
120
|
+
collateral: number;
|
|
121
|
+
rank: number | null;
|
|
122
|
+
sourceIndex: number | null;
|
|
123
|
+
trashers?: Array<{
|
|
124
|
+
index: number;
|
|
125
|
+
prevValue: unknown;
|
|
126
|
+
currentValue: unknown;
|
|
127
|
+
}>;
|
|
128
|
+
isRepeat?: boolean;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Serializable Report - minimal data for metrics and analysis.
|
|
132
|
+
* All non-serializable fields (fiber, type) are omitted.
|
|
133
|
+
*/
|
|
134
|
+
export interface SuspenseBoundaryEventDTO {
|
|
135
|
+
depth: number;
|
|
136
|
+
entered: boolean;
|
|
137
|
+
left: boolean;
|
|
138
|
+
}
|
|
139
|
+
export interface UnmountSampleDTO {
|
|
140
|
+
name: string;
|
|
141
|
+
key: string | null;
|
|
142
|
+
depth: number | null;
|
|
143
|
+
count: number;
|
|
144
|
+
source?: {
|
|
145
|
+
fileName?: string;
|
|
146
|
+
lineNumber?: number;
|
|
147
|
+
columnNumber?: number;
|
|
148
|
+
} | null;
|
|
149
|
+
}
|
|
150
|
+
export type PropChangeKindDTO = 'same' | 'ref-changed' | 'scalar-changed' | 'added' | 'removed';
|
|
151
|
+
export interface PropValueSummaryDTO {
|
|
152
|
+
type: string;
|
|
153
|
+
isArray: boolean;
|
|
154
|
+
isFunction: boolean;
|
|
155
|
+
isNull: boolean;
|
|
156
|
+
preview: string;
|
|
157
|
+
display?: string;
|
|
158
|
+
length?: number;
|
|
159
|
+
keysTop?: string[];
|
|
160
|
+
sample?: unknown[];
|
|
161
|
+
}
|
|
162
|
+
export interface PropChangeEvidenceDTO {
|
|
163
|
+
name: string;
|
|
164
|
+
kind: PropChangeKindDTO;
|
|
165
|
+
prev: PropValueSummaryDTO;
|
|
166
|
+
current: PropValueSummaryDTO;
|
|
167
|
+
}
|
|
168
|
+
export interface RenderedComponentEvidenceDTO {
|
|
169
|
+
sourceId: string;
|
|
170
|
+
name: string;
|
|
171
|
+
depth: number;
|
|
172
|
+
parentSourceId: string | null;
|
|
173
|
+
ownerSourceId: string | null;
|
|
174
|
+
isSelfSource: boolean;
|
|
175
|
+
propChanges: PropChangeEvidenceDTO[];
|
|
176
|
+
hasPropChanges: boolean;
|
|
177
|
+
trasherCounts: {
|
|
178
|
+
effects: number;
|
|
179
|
+
callbacks: number;
|
|
180
|
+
memos: number;
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
export interface CommitInteractionActionDTO {
|
|
184
|
+
id: number;
|
|
185
|
+
lastCommitId: number;
|
|
186
|
+
deltaTime: number;
|
|
187
|
+
action: string;
|
|
188
|
+
location: {
|
|
189
|
+
dom: {
|
|
190
|
+
tag: string | null;
|
|
191
|
+
text: string;
|
|
192
|
+
nearestTestId: string | null;
|
|
193
|
+
};
|
|
194
|
+
targetFiber: {
|
|
195
|
+
name: string | null;
|
|
196
|
+
key: string | null;
|
|
197
|
+
source: {
|
|
198
|
+
fileName?: string;
|
|
199
|
+
lineNumber?: number;
|
|
200
|
+
columnNumber?: number;
|
|
201
|
+
} | null;
|
|
202
|
+
ownerStackKind: 'owners' | 'parents';
|
|
203
|
+
ownerStack: Array<{
|
|
204
|
+
name: string | null;
|
|
205
|
+
key: string | null;
|
|
206
|
+
props: string[];
|
|
207
|
+
hookCount: number;
|
|
208
|
+
hookCountTruncated: boolean;
|
|
209
|
+
hookCountMax: number;
|
|
210
|
+
source: {
|
|
211
|
+
fileName?: string;
|
|
212
|
+
lineNumber?: number;
|
|
213
|
+
columnNumber?: number;
|
|
214
|
+
} | null;
|
|
215
|
+
}>;
|
|
216
|
+
} | null;
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
export interface ReportDTO {
|
|
220
|
+
meta: ReportMetaDTO;
|
|
221
|
+
sources: SourceDTO[];
|
|
222
|
+
commitStats: Record<number, CommitStatsDTO>;
|
|
223
|
+
suspenseByCommit: Record<number, SuspenseBoundaryEventDTO[]>;
|
|
224
|
+
sourcesByCommit?: Record<number, SourceByCommitDTO[]>;
|
|
225
|
+
interactionsByCommit?: Record<number, CommitInteractionActionDTO[]>;
|
|
226
|
+
renderedByCommit?: Record<number, RenderedComponentEvidenceDTO[]>;
|
|
227
|
+
metricsByCommit?: Record<number, CommitMetricsDeltaDTO>;
|
|
228
|
+
/** @deprecated Alias of `metricsByCommit`, kept for one release. */
|
|
229
|
+
atlByCommit?: Record<number, CommitMetricsDeltaDTO>;
|
|
230
|
+
timing?: Record<number, CommitTimingDTO>;
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Convert Report to serializable DTO.
|
|
234
|
+
*
|
|
235
|
+
* Strips non-serializable fields (fiber, type) and keeps only essential metrics.
|
|
236
|
+
*
|
|
237
|
+
* @param report - Full Report from detector.report()
|
|
238
|
+
* @returns Minimal serializable ReportDTO safe for JSON.stringify()
|
|
239
|
+
*/
|
|
240
|
+
export declare function serializeReport(report: {
|
|
241
|
+
meta: ReportMetaDTO;
|
|
242
|
+
sources: Array<{
|
|
243
|
+
sourceId: string;
|
|
244
|
+
depth: number;
|
|
245
|
+
causedUpdates: number;
|
|
246
|
+
collateralUpdates: number;
|
|
247
|
+
maxCollateralUpdates: number;
|
|
248
|
+
maxPenetrationDepth: number;
|
|
249
|
+
restartWaste?: number;
|
|
250
|
+
maxRestartWaste?: number;
|
|
251
|
+
}>;
|
|
252
|
+
commitStats: Record<number, CommitStatsDTO>;
|
|
253
|
+
sourcesByCommit?: Record<number, Array<{
|
|
254
|
+
sourceId: string;
|
|
255
|
+
depth: number;
|
|
256
|
+
collateral: number;
|
|
257
|
+
rank: number | null;
|
|
258
|
+
sourceIndex: number | null;
|
|
259
|
+
hooks?: Array<{
|
|
260
|
+
index: number;
|
|
261
|
+
prevValue: unknown;
|
|
262
|
+
currentValue: unknown;
|
|
263
|
+
}>;
|
|
264
|
+
trashers?: Array<{
|
|
265
|
+
index: number;
|
|
266
|
+
prevValue: unknown;
|
|
267
|
+
currentValue: unknown;
|
|
268
|
+
}>;
|
|
269
|
+
isRepeat?: boolean;
|
|
270
|
+
}>>;
|
|
271
|
+
suspenseByCommit?: Record<number, Array<{
|
|
272
|
+
depth: number;
|
|
273
|
+
entered: boolean;
|
|
274
|
+
left: boolean;
|
|
275
|
+
fiber?: unknown;
|
|
276
|
+
}>>;
|
|
277
|
+
interactionsByCommit?: Record<number, CommitInteractionActionDTO[]>;
|
|
278
|
+
renderedByCommit?: Record<number, RenderedComponentEvidenceDTO[]>;
|
|
279
|
+
metricsByCommit?: Record<number, CommitMetricsDeltaDTO>;
|
|
280
|
+
/** @deprecated Alias of `metricsByCommit`, kept for one release. */
|
|
281
|
+
atlByCommit?: Record<number, CommitMetricsDeltaDTO>;
|
|
282
|
+
timing?: Record<number, CommitTimingDTO>;
|
|
283
|
+
}): ReportDTO;
|