@atlassian/chippy 0.0.1-beta.1 → 0.0.1-beta.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.
- package/README.md +142 -54
- package/bin/chippy.mjs +53 -95
- package/bin/pack.mjs +20 -0
- package/bin/skill-dir.mjs +15 -0
- package/lib/avalanche.js +54 -23
- package/lib/avalanche.js.map +2 -2
- package/lib/bootstrap.js +20 -1
- package/lib/bootstrap.js.map +3 -3
- package/lib/extension/avalanche.es.js +173 -34
- package/lib/extension/avalanche.es.js.map +1 -1
- package/lib/extension/chippy-page-bridge.js +164 -44
- package/lib/mcp-skill/README.md +2 -4
- package/lib/mcp-skill/SKILL.md +21 -16
- package/lib/mcp-skill/extension/armed-reload-startup.js +83 -0
- package/lib/mcp-skill/extension/avalanche.es.js +173 -34
- package/lib/mcp-skill/extension/avalanche.es.js.map +1 -1
- package/lib/mcp-skill/extension/avalanche.iife.js +173 -34
- package/lib/mcp-skill/extension/avalanche.iife.js.map +1 -1
- package/lib/mcp-skill/extension/background.js +2 -0
- package/lib/mcp-skill/extension/chippy-page-bridge.js +164 -44
- package/lib/mcp-skill/extension/content-script.js +23 -0
- package/lib/mcp-skill/extension/devtools-hook-shim.js +18 -1
- package/lib/mcp-skill/extension/early-bootstrap.js +3 -1
- package/lib/mcp-skill/extension/manifest.json +1 -1
- package/lib/mcp-skill/extension/panel-settings.js +2 -20
- package/lib/mcp-skill/extension/startup-handoff.js +30 -0
- package/lib/mcp-skill/references/README.md +2 -2
- package/lib/mcp-skill/references/avalanche-detector.md +3 -3
- package/lib/mcp-skill/references/browser-runtime-api.md +4 -4
- package/lib/mcp-skill/references/command-output-formats.md +12 -2
- package/lib/mcp-skill/references/command-surface.md +6 -6
- package/lib/mcp-skill/references/mode-a-injection.md +43 -9
- package/lib/mcp-skill/references/playwright-cli-setup.md +5 -5
- package/lib/mcp-skill/references/playwright-probes.md +1 -1
- package/lib/mcp-skill/references/recipes.txt +1 -1
- package/lib/mcp-skill/references/stability-render.md +4 -4
- package/lib/mcp-skill/references/test-mode-playbook.md +2 -1
- package/lib/mcp-skill/references/troubleshooting.md +6 -1
- package/lib/mcp-skill/scripts/chippy-helper-server.js +116 -58
- package/lib/mcp-skill/scripts/chippy.sh +41 -7
- package/lib/mcp-skill/scripts/helper-access.js +20 -6
- package/lib/mcp-skill/scripts/helper-proxy.js +87 -0
- package/lib/mcp-skill/scripts/page-socket-trust.js +81 -0
- package/lib/plugin.js.map +2 -2
- package/lib/storybook/connection-fallback.jsx +1 -1
- package/lib/storybook/manager-owner.js +42 -0
- package/lib/storybook/manager.jsx +22 -0
- package/lib/storybook/preview.js +53 -18
- package/lib/storybook/setup.js +15 -4
- package/lib/types/chippy-bridge/fiber-source.d.ts +14 -3
- package/lib/types/chippy-bridge/react-renderer.d.ts +30 -5
- package/lib/types/chippy-bridge/recorded-source.d.ts +44 -0
- package/lib/types/debug-render/core.d.ts +6 -0
- package/package.json +3 -1
|
@@ -34,7 +34,7 @@ Important behavior:
|
|
|
34
34
|
- extension-owned pages initially render one small bottom-corner Chippy launcher; expanding it reveals compact `P1 — drag to source` / `P2 — drag to source` rows that serve as each probe's dock and detail surface
|
|
35
35
|
- dragging a probe does not collapse the panel; an undocked probe uses document coordinates and stays anchored to its target while the page scrolls
|
|
36
36
|
- the extension toolbar popup contains only Enable and Disable for the current origin; helper and proxy configuration stay in the in-page panel
|
|
37
|
-
- extension-owned panels expose the helper URL and
|
|
37
|
+
- extension-owned panels expose the helper URL and plugin settings behind the gear; the isolated content script mounts the form in a closed shadow root, with no iframe and no page access to extension storage
|
|
38
38
|
- Storybook host-panel mode keeps a standalone dock in the preview frame because probe details live in the manager frame
|
|
39
39
|
- docked probes are inactive
|
|
40
40
|
- while dragging:
|
|
@@ -66,7 +66,7 @@ The helper must be a real local process reachable by the user's browser. The age
|
|
|
66
66
|
|
|
67
67
|
`contextUiEnabled` defaults to `true`. It controls only context-provider cards in the active probe UI, including Storybook marker cards; generic probe resolution and snapshots continue when it is false.
|
|
68
68
|
|
|
69
|
-
Source reads are cross-version. React <=18 locations come from `_debugSource
|
|
69
|
+
Source reads are cross-version. React <=18 locations come from `_debugSource`; when the module the page loaded for that file carries a source map, its recorded literal is mapped back to correct lines shifted by an earlier transform. React 19 locations start at `_debugStack`, skip dependency frames, and resolve the served module through its inline or external Source Map v3 payload. Snapshot publication is immediate and may be followed by a `<reason>-source-resolved` snapshot when the authored position differs; `find-fibers`, `describe-component`, and `explain-component` await the mapped position.
|
|
70
70
|
|
|
71
71
|
`integration.kind` is `extension`, `import`, or `storybook`. `who` names the host that established Chippy and `source` points to its real setup source file. Import integrations report `reinjectsOnReload: false`; a full reload/navigation requires the user or automation to run the import again.
|
|
72
72
|
|
|
@@ -83,10 +83,10 @@ The Avalanche panel installs and refreshes capture state while selected. It grou
|
|
|
83
83
|
When either panel is `failed` or `reconnecting`, it may offer:
|
|
84
84
|
|
|
85
85
|
```bash
|
|
86
|
-
npx
|
|
86
|
+
npx skills add atlassian-labs/chippy --skill chippy -g
|
|
87
87
|
```
|
|
88
88
|
|
|
89
|
-
That command installs Chippy when it is absent. It does not start or verify the helper; the agent still follows [troubleshooting](troubleshooting.md) and runs the helper checks.
|
|
89
|
+
That command installs the Chippy skill with the skills CLI when it is absent. It does not start or verify the helper; the agent still follows [troubleshooting](troubleshooting.md) and runs the helper checks.
|
|
90
90
|
|
|
91
91
|
## `window.__CHIPPY.resolveProbes` / `window.__CHIPPY.resolveProbesCompact`
|
|
92
92
|
|
|
@@ -53,10 +53,11 @@ Fields: `ok` (bool), `now` (ISO 8601 timestamp).
|
|
|
53
53
|
|
|
54
54
|
## `inject-url`
|
|
55
55
|
|
|
56
|
-
Prints a lifecycle warning to stderr:
|
|
56
|
+
Prints a lifecycle warning and the second required asset to stderr:
|
|
57
57
|
|
|
58
58
|
```text
|
|
59
59
|
Import integration is document-scoped: a full reload/navigation removes Chippy and requires the user or automation to inject it again.
|
|
60
|
+
The classic inject.js installs Chippy only; load http://127.0.0.1:7823/__chippy/avalanche.iife.js after it for bridge and Avalanche commands, or import http://127.0.0.1:7823/__chippy/inject.mjs instead.
|
|
60
61
|
```
|
|
61
62
|
|
|
62
63
|
Then prints the classic-script URL to stdout, one line:
|
|
@@ -153,7 +154,7 @@ Records are separated by one blank line. `score` is useful only for ordering res
|
|
|
153
154
|
|
|
154
155
|
`buildMode`: `"dev" | "production" | "unknown"`
|
|
155
156
|
|
|
156
|
-
`dev` source evidence is either React <=18 `_debugSource` or React 19 `_debugStack`. For React 19, the first snapshot may carry the served-module URL and generated position; the bridge resolves the module's inline or external Source Map v3 payload in the page realm and republishes the authored `fileName`, `lineNumber`, and `columnNumber` with reason `<original-reason>-source-resolved`.
|
|
157
|
+
`dev` source evidence is either React <=18 `_debugSource` or React 19 `_debugStack`. For React 19, the first snapshot may carry the served-module URL and generated position; the bridge resolves the module's inline or external Source Map v3 payload in the page realm and republishes the authored `fileName`, `lineNumber`, and `columnNumber` with reason `<original-reason>-source-resolved`. For React <=18, the same resolution corrects a `_debugSource` line that a dev-server transform shifted; `fileName` stays the recorded path. `find-fibers` and explicit component descriptions await that resolution. If the module or map is unavailable, the recorded or served position remains the fallback.
|
|
157
158
|
|
|
158
159
|
**`integration`** — identifies who established Chippy on this page:
|
|
159
160
|
```json
|
|
@@ -1034,6 +1035,7 @@ Proxy active:
|
|
|
1034
1035
|
"proxy": {
|
|
1035
1036
|
"active": true,
|
|
1036
1037
|
"targetPort": 3000,
|
|
1038
|
+
"targetHost": "localhost:3000",
|
|
1037
1039
|
"originalUrl": "http://localhost:3000/issues/ABC-123",
|
|
1038
1040
|
"injectTarget": { "pathname": "/issues/ABC-123", "search": "" },
|
|
1039
1041
|
"startedAt": "2026-04-16T08:00:00.000Z"
|
|
@@ -1043,6 +1045,8 @@ Proxy active:
|
|
|
1043
1045
|
|
|
1044
1046
|
`injectTarget` — the path+search the proxy will inject the Chippy bundle into. Derived from `originalUrl`. `null` if no `originalUrl` was given.
|
|
1045
1047
|
|
|
1048
|
+
`targetHost` — where requests are forwarded. The proxy forwards only to this machine: it uses the loopback host of `originalUrl` (`localhost`, `127.0.0.1`, `[::1]`), or `localhost` when none is given, and reaches servers listening on either IPv4 or IPv6. Into the injected document it adds the DevTools hook shim and the Avalanche runtime before page scripts, and the page bridge at the end of the body.
|
|
1049
|
+
|
|
1046
1050
|
---
|
|
1047
1051
|
|
|
1048
1052
|
## `proxy-start <targetPort> [originalUrl]`
|
|
@@ -1054,6 +1058,7 @@ Success:
|
|
|
1054
1058
|
"proxy": {
|
|
1055
1059
|
"active": true,
|
|
1056
1060
|
"targetPort": 3000,
|
|
1061
|
+
"targetHost": "localhost:3000",
|
|
1057
1062
|
"originalUrl": "http://localhost:3000/issues/ABC-123",
|
|
1058
1063
|
"injectTarget": { "pathname": "/issues/ABC-123", "search": "" },
|
|
1059
1064
|
"startedAt": "2026-04-16T08:00:00.000Z"
|
|
@@ -1066,6 +1071,11 @@ Bad port:
|
|
|
1066
1071
|
{ "ok": false, "error": "Invalid target port: abc" }
|
|
1067
1072
|
```
|
|
1068
1073
|
|
|
1074
|
+
Target off this machine:
|
|
1075
|
+
```json
|
|
1076
|
+
{ "ok": false, "error": "Proxy targets must be on this machine; originalUrl host example.com is not a loopback name" }
|
|
1077
|
+
```
|
|
1078
|
+
|
|
1069
1079
|
---
|
|
1070
1080
|
|
|
1071
1081
|
## `proxy-stop`
|
|
@@ -21,7 +21,7 @@ Use recipe search when the operation or recovery route is not already obvious. I
|
|
|
21
21
|
| Command | Purpose |
|
|
22
22
|
|---|---|
|
|
23
23
|
| `start`, `stop`, `health` | Own the local helper lifecycle and readiness check. `start` backgrounds itself and binds `127.0.0.1`; `start --host 0.0.0.0` binds wide only when the user asks for network access. |
|
|
24
|
-
| `inject-url` | Print the classic `inject.js` URL to stdout and the document-scoped reload warning to stderr.
|
|
24
|
+
| `inject-url` | Print the classic `inject.js` URL to stdout, and the document-scoped reload warning plus the second required asset to stderr. `inject.js` alone installs Chippy without the bridge; load `avalanche.iife.js` after it, or prefer the single ESM import for new injection workflows. |
|
|
25
25
|
| `pages [slice]` | List currently connected pages. This is connection truth. |
|
|
26
26
|
| `recent-pages` | List recently disconnected page summaries for reload/navigation diagnosis. |
|
|
27
27
|
| `page <clientId> [slice]` | Read one connected page with `minimal`, `standard`, or `full` detail. |
|
|
@@ -91,9 +91,9 @@ Load [active-stimulus](active-stimulus.md) before an active command. A `fiber:*`
|
|
|
91
91
|
|
|
92
92
|
| Mode | Use it for | Boundary |
|
|
93
93
|
|---|---|---|
|
|
94
|
-
| `sources` | Default source and commit attribution
|
|
95
|
-
| `full` |
|
|
96
|
-
| `stats` | Aggregate capture statistics | No source
|
|
94
|
+
| `sources` | Default source and commit attribution; rendered components with prop changes and `isSelfSource` | `trasherCounts` stay zero |
|
|
95
|
+
| `full` | Everything in `sources` plus amplifier (`trasherCounts`) evidence | Higher collection cost |
|
|
96
|
+
| `stats` | Aggregate capture statistics; rendered components with prop changes | No source tracking: `isSelfSource` stays false |
|
|
97
97
|
| `amplifiers` | Amplifier-focused capture | Specialized analysis; load Avalanche reference first |
|
|
98
98
|
|
|
99
99
|
`avalanche-arm` and `reload-with-avalanche` also accept `captureFibers=true|false`. Keep it `true` when debug-hook or fiber-backed analysis may follow.
|
|
@@ -102,7 +102,7 @@ Load [active-stimulus](active-stimulus.md) before an active command. A `fiber:*`
|
|
|
102
102
|
|
|
103
103
|
`avalanche-commit-list` live `by` values are `collateral`, `sources`, `restarts`, `performedWork`, `effects`, `memos`, `callbacks`, `contextUpdates`, `unmountedComponents`, and `unmountedSubtrees`.
|
|
104
104
|
|
|
105
|
-
`avalanche-commit-peek` live `include` values are `stats`, `sources`, `timing`, `metrics`, `unmounts`, `actions`, and `rendered`; `atl` is a deprecated alias of `metrics`. `rendered`
|
|
105
|
+
`avalanche-commit-peek` live `include` values are `stats`, `sources`, `timing`, `metrics`, `unmounts`, `actions`, and `rendered`; `atl` is a deprecated alias of `metrics`. `rendered` works in every mode; `trasherCounts` in it need `full` or `amplifiers`.
|
|
106
106
|
|
|
107
107
|
Load [avalanche-detector](avalanche-detector.md) for schemas and evidence-reading rules.
|
|
108
108
|
|
|
@@ -112,7 +112,7 @@ Load [avalanche-detector](avalanche-detector.md) for schemas and evidence-readin
|
|
|
112
112
|
|---|---|
|
|
113
113
|
| `eval-snippets` | List packaged snippets. |
|
|
114
114
|
| `eval-page` | Execute one packaged or local snippet in the connected page realm with `--key value` arguments. |
|
|
115
|
-
| `page-reload`, `page-wait-reload` | Request a reload and wait for the helper's reconnect transition. For a Storybook integration, `page-reload` emits `FORCE_REMOUNT`, remounting only the current SUT without navigating the preview iframe. |
|
|
115
|
+
| `page-reload`, `page-wait-reload` | Request a reload and wait for the helper's reconnect transition. For a Storybook integration, `page-reload` emits `FORCE_REMOUNT`, remounting only the current SUT without navigating the preview iframe; it fails with HTTP 409 when no rendered story matches the selection. |
|
|
116
116
|
| `handoff-to-playwright` | Transfer a connected page URL and selected probes into a Playwright session configuration. |
|
|
117
117
|
| `proxy-state`, `proxy-start`, `proxy-stop` | Inspect or control the helper's local proxy. |
|
|
118
118
|
|
|
@@ -12,7 +12,7 @@ If the user is using their own browser with the extension, this contract does NO
|
|
|
12
12
|
|
|
13
13
|
## Required bootstrap and install order
|
|
14
14
|
|
|
15
|
-
Mode A has two
|
|
15
|
+
Mode A has two runtime-loading variants that end with the same explicit detector install. To record the initial load, use [pre-page start-up](#pre-page-start-up) instead; it installs the detector before React on every document.
|
|
16
16
|
|
|
17
17
|
1. **Install the DevTools hook shim before navigation.** Use `page.addInitScript({ content: DEVTOOLS_HOOK_SHIM })` before `page.goto(...)`.
|
|
18
18
|
React-DOM checks `__REACT_DEVTOOLS_GLOBAL_HOOK__` at module-evaluation time. Installing the shim after navigation = no `currentDispatcherRef` = `replayComponentHooks` collapses to fiber-only fallback. The shim file is shipped with the Chippy skill at `extension/devtools-hook-shim.js`; the helper serves it at `/__chippy/devtools-hook-shim.js` (load that contents into the init script).
|
|
@@ -21,16 +21,48 @@ Mode A has two supported runtime-loading variants. Both end with the same explic
|
|
|
21
21
|
- **Ad-hoc / playwright-cli:** navigate first, then import `http://127.0.0.1:7823/__chippy/inject.mjs` (preferred), or add `inject.js` followed by `avalanche.iife.js`. The classic `inject.js` is intentionally split; bridge commands return `bridge module not loaded` until the IIFE is present.
|
|
22
22
|
3. **Wait for the page client in `chippy.sh pages`.** A loaded global is not connection proof.
|
|
23
23
|
4. **Run `chippy.sh avalanche-install <clientId>`.** Loading either runtime does not auto-install the detector in Mode A.
|
|
24
|
-
Auto-install is gated on `__CHIPPY_STARTUP_CONFIG.avalanche.autoStart`, which is written by the extension's MAIN-world script in Mode B. Neither
|
|
24
|
+
Auto-install is gated on `__CHIPPY_STARTUP_CONFIG.avalanche.autoStart`, which is written by the extension's MAIN-world script in Mode B. Neither loader above writes that startup configuration, so both must trigger install explicitly.
|
|
25
|
+
|
|
26
|
+
## Pre-page start-up
|
|
27
|
+
|
|
28
|
+
Use this variant when the agent must record the initial page load without the extension. It writes the startup configuration that the extension writes in Mode B, then adds the early scripts and the page bridge as init scripts. Every document, including each reload, installs Avalanche before React DOM evaluates.
|
|
29
|
+
|
|
30
|
+
Register the init scripts before `page.goto(...)`, in this order. The files ship in this skill's `extension/` folder:
|
|
31
|
+
|
|
32
|
+
```js
|
|
33
|
+
const read = (file) => fs.readFileSync(path.join(skillDir, 'extension', file), 'utf8');
|
|
34
|
+
|
|
35
|
+
await page.addInitScript(() => {
|
|
36
|
+
globalThis.__CHIPPY_STARTUP_CONFIG = {
|
|
37
|
+
enabled: true,
|
|
38
|
+
helperBaseUrl: 'http://127.0.0.1:7823',
|
|
39
|
+
avalanche: { autoStart: true },
|
|
40
|
+
};
|
|
41
|
+
});
|
|
42
|
+
await page.addInitScript({ content: read('devtools-hook-shim.js') });
|
|
43
|
+
await page.addInitScript({ content: read('avalanche.iife.js') });
|
|
44
|
+
await page.addInitScript({ content: read('early-bootstrap.js') });
|
|
45
|
+
await page.addInitScript({
|
|
46
|
+
content: ['inspect-react.js', 'panel-dom.js', 'layout-lab.js', 'resolve-probes.js', 'chippy-page-bridge.js']
|
|
47
|
+
.map(read)
|
|
48
|
+
.join('\n'),
|
|
49
|
+
});
|
|
50
|
+
await page.goto(url);
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
- Skip the explicit `avalanche-install`; the detector is already installed and recording. `avalanche.options` accepts `detectionMode` and `captureFibers`, and `avalanche.max` sets the history size.
|
|
54
|
+
- To capture a load, call `page.reload()` and let the page settle. Do not call `avalanche-reset` between the reload and the read; it clears the boot commits.
|
|
55
|
+
- Read the capture with `chippy.sh avalanche-status <clientId>` and `avalanche-export` once the reloaded page appears in `chippy.sh pages`. If the client has not reconnected yet, read `window.__AVALANCHE__.exportLast()` in the page.
|
|
25
56
|
|
|
26
57
|
## On reload (`page.reload(...)`)
|
|
27
58
|
|
|
28
59
|
- Init scripts survive reload. The packaged loader restores its runtimes automatically; the ad-hoc variant must load them again.
|
|
29
|
-
-
|
|
60
|
+
- The client id is kept in the tab's `sessionStorage`, so the reloaded page normally reconnects under the same id (`page-wait-reload` reports `reloaded: true`). The connection and the detector are new: repeat the explicit install.
|
|
61
|
+
- If the runtimes are not loaded again, the page never reconnects: `page-wait-reload` reports `reloaded: false`, and `reload-with-avalanche` exits with an error instead of reading status from a client that no longer exists.
|
|
30
62
|
|
|
31
|
-
## Boot-time commit loss
|
|
63
|
+
## Boot-time commit loss in the packaged and ad-hoc variants
|
|
32
64
|
|
|
33
|
-
The ad-hoc `addScriptTag` variant loads the runtimes after page code. The packaged init-script variant loads them before page code, but its detector still remains uninstalled until the helper observes the new client and sends the explicit install.
|
|
65
|
+
This limit does not apply to [pre-page start-up](#pre-page-start-up). The ad-hoc `addScriptTag` variant loads the runtimes after page code. The packaged init-script variant loads them before page code, but its detector still remains uninstalled until the helper observes the new client and sends the explicit install.
|
|
34
66
|
|
|
35
67
|
Any React commit that fires between page mount and your `avalanche-install` call is **invisible to Avalanche**. This includes:
|
|
36
68
|
- initial mount
|
|
@@ -38,7 +70,7 @@ Any React commit that fires between page mount and your `avalanche-install` call
|
|
|
38
70
|
- Suspense fallback → content swaps
|
|
39
71
|
- route transitions on first paint
|
|
40
72
|
|
|
41
|
-
**Workaround:**
|
|
73
|
+
**Workaround:** use [pre-page start-up](#pre-page-start-up), or trigger the transition from the page after `avalanche-install`.
|
|
42
74
|
|
|
43
75
|
## Failure signatures
|
|
44
76
|
|
|
@@ -54,15 +86,17 @@ Any React commit that fires between page mount and your `avalanche-install` call
|
|
|
54
86
|
|
|
55
87
|
- `chippy.sh avalanche-status <clientId>` → expect `installed: true`, `commitCount > 0`, and `integrationMode` matching the host (`adapter:atl` for a patched Atlassian host, `devtools` otherwise; earlier releases report `atl`), never `none` after a captured commit.
|
|
56
88
|
- In `avalanche-export`, compare `meta.commits` vs `meta.memoizedUpdatersSupport.commitsWithData` — they should match. If `commitsWithData > meta.commits`, early commits were missed.
|
|
57
|
-
-
|
|
89
|
+
- To tell the boot-time gap from a wiring fault, repeat the interaction after install. If that capture is also empty, the injection is broken; if only the pre-install interaction is missing, use [pre-page start-up](#pre-page-start-up).
|
|
58
90
|
|
|
59
91
|
## Mode B reference (for contrast)
|
|
60
92
|
|
|
61
93
|
In Mode B, the extension does the following automatically and silently for every navigation:
|
|
62
94
|
1. `webNavigation.onCommitted` fires
|
|
63
95
|
2. Background fetches `armedAvalanche` config from helper
|
|
64
|
-
3. `chrome.scripting.executeScript({ injectImmediately: true, world: 'MAIN' })` runs the early scripts (`devtools-hook-shim.js`, `avalanche.iife.js`, `early-bootstrap.js`)
|
|
96
|
+
3. `chrome.scripting.executeScript({ injectImmediately: true, world: 'MAIN' })` runs the early scripts (`devtools-hook-shim.js`, `avalanche.iife.js`, `early-bootstrap.js`). Because steps 2–3 wait on network lookups, a fast page can evaluate React first.
|
|
65
97
|
4. iife.ts reads `__CHIPPY_STARTUP_CONFIG.avalanche.autoStart` and self-installs
|
|
66
98
|
5. `chrome.tabs.onUpdated` (`status === 'complete'`) injects late bundle scripts (bridge + probes)
|
|
67
99
|
|
|
68
|
-
|
|
100
|
+
For a helper reload of an armed page (`page-reload` after `avalanche-arm`, as in `reload-with-avalanche`), the page bridge first stores the arm in `sessionStorage` and the extension registers the early scripts plus `startup-handoff.js` as a MAIN-world `document_start` content script for that one navigation. The next document installs Avalanche before any page script runs, so boot commits are captured. The reload ack's `earlyStartup` is `registered` when this path was prepared.
|
|
101
|
+
|
|
102
|
+
The packaged and ad-hoc Mode A loaders do not provide the extension's pre-page `autoStart` configuration. They install only after client connection; that post-connection detector start is the structural reason for their boot-time gap. Pre-page start-up writes the configuration itself and has no such gap.
|
|
@@ -6,7 +6,7 @@ Use this when there is no Chippy browser extension on the page (`playwright-cli`
|
|
|
6
6
|
|
|
7
7
|
Chippy assets are served by the local Chippy helper:
|
|
8
8
|
|
|
9
|
-
- `http://127.0.0.1:7823/__chippy/inject.mjs` — **preferred ESM bootstrap**. Import side-effect installs `window.__CHIPPY`, registers the page with the helper, auto-loads `window.__AVALANCHE__` from the ESM-safe `avalanche.es.js` asset, activates probes immediately
|
|
9
|
+
- `http://127.0.0.1:7823/__chippy/inject.mjs` — **preferred ESM bootstrap**. Import side-effect installs `window.__CHIPPY`, registers the page with the helper, auto-loads `window.__AVALANCHE__` from the ESM-safe `avalanche.es.js` asset, and activates probes immediately. It renders no in-page control panel. The module default export is `window.__CHIPPY`; named export `ready` resolves to `{ chippy, avalanche, connState, integration, activated, probesActive }` immediately after bootstrap.
|
|
10
10
|
- `http://127.0.0.1:7823/__chippy/inject.js` — **classic-script bootstrap**. Installs `window.__CHIPPY` only.
|
|
11
11
|
- `http://127.0.0.1:7823/__chippy/avalanche.iife.js` — **Chippy runtime for bridge / Avalanche-backed commands**. Installs `window.__AVALANCHE__` when the classic bootstrap is used.
|
|
12
12
|
|
|
@@ -18,9 +18,9 @@ The same ESM bootstrap is also valid for a real user-controlled browser tab when
|
|
|
18
18
|
import('http://127.0.0.1:7823/__chippy/inject.mjs')
|
|
19
19
|
```
|
|
20
20
|
|
|
21
|
-
In that mode the import
|
|
21
|
+
In that mode the import activates probes for the current page without the extension's in-page controls.
|
|
22
22
|
|
|
23
|
-
The
|
|
23
|
+
The import lasts only for the current document. A full reload or navigation removes the imported runtime because no extension, proxy, or Storybook host remains to inject it. The user—or Playwright—must run the import command again after every reload/navigation. To keep Chippy across reloads without the extension, use the packaged init-script loader in [mode-a-injection](mode-a-injection.md) or the helper's local proxy.
|
|
24
24
|
|
|
25
25
|
## Steps
|
|
26
26
|
|
|
@@ -36,7 +36,7 @@ The equivalence lasts only for the current document. A full reload or navigation
|
|
|
36
36
|
3. Prefer the ESM bootstrap when module loading is available:
|
|
37
37
|
|
|
38
38
|
```bash
|
|
39
|
-
|
|
39
|
+
playwright-cli -s=<session> run-code "async page => {
|
|
40
40
|
await page.addScriptTag({
|
|
41
41
|
content: `
|
|
42
42
|
const script = document.createElement('script');
|
|
@@ -57,7 +57,7 @@ The equivalence lasts only for the current document. A full reload or navigation
|
|
|
57
57
|
Fallback: classic script injection when ESM import is not available:
|
|
58
58
|
|
|
59
59
|
```bash
|
|
60
|
-
|
|
60
|
+
playwright-cli -s=<session> run-code "async page => {
|
|
61
61
|
await page.addScriptTag({ url: 'http://127.0.0.1:7823/__chippy/inject.js' });
|
|
62
62
|
await page.waitForTimeout(500);
|
|
63
63
|
await page.addScriptTag({ url: 'http://127.0.0.1:7823/__chippy/avalanche.iife.js' });
|
|
@@ -123,7 +123,7 @@ overridden with `CHIPPY_HELPER_BASE`.
|
|
|
123
123
|
|
|
124
124
|
The packaged `launchSession(...)` path installs the Chippy bridge and Avalanche runtime via `addInitScript`, so both runtimes exist before page scripts on every reload. The detector still starts uninstalled in each new page realm. `reloadWithAvalanche` therefore reloads, waits for the new client, calls the Avalanche `install` action explicitly, then settles and reads evidence. It does not use helper origin-arming.
|
|
125
125
|
|
|
126
|
-
Commits that occur before that post-reload install are not captured. Use this helper for post-install triggers and settled-state checks, not to claim complete initial-load coverage.
|
|
126
|
+
Commits that occur before that post-reload install are not captured. Use this helper for post-install triggers and settled-state checks, not to claim complete initial-load coverage. To record the initial load, use [pre-page start-up](mode-a-injection.md#pre-page-start-up).
|
|
127
127
|
|
|
128
128
|
Flow:
|
|
129
129
|
1. `page.reload()` via Playwright
|
|
@@ -21,7 +21,7 @@ id=show-page-status | q=How do I show a short status message inside the inspecte
|
|
|
21
21
|
id=hide-page-status | q=How do I remove Chippy's page-visible status message? | tags=hide status clear message page | a=Run `chippy.sh hide-status <clientId>`. | done=The page-visible Chippy status is absent. | guard=This does not clear probes or capture state. | refs=references/command-surface.md#runtime-and-connection
|
|
22
22
|
id=identify-integration-owner | q=How do I tell whether Chippy came from the extension, Storybook, or a console import? | tags=integration identity owner extension storybook import reload behavior who source | a=Read `integration.kind`, `who`, `source`, `reinjectsOnReload`, and `reloadAction` from `chippy.sh pages`. | done=The injection owner and reload contract are explicit. | guard=Do not infer ownership from globals or the page URL. | refs=SKILL.md#connection-and-bootstrap
|
|
23
23
|
id=inject-console-module | q=How do I load Chippy into a user-controlled page without the extension? | tags=inject import esm console module user controlled page | a=Run `import('http://127.0.0.1:7823/__chippy/inject.mjs')` in the browser console, then resolve the page through `chippy.sh pages`. | done=The page reports `integration.kind: import` and the bridge is ready. | guard=The import is document-scoped and must be repeated after full navigation or reload. | refs=SKILL.md#connection-and-bootstrap
|
|
24
|
-
id=print-classic-inject-url | q=How do I obtain the classic Chippy injection URL? | tags=inject url classic inject.js fallback | a=Run `chippy.sh inject-url`; stdout contains the URL and stderr explains the reload boundary. | done=A valid helper-served `inject.js` URL is returned. | guard
|
|
24
|
+
id=print-classic-inject-url | q=How do I obtain the classic Chippy injection URL? | tags=inject url classic inject.js fallback | a=Run `chippy.sh inject-url`; stdout contains the URL and stderr explains the reload boundary and the second asset. | done=A valid helper-served `inject.js` URL is returned. | guard=`inject.js` alone has no bridge; load `avalanche.iife.js` after it. Prefer the ESM import for new console workflows. | refs=references/command-surface.md#runtime-and-connection
|
|
25
25
|
id=toggle-jira-enrichment | q=How do I show or hide Jira ownership and boundary enrichment in probe cards? | tags=jira context ui ownership error boundary enrichment on off cards | a=Run `chippy.sh context-ui <clientId> on` or `chippy.sh context-ui <clientId> off`. | done=The connected page renders or hides the enrichment consistently. | guard=This changes Chippy UI only and does not change Jira product behavior. | refs=references/command-surface.md#runtime-and-connection,references/jira-taxonomy.md
|
|
26
26
|
|
|
27
27
|
# Probe, source, and component inspection
|
|
@@ -380,7 +380,7 @@ The effect attaches a subscription and dispatches state. It depends on `handler`
|
|
|
380
380
|
- If the subscription is the only side effect, move attach/detach to a `useLayoutEffect` keyed on the stable subscription target rather than on a callback identity.
|
|
381
381
|
|
|
382
382
|
**Pointer for the agent:**
|
|
383
|
-
-
|
|
383
|
+
- Location: the `Leaf` component's `useEffect(..., [handler])`.
|
|
384
384
|
- Question to answer before editing: *what does this effect semantically depend on — the function identity, or the data the function reads?*
|
|
385
385
|
- After the fix, re-run stability-render. Expected: `commitCount` drops to 1; `attach/detach` no longer grows per nudge.
|
|
386
386
|
|
|
@@ -389,7 +389,7 @@ The effect attaches a subscription and dispatches state. It depends on `handler`
|
|
|
389
389
|
After Step 1 the effect is fine, but the callback still flips identity every render. That is harmless on its own — but the moment a memoised child uses it as a prop, the cascade comes back. Fix this *before* memoising any children, not *after*.
|
|
390
390
|
|
|
391
391
|
**Pointer for the agent:**
|
|
392
|
-
-
|
|
392
|
+
- Location: `Leaf`'s `useCallback(handler, [opts])`.
|
|
393
393
|
- Same dep narrowing logic as Step 1: depend on `opts.mode`, not on `opts`. The callback's body only uses `opts.mode`, so the wider dep is overcautious and breaks memoisation.
|
|
394
394
|
- After the fix, re-run stability-render. Expected: callback identity stable across nudges; `Leaf`'s render count for the nudge stays at 1.
|
|
395
395
|
|
|
@@ -398,13 +398,13 @@ After Step 1 the effect is fine, but the callback still flips identity every ren
|
|
|
398
398
|
`Parent` builds `opts = { mode }` inline. Step 1 + Step 2 made downstream consumers immune to that, but the next consumer added to this subtree will get the same trap. Wrap the object once.
|
|
399
399
|
|
|
400
400
|
**Pointer for the agent:**
|
|
401
|
-
-
|
|
401
|
+
- Location: the parent's `const opts = { mode };`.
|
|
402
402
|
- Wrap with `useMemo(() => ({ mode }), [mode])` — or, if `mode` is the only field, pass `mode` directly and drop the object.
|
|
403
403
|
- After the fix, re-run stability-render. Expected: same numbers as after Step 2. This step is *prevention*, not *repair* — measurable improvement is "no regression when a new memoised consumer is added".
|
|
404
404
|
|
|
405
405
|
### What "deep explanation" means here
|
|
406
406
|
|
|
407
|
-
When Chippy reports findings on this
|
|
407
|
+
When Chippy reports findings on this chain, every pointer must answer three questions:
|
|
408
408
|
|
|
409
409
|
1. **What flips?** Name the identity that changes. (`opts` object reference; `handler` function reference; `useEffect` cleanup/attach pair.)
|
|
410
410
|
2. **Why does that flip propagate?** Name the dep array or prop boundary it crosses. (Dep array of `useCallback`; dep array of `useEffect`; prop `opts` from Parent to Leaf.)
|
|
@@ -132,7 +132,8 @@ Examples:
|
|
|
132
132
|
./scripts/chippy.sh pages
|
|
133
133
|
# Select the page whose URL, title, integration identity, and recency match the target.
|
|
134
134
|
CLIENT_ID=<confirmed-clientId>
|
|
135
|
-
|
|
135
|
+
ORIGIN=<that page's origin>
|
|
136
|
+
./scripts/chippy.sh reload-with-avalanche "$CLIENT_ID" "$ORIGIN" 0 15000 5000
|
|
136
137
|
./scripts/chippy.sh avalanche-status "$CLIENT_ID"
|
|
137
138
|
./scripts/chippy.sh avalanche-hot-sources "$CLIENT_ID" 10
|
|
138
139
|
./scripts/chippy.sh avalanche-commit-list "$CLIENT_ID" 10 collateral
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
## Helper is down
|
|
4
4
|
- `/__chippy/health` fails
|
|
5
5
|
- no pages in `/__chippy/api/pages`
|
|
6
|
-
- the Storybook Chippy and Avalanche panels conditionally offer `npx
|
|
6
|
+
- the Storybook Chippy and Avalanche panels conditionally offer `npx skills add atlassian-labs/chippy --skill chippy -g` while their connection state is `failed` or `reconnecting`
|
|
7
7
|
- Chippy must run outside the agent sandbox; the agent owns this, not the user
|
|
8
8
|
- sandbox failure mode: the helper can look alive inside the agent environment, but the browser cannot reach its isolated Node server/port
|
|
9
9
|
- fix: agent runs `./scripts/chippy.sh start` using outside-sandbox / escalated execution, then verifies with `./scripts/chippy.sh health` and `./scripts/chippy.sh pages` (also outside-sandbox)
|
|
@@ -47,6 +47,11 @@
|
|
|
47
47
|
- the served URL and generated line remain as a bounded fallback; do not present them as a mapped repository position
|
|
48
48
|
- check that the page can fetch its own module URL and that the dev server emits an inline or external Source Map v3 payload
|
|
49
49
|
|
|
50
|
+
## React <=18 source line is offset from the file
|
|
51
|
+
- `_debugSource` records the line the JSX transform saw; a transform that ran earlier and added lines shifts it
|
|
52
|
+
- Chippy corrects the line when it can fetch the module the page loaded for that file and the module's source map maps the recorded literal back into the same file
|
|
53
|
+
- if the line still looks offset, check that the page loaded the module from its own origin and that the dev server emits a source map
|
|
54
|
+
|
|
50
55
|
## Multiple pages on same URL
|
|
51
56
|
- use `clientId`, title, `latestSnapshotAt`, and `lastMessageAt` to identify the right page
|
|
52
57
|
- usually prefer the most recently updated page when one candidate is clearly newer than the rest
|