@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.
Files changed (126) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +188 -2
  3. package/bin/chippy.mjs +134 -0
  4. package/bin/pack.mjs +184 -0
  5. package/lib/avalanche.js +2570 -0
  6. package/lib/avalanche.js.map +7 -0
  7. package/lib/bootstrap.d.ts +1 -0
  8. package/lib/bootstrap.js +51 -0
  9. package/lib/bootstrap.js.map +7 -0
  10. package/lib/browser.js +15 -0
  11. package/lib/browser.js.map +7 -0
  12. package/lib/extension/avalanche.es.js +5396 -0
  13. package/lib/extension/avalanche.es.js.map +1 -0
  14. package/lib/extension/chippy-page-bridge.js +1833 -0
  15. package/lib/extension/inspect-react.js +216 -0
  16. package/lib/extension/layout-lab.js +1453 -0
  17. package/lib/extension/panel-dom.js +90 -0
  18. package/lib/extension/resolve-probes.js +342 -0
  19. package/lib/mcp-skill/LICENSE +201 -0
  20. package/lib/mcp-skill/README.md +150 -0
  21. package/lib/mcp-skill/SKILL.md +330 -0
  22. package/lib/mcp-skill/browser-scripts/playwright-probes.js +368 -0
  23. package/lib/mcp-skill/browser-scripts/playwright-session.js +114 -0
  24. package/lib/mcp-skill/extension/avalanche.es.js +5396 -0
  25. package/lib/mcp-skill/extension/avalanche.es.js.map +1 -0
  26. package/lib/mcp-skill/extension/avalanche.iife.js +5397 -0
  27. package/lib/mcp-skill/extension/avalanche.iife.js.map +1 -0
  28. package/lib/mcp-skill/extension/background.js +323 -0
  29. package/lib/mcp-skill/extension/chippy-page-bridge.js +1833 -0
  30. package/lib/mcp-skill/extension/content-script.js +167 -0
  31. package/lib/mcp-skill/extension/devtools-hook-shim.js +68 -0
  32. package/lib/mcp-skill/extension/early-bootstrap.js +47 -0
  33. package/lib/mcp-skill/extension/icon-128.png +0 -0
  34. package/lib/mcp-skill/extension/icon-16.png +0 -0
  35. package/lib/mcp-skill/extension/icon-32.png +0 -0
  36. package/lib/mcp-skill/extension/icon-48.png +0 -0
  37. package/lib/mcp-skill/extension/inspect-react.js +216 -0
  38. package/lib/mcp-skill/extension/layout-lab.js +1453 -0
  39. package/lib/mcp-skill/extension/logo.svg +14 -0
  40. package/lib/mcp-skill/extension/manifest.json +69 -0
  41. package/lib/mcp-skill/extension/panel-dom.js +90 -0
  42. package/lib/mcp-skill/extension/panel-settings.js +191 -0
  43. package/lib/mcp-skill/extension/popup.html +41 -0
  44. package/lib/mcp-skill/extension/popup.js +80 -0
  45. package/lib/mcp-skill/extension/probe-descriptor.js +241 -0
  46. package/lib/mcp-skill/extension/resolve-probes.js +342 -0
  47. package/lib/mcp-skill/package.json +1 -0
  48. package/lib/mcp-skill/references/README.md +56 -0
  49. package/lib/mcp-skill/references/active-stimulus.md +85 -0
  50. package/lib/mcp-skill/references/avalanche-detector.md +731 -0
  51. package/lib/mcp-skill/references/bdd-router.md +310 -0
  52. package/lib/mcp-skill/references/browser-runtime-api.md +193 -0
  53. package/lib/mcp-skill/references/command-output-formats.md +1075 -0
  54. package/lib/mcp-skill/references/command-surface.md +183 -0
  55. package/lib/mcp-skill/references/cynefin.md +99 -0
  56. package/lib/mcp-skill/references/debug-hook.md +161 -0
  57. package/lib/mcp-skill/references/fixing-performance.md +490 -0
  58. package/lib/mcp-skill/references/hook-metrics.md +199 -0
  59. package/lib/mcp-skill/references/hooks-inspection.md +61 -0
  60. package/lib/mcp-skill/references/jira-taxonomy.md +81 -0
  61. package/lib/mcp-skill/references/mcp.md +122 -0
  62. package/lib/mcp-skill/references/mode-a-injection.md +68 -0
  63. package/lib/mcp-skill/references/operating-model.md +128 -0
  64. package/lib/mcp-skill/references/playwright-cli-setup.md +105 -0
  65. package/lib/mcp-skill/references/playwright-probes.md +205 -0
  66. package/lib/mcp-skill/references/procedures.md +545 -0
  67. package/lib/mcp-skill/references/recipes.txt +114 -0
  68. package/lib/mcp-skill/references/stability-render.md +428 -0
  69. package/lib/mcp-skill/references/test-mode-playbook.md +193 -0
  70. package/lib/mcp-skill/references/troubleshooting.md +54 -0
  71. package/lib/mcp-skill/scripts/avalanche-analyze.cjs +495 -0
  72. package/lib/mcp-skill/scripts/build-avalanche-command.js +34 -0
  73. package/lib/mcp-skill/scripts/build-fiber-state-command.js +19 -0
  74. package/lib/mcp-skill/scripts/chippy-helper-server.js +1710 -0
  75. package/lib/mcp-skill/scripts/chippy-mcp.cjs +273 -0
  76. package/lib/mcp-skill/scripts/chippy.sh +1218 -0
  77. package/lib/mcp-skill/scripts/format-probe-result.js +34 -0
  78. package/lib/mcp-skill/scripts/helper-access.js +144 -0
  79. package/lib/mcp-skill/scripts/probe-annotation-channel.js +116 -0
  80. package/lib/mcp-skill/scripts/search-recipes.js +248 -0
  81. package/lib/mcp-skill/snippets/README.md +89 -0
  82. package/lib/mcp-skill/snippets/count-context-consumers.js +40 -0
  83. package/lib/mcp-skill/snippets/find-context-providers.js +38 -0
  84. package/lib/mcp-skill/snippets/find-legacy-context.js +47 -0
  85. package/lib/mcp-skill/snippets/find-prop.js +83 -0
  86. package/lib/mcp-skill/snippets/hook-metrics-sample.js +69 -0
  87. package/lib/mcp-skill/snippets/hook-metrics.js +60 -0
  88. package/lib/mcp-skill/snippets/hook-tracker.js +198 -0
  89. package/lib/mcp-skill/snippets/stability-nudge.js +101 -0
  90. package/lib/package.json +1 -0
  91. package/lib/plugin.js +119 -0
  92. package/lib/plugin.js.map +7 -0
  93. package/lib/storybook/avalanche-panel-model.js +79 -0
  94. package/lib/storybook/brand.jsx +6 -0
  95. package/lib/storybook/connection-fallback.jsx +47 -0
  96. package/lib/storybook/constants.js +15 -0
  97. package/lib/storybook/context-card.jsx +171 -0
  98. package/lib/storybook/manager.jsx +403 -0
  99. package/lib/storybook/preset.js +7 -0
  100. package/lib/storybook/preview.js +263 -0
  101. package/lib/storybook/probe-annotation-editor.jsx +52 -0
  102. package/lib/storybook/probe-intent.js +23 -0
  103. package/lib/storybook/setup.js +93 -0
  104. package/lib/types/avalanche/commit-metrics-adapter.d.ts +76 -0
  105. package/lib/types/avalanche/commit-stats-indices.d.ts +41 -0
  106. package/lib/types/avalanche/commit-surface-ownership.d.ts +9 -0
  107. package/lib/types/avalanche/detector.d.ts +183 -0
  108. package/lib/types/avalanche/interaction-capture.d.ts +25 -0
  109. package/lib/types/avalanche/internals.d.ts +189 -0
  110. package/lib/types/avalanche/report-serializer.d.ts +283 -0
  111. package/lib/types/avalanche/reporter.d.ts +610 -0
  112. package/lib/types/chippy-bridge/fiber-source.d.ts +37 -0
  113. package/lib/types/chippy-bridge/react-renderer.d.ts +49 -0
  114. package/lib/types/chippy-bridge/source-map.d.ts +30 -0
  115. package/lib/types/debug-render/core.d.ts +72 -0
  116. package/lib/types/layout-lab/fiber-boundaries.d.ts +51 -0
  117. package/lib/types/layout-lab/fiber-walk.d.ts +131 -0
  118. package/lib/types/layout-lab/marker-context.d.ts +94 -0
  119. package/lib/types/package/avalanche.d.ts +6 -0
  120. package/lib/types/package/browser.d.ts +10 -0
  121. package/lib/types/package/plugin.d.ts +15 -0
  122. package/lib/types/plugins/atl/commit-metrics-adapter.d.ts +65 -0
  123. package/lib/types/plugins/atl/metrics-slot.d.ts +37 -0
  124. package/lib/types/plugins/index.d.ts +49 -0
  125. package/lib/types/plugins/jira/context-provider.d.ts +36 -0
  126. 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;