@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,128 @@
|
|
|
1
|
+
# Chippy Operating Model
|
|
2
|
+
|
|
3
|
+
Chippy works in four separated phases: **Observe → Define → Prove → Apply**. This is the enforcement layer for evidence-first work. Do not collapse these phases.
|
|
4
|
+
|
|
5
|
+
Cynefin positions the work; OODA drives repeated evidence steps inside Prove. See [cynefin](cynefin.md) for the full positioning and iteration rules.
|
|
6
|
+
|
|
7
|
+
| Phase | Position or iteration role |
|
|
8
|
+
|---|---|
|
|
9
|
+
| Observe | Use read-only orientation to exit ❓ Disorder and name the domain. If it is 🔥, stabilize before further analysis. |
|
|
10
|
+
| Define | Frame the case in the language of the named domain — sensor question for 🔍, experiment hypothesis for 🌀. |
|
|
11
|
+
| Prove | Repeat OODA inside the named domain. Run sensors in 🔍; run safe-to-fail experiments through an observable SUT in 🌀. Never demand 🔍 certainty from a 🌀 system. |
|
|
12
|
+
| Apply | Separate from OODA Act. Allowed only when the proof packet meets the per-domain confidence rule, identifies a fix layer, and supplies repeatable verification. |
|
|
13
|
+
|
|
14
|
+
| Phase | Purpose | Question | Output | May edit? |
|
|
15
|
+
|---|---|---|---|---|
|
|
16
|
+
| **Observe** | Anchor the symptom in runtime or source reality | What is actually there? | Observation anchor: page/client, probe/fiber/testId/interaction/load window, first signal | No |
|
|
17
|
+
| **Define** | Name the observed thing and the invariant under test | What case did observation reveal? | Case definition: target, scope, invariant, suspected dimensions | No |
|
|
18
|
+
| **Prove** | Gather evidence until the case is confirmed, falsified, or bounded | What does runtime/source evidence prove? | Proof packet: runtime + structure + source + signal facts, confidence, next gap | No |
|
|
19
|
+
| **Apply** | Change source only after proof identifies a fix layer | What is the smallest source change that preserves the invariant? | Edit + same-signal verification | Yes, only after explicit proof |
|
|
20
|
+
|
|
21
|
+
## OODA inside Prove
|
|
22
|
+
|
|
23
|
+
The Prove phase repeats a bounded loop:
|
|
24
|
+
|
|
25
|
+
1. **Observe** the smallest current signal.
|
|
26
|
+
2. **Orient** it against the domain, invariant, accumulated facts, and next gap.
|
|
27
|
+
3. **Decide** the next move permitted by the domain and documented command surface.
|
|
28
|
+
4. **Act** by executing that evidence move, then update the proof packet.
|
|
29
|
+
|
|
30
|
+
OODA Act can be read-only. It can also be a bounded stimulus or stabilizer when the domain permits one. It is never implicit authorization to edit source: only the Apply phase can do that. If new evidence changes the cause/effect posture, return to Observe, reposition, and continue with the new domain.
|
|
31
|
+
|
|
32
|
+
## Observation contract
|
|
33
|
+
|
|
34
|
+
Before defining the case, anchor it in observed data:
|
|
35
|
+
|
|
36
|
+
```text
|
|
37
|
+
Observation: <probe/fiber/interaction/load window/page state> shows <first concrete signal>.
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Examples:
|
|
41
|
+
|
|
42
|
+
```text
|
|
43
|
+
Observation: probe 1 resolves to a status label with text "Done" under IssueHeader.
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
```text
|
|
47
|
+
Observation: after arming Avalanche and clicking Save, commit 42 has high collateral under the Save panel.
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Case definition contract
|
|
51
|
+
|
|
52
|
+
After observation, define the case in one sentence:
|
|
53
|
+
|
|
54
|
+
```text
|
|
55
|
+
Case: <visible/runtime symptom> violates <expected invariant> at <scope>.
|
|
56
|
+
Need to prove: <prop | hook | provider | store | boundary | source | load/runtime wave>.
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Examples:
|
|
60
|
+
|
|
61
|
+
```text
|
|
62
|
+
Case: clicking Save causes the whole panel to lag; invariant is one bounded update under the Save branch.
|
|
63
|
+
Need to prove: whether the trigger is local state, context propagation, store restart, or missing memo boundary.
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
```text
|
|
67
|
+
Case: this status label says Done; invariant is that displayed text comes from issue status data, not presentation fallback.
|
|
68
|
+
Need to prove: which owner passes the label prop and where the value is derived.
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Proof packet contract
|
|
72
|
+
|
|
73
|
+
A claim is not ready for Apply until it has a proof packet.
|
|
74
|
+
|
|
75
|
+
```text
|
|
76
|
+
Definition:
|
|
77
|
+
target: <probe/fiber/story/page/interaction>
|
|
78
|
+
invariant: <what should stay true>
|
|
79
|
+
scope: <component/subtree/page/load/interaction>
|
|
80
|
+
|
|
81
|
+
Evidence:
|
|
82
|
+
runtime: <probe-dom/pages/snapshot/avalanche status/logged transition>
|
|
83
|
+
structure: <owners/parents/fiber/hook tree>
|
|
84
|
+
source: <file:line and render block>
|
|
85
|
+
signal: <prop value/hook primitive/context wave/commit stats>
|
|
86
|
+
fact split: <source fact | runtime fact | unknown bridge>
|
|
87
|
+
|
|
88
|
+
Decision:
|
|
89
|
+
role: <source | boundary | collateral | provider | store | mount | unknown>
|
|
90
|
+
confidence: confirmed | likely | partial
|
|
91
|
+
next gap: <none or exact missing fact>
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Apply gate
|
|
95
|
+
|
|
96
|
+
Apply is allowed when the proof packet answers four questions:
|
|
97
|
+
|
|
98
|
+
1. **Case + evidence** — what invariant is in scope, and which runtime/source facts support it?
|
|
99
|
+
2. **Signal movement** — for no-rush or emergent work, did the last tapped contract or safe-to-fail experiment move, reproduce, or falsify the observed failure?
|
|
100
|
+
3. **Fix layer** — is the change above source, at a boundary, or below source?
|
|
101
|
+
4. **Verification** — can the same measurement be repeated after edit, with confidence appropriate to the domain?
|
|
102
|
+
|
|
103
|
+
If any gate fails, Chippy continues proving or reports the gap. Chippy does not patch while still discovering the essence.
|
|
104
|
+
|
|
105
|
+
### Per-domain confidence rule
|
|
106
|
+
|
|
107
|
+
Confidence is not a free-floating field. It is bounded by the Cynefin domain Observe declared. See [cynefin](cynefin.md).
|
|
108
|
+
|
|
109
|
+
| Domain | Minimum confidence to Apply | Why |
|
|
110
|
+
|---|---|---|
|
|
111
|
+
| ✅ Clear | `confirmed` | Sense → categorize → respond. The answer is deterministic; anything less than `confirmed` means the situation was misclassified. Reposition first. |
|
|
112
|
+
| 🔍 Complicated | `confirmed` | Sense → analyze → respond. The chain is knowable; `likely`/`partial` means analysis is incomplete — keep proving, do not apply. |
|
|
113
|
+
| 🌀 Complex | `likely` is sufficient **iff** the experiment is repeatable | Probe → sense → respond. Emergent systems rarely produce `confirmed`. Apply is allowed when (a) the same safe-to-fail experiment yields the same outcome on rerun, and (b) the verification command in gate 4 *is* that repeatable experiment. Never apply on `partial` in 🌀. |
|
|
114
|
+
| 🔥 Chaotic | — | Apply is forbidden. Stabilize first, then re-classify. |
|
|
115
|
+
| ❓ Disorder | — | Apply is forbidden. Use read-only orientation to position first. |
|
|
116
|
+
|
|
117
|
+
Rule of thumb: if the proof packet reports `confidence: partial`, Apply is never allowed. If it reports `confidence: likely` in 🌀, the verification command must be the *same* experiment that produced the `likely` reading.
|
|
118
|
+
|
|
119
|
+
## Fixing is a separate capability
|
|
120
|
+
|
|
121
|
+
Fixing is not a natural continuation of tracing. It is invoked only after Observe, Define, and Prove.
|
|
122
|
+
|
|
123
|
+
```text
|
|
124
|
+
Understand path: Observe → Define → Prove → Report essence
|
|
125
|
+
Fix path: Observe → Define → Prove → Apply → Verify
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
A user may ask for understanding only. In that case, stop after Prove and report the proof packet. Do not apply.
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# Chippy with `playwright-cli`
|
|
2
|
+
|
|
3
|
+
Use this when there is no Chippy browser extension on the page (`playwright-cli` opens a vanilla Chromium).
|
|
4
|
+
|
|
5
|
+
## What is Chippy on the page
|
|
6
|
+
|
|
7
|
+
Chippy assets are served by the local Chippy helper:
|
|
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, and installs a small 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
|
+
- `http://127.0.0.1:7823/__chippy/inject.js` — **classic-script bootstrap**. Installs `window.__CHIPPY` only.
|
|
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
|
+
|
|
13
|
+
Both paths are Chippy. `playwright-cli` is only the transport that loads them into the page.
|
|
14
|
+
|
|
15
|
+
The same ESM bootstrap is also valid for a real user-controlled browser tab when the page allows helper-served module import:
|
|
16
|
+
|
|
17
|
+
```js
|
|
18
|
+
import('http://127.0.0.1:7823/__chippy/inject.mjs')
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
In that mode the import is intended to be extension-equivalent for the current page: it activates probes immediately and installs the in-page Chippy controls.
|
|
22
|
+
|
|
23
|
+
The equivalence lasts only for the current document. A full reload or navigation removes the imported runtime because no extension or Storybook host remains to inject it. The in-page import controls display this warning. The user—or Playwright—must run the import command again after every reload/navigation.
|
|
24
|
+
|
|
25
|
+
## Steps
|
|
26
|
+
|
|
27
|
+
1. Start the helper:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
./scripts/chippy.sh start
|
|
31
|
+
./scripts/chippy.sh health
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
2. Open or reuse one `playwright-cli` Chromium session on the target URL.
|
|
35
|
+
|
|
36
|
+
3. Prefer the ESM bootstrap when module loading is available:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
yarn exec playwright-cli -s=<session> run-code "async page => {
|
|
40
|
+
await page.addScriptTag({
|
|
41
|
+
content: `
|
|
42
|
+
const script = document.createElement('script');
|
|
43
|
+
script.type = 'module';
|
|
44
|
+
script.textContent = \"import 'http://127.0.0.1:7823/__chippy/inject.mjs';\";
|
|
45
|
+
document.head.appendChild(script);
|
|
46
|
+
`,
|
|
47
|
+
});
|
|
48
|
+
await page.waitForTimeout(700);
|
|
49
|
+
return await page.evaluate(() => ({
|
|
50
|
+
hasChippy: !!window.__CHIPPY,
|
|
51
|
+
hasAvalanche: !!window.__AVALANCHE__,
|
|
52
|
+
href: location.href,
|
|
53
|
+
}));
|
|
54
|
+
}"
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Fallback: classic script injection when ESM import is not available:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
yarn exec playwright-cli -s=<session> run-code "async page => {
|
|
61
|
+
await page.addScriptTag({ url: 'http://127.0.0.1:7823/__chippy/inject.js' });
|
|
62
|
+
await page.waitForTimeout(500);
|
|
63
|
+
await page.addScriptTag({ url: 'http://127.0.0.1:7823/__chippy/avalanche.iife.js' });
|
|
64
|
+
await page.waitForTimeout(200);
|
|
65
|
+
return await page.evaluate(() => ({
|
|
66
|
+
hasChippy: !!window.__CHIPPY,
|
|
67
|
+
hasAvalanche: !!window.__AVALANCHE__,
|
|
68
|
+
href: location.href,
|
|
69
|
+
}));
|
|
70
|
+
}"
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
4. Confirm the page is connected:
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
./scripts/chippy.sh pages
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
The connected page is the one whose URL matches the opened tab.
|
|
80
|
+
|
|
81
|
+
5. Before the first Avalanche capture or analysis command, install the detector explicitly:
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
./scripts/chippy.sh avalanche-install <clientId>
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Both bootstraps load the Avalanche runtime; neither auto-installs its detector in this extension-free mode. Probe, fiber, and describe commands need only the loaded runtime and connection. Avalanche commands additionally need this install step.
|
|
88
|
+
|
|
89
|
+
## Re-injection after reload
|
|
90
|
+
|
|
91
|
+
A full reload wipes both globals and the `import` integration does not return by itself. Re-run steps 3–5 with the same bootstrap path (`inject.mjs` preferred; `inject.js` + `avalanche.iife.js` fallback). In a user-controlled tab, ask the user to run the console import again, then install Avalanche through Chippy. Verify connection with `chippy.sh pages`, not by checking `window.__chippyPageBridge`.
|
|
92
|
+
|
|
93
|
+
## Common bridge failure
|
|
94
|
+
|
|
95
|
+
If a bridge / Avalanche command returns:
|
|
96
|
+
|
|
97
|
+
```text
|
|
98
|
+
bridge module not loaded
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
The cause is missing `avalanche.iife.js`. Inject it (step 3 second `addScriptTag`) and retry.
|
|
102
|
+
|
|
103
|
+
## Dispatcher replay ancestry (only when explicitly needed)
|
|
104
|
+
|
|
105
|
+
Dispatcher-based component-structure paths (`explain-component`, `describe-component`, and `inspect-fiber-structure`) need the devtools-hook shim installed **before React evaluates**. With `playwright-cli` that means `addInitScript` before navigation, using the helper-served shim at `http://127.0.0.1:7823/__chippy/devtools-hook-shim.js`. Run the debug replay preflight before those commands. `avalanche-debug-hook` is different: it reads hook events passively captured during real renders and does not execute component bodies. Ordinary bridge work does not need dispatcher replay.
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
# Playwright probes
|
|
2
|
+
|
|
3
|
+
How Chippy operates inside a Playwright-driven browser. Same shared runtime as
|
|
4
|
+
the extension, different transport. No drag UI. AI-driven targets, not pixels.
|
|
5
|
+
|
|
6
|
+
## What a probe is
|
|
7
|
+
|
|
8
|
+
A probe is **a focus descriptor + a resolved target**. It is not a marker.
|
|
9
|
+
|
|
10
|
+
```
|
|
11
|
+
Probe {
|
|
12
|
+
id string // "p1", "p2", ...
|
|
13
|
+
intent string|null // optional human note
|
|
14
|
+
descriptor { // portable identity
|
|
15
|
+
dom: { tag, attrs, text, nearestTestId, siblingIndex }
|
|
16
|
+
component: { name, source, ownerNames }
|
|
17
|
+
}
|
|
18
|
+
resolved { // per-session, recomputed
|
|
19
|
+
confidence: "strict"|"high"|"medium"|"low"|"none"
|
|
20
|
+
candidateKind: "fiber"|"dom"
|
|
21
|
+
score: number
|
|
22
|
+
matches: { ...field flags }
|
|
23
|
+
component, dom, alternates[]
|
|
24
|
+
resolvedAt: iso
|
|
25
|
+
} | null
|
|
26
|
+
history[] // confidence/score timeline
|
|
27
|
+
createdAt iso
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Identity rules:
|
|
32
|
+
|
|
33
|
+
- Descriptor is portable across windows, runs, browsers.
|
|
34
|
+
- Resolved is per-session and re-derived on demand.
|
|
35
|
+
- **Coordinates are never identity.**
|
|
36
|
+
|
|
37
|
+
## Lifecycle
|
|
38
|
+
|
|
39
|
+
1. **Acquire** — derive a descriptor (AI, prior browser, selector hint).
|
|
40
|
+
2. **Resolve** — fiber-first candidates, DOM fallback, ranked.
|
|
41
|
+
3. **Inspect** — DOM, fiber props, hooks, owners, styles.
|
|
42
|
+
4. **Measure** — avalanche around an interaction.
|
|
43
|
+
5. **Maybe Apply** — when user intent and the P-15/P-16 gate permit, edit source and reload/HMR.
|
|
44
|
+
6. **Re-resolve** — confirm the probe still lands; compare.
|
|
45
|
+
7. **Handoff** — extension client → Playwright client via helper.
|
|
46
|
+
|
|
47
|
+
## Operations
|
|
48
|
+
|
|
49
|
+
All operations live in:
|
|
50
|
+
|
|
51
|
+
```
|
|
52
|
+
./browser-scripts/playwright-probes.js
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Session
|
|
56
|
+
- `launch({ browser, url, headless })`
|
|
57
|
+
- `close(session)`
|
|
58
|
+
- `goto(session, url, options?)`
|
|
59
|
+
- `reload(session, options?)`
|
|
60
|
+
|
|
61
|
+
### Probes
|
|
62
|
+
- `defineProbe({ id, intent, descriptor })`
|
|
63
|
+
- `registerProbe(session, probe)`
|
|
64
|
+
- `captureFromNode(session, locator)`
|
|
65
|
+
- `captureFromSelector(session, selector)`
|
|
66
|
+
- `resolveProbe(session, probe, options?)`
|
|
67
|
+
- `refreshProbe(session, probeId, options?)`
|
|
68
|
+
- `listProbes(session)`
|
|
69
|
+
- `removeProbe(session, probeId)`
|
|
70
|
+
|
|
71
|
+
### Inspect
|
|
72
|
+
- `probeDom(session, probe, parentLevel?)`
|
|
73
|
+
- `probeOwners(session, probe)`
|
|
74
|
+
- `probeOwner(session, probe, ownerIndex)`
|
|
75
|
+
- `probeProps(session, probe, ownerIndex?)`
|
|
76
|
+
- `probePropValue(session, probe, propName, ownerIndex?)`
|
|
77
|
+
- `probeHooks(session, probe)`
|
|
78
|
+
- `getComputedStyle(session, probe, parentLevel?)`
|
|
79
|
+
|
|
80
|
+
### Measure (avalanche)
|
|
81
|
+
|
|
82
|
+
The Playwright session connects to the helper as a normal client. All
|
|
83
|
+
avalanche calls go through the helper HTTP API; the helper drives
|
|
84
|
+
`__AVALANCHE__` on the page over the existing WS bridge. Playwright never
|
|
85
|
+
calls `__AVALANCHE__` directly.
|
|
86
|
+
|
|
87
|
+
Why route through the helper:
|
|
88
|
+
- one transport and explicit detector-install path
|
|
89
|
+
- one result format across extension and Playwright
|
|
90
|
+
- one place to reason about cross-session capture state
|
|
91
|
+
- helper is the context manager for everything Chippy does
|
|
92
|
+
|
|
93
|
+
Read flow (each call):
|
|
94
|
+
```
|
|
95
|
+
Playwright → helper HTTP /api/pages/:clientId/avalanche
|
|
96
|
+
→ WS to client → __CHIPPY.pageBridge.evalAvalanche
|
|
97
|
+
→ __AVALANCHE__.<action>
|
|
98
|
+
→ result back through WS → helper HTTP body → Playwright
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
How Playwright reads data:
|
|
102
|
+
- `clientId` is read once via `__CHIPPY.pageBridge.getState().clientId`
|
|
103
|
+
and cached on the session
|
|
104
|
+
- each avalanche call returns `{ ok, status, payload }` from the helper
|
|
105
|
+
- `payload` is the standard helper avalanche response (`action`, `available`,
|
|
106
|
+
`status`, `payload`, etc.)
|
|
107
|
+
- the actual data lives on the page in `__AVALANCHE__`; we only ever read it
|
|
108
|
+
through the helper
|
|
109
|
+
|
|
110
|
+
Operations:
|
|
111
|
+
- `avalanche(session, action, payload?)` — generic dispatcher
|
|
112
|
+
- `avalancheStatus(session)`
|
|
113
|
+
- `avalancheHotSources(session, limit?)`
|
|
114
|
+
- `avalancheExport(session, lastN?)`
|
|
115
|
+
- `reloadWithAvalanche(session, { settleMs?, hotLimit? })`
|
|
116
|
+
|
|
117
|
+
Supported generic actions are `install`, `uninstall`, `reset`/`clear`, `status`, `export`, `export-last`, `debug-hook`, `hot-sources`, `commit-list`, `commit-peek`, and `describe-action`. The module still exports legacy `avalancheStart`, `avalancheStop`, and `avalancheMetrics` wrappers for compatibility; do not use them in new workflows. `avalancheStart` is only an alias for `install`, while `stop` and `metrics` are not actions on the current bridge contract.
|
|
118
|
+
|
|
119
|
+
Helper base URL is `http://127.0.0.1:7823/__chippy` by default and can be
|
|
120
|
+
overridden with `CHIPPY_HELPER_BASE`.
|
|
121
|
+
|
|
122
|
+
### reloadWithAvalanche
|
|
123
|
+
|
|
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
|
+
|
|
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.
|
|
127
|
+
|
|
128
|
+
Flow:
|
|
129
|
+
1. `page.reload()` via Playwright
|
|
130
|
+
2. wait for the reinjected runtime and a fresh `clientId`
|
|
131
|
+
3. install the detector through the helper
|
|
132
|
+
4. settle for `settleMs` (default 3000)
|
|
133
|
+
5. read `status` and `hot-sources` through the helper
|
|
134
|
+
|
|
135
|
+
Returns:
|
|
136
|
+
```js
|
|
137
|
+
{
|
|
138
|
+
previousClientId,
|
|
139
|
+
clientId, // new clientId after reload
|
|
140
|
+
install, // explicit detector-install response
|
|
141
|
+
status, // helper avalanche-status response
|
|
142
|
+
hot, // helper hot-sources response
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
Notes:
|
|
147
|
+
- requires the session to have been started with `launch(...)`, which uses
|
|
148
|
+
`installHelpers({ init: true })` under the hood
|
|
149
|
+
- bump `settleMs` to 5000+ for heavy app loads
|
|
150
|
+
- this packaged init-script loader and the ad-hoc `addScriptTag` flow are two Mode A bootstrap variants; both require detector installation and both miss commits before that install
|
|
151
|
+
|
|
152
|
+
### Compare
|
|
153
|
+
- `snapshotProbe(session, probe)`
|
|
154
|
+
- `diffProbeSnapshots(a, b)`
|
|
155
|
+
|
|
156
|
+
## Operating rules
|
|
157
|
+
|
|
158
|
+
- **Probes are descriptors first.** Resolution is recomputed, not cached identity.
|
|
159
|
+
- **Fiber beats DOM** when scoring matches.
|
|
160
|
+
- **Strict identity wins** over fuzzy when both available.
|
|
161
|
+
- **No coordinates as identity.** Pixels never cross window boundaries.
|
|
162
|
+
- **Confidence is reported.** Low-confidence ops must be acknowledged.
|
|
163
|
+
- **Re-resolve after** any reload, navigation, code edit, HMR, route change.
|
|
164
|
+
- **Avalanche is per-session.** Probes interpret hot sources, not gate them.
|
|
165
|
+
- **Browser is Chromium or WebKit.** Never user's Chrome.
|
|
166
|
+
- **DRY:** the same shared runtime files power extension and Playwright.
|
|
167
|
+
|
|
168
|
+
## Handoff from extension to Playwright
|
|
169
|
+
|
|
170
|
+
Helper command:
|
|
171
|
+
```
|
|
172
|
+
./scripts/chippy.sh handoff-to-playwright <clientId> [url] [probeIdsCsv] [browserName] [headless]
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
What it does:
|
|
176
|
+
1. Captures live probe descriptors from the source extension client.
|
|
177
|
+
2. Launches Playwright Chromium and navigates to URL.
|
|
178
|
+
3. Injects shared __CHIPPY runtime via `playwright-session.js`.
|
|
179
|
+
4. Registers the new page as another helper client.
|
|
180
|
+
5. Returns descriptors so Playwright probe code can resolve them.
|
|
181
|
+
|
|
182
|
+
The Playwright session is then operated like any other helper client.
|
|
183
|
+
|
|
184
|
+
## When to use Playwright vs extension
|
|
185
|
+
|
|
186
|
+
Use the **extension**:
|
|
187
|
+
- user is exploring
|
|
188
|
+
- target is unclear
|
|
189
|
+
- live page already has the right state
|
|
190
|
+
- user needs to point at things
|
|
191
|
+
|
|
192
|
+
Use **Playwright**:
|
|
193
|
+
- iteration loop is repetitive (reload + interact + measure)
|
|
194
|
+
- target is already known via descriptor
|
|
195
|
+
- need a clean, controlled environment
|
|
196
|
+
- need reproducibility across runs
|
|
197
|
+
- user is not in front of the page
|
|
198
|
+
|
|
199
|
+
Both share:
|
|
200
|
+
- inspect-react.js
|
|
201
|
+
- layout-lab.js
|
|
202
|
+
- resolve-probes.js
|
|
203
|
+
- probe-descriptor.js
|
|
204
|
+
- avalanche.iife.js
|
|
205
|
+
- chippy-page-bridge.js
|