@supportpages.io/wtfm 0.0.0-stage → 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 (275) hide show
  1. package/LICENSE +201 -0
  2. package/NOTICE +23 -0
  3. package/README.md +392 -2
  4. package/dist/actions.d.ts +98 -0
  5. package/dist/actions.js +86 -0
  6. package/dist/actions.js.map +1 -0
  7. package/dist/agent-settings.d.ts +22 -0
  8. package/dist/agent-settings.js +35 -0
  9. package/dist/agent-settings.js.map +1 -0
  10. package/dist/api.d.ts +14 -0
  11. package/dist/api.js +159 -0
  12. package/dist/api.js.map +1 -0
  13. package/dist/article-link.d.ts +16 -0
  14. package/dist/article-link.js +25 -0
  15. package/dist/article-link.js.map +1 -0
  16. package/dist/artifacts.d.ts +45 -0
  17. package/dist/artifacts.js +144 -0
  18. package/dist/artifacts.js.map +1 -0
  19. package/dist/brand.d.ts +4 -0
  20. package/dist/brand.js +9 -0
  21. package/dist/brand.js.map +1 -0
  22. package/dist/bridge.d.ts +2964 -0
  23. package/dist/bridge.js +1036 -0
  24. package/dist/bridge.js.map +1 -0
  25. package/dist/capacity.d.ts +5 -0
  26. package/dist/capacity.js +11 -0
  27. package/dist/capacity.js.map +1 -0
  28. package/dist/credentials.d.ts +13 -0
  29. package/dist/credentials.js +88 -0
  30. package/dist/credentials.js.map +1 -0
  31. package/dist/development-tls.d.ts +8 -0
  32. package/dist/development-tls.js +38 -0
  33. package/dist/development-tls.js.map +1 -0
  34. package/dist/errors.d.ts +15 -0
  35. package/dist/errors.js +18 -0
  36. package/dist/errors.js.map +1 -0
  37. package/dist/export.d.ts +11 -0
  38. package/dist/export.js +91 -0
  39. package/dist/export.js.map +1 -0
  40. package/dist/hosted-operations.d.ts +108 -0
  41. package/dist/hosted-operations.js +120 -0
  42. package/dist/hosted-operations.js.map +1 -0
  43. package/dist/hosting-benefits.d.ts +66 -0
  44. package/dist/hosting-benefits.js +67 -0
  45. package/dist/hosting-benefits.js.map +1 -0
  46. package/dist/index.d.ts +2 -0
  47. package/dist/index.js +49 -0
  48. package/dist/index.js.map +1 -0
  49. package/dist/local-inventory.d.ts +22 -0
  50. package/dist/local-inventory.js +59 -0
  51. package/dist/local-inventory.js.map +1 -0
  52. package/dist/local-setup.d.ts +208 -0
  53. package/dist/local-setup.js +140 -0
  54. package/dist/local-setup.js.map +1 -0
  55. package/dist/pairing.d.ts +71 -0
  56. package/dist/pairing.js +235 -0
  57. package/dist/pairing.js.map +1 -0
  58. package/dist/preferences.d.ts +18 -0
  59. package/dist/preferences.js +44 -0
  60. package/dist/preferences.js.map +1 -0
  61. package/dist/progress.d.ts +205 -0
  62. package/dist/progress.js +224 -0
  63. package/dist/progress.js.map +1 -0
  64. package/dist/reminders.d.ts +31 -0
  65. package/dist/reminders.js +73 -0
  66. package/dist/reminders.js.map +1 -0
  67. package/dist/replace-connection.d.ts +6 -0
  68. package/dist/replace-connection.js +77 -0
  69. package/dist/replace-connection.js.map +1 -0
  70. package/dist/repository-actions.d.ts +18 -0
  71. package/dist/repository-actions.js +9 -0
  72. package/dist/repository-actions.js.map +1 -0
  73. package/dist/repository-benefits.d.ts +96 -0
  74. package/dist/repository-benefits.js +64 -0
  75. package/dist/repository-benefits.js.map +1 -0
  76. package/dist/run-update.d.ts +17 -0
  77. package/dist/run-update.js +27 -0
  78. package/dist/run-update.js.map +1 -0
  79. package/dist/runs.d.ts +541 -0
  80. package/dist/runs.js +146 -0
  81. package/dist/runs.js.map +1 -0
  82. package/dist/runtime.d.ts +12 -0
  83. package/dist/runtime.js +58 -0
  84. package/dist/runtime.js.map +1 -0
  85. package/dist/schema.d.ts +277 -0
  86. package/dist/schema.js +66 -0
  87. package/dist/schema.js.map +1 -0
  88. package/dist/server.d.ts +4 -0
  89. package/dist/server.js +298 -0
  90. package/dist/server.js.map +1 -0
  91. package/dist/session.d.ts +1714 -0
  92. package/dist/session.js +619 -0
  93. package/dist/session.js.map +1 -0
  94. package/dist/settings.d.ts +9 -0
  95. package/dist/settings.js +21 -0
  96. package/dist/settings.js.map +1 -0
  97. package/dist/sync.d.ts +495 -0
  98. package/dist/sync.js +191 -0
  99. package/dist/sync.js.map +1 -0
  100. package/dist/telemetry-scrub.d.ts +13 -0
  101. package/dist/telemetry-scrub.js +51 -0
  102. package/dist/telemetry-scrub.js.map +1 -0
  103. package/dist/telemetry.d.ts +73 -0
  104. package/dist/telemetry.js +173 -0
  105. package/dist/telemetry.js.map +1 -0
  106. package/dist/walkthroughs.d.ts +224 -0
  107. package/dist/walkthroughs.js +109 -0
  108. package/dist/walkthroughs.js.map +1 -0
  109. package/dist/workspace.d.ts +14 -0
  110. package/dist/workspace.js +127 -0
  111. package/dist/workspace.js.map +1 -0
  112. package/dist/writer-agent.d.ts +21 -0
  113. package/dist/writer-agent.js +27 -0
  114. package/dist/writer-agent.js.map +1 -0
  115. package/dist/writer-entry.d.ts +171 -0
  116. package/dist/writer-entry.js +233 -0
  117. package/dist/writer-entry.js.map +1 -0
  118. package/dist/writing-style.d.ts +7 -0
  119. package/dist/writing-style.js +52 -0
  120. package/dist/writing-style.js.map +1 -0
  121. package/engine/SYNC.json +4 -0
  122. package/engine/VERSION +1 -0
  123. package/engine/detect-project/README.md +141 -0
  124. package/engine/detect-project/SKILL.md +1421 -0
  125. package/engine/detect-project/assets/desktop/desktop-frame.css +428 -0
  126. package/engine/detect-project/assets/game/game-frame.css +132 -0
  127. package/engine/detect-project/assets/macosui/LICENSE-puppertino.txt +21 -0
  128. package/engine/detect-project/assets/macosui/VERSIONS.txt +1 -0
  129. package/engine/detect-project/assets/macosui/fonts.css +15 -0
  130. package/engine/detect-project/assets/macosui/macos-frame.css +481 -0
  131. package/engine/detect-project/assets/macosui/puppertino.css +2153 -0
  132. package/engine/detect-project/assets/mobileui/LICENSE-fonts.txt +13 -0
  133. package/engine/detect-project/assets/mobileui/LICENSE-framework7.txt +52 -0
  134. package/engine/detect-project/assets/mobileui/VERSIONS.txt +6 -0
  135. package/engine/detect-project/assets/mobileui/device-frame.css +316 -0
  136. package/engine/detect-project/assets/mobileui/f7-color-theme.mjs +1345 -0
  137. package/engine/detect-project/assets/mobileui/f7-icons-names.json +1254 -0
  138. package/engine/detect-project/assets/mobileui/fonts.css +16 -0
  139. package/engine/detect-project/assets/mobileui/framework7-components.css +39 -0
  140. package/engine/detect-project/assets/mobileui/framework7-core.css +5245 -0
  141. package/engine/detect-project/assets/mobileui/icons.css +31 -0
  142. package/engine/detect-project/assets/mobileui/md3-defaults.css +89 -0
  143. package/engine/detect-project/assets/mobileui/platforms.json +46 -0
  144. package/engine/detect-project/assets/tailwind-fallback.css +1729 -0
  145. package/engine/detect-project/assets/webtui/LICENSE-webtui.txt +28 -0
  146. package/engine/detect-project/assets/webtui/VERSIONS.txt +7 -0
  147. package/engine/detect-project/assets/webtui/terminal-frame.css +195 -0
  148. package/engine/detect-project/assets/webtui/theme-catppuccin.css +1 -0
  149. package/engine/detect-project/assets/webtui/theme-everforest.css +1 -0
  150. package/engine/detect-project/assets/webtui/theme-gruvbox.css +1 -0
  151. package/engine/detect-project/assets/webtui/theme-nord.css +1 -0
  152. package/engine/detect-project/assets/webtui/theme-vitesse.css +1 -0
  153. package/engine/detect-project/assets/webtui/themes.json +37 -0
  154. package/engine/detect-project/assets/webtui/webtui-core.css +1 -0
  155. package/engine/detect-project/assets/win32ui/7css.css +2 -0
  156. package/engine/detect-project/assets/win32ui/LICENSE-7css.txt +21 -0
  157. package/engine/detect-project/assets/win32ui/VERSIONS.txt +1 -0
  158. package/engine/detect-project/assets/win32ui/win32-frame.css +278 -0
  159. package/engine/detect-project/package-lock.json +12 -0
  160. package/engine/detect-project/package.json +10 -0
  161. package/engine/detect-project/scripts/apply_runtime_profiles.js +313 -0
  162. package/engine/detect-project/scripts/check_css_health.js +412 -0
  163. package/engine/detect-project/scripts/check_project_map.js +150 -0
  164. package/engine/detect-project/scripts/check_runtime_coverage.js +311 -0
  165. package/engine/detect-project/scripts/check_runtime_recipe_quality.js +184 -0
  166. package/engine/detect-project/scripts/classify_app_type.sh +246 -0
  167. package/engine/detect-project/scripts/classify_surface.sh +95 -0
  168. package/engine/detect-project/scripts/classify_workspace.js +39 -0
  169. package/engine/detect-project/scripts/compile_css.sh +447 -0
  170. package/engine/detect-project/scripts/detect_static.js +645 -0
  171. package/engine/detect-project/scripts/detect_structure.js +187 -0
  172. package/engine/detect-project/scripts/include_census.js +451 -0
  173. package/engine/detect-project/scripts/json_get.js +142 -0
  174. package/engine/detect-project/scripts/merge_json.js +52 -0
  175. package/engine/detect-project/scripts/recommend_model_tier.js +252 -0
  176. package/engine/detect-project/scripts/resolve_route_chains.js +135 -0
  177. package/engine/detect-project/scripts/run_css_build.sh +40 -0
  178. package/engine/detect-project/scripts/sanitize_css.js +83 -0
  179. package/engine/detect-project/scripts/test_classify_surface.js +108 -0
  180. package/engine/detect-project/scripts/test_node_helpers.js +142 -0
  181. package/engine/detect-project/scripts/test_recommend_model_tier.js +119 -0
  182. package/engine/detect-project/scripts/test_resolve_route_chains.js +182 -0
  183. package/engine/detect-project/scripts/test_runtime_coverage.js +323 -0
  184. package/engine/detect-project/scripts/test_runtime_recipe_quality.js +187 -0
  185. package/engine/detect-project/scripts/theme_overrides.js +169 -0
  186. package/engine/detect-project/scripts/write_branding.js +129 -0
  187. package/engine/generate-illustrated-article/SKILL.md +461 -0
  188. package/engine/generate-illustrated-article/contracts/desktop.md +90 -0
  189. package/engine/generate-illustrated-article/contracts/game.md +38 -0
  190. package/engine/generate-illustrated-article/contracts/label-evidence.md +38 -0
  191. package/engine/generate-illustrated-article/contracts/macos.md +79 -0
  192. package/engine/generate-illustrated-article/contracts/mobile.md +40 -0
  193. package/engine/generate-illustrated-article/contracts/terminal.md +29 -0
  194. package/engine/generate-illustrated-article/contracts/win32.md +43 -0
  195. package/engine/generate-illustrated-article/package-lock.json +366 -0
  196. package/engine/generate-illustrated-article/package.json +15 -0
  197. package/engine/generate-illustrated-article/scripts/article_blocks.js +34 -0
  198. package/engine/generate-illustrated-article/scripts/check_article_json.js +105 -0
  199. package/engine/generate-illustrated-article/scripts/emit_walkthrough_signals.js +100 -0
  200. package/engine/generate-illustrated-article/scripts/extract_images.js +187 -0
  201. package/engine/generate-illustrated-article/scripts/generate_content_images.js +376 -0
  202. package/engine/generate-illustrated-article/scripts/include_census.js +451 -0
  203. package/engine/generate-illustrated-article/scripts/inject_assets.js +1691 -0
  204. package/engine/generate-illustrated-article/scripts/jit_mockup_css.js +191 -0
  205. package/engine/generate-illustrated-article/scripts/label_evidence.js +87 -0
  206. package/engine/generate-illustrated-article/scripts/lint_article_copy.js +252 -0
  207. package/engine/generate-illustrated-article/scripts/lint_mockup_fidelity.js +2403 -0
  208. package/engine/generate-illustrated-article/scripts/polish_tickets.js +1148 -0
  209. package/engine/generate-illustrated-article/scripts/related_repos.sh +52 -0
  210. package/engine/generate-illustrated-article/scripts/render_all.js +177 -0
  211. package/engine/generate-illustrated-article/scripts/render_mockup.js +665 -0
  212. package/engine/generate-illustrated-article/scripts/render_ready.js +164 -0
  213. package/engine/generate-illustrated-article/scripts/resolve_workspace.sh +86 -0
  214. package/engine/generate-illustrated-article/scripts/runtime_region_geometry.js +55 -0
  215. package/engine/generate-illustrated-article/scripts/source_paths.js +49 -0
  216. package/engine/generate-illustrated-article/scripts/test_control_visibility.js +30 -0
  217. package/engine/generate-illustrated-article/scripts/test_emit_walkthrough_signals.js +157 -0
  218. package/engine/generate-illustrated-article/scripts/test_generate_content_images.js +168 -0
  219. package/engine/generate-illustrated-article/scripts/test_include_census.js +126 -0
  220. package/engine/generate-illustrated-article/scripts/test_label_evidence.js +49 -0
  221. package/engine/generate-illustrated-article/scripts/test_lint_article_copy.js +138 -0
  222. package/engine/generate-illustrated-article/scripts/test_lint_mockup_fidelity.js +653 -0
  223. package/engine/generate-illustrated-article/scripts/test_node_ports.js +152 -0
  224. package/engine/generate-illustrated-article/scripts/test_polish_tickets.js +481 -0
  225. package/engine/generate-illustrated-article/scripts/test_related_repos.js +64 -0
  226. package/engine/generate-illustrated-article/scripts/test_render_ready.js +85 -0
  227. package/engine/generate-illustrated-article/scripts/test_source_paths.js +68 -0
  228. package/engine/generate-illustrated-article/scripts/trace_hook.js +79 -0
  229. package/engine/generate-illustrated-article/scripts/trace_hook.sh +4 -0
  230. package/engine/generate-illustrated-article/scripts/validate_html.js +114 -0
  231. package/engine/generate-illustrated-article/scripts/watermark.js +69 -0
  232. package/install.sh +14 -0
  233. package/package.json +57 -4
  234. package/scripts/auth.mjs +33 -0
  235. package/scripts/auto-update.mjs +7 -0
  236. package/scripts/build-plugin.mjs +58 -0
  237. package/scripts/build-release.mjs +94 -0
  238. package/scripts/check-release.mjs +40 -0
  239. package/scripts/check-runtime.mjs +10 -0
  240. package/scripts/cli.mjs +8 -0
  241. package/scripts/install.mjs +64 -0
  242. package/scripts/lib/agent-runner.mjs +181 -0
  243. package/scripts/lib/agent-settings.mjs +215 -0
  244. package/scripts/lib/article-skills.mjs +82 -0
  245. package/scripts/lib/auto-update.mjs +50 -0
  246. package/scripts/lib/brand.mjs +9 -0
  247. package/scripts/lib/browser.mjs +12 -0
  248. package/scripts/lib/claude-connection.mjs +33 -0
  249. package/scripts/lib/claude-permissions.mjs +47 -0
  250. package/scripts/lib/claude-plugin.mjs +15 -0
  251. package/scripts/lib/claude-writer.mjs +10 -0
  252. package/scripts/lib/cli-main.mjs +85 -0
  253. package/scripts/lib/cli.mjs +888 -0
  254. package/scripts/lib/codex-config.mjs +51 -0
  255. package/scripts/lib/codex-integration.mjs +61 -0
  256. package/scripts/lib/codex-skill.mjs +34 -0
  257. package/scripts/lib/harness-models.mjs +109 -0
  258. package/scripts/lib/install.mjs +269 -0
  259. package/scripts/lib/managed-writer.mjs +38 -0
  260. package/scripts/lib/planning.mjs +263 -0
  261. package/scripts/lib/prepare-update.mjs +85 -0
  262. package/scripts/lib/refresh-writers.mjs +12 -0
  263. package/scripts/lib/remove.mjs +167 -0
  264. package/scripts/lib/renderer.mjs +34 -0
  265. package/scripts/lib/terminal.mjs +252 -0
  266. package/scripts/lib/uninit.mjs +72 -0
  267. package/scripts/lib/update.mjs +55 -0
  268. package/scripts/lib/writer-recovery.mjs +35 -0
  269. package/scripts/lib/yolo.mjs +362 -0
  270. package/scripts/plugin-session.mjs +65 -0
  271. package/scripts/prepare-update.mjs +12 -0
  272. package/scripts/publish-release.mjs +92 -0
  273. package/scripts/skills/supportpages/SKILL.md +120 -0
  274. package/scripts/smoke-release.mjs +101 -0
  275. package/server.json +27 -0
@@ -0,0 +1,366 @@
1
+ {
2
+ "name": "rtfm-generate-illustrated-article",
3
+ "version": "0.1.0",
4
+ "lockfileVersion": 3,
5
+ "requires": true,
6
+ "packages": {
7
+ "": {
8
+ "name": "rtfm-generate-illustrated-article",
9
+ "version": "0.1.0",
10
+ "dependencies": {
11
+ "puppeteer": "25.11.0"
12
+ },
13
+ "engines": {
14
+ "node": ">=22.12.0"
15
+ }
16
+ },
17
+ "node_modules/@puppeteer/browsers": {
18
+ "version": "3.2.2",
19
+ "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-3.2.2.tgz",
20
+ "integrity": "sha512-q2BU4YfO9h/Wt7IcWPcggpOOqLk2Tbs1hDwolvKZrweRjy751OJBKMN9zO5bfD0pzU7X/tvKw/exQds4pM/LOg==",
21
+ "license": "Apache-2.0",
22
+ "dependencies": {
23
+ "modern-tar": "^0.8.4",
24
+ "yargs": "^18.0.0"
25
+ },
26
+ "bin": {
27
+ "browsers": "lib/main-cli.js"
28
+ },
29
+ "engines": {
30
+ "node": ">=22.12.0"
31
+ },
32
+ "peerDependencies": {
33
+ "proxy-agent": ">=8.0.1",
34
+ "yauzl": "^2.10.0 || ^3.4.0"
35
+ },
36
+ "peerDependenciesMeta": {
37
+ "proxy-agent": {
38
+ "optional": true
39
+ },
40
+ "yauzl": {
41
+ "optional": true
42
+ }
43
+ }
44
+ },
45
+ "node_modules/ansi-regex": {
46
+ "version": "6.3.0",
47
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.3.0.tgz",
48
+ "integrity": "sha512-WpDfL7NO6j7tH88IDBNVdUJxDh9nmCteAVW9dsep846XdwF4naCBK+/tGLX3KJgcpgMRXCFlTM2hKGoK9FsdrQ==",
49
+ "license": "MIT",
50
+ "engines": {
51
+ "node": ">=12"
52
+ },
53
+ "funding": {
54
+ "url": "https://github.com/chalk/ansi-regex?sponsor=1"
55
+ }
56
+ },
57
+ "node_modules/ansi-styles": {
58
+ "version": "6.2.3",
59
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz",
60
+ "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==",
61
+ "license": "MIT",
62
+ "engines": {
63
+ "node": ">=12"
64
+ },
65
+ "funding": {
66
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
67
+ }
68
+ },
69
+ "node_modules/chromium-bidi": {
70
+ "version": "17.0.2",
71
+ "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-17.0.2.tgz",
72
+ "integrity": "sha512-5v9GQFhTktFvotn/OFNJBmKLKRAb6n9r0bVCwf7sHgWc3/JryK0bj1nn93L3pHFrfgcsu6Be6EWsDi+1XHTGDg==",
73
+ "license": "Apache-2.0",
74
+ "dependencies": {
75
+ "mitt": "^3.0.1",
76
+ "zod": "^3.24.1"
77
+ },
78
+ "engines": {
79
+ "node": ">=20.19.0 <22.0.0 || >=22.12.0"
80
+ },
81
+ "peerDependencies": {
82
+ "devtools-protocol": "*"
83
+ }
84
+ },
85
+ "node_modules/cliui": {
86
+ "version": "9.0.1",
87
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-9.0.1.tgz",
88
+ "integrity": "sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w==",
89
+ "license": "ISC",
90
+ "dependencies": {
91
+ "string-width": "^7.2.0",
92
+ "strip-ansi": "^7.1.0",
93
+ "wrap-ansi": "^9.0.0"
94
+ },
95
+ "engines": {
96
+ "node": ">=20"
97
+ }
98
+ },
99
+ "node_modules/cliui/node_modules/string-width": {
100
+ "version": "7.2.0",
101
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz",
102
+ "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==",
103
+ "license": "MIT",
104
+ "dependencies": {
105
+ "emoji-regex": "^10.3.0",
106
+ "get-east-asian-width": "^1.0.0",
107
+ "strip-ansi": "^7.1.0"
108
+ },
109
+ "engines": {
110
+ "node": ">=18"
111
+ },
112
+ "funding": {
113
+ "url": "https://github.com/sponsors/sindresorhus"
114
+ }
115
+ },
116
+ "node_modules/devtools-protocol": {
117
+ "version": "0.0.1680125",
118
+ "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1680125.tgz",
119
+ "integrity": "sha512-rVARKAvOFJCFkvgX01VLvYqKIvt+cRCqvUxIhB2oAqVGPalxk3w3sb5TUGDagpow/EFblBpm/Zl/29QA2dd+jA==",
120
+ "license": "BSD-3-Clause"
121
+ },
122
+ "node_modules/emoji-regex": {
123
+ "version": "10.6.0",
124
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz",
125
+ "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==",
126
+ "license": "MIT"
127
+ },
128
+ "node_modules/escalade": {
129
+ "version": "3.2.0",
130
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
131
+ "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
132
+ "license": "MIT",
133
+ "engines": {
134
+ "node": ">=6"
135
+ }
136
+ },
137
+ "node_modules/get-caller-file": {
138
+ "version": "2.0.5",
139
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
140
+ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
141
+ "license": "ISC",
142
+ "engines": {
143
+ "node": "6.* || 8.* || >= 10.*"
144
+ }
145
+ },
146
+ "node_modules/get-east-asian-width": {
147
+ "version": "1.7.0",
148
+ "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.7.0.tgz",
149
+ "integrity": "sha512-XjH1AECxf0giL2V1aU8vKyRR2ppRUb5c0EvT7zuJTokQ74bNo52zOtghqdWIqrhUD79fo3x0WfKZdOqxF6LG1Q==",
150
+ "license": "MIT",
151
+ "engines": {
152
+ "node": ">=18"
153
+ },
154
+ "funding": {
155
+ "url": "https://github.com/sponsors/sindresorhus"
156
+ }
157
+ },
158
+ "node_modules/lilconfig": {
159
+ "version": "3.1.3",
160
+ "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz",
161
+ "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==",
162
+ "license": "MIT",
163
+ "engines": {
164
+ "node": ">=14"
165
+ },
166
+ "funding": {
167
+ "url": "https://github.com/sponsors/antonk52"
168
+ }
169
+ },
170
+ "node_modules/mitt": {
171
+ "version": "3.0.1",
172
+ "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz",
173
+ "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==",
174
+ "license": "MIT"
175
+ },
176
+ "node_modules/modern-tar": {
177
+ "version": "0.8.5",
178
+ "resolved": "https://registry.npmjs.org/modern-tar/-/modern-tar-0.8.5.tgz",
179
+ "integrity": "sha512-snEhs+6G5Tjd4I7tLCDOaoln2RgE0bD19RzEKgvgK2hZ5VKy3MpLhLTZ2fWpXSTg4K2cyPwp+VHATFJhxfnOeA==",
180
+ "license": "MIT",
181
+ "engines": {
182
+ "node": ">=18.0.0"
183
+ }
184
+ },
185
+ "node_modules/puppeteer": {
186
+ "version": "25.11.0",
187
+ "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-25.11.0.tgz",
188
+ "integrity": "sha512-n+psxZFH/qlJ3gwTZMxTLUZoE98FAOEjT/BSxHXvPmNCGAfN/kq0UnIZ8m9RB4rAVvJr7zRHUnKKg98GLMUyyQ==",
189
+ "hasInstallScript": true,
190
+ "license": "Apache-2.0",
191
+ "dependencies": {
192
+ "@puppeteer/browsers": "3.2.2",
193
+ "chromium-bidi": "17.0.2",
194
+ "devtools-protocol": "0.0.1680125",
195
+ "lilconfig": "^3.1.3",
196
+ "puppeteer-core": "25.11.0",
197
+ "typed-query-selector": "^2.12.2"
198
+ },
199
+ "bin": {
200
+ "puppeteer": "lib/puppeteer/node/cli.js"
201
+ },
202
+ "engines": {
203
+ "node": ">=22.12.0"
204
+ }
205
+ },
206
+ "node_modules/puppeteer-core": {
207
+ "version": "25.11.0",
208
+ "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-25.11.0.tgz",
209
+ "integrity": "sha512-Ujym7JbxoAqanaxGcHgmTomfhC01HfDCSuGZ8Hs9boHrDjzbNVMnFRJo2KtbDT9LCRgeJoFnkn9JQZ41eEUrLw==",
210
+ "license": "Apache-2.0",
211
+ "dependencies": {
212
+ "@puppeteer/browsers": "3.2.2",
213
+ "chromium-bidi": "17.0.2",
214
+ "devtools-protocol": "0.0.1680125",
215
+ "typed-query-selector": "^2.12.2",
216
+ "webdriver-bidi-protocol": "0.4.3",
217
+ "ws": "^8.21.3"
218
+ },
219
+ "engines": {
220
+ "node": ">=22.12.0"
221
+ }
222
+ },
223
+ "node_modules/string-width": {
224
+ "version": "8.2.2",
225
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-8.2.2.tgz",
226
+ "integrity": "sha512-GaPUh5gfdrYzqeVNZvUfT23vYYxXzKYidUcnMtJg/3rxRV63EFZy3k6xfKlmfeJD0176lnUV/Usr3XcwSvFzpg==",
227
+ "license": "MIT",
228
+ "dependencies": {
229
+ "get-east-asian-width": "^1.5.0",
230
+ "strip-ansi": "^7.1.2"
231
+ },
232
+ "engines": {
233
+ "node": ">=20"
234
+ },
235
+ "funding": {
236
+ "url": "https://github.com/sponsors/sindresorhus"
237
+ }
238
+ },
239
+ "node_modules/strip-ansi": {
240
+ "version": "7.2.0",
241
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz",
242
+ "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==",
243
+ "license": "MIT",
244
+ "dependencies": {
245
+ "ansi-regex": "^6.2.2"
246
+ },
247
+ "engines": {
248
+ "node": ">=12"
249
+ },
250
+ "funding": {
251
+ "url": "https://github.com/chalk/strip-ansi?sponsor=1"
252
+ }
253
+ },
254
+ "node_modules/typed-query-selector": {
255
+ "version": "2.12.2",
256
+ "resolved": "https://registry.npmjs.org/typed-query-selector/-/typed-query-selector-2.12.2.tgz",
257
+ "integrity": "sha512-EOPFbyIub4ngnEdqi2yOcNeDLaX/0jcE1JoAXQDDMIthap7FoN795lc/SHfIq2d416VufXpM8z/lD+WRm2gfOQ==",
258
+ "license": "MIT"
259
+ },
260
+ "node_modules/webdriver-bidi-protocol": {
261
+ "version": "0.4.3",
262
+ "resolved": "https://registry.npmjs.org/webdriver-bidi-protocol/-/webdriver-bidi-protocol-0.4.3.tgz",
263
+ "integrity": "sha512-uuN0goWfxP22B7J/uAgBpOYNPttC+XVseYE+rSY5+rQ+YBeVz/VORw8WbmLVcqW78zNg5A4qnjNXYUWR3il2ig==",
264
+ "license": "Apache-2.0"
265
+ },
266
+ "node_modules/wrap-ansi": {
267
+ "version": "9.0.2",
268
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz",
269
+ "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==",
270
+ "license": "MIT",
271
+ "dependencies": {
272
+ "ansi-styles": "^6.2.1",
273
+ "string-width": "^7.0.0",
274
+ "strip-ansi": "^7.1.0"
275
+ },
276
+ "engines": {
277
+ "node": ">=18"
278
+ },
279
+ "funding": {
280
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
281
+ }
282
+ },
283
+ "node_modules/wrap-ansi/node_modules/string-width": {
284
+ "version": "7.2.0",
285
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz",
286
+ "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==",
287
+ "license": "MIT",
288
+ "dependencies": {
289
+ "emoji-regex": "^10.3.0",
290
+ "get-east-asian-width": "^1.0.0",
291
+ "strip-ansi": "^7.1.0"
292
+ },
293
+ "engines": {
294
+ "node": ">=18"
295
+ },
296
+ "funding": {
297
+ "url": "https://github.com/sponsors/sindresorhus"
298
+ }
299
+ },
300
+ "node_modules/ws": {
301
+ "version": "8.21.3",
302
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.3.tgz",
303
+ "integrity": "sha512-201TZ/kPWxoPr/OKWjquZR1SWKXcvxdH+e1xrx89b3YbmzLMFCLfnaG1HFIgWzJOEWZ7MvpK++odZufgYR50Rw==",
304
+ "license": "MIT",
305
+ "engines": {
306
+ "node": ">=10.0.0"
307
+ },
308
+ "peerDependencies": {
309
+ "bufferutil": "^4.0.1",
310
+ "utf-8-validate": ">=5.0.2"
311
+ },
312
+ "peerDependenciesMeta": {
313
+ "bufferutil": {
314
+ "optional": true
315
+ },
316
+ "utf-8-validate": {
317
+ "optional": true
318
+ }
319
+ }
320
+ },
321
+ "node_modules/y18n": {
322
+ "version": "5.0.8",
323
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
324
+ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
325
+ "license": "ISC",
326
+ "engines": {
327
+ "node": ">=10"
328
+ }
329
+ },
330
+ "node_modules/yargs": {
331
+ "version": "18.2.0",
332
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-18.2.0.tgz",
333
+ "integrity": "sha512-9OpKOLeaoNFecEp7P6iYbzze/5CqWoH7N3SMs/6y1XF4nMvFMspEGZzJ6uFi9MmQwXhyzqYoSEKO3tvA3Z/o2w==",
334
+ "license": "MIT",
335
+ "dependencies": {
336
+ "cliui": "^9.0.1",
337
+ "escalade": "^3.1.1",
338
+ "get-caller-file": "^2.0.5",
339
+ "string-width": "^8.2.1",
340
+ "y18n": "^5.0.5",
341
+ "yargs-parser": "^22.0.0"
342
+ },
343
+ "engines": {
344
+ "node": "^20.19.0 || ^22.12.0 || >=23"
345
+ }
346
+ },
347
+ "node_modules/yargs-parser": {
348
+ "version": "22.0.0",
349
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-22.0.0.tgz",
350
+ "integrity": "sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==",
351
+ "license": "ISC",
352
+ "engines": {
353
+ "node": "^20.19.0 || ^22.12.0 || >=23"
354
+ }
355
+ },
356
+ "node_modules/zod": {
357
+ "version": "3.25.76",
358
+ "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz",
359
+ "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==",
360
+ "license": "MIT",
361
+ "funding": {
362
+ "url": "https://github.com/sponsors/colinhacks"
363
+ }
364
+ }
365
+ }
366
+ }
@@ -0,0 +1,15 @@
1
+ {
2
+ "name": "rtfm-generate-illustrated-article",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "description": "Bundled renderer for the generate-illustrated-article skill",
6
+ "scripts": {
7
+ "test": "node scripts/test_related_repos.js && node scripts/test_source_paths.js && node scripts/test_label_evidence.js && node scripts/test_control_visibility.js && node scripts/test_generate_content_images.js && node scripts/test_lint_article_copy.js && node scripts/test_lint_mockup_fidelity.js && node scripts/test_render_ready.js && node scripts/test_polish_tickets.js && node scripts/test_include_census.js && node scripts/test_emit_walkthrough_signals.js && node scripts/test_node_ports.js"
8
+ },
9
+ "dependencies": {
10
+ "puppeteer": "25.11.0"
11
+ },
12
+ "engines": {
13
+ "node": ">=22.12.0"
14
+ }
15
+ }
@@ -0,0 +1,34 @@
1
+ const ARTICLE_TYPES = ['how-to', 'troubleshooting', 'concept', 'faq'];
2
+ const PRESENTATIONS = {
3
+ prose: ['lead', 'body', 'summary'],
4
+ section: ['numbered', 'plain'],
5
+ list: ['bullets', 'checklist', 'tips'],
6
+ };
7
+
8
+ function blocks(article) {
9
+ if (article && article.schema_version === 2 && Array.isArray(article.blocks)) return article.blocks;
10
+
11
+ const result = [];
12
+ if (article && article.introduction) result.push({ id: 'introduction', type: 'prose', presentation: 'lead', content: article.introduction });
13
+ if (Array.isArray(article && article.prerequisites) && article.prerequisites.length) {
14
+ result.push({ id: 'prerequisites', type: 'list', presentation: 'checklist', title: 'Prerequisites', items: article.prerequisites });
15
+ }
16
+ for (const [index, step] of ((article && article.steps) || []).entries()) {
17
+ result.push({ id: `step-${index + 1}`, type: 'section', presentation: 'numbered', ...step });
18
+ }
19
+ if (Array.isArray(article && article.tips) && article.tips.length) {
20
+ result.push({ id: 'tips', type: 'list', presentation: 'tips', title: 'Tips', items: article.tips });
21
+ }
22
+ if (article && article.summary) result.push({ id: 'summary', type: 'prose', presentation: 'summary', title: 'Summary', content: article.summary });
23
+ return result;
24
+ }
25
+
26
+ function sections(article) {
27
+ return blocks(article).filter(block => block.type === 'section');
28
+ }
29
+
30
+ function articleType(article) {
31
+ return ARTICLE_TYPES.includes(article && article.article_type) ? article.article_type : 'how-to';
32
+ }
33
+
34
+ module.exports = { ARTICLE_TYPES, PRESENTATIONS, blocks, sections, articleType };
@@ -0,0 +1,105 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ /*
5
+ * check_article_json.js — validate the shape of a schema_version 2 article.json
6
+ * before illustration (Phase 2 flips has_image later, so this checks shape only).
7
+ *
8
+ * Usage: node check_article_json.js <article.json>
9
+ * Exits 0 when valid, 1 with one problem per line.
10
+ */
11
+
12
+ const fs = require('fs');
13
+
14
+ const ARTICLE_TYPES = ['how-to', 'troubleshooting', 'concept', 'faq'];
15
+ const PRESENTATIONS = {
16
+ prose: ['lead', 'body', 'summary'],
17
+ section: ['numbered', 'plain'],
18
+ list: ['bullets', 'checklist', 'tips'],
19
+ };
20
+ const BLOCK_ID = /^[a-z0-9]+(-[a-z0-9]+)*$/;
21
+ const CODE_FENCE = /```|~~~/;
22
+
23
+ const isString = value => typeof value === 'string';
24
+
25
+ /** String form of a value, as a JSON round-trip would render it inside a list. */
26
+ function asText(value) {
27
+ return isString(value) ? value : JSON.stringify(value);
28
+ }
29
+
30
+ function check(article) {
31
+ const problems = [];
32
+ if (article === null || typeof article !== 'object' || Array.isArray(article)) return ['article.json must be a JSON object'];
33
+ if (article.schema_version !== 2) problems.push('schema_version must be 2');
34
+ if (!isString(article.title) || !article.title.length) problems.push('title must be a non-empty string');
35
+ if (!ARTICLE_TYPES.includes(article.article_type)) problems.push(`article_type must be one of ${ARTICLE_TYPES.join(', ')}`);
36
+
37
+ const blocks = article.blocks;
38
+ if (!Array.isArray(blocks) || !blocks.length) {
39
+ problems.push('blocks must be a non-empty array');
40
+ return problems;
41
+ }
42
+
43
+ const ids = blocks.map(block => (block && typeof block === 'object' ? block.id : undefined));
44
+ const seen = new Set();
45
+ for (const id of ids) {
46
+ const key = JSON.stringify(id ?? null);
47
+ if (seen.has(key)) problems.push(`duplicate block id ${key}`);
48
+ seen.add(key);
49
+ }
50
+
51
+ blocks.forEach((block, i) => {
52
+ const at = `blocks[${i}]${block && isString(block.id) ? ` (${block.id})` : ''}`;
53
+ if (!block || typeof block !== 'object' || Array.isArray(block)) {
54
+ problems.push(`${at} must be an object`);
55
+ return;
56
+ }
57
+ if (!isString(block.id) || !BLOCK_ID.test(block.id)) problems.push(`${at}.id must be lowercase words joined by hyphens`);
58
+
59
+ const allowed = PRESENTATIONS[block.type];
60
+ if (!allowed) {
61
+ problems.push(`${at}.type must be prose, section or list`);
62
+ return;
63
+ }
64
+ if (!allowed.includes(block.presentation)) problems.push(`${at}.presentation must be one of ${allowed.join(', ')} for ${block.type}`);
65
+
66
+ if (block.type === 'prose') {
67
+ if (!isString(block.content)) problems.push(`${at}.content must be a string`);
68
+ if (block.presentation === 'lead' && CODE_FENCE.test(asText(block.content ?? ''))) problems.push(`${at}: the lead must not contain a code fence`);
69
+ } else if (block.type === 'section') {
70
+ if (!isString(block.title)) problems.push(`${at}.title must be a string`);
71
+ if (!isString(block.content)) problems.push(`${at}.content must be a string`);
72
+ if (typeof block.has_image !== 'boolean') problems.push(`${at}.has_image must be a boolean`);
73
+ } else if (block.type === 'list') {
74
+ if (!isString(block.title)) problems.push(`${at}.title must be a string`);
75
+ if (!Array.isArray(block.items)) problems.push(`${at}.items must be an array`);
76
+ else if (block.items.some(item => CODE_FENCE.test(asText(item)))) problems.push(`${at}: list items must not contain code fences`);
77
+ }
78
+ });
79
+ return problems;
80
+ }
81
+
82
+ function main(argv) {
83
+ const [file] = argv;
84
+ if (!file) {
85
+ process.stderr.write('Usage: check_article_json.js <article.json>\n');
86
+ return 2;
87
+ }
88
+ let article;
89
+ try { article = JSON.parse(fs.readFileSync(file, 'utf8')); }
90
+ catch (error) {
91
+ process.stderr.write(`${file}: ${error.message}\n`);
92
+ return 1;
93
+ }
94
+ const problems = check(article);
95
+ if (problems.length) {
96
+ process.stderr.write(`${file} is not a valid article:\n${problems.map(p => ` - ${p}`).join('\n')}\n`);
97
+ return 1;
98
+ }
99
+ process.stdout.write(`${file} OK\n`);
100
+ return 0;
101
+ }
102
+
103
+ if (require.main === module) process.exitCode = main(process.argv.slice(2));
104
+
105
+ module.exports = { check };
@@ -0,0 +1,100 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ // Distills walkthrough-worthiness signals from a generated article's artifacts
5
+ // (article.json + view_sources.json) into $OUT/walkthrough_signals.json.
6
+ // Consumed later by the recommend-walkthroughs skill via the RTFM context file.
7
+ // Informational, never a lint: any missing or unparsable input logs a warning
8
+ // and exits 0 without writing, so the article pipeline can never fail here.
9
+
10
+ const fs = require('fs');
11
+ const path = require('path');
12
+ const { blocks, articleType } = require('./article_blocks.js');
13
+
14
+ // Interaction kinds record_walkthrough.js cannot perform (supported: click,
15
+ // type-into, select, check, swipe, hover, scroll-to).
16
+ const UNSUPPORTED_KINDS = new Set(['drag', 'upload', 'keyboard']);
17
+
18
+ function readJson(file) {
19
+ return JSON.parse(fs.readFileSync(file, 'utf8'));
20
+ }
21
+
22
+ function atomicWrite(file, value) {
23
+ fs.mkdirSync(path.dirname(file), { recursive: true });
24
+ const temporary = `${file}.tmp-${process.pid}`;
25
+ fs.writeFileSync(temporary, `${JSON.stringify(value, null, 2)}\n`);
26
+ fs.renameSync(temporary, file);
27
+ }
28
+
29
+ function detectAppType(projectRoot) {
30
+ for (const dir of ['.rtfm', '.rtfm-branding']) {
31
+ try {
32
+ const map = readJson(path.join(projectRoot, dir, 'project_map.json'));
33
+ if (map && typeof map.app_type === 'string') return map.app_type;
34
+ } catch (error) { /* missing or unparsable map — fall through */ }
35
+ }
36
+ return 'web';
37
+ }
38
+
39
+ function computeSignals(article, viewSources, appType) {
40
+ const sections = blocks(article).filter(block => block && block.type === 'section');
41
+
42
+ // view_sources step containers: block-keyed `blocks[]` (schema v2 articles)
43
+ // or index-keyed `steps[]` (legacy). External-surface entries carry
44
+ // `external_surface` and no primary_view.
45
+ const entries = Array.isArray(viewSources && viewSources.blocks) ? viewSources.blocks
46
+ : Array.isArray(viewSources && viewSources.steps) ? viewSources.steps : [];
47
+ const surfaces = new Set();
48
+ let externalSurfaces = 0;
49
+ for (const entry of entries) {
50
+ if (!entry || typeof entry !== 'object') continue;
51
+ if (entry.external_surface) externalSurfaces += 1;
52
+ else if (typeof entry.primary_view === 'string' && entry.primary_view.trim()) {
53
+ surfaces.add(entry.primary_view.trim());
54
+ }
55
+ }
56
+
57
+ const coverage = Array.isArray(viewSources && viewSources.action_coverage)
58
+ ? viewSources.action_coverage.filter(item => item && typeof item === 'object') : [];
59
+ const kinds = [...new Set(coverage.map(item => item.kind).filter(kind => typeof kind === 'string' && kind))].sort();
60
+
61
+ return {
62
+ schema_version: 1,
63
+ article_type: articleType(article),
64
+ sections_total: sections.length,
65
+ sections_with_images: sections.filter(section => section.has_image === true).length,
66
+ distinct_surfaces: surfaces.size,
67
+ action_count: coverage.length,
68
+ action_kinds: kinds,
69
+ typed_input: kinds.includes('type'),
70
+ unsupported_action_kinds: kinds.filter(kind => UNSUPPORTED_KINDS.has(kind)),
71
+ external_surfaces: externalSurfaces,
72
+ app_type: appType,
73
+ };
74
+ }
75
+
76
+ function main() {
77
+ const outDir = process.argv[2];
78
+ if (!outDir) {
79
+ console.error('usage: emit_walkthrough_signals.js OUT_DIR');
80
+ process.exitCode = 2;
81
+ return;
82
+ }
83
+ let article;
84
+ let viewSources;
85
+ try {
86
+ article = readJson(path.join(outDir, 'article.json'));
87
+ viewSources = readJson(path.join(outDir, 'view_sources.json'));
88
+ } catch (error) {
89
+ console.error(`walkthrough signals skipped: ${error.message}`);
90
+ return;
91
+ }
92
+ const signals = computeSignals(article, viewSources, detectAppType(process.cwd()));
93
+ atomicWrite(path.join(outDir, 'walkthrough_signals.json'), signals);
94
+ console.log(`walkthrough signals: ${signals.distinct_surfaces} surfaces, `
95
+ + `${signals.action_count} actions (${signals.action_kinds.join(', ') || 'none'})`);
96
+ }
97
+
98
+ module.exports = { UNSUPPORTED_KINDS, computeSignals, detectAppType };
99
+
100
+ if (require.main === module) main();