opendevbrowser 0.0.16 → 0.0.17

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 (210) hide show
  1. package/README.md +51 -27
  2. package/dist/browser/annotation-manager.d.ts +3 -0
  3. package/dist/browser/annotation-manager.d.ts.map +1 -1
  4. package/dist/browser/browser-manager.d.ts +6 -1
  5. package/dist/browser/browser-manager.d.ts.map +1 -1
  6. package/dist/browser/canvas-client.d.ts +53 -0
  7. package/dist/browser/canvas-client.d.ts.map +1 -0
  8. package/dist/browser/canvas-code-sync-manager.d.ts +79 -0
  9. package/dist/browser/canvas-code-sync-manager.d.ts.map +1 -0
  10. package/dist/browser/canvas-manager.d.ts +94 -0
  11. package/dist/browser/canvas-manager.d.ts.map +1 -0
  12. package/dist/browser/canvas-runtime-preview-bridge.d.ts +20 -0
  13. package/dist/browser/canvas-runtime-preview-bridge.d.ts.map +1 -0
  14. package/dist/browser/canvas-session-sync-manager.d.ts +21 -0
  15. package/dist/browser/canvas-session-sync-manager.d.ts.map +1 -0
  16. package/dist/browser/manager-types.d.ts +13 -1
  17. package/dist/browser/manager-types.d.ts.map +1 -1
  18. package/dist/browser/ops-browser-manager.d.ts +11 -1
  19. package/dist/browser/ops-browser-manager.d.ts.map +1 -1
  20. package/dist/canvas/code-sync/apply-tsx.d.ts +23 -0
  21. package/dist/canvas/code-sync/apply-tsx.d.ts.map +1 -0
  22. package/dist/canvas/code-sync/graph.d.ts +5 -0
  23. package/dist/canvas/code-sync/graph.d.ts.map +1 -0
  24. package/dist/canvas/code-sync/hash.d.ts +3 -0
  25. package/dist/canvas/code-sync/hash.d.ts.map +1 -0
  26. package/dist/canvas/code-sync/import.d.ts +18 -0
  27. package/dist/canvas/code-sync/import.d.ts.map +1 -0
  28. package/dist/canvas/code-sync/manifest.d.ts +5 -0
  29. package/dist/canvas/code-sync/manifest.d.ts.map +1 -0
  30. package/dist/canvas/code-sync/tsx-adapter.d.ts +8 -0
  31. package/dist/canvas/code-sync/tsx-adapter.d.ts.map +1 -0
  32. package/dist/canvas/code-sync/types.d.ts +152 -0
  33. package/dist/canvas/code-sync/types.d.ts.map +1 -0
  34. package/dist/canvas/code-sync/write.d.ts +9 -0
  35. package/dist/canvas/code-sync/write.d.ts.map +1 -0
  36. package/dist/canvas/document-store.d.ts +81 -0
  37. package/dist/canvas/document-store.d.ts.map +1 -0
  38. package/dist/canvas/export.d.ts +12 -0
  39. package/dist/canvas/export.d.ts.map +1 -0
  40. package/dist/canvas/repo-store.d.ts +10 -0
  41. package/dist/canvas/repo-store.d.ts.map +1 -0
  42. package/dist/canvas/surface-palette.d.ts +15 -0
  43. package/dist/canvas/surface-palette.d.ts.map +1 -0
  44. package/dist/canvas/types.d.ts +255 -0
  45. package/dist/canvas/types.d.ts.map +1 -0
  46. package/dist/canvas-runtime-preview-bridge-HBEHXM4T.js +7 -0
  47. package/dist/canvas-runtime-preview-bridge-HBEHXM4T.js.map +1 -0
  48. package/dist/{chunk-ST7CO5FA.js → chunk-5J3IFL3X.js} +11577 -13539
  49. package/dist/chunk-5J3IFL3X.js.map +1 -0
  50. package/dist/chunk-D633UO34.js +8149 -0
  51. package/dist/chunk-D633UO34.js.map +1 -0
  52. package/dist/{chunk-7W3SPXIB.js → chunk-FUSXMW3G.js} +4 -1
  53. package/dist/chunk-TBUCZX4A.js +34 -0
  54. package/dist/chunk-TBUCZX4A.js.map +1 -0
  55. package/dist/chunk-V7KUDHDG.js +276 -0
  56. package/dist/chunk-V7KUDHDG.js.map +1 -0
  57. package/dist/chunk-Y2KL55OG.js +59 -0
  58. package/dist/chunk-Y2KL55OG.js.map +1 -0
  59. package/dist/cli/args.d.ts +3 -3
  60. package/dist/cli/args.d.ts.map +1 -1
  61. package/dist/cli/commands/annotate.d.ts +11 -0
  62. package/dist/cli/commands/annotate.d.ts.map +1 -1
  63. package/dist/cli/commands/canvas.d.ts +45 -0
  64. package/dist/cli/commands/canvas.d.ts.map +1 -0
  65. package/dist/cli/commands/devtools/perf.d.ts.map +1 -1
  66. package/dist/cli/commands/devtools/screenshot.d.ts +1 -0
  67. package/dist/cli/commands/devtools/screenshot.d.ts.map +1 -1
  68. package/dist/cli/commands/dom/attr.d.ts.map +1 -1
  69. package/dist/cli/commands/dom/checked.d.ts.map +1 -1
  70. package/dist/cli/commands/dom/enabled.d.ts.map +1 -1
  71. package/dist/cli/commands/dom/html.d.ts.map +1 -1
  72. package/dist/cli/commands/dom/text.d.ts.map +1 -1
  73. package/dist/cli/commands/dom/value.d.ts.map +1 -1
  74. package/dist/cli/commands/dom/visible.d.ts.map +1 -1
  75. package/dist/cli/commands/export/clone-component.d.ts +9 -0
  76. package/dist/cli/commands/export/clone-component.d.ts.map +1 -1
  77. package/dist/cli/commands/export/clone-page.d.ts +8 -0
  78. package/dist/cli/commands/export/clone-page.d.ts.map +1 -1
  79. package/dist/cli/commands/interact/check.d.ts.map +1 -1
  80. package/dist/cli/commands/interact/click.d.ts.map +1 -1
  81. package/dist/cli/commands/interact/hover.d.ts.map +1 -1
  82. package/dist/cli/commands/interact/press.d.ts.map +1 -1
  83. package/dist/cli/commands/interact/scroll-into-view.d.ts.map +1 -1
  84. package/dist/cli/commands/interact/scroll.d.ts.map +1 -1
  85. package/dist/cli/commands/interact/select.d.ts.map +1 -1
  86. package/dist/cli/commands/interact/type.d.ts.map +1 -1
  87. package/dist/cli/commands/interact/uncheck.d.ts.map +1 -1
  88. package/dist/cli/commands/native.d.ts +12 -1
  89. package/dist/cli/commands/native.d.ts.map +1 -1
  90. package/dist/cli/commands/nav/goto.d.ts.map +1 -1
  91. package/dist/cli/commands/nav/snapshot.d.ts.map +1 -1
  92. package/dist/cli/commands/nav/wait.d.ts.map +1 -1
  93. package/dist/cli/commands/serve.d.ts +5 -0
  94. package/dist/cli/commands/serve.d.ts.map +1 -1
  95. package/dist/cli/commands/session/connect.d.ts.map +1 -1
  96. package/dist/cli/commands/status.d.ts +5 -0
  97. package/dist/cli/commands/status.d.ts.map +1 -1
  98. package/dist/cli/daemon-commands.d.ts.map +1 -1
  99. package/dist/cli/help.d.ts +5 -0
  100. package/dist/cli/help.d.ts.map +1 -1
  101. package/dist/cli/index.js +724 -163
  102. package/dist/cli/index.js.map +1 -1
  103. package/dist/cli/remote-canvas-manager.d.ts +8 -0
  104. package/dist/cli/remote-canvas-manager.d.ts.map +1 -0
  105. package/dist/cli/remote-manager.d.ts +3 -1
  106. package/dist/cli/remote-manager.d.ts.map +1 -1
  107. package/dist/cli/remote-relay.d.ts +2 -0
  108. package/dist/cli/remote-relay.d.ts.map +1 -1
  109. package/dist/cli/utils/parse.d.ts +1 -0
  110. package/dist/cli/utils/parse.d.ts.map +1 -1
  111. package/dist/core/bootstrap.d.ts.map +1 -1
  112. package/dist/core/types.d.ts +2 -0
  113. package/dist/core/types.d.ts.map +1 -1
  114. package/dist/fs-UMRKOBNN.js +7 -0
  115. package/dist/fs-UMRKOBNN.js.map +1 -0
  116. package/dist/index.d.ts.map +1 -1
  117. package/dist/index.js +192 -67
  118. package/dist/index.js.map +1 -1
  119. package/dist/{macros-NUBRM44Y.js → macros-ND2M7LWU.js} +2 -2
  120. package/dist/opendevbrowser.d.ts.map +1 -1
  121. package/dist/opendevbrowser.js +192 -67
  122. package/dist/opendevbrowser.js.map +1 -1
  123. package/dist/providers/index.d.ts.map +1 -1
  124. package/dist/providers/shopping/index.d.ts.map +1 -1
  125. package/dist/providers-G3LRHQXX.js +121 -0
  126. package/dist/providers-G3LRHQXX.js.map +1 -0
  127. package/dist/relay/protocol.d.ts +85 -3
  128. package/dist/relay/protocol.d.ts.map +1 -1
  129. package/dist/relay/relay-server.d.ts +14 -1
  130. package/dist/relay/relay-server.d.ts.map +1 -1
  131. package/dist/relay/relay-types.d.ts +3 -0
  132. package/dist/relay/relay-types.d.ts.map +1 -1
  133. package/dist/runtime-factory-BICHDPE7.js +13 -0
  134. package/dist/runtime-factory-BICHDPE7.js.map +1 -0
  135. package/dist/tools/annotate.d.ts.map +1 -1
  136. package/dist/tools/canvas.d.ts +4 -0
  137. package/dist/tools/canvas.d.ts.map +1 -0
  138. package/dist/tools/check.d.ts.map +1 -1
  139. package/dist/tools/click.d.ts.map +1 -1
  140. package/dist/tools/clone_component.d.ts.map +1 -1
  141. package/dist/tools/clone_page.d.ts.map +1 -1
  142. package/dist/tools/connect.d.ts.map +1 -1
  143. package/dist/tools/deps.d.ts +2 -0
  144. package/dist/tools/deps.d.ts.map +1 -1
  145. package/dist/tools/dom_get_html.d.ts.map +1 -1
  146. package/dist/tools/dom_get_text.d.ts.map +1 -1
  147. package/dist/tools/get_attr.d.ts.map +1 -1
  148. package/dist/tools/get_value.d.ts.map +1 -1
  149. package/dist/tools/goto.d.ts.map +1 -1
  150. package/dist/tools/hover.d.ts.map +1 -1
  151. package/dist/tools/index.d.ts.map +1 -1
  152. package/dist/tools/is_checked.d.ts.map +1 -1
  153. package/dist/tools/is_enabled.d.ts.map +1 -1
  154. package/dist/tools/is_visible.d.ts.map +1 -1
  155. package/dist/tools/launch.d.ts.map +1 -1
  156. package/dist/tools/macro_resolve.d.ts.map +1 -1
  157. package/dist/tools/perf.d.ts.map +1 -1
  158. package/dist/tools/press.d.ts.map +1 -1
  159. package/dist/tools/product_video_run.d.ts.map +1 -1
  160. package/dist/tools/research_run.d.ts.map +1 -1
  161. package/dist/tools/response.d.ts +4 -1
  162. package/dist/tools/response.d.ts.map +1 -1
  163. package/dist/tools/screenshot.d.ts.map +1 -1
  164. package/dist/tools/scroll.d.ts.map +1 -1
  165. package/dist/tools/scroll_into_view.d.ts.map +1 -1
  166. package/dist/tools/select.d.ts.map +1 -1
  167. package/dist/tools/shopping_run.d.ts.map +1 -1
  168. package/dist/tools/snapshot.d.ts.map +1 -1
  169. package/dist/tools/type.d.ts.map +1 -1
  170. package/dist/tools/uncheck.d.ts.map +1 -1
  171. package/dist/tools/wait.d.ts.map +1 -1
  172. package/dist/tools/workflow-runtime.d.ts +1 -2
  173. package/dist/tools/workflow-runtime.d.ts.map +1 -1
  174. package/extension/canvas.html +636 -0
  175. package/extension/dist/annotate-content.css +15 -6
  176. package/extension/dist/annotate-content.js +119 -9
  177. package/extension/dist/annotation-payload.js +163 -0
  178. package/extension/dist/background.js +148 -18
  179. package/extension/dist/canvas/canvas-runtime.js +1061 -0
  180. package/extension/dist/canvas/model.js +213 -0
  181. package/extension/dist/canvas/viewport-fit.js +67 -0
  182. package/extension/dist/canvas-page.js +1801 -0
  183. package/extension/dist/ops/dom-bridge.js +116 -3
  184. package/extension/dist/ops/ops-runtime.js +508 -44
  185. package/extension/dist/ops/ops-session-store.js +21 -114
  186. package/extension/dist/ops/target-session-coordinator.js +157 -0
  187. package/extension/dist/popup.js +155 -31
  188. package/extension/dist/services/ConnectionManager.js +17 -0
  189. package/extension/dist/services/RelayClient.js +9 -0
  190. package/extension/dist/services/TabManager.js +35 -12
  191. package/extension/dist/types.js +2 -0
  192. package/extension/manifest.json +1 -1
  193. package/extension/popup.html +52 -0
  194. package/package.json +6 -4
  195. package/skills/AGENTS.md +5 -2
  196. package/skills/opendevbrowser-best-practices/SKILL.md +71 -3
  197. package/skills/opendevbrowser-best-practices/artifacts/canvas-governance-playbook.md +141 -0
  198. package/skills/opendevbrowser-best-practices/artifacts/command-channel-reference.md +113 -17
  199. package/skills/opendevbrowser-best-practices/assets/templates/canvas-blocker-checklist.json +70 -0
  200. package/skills/opendevbrowser-best-practices/assets/templates/canvas-feedback-eval.json +73 -0
  201. package/skills/opendevbrowser-best-practices/assets/templates/canvas-generation-plan.v1.json +67 -0
  202. package/skills/opendevbrowser-best-practices/assets/templates/canvas-handshake-example.json +126 -0
  203. package/skills/opendevbrowser-best-practices/assets/templates/robustness-checklist.json +57 -0
  204. package/skills/opendevbrowser-best-practices/assets/templates/surface-audit-checklist.json +7 -3
  205. package/skills/opendevbrowser-best-practices/scripts/odb-workflow.sh +26 -0
  206. package/skills/opendevbrowser-best-practices/scripts/run-robustness-audit.sh +82 -1
  207. package/skills/opendevbrowser-best-practices/scripts/validate-skill-assets.sh +225 -84
  208. package/dist/chunk-ST7CO5FA.js.map +0 -1
  209. /package/dist/{chunk-7W3SPXIB.js.map → chunk-FUSXMW3G.js.map} +0 -0
  210. /package/dist/{macros-NUBRM44Y.js.map → macros-ND2M7LWU.js.map} +0 -0
@@ -98,6 +98,9 @@ export class RelayClient {
98
98
  this.handlers.onOpsMessage?.(record);
99
99
  return;
100
100
  }
101
+ if (isCanvasEnvelope(record)) {
102
+ this.handlers.onCanvasMessage?.(record);
103
+ }
101
104
  });
102
105
  this.socket.addEventListener("close", (event) => {
103
106
  if (this.pendingHandshakeAckReject) {
@@ -181,6 +184,9 @@ export class RelayClient {
181
184
  sendOpsMessage(message) {
182
185
  this.send(message);
183
186
  }
187
+ sendCanvasMessage(message) {
188
+ this.send(message);
189
+ }
184
190
  async sendHealthCheck(timeoutMs = 1500) {
185
191
  return await this.sendPing(timeoutMs);
186
192
  }
@@ -272,3 +278,6 @@ const isValidPong = (value) => {
272
278
  const isOpsEnvelope = (value) => {
273
279
  return typeof value.type === "string" && value.type.startsWith("ops_");
274
280
  };
281
+ const isCanvasEnvelope = (value) => {
282
+ return typeof value.type === "string" && value.type.startsWith("canvas_");
283
+ };
@@ -16,33 +16,56 @@ export class TabManager {
16
16
  });
17
17
  }
18
18
  async waitForTabComplete(tabId, timeoutMs = 10000) {
19
- const existing = await this.getTab(tabId);
20
- if (existing?.status === "complete") {
19
+ const isComplete = async () => {
20
+ const current = await this.getTab(tabId);
21
+ return current?.status === "complete";
22
+ };
23
+ if (await isComplete()) {
21
24
  return;
22
25
  }
23
26
  await new Promise((resolve, reject) => {
24
27
  let settled = false;
25
- const timeoutId = setTimeout(() => {
28
+ let pollId = null;
29
+ const settle = (error) => {
26
30
  if (settled)
27
31
  return;
28
32
  settled = true;
33
+ clearTimeout(timeoutId);
34
+ if (pollId !== null) {
35
+ clearInterval(pollId);
36
+ }
29
37
  chrome.tabs.onUpdated.removeListener(listener);
30
- reject(new Error("Tab load timeout"));
38
+ if (error) {
39
+ reject(error);
40
+ return;
41
+ }
42
+ resolve();
43
+ };
44
+ const timeoutId = setTimeout(() => {
45
+ settle(new Error("Tab load timeout"));
31
46
  }, timeoutMs);
32
- const listener = (updatedId, changeInfo) => {
47
+ const listener = (updatedId, changeInfo, tab) => {
33
48
  if (updatedId !== tabId) {
34
49
  return;
35
50
  }
36
- if (changeInfo.status === "complete") {
37
- if (settled)
38
- return;
39
- settled = true;
40
- clearTimeout(timeoutId);
41
- chrome.tabs.onUpdated.removeListener(listener);
42
- resolve();
51
+ if (changeInfo.status === "complete" || tab?.status === "complete") {
52
+ settle();
43
53
  }
44
54
  };
45
55
  chrome.tabs.onUpdated.addListener(listener);
56
+ const poll = () => {
57
+ void isComplete()
58
+ .then((complete) => {
59
+ if (complete) {
60
+ settle();
61
+ }
62
+ })
63
+ .catch(() => {
64
+ // Ignore transient tab lookup failures and let the timeout decide.
65
+ });
66
+ };
67
+ pollId = setInterval(poll, Math.min(250, Math.max(50, Math.floor(timeoutMs / 20))));
68
+ poll();
46
69
  });
47
70
  }
48
71
  async closeTab(tabId) {
@@ -1,3 +1,5 @@
1
1
  export const OPS_PROTOCOL_VERSION = "1";
2
2
  export const MAX_OPS_PAYLOAD_BYTES = 12 * 1024 * 1024;
3
3
  export const MAX_SNAPSHOT_BYTES = 2 * 1024 * 1024;
4
+ export const CANVAS_PROTOCOL_VERSION = "1";
5
+ export const MAX_CANVAS_PAYLOAD_BYTES = 12 * 1024 * 1024;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "manifest_version": 3,
3
3
  "name": "OpenDevBrowser Relay",
4
- "version": "0.0.16",
4
+ "version": "0.0.17",
5
5
  "description": "Optional bridge to reuse existing Chrome tabs with OpenDevBrowser.",
6
6
  "permissions": [
7
7
  "debugger",
@@ -376,6 +376,51 @@
376
376
  gap: 10px;
377
377
  }
378
378
 
379
+ .annotation-list {
380
+ display: grid;
381
+ gap: 8px;
382
+ margin-top: 10px;
383
+ max-height: 180px;
384
+ overflow: auto;
385
+ }
386
+
387
+ .annotation-item {
388
+ display: grid;
389
+ gap: 8px;
390
+ padding: 10px;
391
+ border-radius: 12px;
392
+ border: 1px solid var(--stroke);
393
+ background: var(--panel-strong);
394
+ }
395
+
396
+ .annotation-item-summary {
397
+ font-size: 11px;
398
+ color: var(--text);
399
+ line-height: 1.4;
400
+ word-break: break-word;
401
+ }
402
+
403
+ .annotation-item-meta {
404
+ font-size: 10px;
405
+ color: var(--muted);
406
+ }
407
+
408
+ .annotation-item-actions {
409
+ display: grid;
410
+ grid-template-columns: repeat(2, minmax(0, 1fr));
411
+ gap: 8px;
412
+ }
413
+
414
+ .annotation-empty {
415
+ font-size: 10px;
416
+ color: var(--muted);
417
+ text-align: center;
418
+ padding: 12px;
419
+ border-radius: 12px;
420
+ border: 1px dashed var(--stroke);
421
+ background: rgba(255, 255, 255, 0.03);
422
+ }
423
+
379
424
  @media (prefers-reduced-motion: reduce) {
380
425
  * {
381
426
  transition: none !important;
@@ -503,6 +548,13 @@
503
548
  <button id="annotationStart" class="secondary">Annotate</button>
504
549
  <button id="annotationCopy" class="secondary" disabled>Copy payload</button>
505
550
  </div>
551
+ <div class="button-row">
552
+ <button id="annotationSend" class="secondary" disabled>Send to agent</button>
553
+ <button id="annotationRefresh" class="secondary">Refresh payload</button>
554
+ </div>
555
+ <div id="annotationItems" class="annotation-list">
556
+ <div class="annotation-empty">No annotation items available.</div>
557
+ </div>
506
558
  </section>
507
559
 
508
560
  <button id="toggle" class="primary">Connect</button>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opendevbrowser",
3
- "version": "0.0.16",
3
+ "version": "0.0.17",
4
4
  "description": "OpenCode plugin for browser automation via CDP with snapshot-refs-actions workflow",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -12,6 +12,7 @@
12
12
  "dist",
13
13
  "skills",
14
14
  "scripts/native",
15
+ "extension/canvas.html",
15
16
  "extension/manifest.json",
16
17
  "extension/popup.html",
17
18
  "extension/dist",
@@ -41,7 +42,7 @@
41
42
  "dev": "tsup src/index.ts src/cli/index.ts --format esm --dts --watch",
42
43
  "lint": "eslint \"src/**/*.ts\" \"tests/**/*.ts\"",
43
44
  "typecheck": "tsc --noEmit -p tsconfig.json",
44
- "test": "vitest run --coverage",
45
+ "test": "node --input-type=module -e \"import { mkdirSync } from 'node:fs'; mkdirSync('coverage/.tmp', { recursive: true });\" && vitest run --coverage",
45
46
  "test:release-gate": "node scripts/release-gate-test-groups.mjs",
46
47
  "test:release-gate:g1": "node scripts/release-gate-test-groups.mjs --group 1",
47
48
  "test:release-gate:g2": "node scripts/release-gate-test-groups.mjs --group 2",
@@ -50,7 +51,7 @@
50
51
  "test:release-gate:g5": "node scripts/release-gate-test-groups.mjs --group 5",
51
52
  "extension:sync": "node scripts/sync-extension-version.mjs",
52
53
  "extension:build": "npm run extension:sync && tsc -p extension/tsconfig.json && node scripts/copy-extension-assets.mjs",
53
- "extension:pack": "cd extension && zip -r ../opendevbrowser-extension.zip manifest.json popup.html dist/ icons/",
54
+ "extension:pack": "cd extension && zip -r ../opendevbrowser-extension.zip manifest.json popup.html canvas.html dist/ icons/",
54
55
  "extension:store": "node scripts/chrome-store-publish.mjs",
55
56
  "version:check": "node scripts/verify-versions.mjs",
56
57
  "prepack": "npm run version:check && npm run build && npm run extension:build"
@@ -61,7 +62,9 @@
61
62
  "async-mutex": "^0.5.0",
62
63
  "jsonc-parser": "^3.2.0",
63
64
  "playwright-core": "^1.58.2",
65
+ "typescript": "^5.9.3",
64
66
  "ws": "^8.19.0",
67
+ "yjs": "^13.6.29",
65
68
  "zod": "^3.25.76"
66
69
  },
67
70
  "devDependencies": {
@@ -74,7 +77,6 @@
74
77
  "eslint": "^9.39.3",
75
78
  "happy-dom": "^20.7.0",
76
79
  "tsup": "^8.5.1",
77
- "typescript": "^5.9.3",
78
80
  "vitest": "^4.0.18"
79
81
  }
80
82
  }
package/skills/AGENTS.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # skills/ — Agent Guidelines
2
2
 
3
- Bundled canonical skill packs (8 total). Extends root `AGENTS.md`.
3
+ Bundled canonical OpenDevBrowser skill packs (8 total) plus shared compatibility dirs (`research/`, `shopping/`). Extends root `AGENTS.md`.
4
4
 
5
5
  ## Structure
6
6
 
@@ -13,7 +13,9 @@ skills/
13
13
  ├── opendevbrowser-data-extraction/SKILL.md
14
14
  ├── opendevbrowser-research/SKILL.md
15
15
  ├── opendevbrowser-shopping/SKILL.md
16
- └── opendevbrowser-product-presentation-asset/SKILL.md
16
+ ├── opendevbrowser-product-presentation-asset/SKILL.md
17
+ ├── research/ # Empty compatibility alias dir; keep non-canonical
18
+ └── shopping/ # Empty compatibility alias dir; keep non-canonical
17
19
  ```
18
20
 
19
21
  ## SKILL.md Format
@@ -50,6 +52,7 @@ Content organized by topic for filtering.
50
52
  - Examples must use `opendevbrowser_*` tool names
51
53
  - Never include secrets or page data in content
52
54
  - Keep canonical guidance in `opendevbrowser-*` packs; do not add legacy alias directories.
55
+ - Leave `skills/research/` and `skills/shopping/` empty unless a verified migration plan explicitly repurposes them.
53
56
  - Match the snapshot → refs → actions flow in `docs/ARCHITECTURE.md` and tool list in `docs/CLI.md`.
54
57
  - Note that extension relay requires Chrome 125+ and uses hub-only relay ownership when enabled.
55
58
  - Refer to root `AGENTS.md` for connection flag/status semantics (extensionConnected, handshake, cdpConnected, pairingRequired).
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: opendevbrowser-best-practices
3
3
  description: This skill should be used when the user asks to design or run OpenDevBrowser provider workflows, scraping pipelines, QA/debug automation, parity checks across modes, or resilient browser operations with codified scripts and artifacts.
4
- version: 2.3.0
4
+ version: 2.5.0
5
5
  ---
6
6
 
7
7
  # OpenDevBrowser Best Practices
@@ -23,12 +23,17 @@ Use this skill when you need:
23
23
  - `artifacts/fingerprint-tiers.md` — hardening tiers and when to use each.
24
24
  - `artifacts/macro-workflows.md` — macro design and expansion standards.
25
25
  - `artifacts/browser-agent-known-issues-matrix.md` — known browser-agent failure modes mapped to required controls.
26
- - `artifacts/command-channel-reference.md` — CLI/tool/`/ops`/`/cdp` surface map plus cross-agent skill-sync targets.
26
+ - `artifacts/command-channel-reference.md` — CLI/tool/`/ops`/`/canvas`/`/cdp` surface map plus cross-agent skill-sync targets.
27
+ - `artifacts/canvas-governance-playbook.md` — `/canvas` preflight, blocker, and feedback-evaluation guidance.
27
28
  - `assets/templates/mode-flag-matrix.json` — mode + flag verification template.
28
29
  - `assets/templates/ops-request-envelope.json` — `/ops` request envelope template.
29
30
  - `assets/templates/cdp-forward-envelope.json` — `/cdp` relay envelope template.
30
31
  - `assets/templates/robustness-checklist.json` — shared issue-status checklist for workflow robustness audits.
31
32
  - `assets/templates/surface-audit-checklist.json` — docs/surface audit checklist template.
33
+ - `assets/templates/canvas-handshake-example.json` — canonical `/canvas` handshake example.
34
+ - `assets/templates/canvas-generation-plan.v1.json` — required `canvas.plan.set` request skeleton.
35
+ - `assets/templates/canvas-feedback-eval.json` — target-attributed feedback evaluation checklist.
36
+ - `assets/templates/canvas-blocker-checklist.json` — machine-readable blocker and warning audit map.
32
37
  - `scripts/odb-workflow.sh` — prints codified command sequences by workflow.
33
38
  - `scripts/run-robustness-audit.sh` — validates workflow skill coverage against known issue IDs.
34
39
  - `scripts/validate-skill-assets.sh` — validates required artifacts/templates.
@@ -53,6 +58,7 @@ Use this skill when you need:
53
58
 
54
59
  ```bash
55
60
  npx opendevbrowser --help
61
+ npx opendevbrowser help
56
62
  ```
57
63
 
58
64
  5. Run robustness coverage checks across workflow skills:
@@ -170,6 +176,8 @@ Use the router script to avoid retyping flows:
170
176
  ./skills/opendevbrowser-best-practices/scripts/odb-workflow.sh cdp-channel-check
171
177
  ./skills/opendevbrowser-best-practices/scripts/odb-workflow.sh mode-flag-matrix
172
178
  ./skills/opendevbrowser-best-practices/scripts/odb-workflow.sh robustness-audit
179
+ ./skills/opendevbrowser-best-practices/scripts/odb-workflow.sh canvas-preflight
180
+ ./skills/opendevbrowser-best-practices/scripts/odb-workflow.sh canvas-feedback-eval
173
181
  ```
174
182
 
175
183
  ## Modes and Surface Parity
@@ -194,9 +202,69 @@ node scripts/provider-live-matrix.mjs --use-global-env --skip-live-regression --
194
202
  ```
195
203
 
196
204
  Surface inventory source of truth:
197
- - `docs/SURFACE_REFERENCE.md` (55 CLI commands, 48 tools, 38 `/ops` commands, `/cdp` envelope contracts)
205
+ - `docs/SURFACE_REFERENCE.md` (56 CLI commands, 49 tools, 38 `/ops` commands, 26 `/canvas` commands, `/cdp` envelope contracts; mirrored by `npx opendevbrowser --help` and `npx opendevbrowser help`)
198
206
  - `artifacts/command-channel-reference.md` (skill-pack operational digest)
199
207
 
208
+ ## Canvas Governance Handshake
209
+
210
+ Use the design-canvas surface when the workflow needs persisted design documents, explicit governance state, preview tabs, or overlay selection.
211
+
212
+ Recommended command order:
213
+ 1. `opendevbrowser_canvas` or `opendevbrowser canvas --command canvas.session.open` to get `canvasSessionId`, `leaseId`, `preflightState`, governance block states, and generation-plan requirements.
214
+ 2. Read the handshake before mutating. The handshake is the source of truth for:
215
+ - `governanceRequirements.requiredBeforeMutation`
216
+ - `governanceRequirements.requiredBeforeSave`
217
+ - `generationPlanRequirements.requiredBeforeMutation`
218
+ - `allowedLibraries`
219
+ - `mutationPolicy.allowedBeforePlan`
220
+ - treat `allowedLibraries.components`, `allowedLibraries.icons`, and `allowedLibraries.styling` as separate policy lanes:
221
+ `components` are reusable UI adapters such as `shadcn`,
222
+ `icons` are approved icon families,
223
+ `styling` is for utility/theme adapters such as `tailwindcss`
224
+ 3. Submit `canvas.plan.set` with all required non-empty objects:
225
+ - `targetOutcome`
226
+ - `visualDirection`
227
+ - `layoutStrategy`
228
+ - `contentStrategy`
229
+ - `componentStrategy`
230
+ - `motionPosture`
231
+ - `responsivePosture`
232
+ - `accessibilityPosture`
233
+ - `validationTargets`
234
+ 4. Only after the plan is accepted, call `canvas.document.patch`.
235
+ 5. Use `canvas.preview.render`, `canvas.tab.open`, `canvas.overlay.mount`, and `canvas.overlay.select` when a browser-backed live view is required.
236
+ 6. Use `canvas.feedback.poll` between mutation rounds and `canvas.document.save` or `canvas.document.export` to persist artifacts.
237
+
238
+ Code-sync surface:
239
+ - `canvas.session.attach` joins an existing canvas session as an `observer` or reclaims the write lease with `attachMode=lease_reclaim`.
240
+ - `canvas.code.bind`, `canvas.code.unbind`, `canvas.code.pull`, `canvas.code.push`, `canvas.code.status`, and `canvas.code.resolve` manage TSX-first document bindings when a canvas file is round-tripped to repo code.
241
+
242
+ Current `/canvas` parity notes:
243
+ - All 26 public `canvas.*` commands are agent-callable through `opendevbrowser_canvas` and `opendevbrowser canvas --command ...`.
244
+ - `canvas.feedback.subscribe` live streaming is public through the CLI only: use `--output-format stream-json` for the built-in polling bridge.
245
+ - Tool-driven agents can achieve the same behavior by calling `canvas.feedback.subscribe` once and then looping on `canvas.feedback.poll` with the returned cursor.
246
+ - `canvas.tab.sync` and `canvas.overlay.sync` are internal extension runtime helpers, not public commands.
247
+ - `canvas_html` is still the default preview/export contract. `bound_app_runtime` is opt-in and only valid when runtime preflight and app-side instrumentation succeed.
248
+ - Component and icon libraries currently render semantically, not package-faithfully. Treat `shadcn`, `tailwindcss`, `tabler`, `microsoft-fluent-ui-system-icons`, `3dicons`, and `@lobehub/fluent-emoji-3d` as metadata and constrained render lanes, not as general library import/export parity.
249
+ - Annotation remains a separate surface today, but popup and canvas both ship per-item and combined `Copy` / `Send` actions. The remaining gap is that `Send` persists payloads for later `annotate --stored` retrieval instead of proactively injecting them into the active agent chat.
250
+
251
+ Tailwind usage rule:
252
+ - When `allowedLibraries.styling` includes `tailwindcss`, use it for layout, spacing, responsive, and state styling over canonical tokens/theme variables.
253
+ - Do not treat Tailwind as a component inventory source or mix it into `componentStrategy.approvedLibraries`.
254
+ - Preview/export should materialize a deterministic utility-class layer and stay self-contained; do not depend on a remote Tailwind CDN for canvas preview correctness.
255
+
256
+ Failure handling:
257
+ - `plan_required`: immediately call `canvas.plan.set`.
258
+ - `revision_conflict`: reload with `canvas.document.load` and replay the patch batch against the latest revision.
259
+ - `unsupported_target` or `restricted_url`: move the preview to a normal http(s) tab or fall back to managed mode.
260
+
261
+ Operational references:
262
+ - `artifacts/canvas-governance-playbook.md`
263
+ - `assets/templates/canvas-handshake-example.json`
264
+ - `assets/templates/canvas-generation-plan.v1.json`
265
+ - `assets/templates/canvas-feedback-eval.json`
266
+ - `assets/templates/canvas-blocker-checklist.json`
267
+
200
268
  ## Diagnostics and Traceability
201
269
 
202
270
  Current diagnostics tools:
@@ -0,0 +1,141 @@
1
+ # Canvas Governance Playbook
2
+
3
+ ## Purpose
4
+
5
+ Use this playbook before any `/canvas` mutation and during every design-feedback loop. It keeps the runtime handshake, governance state, and evaluation rules aligned with the design-canvas spec.
6
+
7
+ ## Required command order
8
+
9
+ 1. `canvas.session.open`
10
+ 2. Read the handshake and confirm `preflightState: "handshake_read"`
11
+ 3. `canvas.plan.set`
12
+ 4. `canvas.plan.get` or `canvas.capabilities.get` until the runtime reports `plan_accepted`
13
+ 5. `canvas.document.patch`
14
+ 6. `canvas.preview.render` or `canvas.tab.open`
15
+ 7. `canvas.feedback.poll`
16
+ 8. `canvas.document.save` or `canvas.document.export`
17
+
18
+ Mutation is blocked until the handshake has been read and the plan is accepted. A save is still invalid when required governance blocks remain missing in `requiredBeforeSave`.
19
+
20
+ ## Handshake requirements
21
+
22
+ Every `canvas.session.open` response is the runtime contract. Read these fields before sending a patch:
23
+
24
+ - `canvasSessionId`
25
+ - `browserSessionId`
26
+ - `documentId`
27
+ - `leaseId`
28
+ - `preflightState`
29
+ - `governanceRequirements.requiredBeforeMutation`
30
+ - `governanceRequirements.requiredBeforeSave`
31
+ - `generationPlanRequirements.requiredBeforeMutation`
32
+ - `allowedLibraries`
33
+ - `allowedBeforePlan`
34
+
35
+ Interpret `allowedLibraries` by lane:
36
+ - `components` are reusable UI adapters such as `shadcn`
37
+ - `icons` are approved icon families
38
+ - `styling` is for utility/theme adapters such as `tailwindcss`
39
+ - do not mix icon or styling libraries into `componentStrategy.approvedLibraries`
40
+
41
+ Preflight states:
42
+ - `handshake_read`
43
+ - `plan_submitted`
44
+ - `plan_accepted`
45
+ - `patching_enabled`
46
+
47
+ ## Governance blocks
48
+
49
+ The document must declare `designGovernance` with at least:
50
+
51
+ - `intent`
52
+ - `designLanguage`
53
+ - `contentModel`
54
+ - `layoutSystem`
55
+ - `typographySystem`
56
+ - `colorSystem`
57
+ - `surfaceSystem`
58
+ - `iconSystem`
59
+ - `motionSystem`
60
+ - `responsiveSystem`
61
+ - `accessibilityPolicy`
62
+ - `libraryPolicy`
63
+ - `runtimeBudgets`
64
+
65
+ The first accepted `generationPlan` must include:
66
+
67
+ - `targetOutcome`
68
+ - `visualDirection`
69
+ - `layoutStrategy`
70
+ - `contentStrategy`
71
+ - `componentStrategy`
72
+ - `motionPosture`
73
+ - `responsivePosture`
74
+ - `accessibilityPosture`
75
+ - `validationTargets`
76
+
77
+ ## Blocker handling
78
+
79
+ Canonical blocker path:
80
+
81
+ ```json
82
+ {
83
+ "code": "plan_required",
84
+ "blockingCommand": "canvas.document.patch",
85
+ "requiredNextCommands": ["canvas.plan.set"],
86
+ "details": { "auditId": "CANVAS-01" }
87
+ }
88
+ ```
89
+
90
+ If `canvas.document.patch` or `canvas.document.save` returns a blocker, stop mutating and fix the missing handshake, governance, or plan requirement before retrying.
91
+
92
+ ## Canvas robustness issue classes
93
+
94
+ | Audit ID | Failure class | Typical signal | Required response |
95
+ |---|---|---|---|
96
+ | `CANVAS-01` | Handshake missing or unread before mutation | `plan_required`, missing `handshake_read` evidence | Re-run `canvas.session.open` or `canvas.capabilities.get`, then `canvas.plan.set` |
97
+ | `CANVAS-02` | Required governance block missing | save blocker, empty `requiredBeforeSave`, validation warning | Fill missing `designGovernance.*` fields before save/export |
98
+ | `CANVAS-03` | Required `generationPlan` field missing or malformed | `canvas.plan.set` rejected or warnings retained | Submit a complete plan and wait for acceptance |
99
+ | `CANVAS-04` | Library or icon-policy violation | validation warning, policy blocker, downgraded export | Adjust component/library choice to match `libraryPolicy` and `iconSystem` |
100
+ | `CANVAS-05` | Unsupported target or overlay mount failure | `unsupported_target`, `restricted_url`, overlay mount error | Move to a normal http(s) preview target or managed mode |
101
+ | `CANVAS-06` | Runtime budget exceeded or preview downgrade ignored | degrade warning, overflowed media/fonts/telemetry budget | Reduce preview cost or accept the downgrade before proceeding |
102
+ | `CANVAS-07` | Feedback missing target attribution or validation metadata | feedback lacks `targetId`, `pageId`, `class`, or `evidenceRefs` | Re-poll or fix the feedback source before trusting the result |
103
+
104
+ ## Feedback evaluation loop
105
+
106
+ Required categories:
107
+
108
+ - `render`
109
+ - `console`
110
+ - `network`
111
+ - `validation`
112
+ - `performance`
113
+ - `asset`
114
+ - `export`
115
+
116
+ Required fields per feedback item:
117
+
118
+ - `documentId`
119
+ - `pageId`
120
+ - `prototypeId`
121
+ - `targetId`
122
+ - `documentRevision`
123
+ - `severity`
124
+ - `class`
125
+ - `message`
126
+ - `evidenceRefs`
127
+
128
+ Streaming checks:
129
+
130
+ - `feedback.item` carries the canonical feedback payload
131
+ - `feedback.heartbeat` proves the subscription is still alive
132
+ - `feedback.complete` explains why the stream ended
133
+
134
+ ## Router and template references
135
+
136
+ - `scripts/odb-workflow.sh canvas-preflight`
137
+ - `scripts/odb-workflow.sh canvas-feedback-eval`
138
+ - `assets/templates/canvas-handshake-example.json`
139
+ - `assets/templates/canvas-generation-plan.v1.json`
140
+ - `assets/templates/canvas-feedback-eval.json`
141
+ - `assets/templates/canvas-blocker-checklist.json`