screenhand 0.1.1 → 0.3.0

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 (241) hide show
  1. package/README.md +193 -109
  2. package/bin/darwin-arm64/macos-bridge +0 -0
  3. package/dist/mcp-desktop.js +5876 -0
  4. package/dist/scripts/codex-monitor-daemon.js +335 -0
  5. package/dist/scripts/export-help-center.js +112 -0
  6. package/dist/scripts/marketing-loop.js +117 -0
  7. package/dist/scripts/observer-daemon.js +288 -0
  8. package/dist/scripts/orchestrator-daemon.js +399 -0
  9. package/dist/scripts/supervisor-daemon.js +272 -0
  10. package/dist/scripts/threads-campaign.js +208 -0
  11. package/dist/scripts/worker-daemon.js +228 -0
  12. package/dist/src/agent/cli.js +82 -0
  13. package/dist/src/agent/loop.js +274 -0
  14. package/dist/src/community/fetcher.js +109 -0
  15. package/dist/src/community/index.js +6 -0
  16. package/dist/src/community/publisher.js +191 -0
  17. package/dist/src/community/remote-api.js +121 -0
  18. package/dist/src/community/types.js +3 -0
  19. package/dist/src/community/validator.js +95 -0
  20. package/{src/config.ts → dist/src/config.js} +5 -10
  21. package/dist/src/context-tracker.js +489 -0
  22. package/{src/index.ts → dist/src/index.js} +32 -52
  23. package/dist/src/ingestion/coverage-auditor.js +233 -0
  24. package/dist/src/ingestion/doc-parser.js +164 -0
  25. package/dist/src/ingestion/index.js +8 -0
  26. package/dist/src/ingestion/menu-scanner.js +152 -0
  27. package/dist/src/ingestion/reference-merger.js +186 -0
  28. package/dist/src/ingestion/shortcut-extractor.js +180 -0
  29. package/dist/src/ingestion/tutorial-extractor.js +170 -0
  30. package/dist/src/ingestion/types.js +3 -0
  31. package/dist/src/jobs/manager.js +305 -0
  32. package/dist/src/jobs/runner.js +806 -0
  33. package/dist/src/jobs/store.js +102 -0
  34. package/dist/src/jobs/types.js +30 -0
  35. package/dist/src/jobs/worker.js +97 -0
  36. package/dist/src/learning/engine.js +356 -0
  37. package/dist/src/learning/index.js +9 -0
  38. package/dist/src/learning/locator-policy.js +120 -0
  39. package/dist/src/learning/pattern-policy.js +89 -0
  40. package/dist/src/learning/recovery-policy.js +116 -0
  41. package/dist/src/learning/sensor-policy.js +115 -0
  42. package/dist/src/learning/timing-model.js +204 -0
  43. package/dist/src/learning/topology-policy.js +90 -0
  44. package/dist/src/learning/types.js +9 -0
  45. package/dist/src/logging/timeline-logger.js +48 -0
  46. package/dist/src/mcp/mcp-stdio-server.js +464 -0
  47. package/dist/src/mcp/server.js +363 -0
  48. package/dist/src/mcp-entry.js +60 -0
  49. package/dist/src/memory/playbook-seeds.js +200 -0
  50. package/dist/src/memory/recall.js +222 -0
  51. package/dist/src/memory/research.js +104 -0
  52. package/dist/src/memory/seeds.js +101 -0
  53. package/dist/src/memory/service.js +446 -0
  54. package/dist/src/memory/session.js +169 -0
  55. package/dist/src/memory/store.js +451 -0
  56. package/{src/runtime/locator-cache.ts → dist/src/memory/types.js} +1 -17
  57. package/dist/src/monitor/codex-monitor.js +382 -0
  58. package/dist/src/monitor/task-queue.js +97 -0
  59. package/dist/src/monitor/types.js +62 -0
  60. package/dist/src/native/bridge-client.js +412 -0
  61. package/{src/native/macos-bridge-client.ts → dist/src/native/macos-bridge-client.js} +0 -1
  62. package/dist/src/observer/state.js +199 -0
  63. package/dist/src/observer/types.js +43 -0
  64. package/dist/src/orchestrator/state.js +68 -0
  65. package/dist/src/orchestrator/types.js +22 -0
  66. package/dist/src/perception/ax-source.js +162 -0
  67. package/dist/src/perception/cdp-source.js +162 -0
  68. package/dist/src/perception/coordinator.js +771 -0
  69. package/dist/src/perception/frame-differ.js +287 -0
  70. package/dist/src/perception/index.js +22 -0
  71. package/dist/src/perception/manager.js +199 -0
  72. package/dist/src/perception/types.js +47 -0
  73. package/dist/src/perception/vision-source.js +399 -0
  74. package/dist/src/planner/deterministic.js +298 -0
  75. package/dist/src/planner/executor.js +870 -0
  76. package/dist/src/planner/goal-store.js +92 -0
  77. package/dist/src/planner/index.js +21 -0
  78. package/dist/src/planner/planner.js +520 -0
  79. package/dist/src/planner/tool-registry.js +71 -0
  80. package/dist/src/planner/types.js +22 -0
  81. package/dist/src/platform/explorer.js +213 -0
  82. package/dist/src/platform/help-center-markdown.js +527 -0
  83. package/dist/src/platform/learner.js +257 -0
  84. package/dist/src/playbook/engine.js +486 -0
  85. package/dist/src/playbook/index.js +20 -0
  86. package/dist/src/playbook/mcp-recorder.js +204 -0
  87. package/dist/src/playbook/recorder.js +536 -0
  88. package/dist/src/playbook/runner.js +408 -0
  89. package/dist/src/playbook/store.js +312 -0
  90. package/dist/src/playbook/types.js +17 -0
  91. package/dist/src/recovery/detectors.js +156 -0
  92. package/dist/src/recovery/engine.js +327 -0
  93. package/dist/src/recovery/index.js +20 -0
  94. package/dist/src/recovery/strategies.js +274 -0
  95. package/dist/src/recovery/types.js +20 -0
  96. package/dist/src/runtime/accessibility-adapter.js +430 -0
  97. package/dist/src/runtime/app-adapter.js +64 -0
  98. package/dist/src/runtime/applescript-adapter.js +305 -0
  99. package/dist/src/runtime/ax-role-map.js +96 -0
  100. package/dist/src/runtime/browser-adapter.js +52 -0
  101. package/dist/src/runtime/cdp-chrome-adapter.js +521 -0
  102. package/dist/src/runtime/composite-adapter.js +221 -0
  103. package/dist/src/runtime/execution-contract.js +159 -0
  104. package/dist/src/runtime/executor.js +286 -0
  105. package/dist/src/runtime/locator-cache.js +50 -0
  106. package/dist/src/runtime/planning-loop.js +63 -0
  107. package/dist/src/runtime/service.js +432 -0
  108. package/dist/src/runtime/session-manager.js +63 -0
  109. package/dist/src/runtime/state-observer.js +121 -0
  110. package/dist/src/runtime/vision-adapter.js +225 -0
  111. package/dist/src/state/app-map-types.js +72 -0
  112. package/dist/src/state/app-map.js +1974 -0
  113. package/dist/src/state/entity-tracker.js +108 -0
  114. package/dist/src/state/fusion.js +96 -0
  115. package/dist/src/state/index.js +21 -0
  116. package/dist/src/state/ladder-generator.js +236 -0
  117. package/dist/src/state/persistence.js +156 -0
  118. package/dist/src/state/types.js +17 -0
  119. package/dist/src/state/world-model.js +1456 -0
  120. package/dist/src/supervisor/locks.js +186 -0
  121. package/dist/src/supervisor/supervisor.js +403 -0
  122. package/dist/src/supervisor/types.js +30 -0
  123. package/dist/src/test-mcp-protocol.js +154 -0
  124. package/dist/src/types.js +17 -0
  125. package/dist/src/util/atomic-write.js +133 -0
  126. package/dist/src/util/sanitize.js +146 -0
  127. package/dist-app-maps/com.figma.Desktop.json +959 -0
  128. package/dist-app-maps/com.hnc.Discord.json +1146 -0
  129. package/dist-app-maps/notion.id.json +2831 -0
  130. package/dist-playbooks/canva-screenhand-carousel.json +445 -0
  131. package/dist-playbooks/codex-desktop.json +76 -0
  132. package/dist-playbooks/competitor-research-stack.json +122 -0
  133. package/dist-playbooks/davinci-color-grade.json +153 -0
  134. package/dist-playbooks/davinci-edit-timeline.json +162 -0
  135. package/dist-playbooks/davinci-render.json +114 -0
  136. package/dist-playbooks/devto.json +52 -0
  137. package/dist-playbooks/discord.json +41 -0
  138. package/dist-playbooks/google-flow-create-project.json +59 -0
  139. package/dist-playbooks/google-flow-edit-image.json +90 -0
  140. package/dist-playbooks/google-flow-edit-video.json +90 -0
  141. package/dist-playbooks/google-flow-generate-image.json +68 -0
  142. package/dist-playbooks/google-flow-generate-video.json +191 -0
  143. package/dist-playbooks/google-flow-open-project.json +48 -0
  144. package/dist-playbooks/google-flow-open-scenebuilder.json +64 -0
  145. package/dist-playbooks/google-flow-search-assets.json +64 -0
  146. package/dist-playbooks/instagram.json +57 -0
  147. package/dist-playbooks/linkedin.json +52 -0
  148. package/dist-playbooks/n8n.json +43 -0
  149. package/dist-playbooks/reddit.json +52 -0
  150. package/dist-playbooks/threads.json +59 -0
  151. package/dist-playbooks/x-twitter.json +59 -0
  152. package/dist-playbooks/youtube.json +59 -0
  153. package/dist-references/canva.json +646 -0
  154. package/dist-references/codex-desktop.json +305 -0
  155. package/dist-references/davinci-resolve-keyboard.json +594 -0
  156. package/dist-references/davinci-resolve-menu-map.json +1139 -0
  157. package/dist-references/davinci-resolve-menus-batch1.json +116 -0
  158. package/dist-references/davinci-resolve-menus-batch2.json +372 -0
  159. package/dist-references/davinci-resolve-menus-batch3.json +330 -0
  160. package/dist-references/davinci-resolve-menus-batch4.json +297 -0
  161. package/dist-references/davinci-resolve-shortcuts.json +333 -0
  162. package/dist-references/devto.json +317 -0
  163. package/dist-references/discord.json +549 -0
  164. package/dist-references/figma.json +1186 -0
  165. package/dist-references/finder.json +146 -0
  166. package/dist-references/google-ads-transparency.json +95 -0
  167. package/dist-references/google-flow.json +649 -0
  168. package/dist-references/instagram.json +341 -0
  169. package/dist-references/linkedin.json +324 -0
  170. package/dist-references/meta-ad-library.json +86 -0
  171. package/dist-references/n8n.json +387 -0
  172. package/dist-references/notes.json +27 -0
  173. package/dist-references/notion.json +163 -0
  174. package/dist-references/reddit.json +341 -0
  175. package/dist-references/threads.json +337 -0
  176. package/dist-references/x-twitter.json +403 -0
  177. package/dist-references/youtube.json +373 -0
  178. package/native/macos-bridge/Package.swift +1 -0
  179. package/native/macos-bridge/Sources/AccessibilityBridge.swift +257 -36
  180. package/native/macos-bridge/Sources/AppManagement.swift +212 -2
  181. package/native/macos-bridge/Sources/CoreGraphicsBridge.swift +348 -53
  182. package/native/macos-bridge/Sources/StreamCapture.swift +136 -0
  183. package/native/macos-bridge/Sources/VisionBridge.swift +165 -7
  184. package/native/macos-bridge/Sources/main.swift +169 -16
  185. package/native/windows-bridge/Program.cs +5 -0
  186. package/native/windows-bridge/ScreenCapture.cs +124 -0
  187. package/package.json +29 -4
  188. package/scripts/postinstall.cjs +127 -0
  189. package/.claude/commands/automate.md +0 -28
  190. package/.claude/commands/debug-ui.md +0 -19
  191. package/.claude/commands/screenshot.md +0 -15
  192. package/.github/FUNDING.yml +0 -1
  193. package/.github/ISSUE_TEMPLATE/bug_report.md +0 -27
  194. package/.github/ISSUE_TEMPLATE/feature_request.md +0 -20
  195. package/.mcp.json +0 -8
  196. package/DESKTOP_MCP_GUIDE.md +0 -92
  197. package/SECURITY.md +0 -44
  198. package/docs/architecture.md +0 -47
  199. package/install-skills.sh +0 -19
  200. package/mcp-bridge.ts +0 -271
  201. package/mcp-desktop.ts +0 -1221
  202. package/playbooks/instagram.json +0 -41
  203. package/playbooks/instagram_v2.json +0 -201
  204. package/playbooks/x_v1.json +0 -211
  205. package/scripts/devpost-live-loop.mjs +0 -421
  206. package/src/logging/timeline-logger.ts +0 -55
  207. package/src/mcp/server.ts +0 -449
  208. package/src/memory/recall.ts +0 -191
  209. package/src/memory/research.ts +0 -146
  210. package/src/memory/seeds.ts +0 -123
  211. package/src/memory/session.ts +0 -201
  212. package/src/memory/store.ts +0 -434
  213. package/src/memory/types.ts +0 -69
  214. package/src/native/bridge-client.ts +0 -239
  215. package/src/runtime/accessibility-adapter.ts +0 -487
  216. package/src/runtime/app-adapter.ts +0 -169
  217. package/src/runtime/applescript-adapter.ts +0 -376
  218. package/src/runtime/ax-role-map.ts +0 -102
  219. package/src/runtime/browser-adapter.ts +0 -129
  220. package/src/runtime/cdp-chrome-adapter.ts +0 -676
  221. package/src/runtime/composite-adapter.ts +0 -274
  222. package/src/runtime/executor.ts +0 -396
  223. package/src/runtime/planning-loop.ts +0 -81
  224. package/src/runtime/service.ts +0 -448
  225. package/src/runtime/session-manager.ts +0 -50
  226. package/src/runtime/state-observer.ts +0 -136
  227. package/src/runtime/vision-adapter.ts +0 -297
  228. package/src/types.ts +0 -297
  229. package/tests/bridge-client.test.ts +0 -176
  230. package/tests/browser-stealth.test.ts +0 -210
  231. package/tests/composite-adapter.test.ts +0 -64
  232. package/tests/mcp-server.test.ts +0 -151
  233. package/tests/memory-recall.test.ts +0 -339
  234. package/tests/memory-research.test.ts +0 -159
  235. package/tests/memory-seeds.test.ts +0 -120
  236. package/tests/memory-store.test.ts +0 -392
  237. package/tests/types.test.ts +0 -92
  238. package/tsconfig.check.json +0 -17
  239. package/tsconfig.json +0 -19
  240. package/vitest.config.ts +0 -8
  241. /package/{playbooks → dist-references}/devpost.json +0 -0
@@ -1,41 +0,0 @@
1
- {
2
- "platform": "instagram",
3
- "version": "1.0.0",
4
- "updated": "2026-03-05",
5
- "description": "Instagram platform knowledge discovered via Screenhand exploration",
6
- "urls": {
7
- "home": "https://www.instagram.com/",
8
- "accounts_activity_": "https://www.instagram.com/accounts/activity/",
9
- "accounts_center_": "https://www.instagram.com/accounts/center/",
10
- "accounts_edit_": "https://www.instagram.com/accounts/edit/",
11
- "accounts_emailsignup_": "https://www.instagram.com/accounts/emailsignup/",
12
- "create_select_": "https://www.instagram.com/create/select/",
13
- "direct_inbox_": "https://www.instagram.com/direct/inbox/",
14
- "explore_": "https://www.instagram.com/explore/",
15
- "notifications_": "https://www.instagram.com/notifications/",
16
- "professional_dashboard_": "https://www.instagram.com/professional_dashboard/",
17
- "reels_": "https://www.instagram.com/reels/",
18
- "reels_DVEhlImkuX5_": "https://www.instagram.com/reels/DVEhlImkuX5/",
19
- "reels_DVOV4_KjRVo_": "https://www.instagram.com/reels/DVOV4_KjRVo/",
20
- "reels_DVc8QemCByv_": "https://www.instagram.com/reels/DVc8QemCByv/"
21
- },
22
- "flows": {
23
- "discovered": {
24
- "steps": [
25
- "No strategies recorded yet. Use the platform, then call export_playbook again."
26
- ],
27
- "selectors": {
28
- "switch_display_language": "[aria-label=\"Switch Display Language\"]"
29
- }
30
- }
31
- },
32
- "detection": {
33
- "is_logged_in": "// Add detection JS for logged-in state"
34
- },
35
- "errors": [],
36
- "_meta": {
37
- "exported_from": "screenhand",
38
- "actions_count": 31,
39
- "strategies_count": 0
40
- }
41
- }
@@ -1,201 +0,0 @@
1
- {
2
- "platform": "instagram",
3
- "playbook": "instagram_v2",
4
- "version": "2.0.0",
5
- "updated": "2026-03-05",
6
- "description": "Instagram Web automation playbook with verified selectors from a live logged-in session.",
7
- "urls": {
8
- "home": "https://www.instagram.com/",
9
- "reels": "https://www.instagram.com/reels/",
10
- "messages": "https://www.instagram.com/direct/inbox/",
11
- "notifications": "https://www.instagram.com/notifications/",
12
- "edit_profile": "https://www.instagram.com/accounts/edit/"
13
- },
14
- "selectors": {
15
- "navigation": {
16
- "home": "a[href='/']",
17
- "reels": "a[href='/reels/']",
18
- "messages": "a[href='/direct/inbox/']",
19
- "explore": "a[href='/explore/']",
20
- "notifications": "a[href='/notifications/'], a[href='/accounts/activity/']",
21
- "create_href": "a[href='/create/']",
22
- "create_text_fallback": "a,button,[role='button'] (text=/new post|create/i)",
23
- "profile_generic": "a[href^='/'][href$='/'] (exclude known static routes)"
24
- },
25
- "engagement": {
26
- "like": "[aria-label='Like'], svg[aria-label='Like']",
27
- "comment": "[aria-label='Comment'], svg[aria-label='Comment']",
28
- "share": "[aria-label='Share'], [aria-label='Send'], svg[aria-label='Share']",
29
- "save": "[aria-label='Save'], svg[aria-label='Save']",
30
- "follow_text": "button,[role='button'] (text=/^Follow$/i)",
31
- "comment_input": "textarea[aria-label='Add a comment…'], textarea[placeholder='Add a comment…'], textarea[placeholder*='comment']"
32
- },
33
- "dm": {
34
- "search_input": "input[name='searchInput'], input[placeholder='Search'], input[aria-label='Search input']",
35
- "new_message": "a[href='/direct/new/'], [aria-label='New message'], button[aria-label='New message']",
36
- "composer_fallback": "textarea[placeholder*='Message'], div[contenteditable='true'][role='textbox']"
37
- },
38
- "settings": {
39
- "website": "input[placeholder='Website']",
40
- "bio": "textarea#pepBio, textarea[placeholder='Bio']",
41
- "submit": "button[type='submit']",
42
- "avatar_file": "input[type='file']",
43
- "account_suggestions_toggle": "input[role='switch'][aria-label='Show account suggestions on profiles']"
44
- },
45
- "create_post": {
46
- "trigger": "a,button,[role='button'] (text=/new post|create/i)",
47
- "file_input": "input[type='file']",
48
- "caption": "textarea[aria-label*='caption' i], textarea[placeholder*='caption' i]",
49
- "next": "button (text=/^Next$/i)",
50
- "share": "button (text=/^Share$/i)"
51
- }
52
- },
53
- "flows": {
54
- "create_post": {
55
- "steps": [
56
- "Navigate to home URL.",
57
- "Click create trigger by text match (new post/create).",
58
- "Upload media via input[type='file'].",
59
- "Fill caption field.",
60
- "Click Next, then Share."
61
- ],
62
- "selectors": {
63
- "entry": "a,button,[role='button'] (text=/new post|create/i)",
64
- "file_input": "input[type='file']",
65
- "caption": "textarea[aria-label*='caption' i], textarea[placeholder*='caption' i]",
66
- "next": "button (text=/^Next$/i)",
67
- "share": "button (text=/^Share$/i)"
68
- },
69
- "notes": [
70
- "Do not rely on /create/select/ directly; it can resolve to @create profile in some sessions.",
71
- "Prefer text-based create trigger from left nav when href selector is absent."
72
- ]
73
- },
74
- "reel_engagement": {
75
- "steps": [
76
- "Navigate to reels URL.",
77
- "Use like/comment/share/save selectors on active reel.",
78
- "Use follow_text selector for creator follow button."
79
- ],
80
- "selectors": {
81
- "like": "[aria-label='Like'], svg[aria-label='Like']",
82
- "comment": "[aria-label='Comment'], svg[aria-label='Comment']",
83
- "share": "[aria-label='Share'], [aria-label='Send'], svg[aria-label='Share']",
84
- "save": "[aria-label='Save'], svg[aria-label='Save']",
85
- "follow_text": "button,[role='button'] (text=/^Follow$/i)"
86
- }
87
- },
88
- "dm_send_message": {
89
- "steps": [
90
- "Navigate to messages URL.",
91
- "Use dm.search_input to find recipient.",
92
- "Click dm.new_message if inbox is empty.",
93
- "Type in dm.composer_fallback once thread opens."
94
- ],
95
- "selectors": {
96
- "search_input": "input[name='searchInput'], input[placeholder='Search'], input[aria-label='Search input']",
97
- "new_message": "a[href='/direct/new/'], [aria-label='New message'], button[aria-label='New message']",
98
- "composer_fallback": "textarea[placeholder*='Message'], div[contenteditable='true'][role='textbox']"
99
- }
100
- },
101
- "comment_on_post": {
102
- "steps": [
103
- "On home/reels, click engagement.comment selector.",
104
- "Wait for post page/dialog to open.",
105
- "Type into engagement.comment_input and submit."
106
- ],
107
- "selectors": {
108
- "comment_button": "[aria-label='Comment'], svg[aria-label='Comment']",
109
- "comment_input": "textarea[aria-label='Add a comment…'], textarea[placeholder='Add a comment…'], textarea[placeholder*='comment']"
110
- },
111
- "notes": [
112
- "Verified path opened https://www.instagram.com/p/... and exposed aria-label='Add a comment…'."
113
- ]
114
- },
115
- "follow_account": {
116
- "steps": [
117
- "Use follow_text (text=/^Follow$/i) on feed/reels/profile context.",
118
- "Avoid class-based selectors; they are unstable."
119
- ],
120
- "selectors": {
121
- "follow_text": "button,[role='button'] (text=/^Follow$/i)"
122
- }
123
- },
124
- "update_profile_settings": {
125
- "steps": [
126
- "Navigate to edit_profile URL.",
127
- "Set settings.website and settings.bio.",
128
- "Submit via settings.submit (type='submit')."
129
- ],
130
- "selectors": {
131
- "website": "input[placeholder='Website']",
132
- "bio": "textarea#pepBio, textarea[placeholder='Bio']",
133
- "submit": "button[type='submit']"
134
- },
135
- "notes": [
136
- "Verified on Edit profile page title: 'Edit profile • Instagram'."
137
- ]
138
- }
139
- },
140
- "detection": {
141
- "is_logged_in": "!!document.querySelector(\"a[href='/direct/inbox/']\")",
142
- "on_home": "location.pathname === '/'",
143
- "on_reels": "location.pathname.startsWith('/reels')",
144
- "on_messages": "location.pathname.startsWith('/direct/inbox')",
145
- "on_notifications": "location.pathname.startsWith('/notifications')",
146
- "on_edit_profile": "location.pathname.startsWith('/accounts/edit')",
147
- "has_comment_input": "!!document.querySelector(\"textarea[aria-label='Add a comment…'], textarea[placeholder='Add a comment…']\")"
148
- },
149
- "errors": [
150
- {
151
- "error": "Create route resolves to profile @create instead of composer",
152
- "context": "Direct open of /create/select/ in this session",
153
- "solution": "Use UI create trigger by text (new post/create) from home navigation.",
154
- "severity": "high"
155
- },
156
- {
157
- "error": "Notifications nav href not always present in left rail",
158
- "context": "Selector a[href='/notifications/'] may be absent",
159
- "solution": "Navigate directly to /notifications/ or click Notifications by text/aria.",
160
- "severity": "medium"
161
- },
162
- {
163
- "error": "Follow button lacks stable unique CSS attributes",
164
- "context": "Follow discovered as plain button text in multiple contexts",
165
- "solution": "Use text-based matcher: button,[role='button'] with /^Follow$/i.",
166
- "severity": "medium"
167
- }
168
- ],
169
- "verification": {
170
- "audit_date": "2026-03-05",
171
- "home": {
172
- "like_count": 3,
173
- "comment_count": 3,
174
- "share_count": 3,
175
- "save_count": 3,
176
- "follow_text_buttons": 8,
177
- "create_by_text": true
178
- },
179
- "reels": {
180
- "like_count": 2,
181
- "comment_count": 2,
182
- "share_count": 2,
183
- "save_count": 2,
184
- "follow_text_buttons": 2
185
- },
186
- "messages": {
187
- "search_input_present": true,
188
- "new_message_present": true
189
- },
190
- "edit_profile": {
191
- "website_present": true,
192
- "bio_present": true,
193
- "submit_type_button_present": true
194
- },
195
- "comment_flow": {
196
- "comment_click_result": "Clicked: \"Comment\"",
197
- "comment_input_present_after_click": true,
198
- "comment_page_pattern": "https://www.instagram.com/p/..."
199
- }
200
- }
201
- }
@@ -1,211 +0,0 @@
1
- {
2
- "platform": "x",
3
- "playbook": "x_v1",
4
- "version": "1.0.0",
5
- "updated": "2026-03-06",
6
- "description": "X (Twitter) web automation playbook for ScreenHand using Chrome CDP + OCR fallback.",
7
- "urls": {
8
- "home": "https://x.com/home",
9
- "explore": "https://x.com/explore",
10
- "notifications": "https://x.com/notifications",
11
- "messages": "https://x.com/messages",
12
- "compose": "https://x.com/compose/post",
13
- "profile": "https://x.com/{handle}",
14
- "status": "https://x.com/{handle}/status/{status_id}",
15
- "settings_profile": "https://x.com/settings/profile"
16
- },
17
- "selectors": {
18
- "compose": {
19
- "textbox_primary": "[data-testid='tweetTextarea_0']",
20
- "textbox_fallback": "div[role='textbox'][contenteditable='true']",
21
- "post_button_inline": "[data-testid='tweetButtonInline']",
22
- "post_button_generic": "[data-testid='tweetButton']",
23
- "media_input": "[data-testid='fileInput'], input[type='file']"
24
- },
25
- "engagement": {
26
- "reply": "[data-testid='reply']",
27
- "like": "[data-testid='like']",
28
- "unlike": "[data-testid='unlike']",
29
- "repost": "[data-testid='retweet']",
30
- "unrepost": "[data-testid='unretweet']",
31
- "bookmark": "[data-testid='bookmark']",
32
- "remove_bookmark": "[data-testid='removeBookmark']"
33
- },
34
- "post_menu": {
35
- "open": "[data-testid='caret'], button[aria-label='More']",
36
- "menu": "[role='menu']",
37
- "menu_item": "[role='menuitem']",
38
- "delete_item_text": "Delete",
39
- "edit_item_text": "Edit"
40
- },
41
- "delete_confirm": {
42
- "primary": "[data-testid='confirmationSheetConfirm']",
43
- "dialog": "[role='dialog']",
44
- "button_text": "Delete"
45
- },
46
- "edit": {
47
- "editor": "[data-testid='tweetTextarea_0'], div[role='textbox'][contenteditable='true']",
48
- "submit_update_or_save": "button matching /update|save/i",
49
- "must_not_click": "button matching /reply/i"
50
- },
51
- "dm": {
52
- "new_message": "[data-testid='DM_New_Direct_Message_Button'], a[href='/messages/compose'], [aria-label*='New message']",
53
- "search_people": "input[data-testid='searchPeople'], input[placeholder*='Search'], input[aria-label*='Search']",
54
- "composer": "[data-testid='dmComposerTextInput'], div[role='textbox'][data-testid='dmComposerTextInput'], div[role='textbox'][contenteditable='true']",
55
- "send": "[data-testid='dmComposerSendButton'], [aria-label='Send']"
56
- },
57
- "profile": {
58
- "edit_profile_button_text": "Edit profile",
59
- "name_input_label": "Name",
60
- "bio_input_label": "Bio",
61
- "location_input_label": "Location",
62
- "website_input_label": "Website",
63
- "save_profile": "[data-testid='Profile_Save_Button']"
64
- }
65
- },
66
- "flows": {
67
- "create_post": {
68
- "steps": [
69
- "Focus Chrome and use browser_tabs to get current X tab.",
70
- "Navigate to compose URL or home.",
71
- "Prefer CDP: fill [data-testid='tweetTextarea_0'] then click [data-testid='tweetButtonInline'].",
72
- "Fallback: click_text('What's happening?'), type_text, key('cmd+enter').",
73
- "Verify by opening profile and reading latest /status/{id} link."
74
- ],
75
- "guards": [
76
- "If X returns 'Whoops! You already said that.', regenerate unique copy and repost.",
77
- "If type_text times out on long text, shorten copy and retry.",
78
- "Keep one active Chrome window; avoid about:blank target drift."
79
- ]
80
- },
81
- "replace_post_without_premium": {
82
- "steps": [
83
- "Open target status URL.",
84
- "Open post menu (caret).",
85
- "Click Delete and then confirm Delete in modal.",
86
- "Create a fresh replacement post from compose.",
87
- "Optionally pin replacement post."
88
- ],
89
- "why": "Non-Premium accounts cannot edit posts reliably; delete+repost is the primary workflow."
90
- },
91
- "edit_post_premium_only": {
92
- "steps": [
93
- "Open target status URL and open post menu.",
94
- "Click 'Edit'.",
95
- "Replace content in edit editor.",
96
- "Submit only via button text matching Update/Save.",
97
- "Reload status URL and verify updated text."
98
- ],
99
- "guards": [
100
- "Abort if no Update/Save button is detected.",
101
- "Do not click Reply when intending to edit.",
102
- "Edit availability is restricted by account plan and post state."
103
- ]
104
- },
105
- "delete_post": {
106
- "steps": [
107
- "Open target status URL.",
108
- "Open post menu and click Delete.",
109
- "Confirm via [data-testid='confirmationSheetConfirm'] or dialog Delete button.",
110
- "Reload status URL and verify deleted marker text."
111
- ],
112
- "verification_text_patterns": [
113
- "this post was deleted",
114
- "post not found",
115
- "doesn't exist",
116
- "try searching for something else"
117
- ]
118
- },
119
- "engagement_actions": {
120
- "steps": [
121
- "Like: click [data-testid='like'].",
122
- "Reply: click [data-testid='reply'], fill composer, click tweetButtonInline.",
123
- "Repost: click [data-testid='retweet'] and choose repost option.",
124
- "Bookmark: click [data-testid='bookmark']."
125
- ]
126
- },
127
- "dm_send": {
128
- "steps": [
129
- "Navigate to /messages.",
130
- "Click new message button.",
131
- "Search recipient.",
132
- "Type in DM composer.",
133
- "Send via dmComposerSendButton."
134
- ]
135
- }
136
- },
137
- "detection": {
138
- "is_logged_in": "!/log in|sign in|join x|create account/i.test((document.body?.innerText||''))",
139
- "on_compose": "location.href.includes('/compose/post')",
140
- "on_messages": "location.pathname.startsWith('/messages')",
141
- "has_compose_box": "!!document.querySelector('[data-testid=\"tweetTextarea_0\"], div[role=\"textbox\"][contenteditable=\"true\"]')",
142
- "has_post_menu_caret": "document.querySelectorAll('[data-testid=\"caret\"], button[aria-label=\"More\"]').length > 0",
143
- "has_delete_confirm": "!!document.querySelector('[data-testid=\"confirmationSheetConfirm\"], [role=\"dialog\"]')"
144
- },
145
- "errors": [
146
- {
147
- "error": "Edit option missing",
148
- "context": "Post menu shows Delete/Pin/etc but no Edit",
149
- "solution": "Treat as non-editable; use delete+repost flow.",
150
- "severity": "high"
151
- },
152
- {
153
- "error": "Reply clicked instead of update",
154
- "context": "Edit flow opened composer-like surface and submit hit Reply",
155
- "solution": "Submit only when button label matches Update/Save; abort otherwise.",
156
- "severity": "high"
157
- },
158
- {
159
- "error": "Duplicate post rejection",
160
- "context": "X message: 'Whoops! You already said that.'",
161
- "solution": "Regenerate unique copy and retry post.",
162
- "severity": "medium"
163
- },
164
- {
165
- "error": "about:blank window steals OCR clicks",
166
- "context": "Multiple Chrome windows; OCR target drifts to about:blank",
167
- "solution": "Close/ignore about:blank window and bind to X-titled window before click_text/type_text.",
168
- "severity": "high"
169
- },
170
- {
171
- "error": "CDP DOM missing tweet controls",
172
- "context": "No article/caret nodes despite visible tweet in UI",
173
- "solution": "Fallback to OCR+Accessibility sequence; then return to CDP for verification.",
174
- "severity": "high"
175
- },
176
- {
177
- "error": "type_text timeout on long content",
178
- "context": "Bridge timeout on long multiline posts",
179
- "solution": "Use shorter copy or DOM insert in editor where available.",
180
- "severity": "medium"
181
- }
182
- ],
183
- "policy_notes": {
184
- "editing": [
185
- "Editing requires X Premium tier support.",
186
- "Editing is time-limited and state-limited (post history/reply state may block edit).",
187
- "Without edit capability, use delete+repost."
188
- ],
189
- "safety": [
190
- "Always verify target status URL before destructive actions.",
191
- "Never auto-confirm delete without detecting delete dialog/button.",
192
- "Never use Reply button as edit submit fallback."
193
- ]
194
- },
195
- "verification": {
196
- "audit_date": "2026-03-06",
197
- "account": "@screenhand_",
198
- "known_post_ids": [
199
- "2029617823178424794",
200
- "2029620157203763699"
201
- ],
202
- "observed_menu_items": [
203
- "Delete",
204
- "Edit",
205
- "Pin to your profile",
206
- "Highlight on your profile",
207
- "View post analytics"
208
- ],
209
- "known_rejection_message": "Whoops! You already said that."
210
- }
211
- }