create-workframe 0.1.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 (415) hide show
  1. package/.dockerignore +22 -0
  2. package/.gitignore +73 -0
  3. package/LICENSE +201 -0
  4. package/NOTICE +12 -0
  5. package/README.md +111 -0
  6. package/SECURITY.md +40 -0
  7. package/bin/create-workframe.js +2814 -0
  8. package/bin/workframe.js +329 -0
  9. package/docs/workspace-instructions/WORKFRAME_DISCORD.md +20 -0
  10. package/docs/workspace-instructions/WORKFRAME_DOCUMENTS_AND_ARTIFACTS.md +20 -0
  11. package/docs/workspace-instructions/WORKFRAME_KANBAN.md +20 -0
  12. package/docs/workspace-instructions/WORKFRAME_ONBOARDING.md +21 -0
  13. package/docs/workspace-instructions/WORKFRAME_ROUTING.md +29 -0
  14. package/docs/workspace-instructions/WORKFRAME_TELEGRAM.md +19 -0
  15. package/package.json +67 -0
  16. package/profiles/README.md +15 -0
  17. package/profiles/architect/AGENTS.md +29 -0
  18. package/profiles/architect/SOUL.md +44 -0
  19. package/profiles/architect/skills/devops/kanban-worker/SKILL.md +27 -0
  20. package/profiles/designer/AGENTS.md +26 -0
  21. package/profiles/designer/SOUL.md +31 -0
  22. package/profiles/designer/skills/devops/kanban-worker/SKILL.md +27 -0
  23. package/profiles/dev/AGENTS.md +28 -0
  24. package/profiles/dev/SOUL.md +31 -0
  25. package/profiles/dev/skills/devops/kanban-worker/SKILL.md +27 -0
  26. package/profiles/docs/AGENTS.md +27 -0
  27. package/profiles/docs/SOUL.md +30 -0
  28. package/profiles/docs/skills/devops/kanban-worker/SKILL.md +27 -0
  29. package/profiles/research/AGENTS.md +26 -0
  30. package/profiles/research/SOUL.md +31 -0
  31. package/profiles/research/skills/devops/kanban-worker/SKILL.md +27 -0
  32. package/profiles/visionary/AGENTS.md +25 -0
  33. package/profiles/visionary/SOUL.md +31 -0
  34. package/profiles/visionary/skills/devops/kanban-worker/SKILL.md +27 -0
  35. package/profiles/workframe-agent/AGENTS.md +37 -0
  36. package/profiles/workframe-agent/SETUP.md +185 -0
  37. package/profiles/workframe-agent/SOUL.md +61 -0
  38. package/profiles/workframe-agent/skills/devops/botfather/SKILL.md +85 -0
  39. package/profiles/workframe-agent/skills/devops/kanban-handoff-pattern/SKILL.md +58 -0
  40. package/profiles/workframe-agent/skills/devops/workframe-cohort/SKILL.md +54 -0
  41. package/prompts/WORKFRAME_PROMPT_TEMPLATES.md +16 -0
  42. package/rules/.hermes.md +11 -0
  43. package/rules/AGENTS.md +22 -0
  44. package/rules/workspace-README.md +5 -0
  45. package/scripts/apply-update-hermes.sh +17 -0
  46. package/scripts/apply-update-workframe.sh +77 -0
  47. package/scripts/bootstrap-workspace-link.sh +8 -0
  48. package/scripts/bundle-workframe-ui.mjs +77 -0
  49. package/scripts/compose-docker-host.sh +37 -0
  50. package/scripts/create_workframe_scaffold.py +648 -0
  51. package/scripts/ensure-compose-host-paths.mjs +51 -0
  52. package/scripts/fix-zk-encryption-key.sh +35 -0
  53. package/scripts/lib/install-identity.mjs +212 -0
  54. package/scripts/lib/workframe-registry.mjs +290 -0
  55. package/scripts/new-project.mjs +68 -0
  56. package/scripts/restart-gateway-hermes.sh +12 -0
  57. package/scripts/security_audit.py +156 -0
  58. package/scripts/select_agent_pack.py +31 -0
  59. package/scripts/set-compose-public-url.mjs +92 -0
  60. package/scripts/setup-stack-secrets.sh +50 -0
  61. package/scripts/sync-canonical-to-package.mjs +146 -0
  62. package/scripts/test-scaffold.mjs +390 -0
  63. package/scripts/verify-public-deploy.sh +105 -0
  64. package/shared/WORKFRAME_AGENT_LIBRARY.md +31 -0
  65. package/shared/WORKFRAME_AGENT_OPERATIONS.md +29 -0
  66. package/shared/WORKFRAME_AGENT_PACKS.json +64 -0
  67. package/shared/WORKFRAME_AGENT_PACKS.yaml +20 -0
  68. package/shared/WORKFRAME_CHAT_PERMISSION_MODEL.md +20 -0
  69. package/shared/WORKFRAME_HANDOFF_SCHEMA.md +25 -0
  70. package/shared/WORKFRAME_SKILL_CURATION.md +27 -0
  71. package/shared/agent-avatars/ada.png +0 -0
  72. package/shared/agent-avatars/aibert.png +0 -0
  73. package/shared/agent-avatars/amelia.png +0 -0
  74. package/shared/agent-avatars/andy.png +0 -0
  75. package/shared/agent-avatars/arc.png +0 -0
  76. package/shared/agent-avatars/bob.png +0 -0
  77. package/shared/agent-avatars/buzz.png +0 -0
  78. package/shared/agent-avatars/carl.png +0 -0
  79. package/shared/agent-avatars/catalog.json +171 -0
  80. package/shared/agent-avatars/corbu.png +0 -0
  81. package/shared/agent-avatars/diana.png +0 -0
  82. package/shared/agent-avatars/ella.png +0 -0
  83. package/shared/agent-avatars/elvis.png +0 -0
  84. package/shared/agent-avatars/f1.png +0 -0
  85. package/shared/agent-avatars/f2.png +0 -0
  86. package/shared/agent-avatars/f3.png +0 -0
  87. package/shared/agent-avatars/f4.png +0 -0
  88. package/shared/agent-avatars/f5.png +0 -0
  89. package/shared/agent-avatars/f6.png +0 -0
  90. package/shared/agent-avatars/frida.png +0 -0
  91. package/shared/agent-avatars/george.png +0 -0
  92. package/shared/agent-avatars/grace.png +0 -0
  93. package/shared/agent-avatars/hedy.png +0 -0
  94. package/shared/agent-avatars/hermes.png +0 -0
  95. package/shared/agent-avatars/isaac.png +0 -0
  96. package/shared/agent-avatars/jes.png +0 -0
  97. package/shared/agent-avatars/john.png +0 -0
  98. package/shared/agent-avatars/joni.png +0 -0
  99. package/shared/agent-avatars/leo.png +0 -0
  100. package/shared/agent-avatars/louis.png +0 -0
  101. package/shared/agent-avatars/ludwig.png +0 -0
  102. package/shared/agent-avatars/m1.png +0 -0
  103. package/shared/agent-avatars/m2.png +0 -0
  104. package/shared/agent-avatars/m3.png +0 -0
  105. package/shared/agent-avatars/m4.png +0 -0
  106. package/shared/agent-avatars/m5.png +0 -0
  107. package/shared/agent-avatars/m6.png +0 -0
  108. package/shared/agent-avatars/marie.png +0 -0
  109. package/shared/agent-avatars/marilyn.png +0 -0
  110. package/shared/agent-avatars/neil.png +0 -0
  111. package/shared/agent-avatars/nikola.png +0 -0
  112. package/shared/agent-avatars/nina.png +0 -0
  113. package/shared/agent-avatars/paul.png +0 -0
  114. package/shared/agent-avatars/ringo.png +0 -0
  115. package/shared/agent-avatars/rosie.png +0 -0
  116. package/shared/agent-avatars/ste.png +0 -0
  117. package/shared/agent-avatars/steve.png +0 -0
  118. package/shared/agent-avatars/sun.png +0 -0
  119. package/shared/agent-avatars/tom.png +0 -0
  120. package/shared/agent-avatars/warren.png +0 -0
  121. package/shared/agent-avatars/woz.png +0 -0
  122. package/shared/agent-avatars/zaha.png +0 -0
  123. package/workframe-api/Dockerfile +14 -0
  124. package/workframe-api/README.md +28 -0
  125. package/workframe-api/action_proxy.py +131 -0
  126. package/workframe-api/auth_rate_limit.py +49 -0
  127. package/workframe-api/catalog/avatar-catalog.json +171 -0
  128. package/workframe-api/catalog/logo-catalog.json +86 -0
  129. package/workframe-api/catalog/user-avatar-catalog.json +171 -0
  130. package/workframe-api/credential_vault.py +445 -0
  131. package/workframe-api/data/.gitkeep +0 -0
  132. package/workframe-api/data/avatar-catalog.json +41 -0
  133. package/workframe-api/data/logo-catalog.json +14 -0
  134. package/workframe-api/data/user-avatar-catalog.json +18 -0
  135. package/workframe-api/email_sender.py +220 -0
  136. package/workframe-api/google_auth.py +90 -0
  137. package/workframe-api/install_api.py +359 -0
  138. package/workframe-api/internal_proxy_auth.py +150 -0
  139. package/workframe-api/llm_proxy.py +277 -0
  140. package/workframe-api/oidc_jwt.py +108 -0
  141. package/workframe-api/package.json +13 -0
  142. package/workframe-api/platform_auth.py +194 -0
  143. package/workframe-api/profile_secret_policy.py +86 -0
  144. package/workframe-api/public/assets/index-DPXu_lGn.css +1 -0
  145. package/workframe-api/public/assets/index-DYnLrCZZ.js +9 -0
  146. package/workframe-api/public/assets/index-DglUqFB_.js +9 -0
  147. package/workframe-api/public/index.html +12 -0
  148. package/workframe-api/requirements.txt +2 -0
  149. package/workframe-api/server.py +19646 -0
  150. package/workframe-api/site_meta.py +271 -0
  151. package/workframe-api/stack_config.py +427 -0
  152. package/workframe-api/tests/__init__.py +0 -0
  153. package/workframe-api/tests/db_setup.py +13 -0
  154. package/workframe-api/tests/test_admin_updates_gated.py +30 -0
  155. package/workframe-api/tests/test_agent_dm_bootstrap.py +196 -0
  156. package/workframe-api/tests/test_agent_profile_sync.py +76 -0
  157. package/workframe-api/tests/test_auth_email.py +222 -0
  158. package/workframe-api/tests/test_auth_hole_fix_selfcheck.py +99 -0
  159. package/workframe-api/tests/test_auth_rate_limit.py +19 -0
  160. package/workframe-api/tests/test_avatar_resolve.py +77 -0
  161. package/workframe-api/tests/test_child_soul_template.py +71 -0
  162. package/workframe-api/tests/test_credential_canary.py +135 -0
  163. package/workframe-api/tests/test_credential_isolation.py +448 -0
  164. package/workframe-api/tests/test_credential_resolution.py +206 -0
  165. package/workframe-api/tests/test_device_oauth.py +108 -0
  166. package/workframe-api/tests/test_doctor_repair.py +103 -0
  167. package/workframe-api/tests/test_ensure_profile_api.py +77 -0
  168. package/workframe-api/tests/test_gateway_compose_security.py +136 -0
  169. package/workframe-api/tests/test_install_secure_host.py +39 -0
  170. package/workframe-api/tests/test_internal_proxy_auth.py +125 -0
  171. package/workframe-api/tests/test_invite_runtime_bootstrap.py +72 -0
  172. package/workframe-api/tests/test_kanban_delegation.py +185 -0
  173. package/workframe-api/tests/test_llm_proxy.py +155 -0
  174. package/workframe-api/tests/test_login_access_policy.py +183 -0
  175. package/workframe-api/tests/test_mvp_model_bootstrap.py +75 -0
  176. package/workframe-api/tests/test_onboarding_bootstrap.py +248 -0
  177. package/workframe-api/tests/test_platform_auth.py +47 -0
  178. package/workframe-api/tests/test_profile_config_path.py +56 -0
  179. package/workframe-api/tests/test_profile_config_yaml_repair.py +63 -0
  180. package/workframe-api/tests/test_profile_create.py +72 -0
  181. package/workframe-api/tests/test_profile_identity_overlay.py +61 -0
  182. package/workframe-api/tests/test_profile_install_health.py +45 -0
  183. package/workframe-api/tests/test_profile_secret_policy.py +57 -0
  184. package/workframe-api/tests/test_profile_workspace_cwd.py +34 -0
  185. package/workframe-api/tests/test_provider_bootstrap.py +75 -0
  186. package/workframe-api/tests/test_provider_connect.py +54 -0
  187. package/workframe-api/tests/test_room_crud.py +192 -0
  188. package/workframe-api/tests/test_room_tenancy.py +701 -0
  189. package/workframe-api/tests/test_runtime_identity_backfill.py +34 -0
  190. package/workframe-api/tests/test_site_meta.py +81 -0
  191. package/workframe-api/tests/test_soul_stub.py +42 -0
  192. package/workframe-api/tests/test_space_member_sync.py +99 -0
  193. package/workframe-api/tests/test_stripe_stack_config.py +37 -0
  194. package/workframe-api/tests/test_supervisor_lifecycle.py +52 -0
  195. package/workframe-api/tests/test_turn_credential_vault.py +125 -0
  196. package/workframe-api/tests/test_updates.py +176 -0
  197. package/workframe-api/tests/test_user_cohort.py +113 -0
  198. package/workframe-api/tests/test_vault_envelope.py +110 -0
  199. package/workframe-api/tests/test_workspace_members.py +183 -0
  200. package/workframe-api/tests/test_workspace_messaging_sync.py +125 -0
  201. package/workframe-api/tests/test_workspace_provider_list.py +57 -0
  202. package/workframe-api/time-bind-chat.py +99 -0
  203. package/workframe-api/turn_credentials.py +226 -0
  204. package/workframe-api/updates.py +417 -0
  205. package/workframe-api/vault_kek.py +159 -0
  206. package/workframe-api/zk_auth.py +633 -0
  207. package/workframe-supervisor/Dockerfile +11 -0
  208. package/workframe-supervisor/profile_secret_policy.py +76 -0
  209. package/workframe-supervisor/server.py +787 -0
  210. package/workframe-supervisor/tests/test_exec_guard.py +42 -0
  211. package/workframe-supervisor/tests/test_server_import.py +21 -0
  212. package/workframe-ui/docker/nginx.conf +85 -0
  213. package/workframe-ui/public/assets/1-DLJbBkOb.png +0 -0
  214. package/workframe-ui/public/assets/10-uwRwj5ce.png +0 -0
  215. package/workframe-ui/public/assets/11-5OuV9F_e.png +0 -0
  216. package/workframe-ui/public/assets/12-u_axjxW-.png +0 -0
  217. package/workframe-ui/public/assets/13-ldSvcMsH.png +0 -0
  218. package/workframe-ui/public/assets/14-xdcALEYD.png +0 -0
  219. package/workframe-ui/public/assets/15-aZ4snEFB.png +0 -0
  220. package/workframe-ui/public/assets/16-L_5-DttY.png +0 -0
  221. package/workframe-ui/public/assets/2-zOPZTppD.png +0 -0
  222. package/workframe-ui/public/assets/3-Dc3WoVu5.png +0 -0
  223. package/workframe-ui/public/assets/4-C50hk7_m.png +0 -0
  224. package/workframe-ui/public/assets/5-Eweetkq4.png +0 -0
  225. package/workframe-ui/public/assets/6-5sOXgfkw.png +0 -0
  226. package/workframe-ui/public/assets/7-BqRBCbiC.png +0 -0
  227. package/workframe-ui/public/assets/8-DEDKS94h.png +0 -0
  228. package/workframe-ui/public/assets/9-DNj34GW-.png +0 -0
  229. package/workframe-ui/public/assets/ada-DsvuOc9n.png +0 -0
  230. package/workframe-ui/public/assets/aibert-BCz8Lo8H.png +0 -0
  231. package/workframe-ui/public/assets/amelia-DUf3EBGu.png +0 -0
  232. package/workframe-ui/public/assets/andy-Cpymuhhx.png +0 -0
  233. package/workframe-ui/public/assets/arc-CBDYvkAF.js +1 -0
  234. package/workframe-ui/public/assets/architecture-7EHR7CIX-CtbQKTuT.js +1 -0
  235. package/workframe-ui/public/assets/architectureDiagram-3BPJPVTR-XnBRKeW0.js +36 -0
  236. package/workframe-ui/public/assets/array-BifhSqXX.js +1 -0
  237. package/workframe-ui/public/assets/avatars/ada.png +0 -0
  238. package/workframe-ui/public/assets/avatars/aibert.png +0 -0
  239. package/workframe-ui/public/assets/avatars/amelia.png +0 -0
  240. package/workframe-ui/public/assets/avatars/andy.png +0 -0
  241. package/workframe-ui/public/assets/avatars/bob.png +0 -0
  242. package/workframe-ui/public/assets/avatars/buzz.png +0 -0
  243. package/workframe-ui/public/assets/avatars/carl.png +0 -0
  244. package/workframe-ui/public/assets/avatars/catalog.json +171 -0
  245. package/workframe-ui/public/assets/avatars/corbu.png +0 -0
  246. package/workframe-ui/public/assets/avatars/diana.png +0 -0
  247. package/workframe-ui/public/assets/avatars/elvis.png +0 -0
  248. package/workframe-ui/public/assets/avatars/frida.png +0 -0
  249. package/workframe-ui/public/assets/avatars/george.png +0 -0
  250. package/workframe-ui/public/assets/avatars/grace.png +0 -0
  251. package/workframe-ui/public/assets/avatars/hedy.png +0 -0
  252. package/workframe-ui/public/assets/avatars/hermes.png +0 -0
  253. package/workframe-ui/public/assets/avatars/isaac.png +0 -0
  254. package/workframe-ui/public/assets/avatars/john.png +0 -0
  255. package/workframe-ui/public/assets/avatars/joni.png +0 -0
  256. package/workframe-ui/public/assets/avatars/leo.png +0 -0
  257. package/workframe-ui/public/assets/avatars/louis.png +0 -0
  258. package/workframe-ui/public/assets/avatars/ludwig.png +0 -0
  259. package/workframe-ui/public/assets/avatars/marie.png +0 -0
  260. package/workframe-ui/public/assets/avatars/marilyn.png +0 -0
  261. package/workframe-ui/public/assets/avatars/nikola.png +0 -0
  262. package/workframe-ui/public/assets/avatars/nina.png +0 -0
  263. package/workframe-ui/public/assets/avatars/paul.png +0 -0
  264. package/workframe-ui/public/assets/avatars/ringo.png +0 -0
  265. package/workframe-ui/public/assets/avatars/rosie.png +0 -0
  266. package/workframe-ui/public/assets/avatars/steve.png +0 -0
  267. package/workframe-ui/public/assets/avatars/sun.png +0 -0
  268. package/workframe-ui/public/assets/avatars/warren.png +0 -0
  269. package/workframe-ui/public/assets/avatars/woz.png +0 -0
  270. package/workframe-ui/public/assets/avatars/zaha.png +0 -0
  271. package/workframe-ui/public/assets/blockDiagram-GPEHLZMM-VYHUfVhd.js +132 -0
  272. package/workframe-ui/public/assets/bob-DRz-48Id.png +0 -0
  273. package/workframe-ui/public/assets/branding/banner.png +0 -0
  274. package/workframe-ui/public/assets/branding/og-default.png +0 -0
  275. package/workframe-ui/public/assets/branding/workframe'white.png +0 -0
  276. package/workframe-ui/public/assets/branding/workframe-1.png +0 -0
  277. package/workframe-ui/public/assets/branding/workframe-2.png +0 -0
  278. package/workframe-ui/public/assets/branding/workframe-3.png +0 -0
  279. package/workframe-ui/public/assets/branding/workframe-4.png +0 -0
  280. package/workframe-ui/public/assets/branding/workframe-5.png +0 -0
  281. package/workframe-ui/public/assets/branding/workframe-banner.png +0 -0
  282. package/workframe-ui/public/assets/branding/workframe-logo-horizontal-mini.png +0 -0
  283. package/workframe-ui/public/assets/branding/workframe-logo-horizontal-nano.png +0 -0
  284. package/workframe-ui/public/assets/branding/workframe-logo-horizontal.png +0 -0
  285. package/workframe-ui/public/assets/branding/workframe-logo-vertical-alt.png +0 -0
  286. package/workframe-ui/public/assets/branding/workframe-logo-vertical.png +0 -0
  287. package/workframe-ui/public/assets/branding/workframe.png +0 -0
  288. package/workframe-ui/public/assets/buzz-mC4PtMvC.png +0 -0
  289. package/workframe-ui/public/assets/c4Diagram-AAUBKEIU-BTjUcJpm.js +10 -0
  290. package/workframe-ui/public/assets/carl-CtE74db_.png +0 -0
  291. package/workframe-ui/public/assets/channel-Dy4Z4-jn.js +1 -0
  292. package/workframe-ui/public/assets/chunk-2J33WTMH-w7uu7R-b.js +1 -0
  293. package/workframe-ui/public/assets/chunk-3OPIFGDE-Cb9LtnDX.js +62 -0
  294. package/workframe-ui/public/assets/chunk-4BX2VUAB-DiQ-qCwH.js +1 -0
  295. package/workframe-ui/public/assets/chunk-55IACEB6-C-mLFr7z.js +1 -0
  296. package/workframe-ui/public/assets/chunk-5ZQYHXKU-DOesfiCI.js +2 -0
  297. package/workframe-ui/public/assets/chunk-727SXJPM-BJ3oBZuz.js +206 -0
  298. package/workframe-ui/public/assets/chunk-AQP2D5EJ-CCA6xpGs.js +231 -0
  299. package/workframe-ui/public/assets/chunk-BSJP7CBP-a0cMNFb2.js +1 -0
  300. package/workframe-ui/public/assets/chunk-CSCIHK7Q-kuqN8EIY.js +122 -0
  301. package/workframe-ui/public/assets/chunk-FMBD7UC4-DyPgYHCg.js +15 -0
  302. package/workframe-ui/public/assets/chunk-KSCS5N6A-CdUuvR0V.js +10 -0
  303. package/workframe-ui/public/assets/chunk-L5ZTLDWV-Dq9NoWmK.js +1 -0
  304. package/workframe-ui/public/assets/chunk-LZXEDZCA-p74rddlO.js +2 -0
  305. package/workframe-ui/public/assets/chunk-ND2GUHAM-DBD2u1Gz.js +1 -0
  306. package/workframe-ui/public/assets/chunk-NNHCCRGN-DlpIbxXb.js +159 -0
  307. package/workframe-ui/public/assets/chunk-NZK2D7GU-BeIeYFnd.js +1 -0
  308. package/workframe-ui/public/assets/chunk-O5CBEL6O-ClHc56ib.js +70 -0
  309. package/workframe-ui/public/assets/chunk-QZHKN3VN-CtBEchFK.js +1 -0
  310. package/workframe-ui/public/assets/chunk-WU5MYG2G-B9pBtriN.js +1 -0
  311. package/workframe-ui/public/assets/chunk-XPW4576I-EFr8R_1p.js +32 -0
  312. package/workframe-ui/public/assets/classDiagram-4FO5ZUOK-BMAEA8jI.js +1 -0
  313. package/workframe-ui/public/assets/classDiagram-v2-Q7XG4LA2-BMAEA8jI.js +1 -0
  314. package/workframe-ui/public/assets/corbu-KiaMXzXQ.png +0 -0
  315. package/workframe-ui/public/assets/cose-bilkent-S5V4N54A-C7aPBODd.js +1 -0
  316. package/workframe-ui/public/assets/cytoscape.esm-h6BdjjI9.js +321 -0
  317. package/workframe-ui/public/assets/dagre-BM42HDAG-BdU1Rv-H.js +4 -0
  318. package/workframe-ui/public/assets/dagre-Bx709z4p.js +1 -0
  319. package/workframe-ui/public/assets/defaultLocale-C8Fc0cco.js +1 -0
  320. package/workframe-ui/public/assets/diagram-2AECGRRQ-DWowSo85.js +43 -0
  321. package/workframe-ui/public/assets/diagram-5GNKFQAL-MnxBbceO.js +10 -0
  322. package/workframe-ui/public/assets/diagram-KO2AKTUF-DQaLRXFf.js +3 -0
  323. package/workframe-ui/public/assets/diagram-LMA3HP47-CQaBud9k.js +24 -0
  324. package/workframe-ui/public/assets/diagram-OG6HWLK6-D8bAXbY9.js +24 -0
  325. package/workframe-ui/public/assets/diana-DW0MsL38.png +0 -0
  326. package/workframe-ui/public/assets/dist-DGpTLHr_.js +1 -0
  327. package/workframe-ui/public/assets/elvis-LCFaZIcT.png +0 -0
  328. package/workframe-ui/public/assets/erDiagram-TEJ5UH35-1E-xSvBK.js +85 -0
  329. package/workframe-ui/public/assets/eventmodeling-FCH6USID-D75cstNT.js +1 -0
  330. package/workframe-ui/public/assets/flowDiagram-I6XJVG4X-CgOVD5hu.js +162 -0
  331. package/workframe-ui/public/assets/frida-CXFA0w3F.png +0 -0
  332. package/workframe-ui/public/assets/ganttDiagram-6RSMTGT7-JFYAIauo.js +292 -0
  333. package/workframe-ui/public/assets/george-DBSH2Sm2.png +0 -0
  334. package/workframe-ui/public/assets/gitGraph-WXDBUCRP-B9REenIl.js +1 -0
  335. package/workframe-ui/public/assets/gitGraphDiagram-PVQCEYII-BQ7NcMSn.js +106 -0
  336. package/workframe-ui/public/assets/grace-BhV0UPc0.png +0 -0
  337. package/workframe-ui/public/assets/graphlib-B8gBHxth.js +1 -0
  338. package/workframe-ui/public/assets/hedy-BR2IHift.png +0 -0
  339. package/workframe-ui/public/assets/hermes-CqCzcE0y.png +0 -0
  340. package/workframe-ui/public/assets/index-Dnw6vjqb.js +133 -0
  341. package/workframe-ui/public/assets/index-DpAGxump.css +1 -0
  342. package/workframe-ui/public/assets/info-J43DQDTF-CL6-eTjH.js +1 -0
  343. package/workframe-ui/public/assets/infoDiagram-5YYISTIA-LJTODW4W.js +2 -0
  344. package/workframe-ui/public/assets/init-D6jRqBbL.js +1 -0
  345. package/workframe-ui/public/assets/isaac-D1nhJAuv.png +0 -0
  346. package/workframe-ui/public/assets/ishikawaDiagram-YF4QCWOH-bchrQVuo.js +70 -0
  347. package/workframe-ui/public/assets/john-zSPWwNi4.png +0 -0
  348. package/workframe-ui/public/assets/joni-BFLoyfJP.png +0 -0
  349. package/workframe-ui/public/assets/journeyDiagram-JHISSGLW-DkrvYuxP.js +139 -0
  350. package/workframe-ui/public/assets/kanban-definition-UN3LZRKU-DFRbj0IG.js +89 -0
  351. package/workframe-ui/public/assets/katex-Vhh-h91d.js +257 -0
  352. package/workframe-ui/public/assets/leo-C_3IOL11.png +0 -0
  353. package/workframe-ui/public/assets/line-Vd48P7-O.js +1 -0
  354. package/workframe-ui/public/assets/linear-Ckizh2G7.js +1 -0
  355. package/workframe-ui/public/assets/louis-DEEECFSX.png +0 -0
  356. package/workframe-ui/public/assets/ludwig-_hoKhhyK.png +0 -0
  357. package/workframe-ui/public/assets/marie-DET6MsfO.png +0 -0
  358. package/workframe-ui/public/assets/marilyn-DTqwt8Yh.png +0 -0
  359. package/workframe-ui/public/assets/mermaid-parser.core-Bkimsnqj.js +4 -0
  360. package/workframe-ui/public/assets/mermaid.core-x0TvVuPo.js +9 -0
  361. package/workframe-ui/public/assets/mindmap-definition-RKZ34NQL-6ykAFPEz.js +96 -0
  362. package/workframe-ui/public/assets/nikola-B4PtHrJv.png +0 -0
  363. package/workframe-ui/public/assets/nina-BYbrOn0d.png +0 -0
  364. package/workframe-ui/public/assets/ordinal-hYBb2elL.js +1 -0
  365. package/workframe-ui/public/assets/packet-YPE3B663-Dw3xgMDt.js +1 -0
  366. package/workframe-ui/public/assets/path-BWPyau1x.js +1 -0
  367. package/workframe-ui/public/assets/paul-CGURYQIn.png +0 -0
  368. package/workframe-ui/public/assets/pie-LRSECV5Y-DATysawG.js +1 -0
  369. package/workframe-ui/public/assets/pieDiagram-4H26LBE5-SJKD1S0S.js +30 -0
  370. package/workframe-ui/public/assets/project-logos/1.png +0 -0
  371. package/workframe-ui/public/assets/project-logos/10.png +0 -0
  372. package/workframe-ui/public/assets/project-logos/11.png +0 -0
  373. package/workframe-ui/public/assets/project-logos/12.png +0 -0
  374. package/workframe-ui/public/assets/project-logos/13.png +0 -0
  375. package/workframe-ui/public/assets/project-logos/14.png +0 -0
  376. package/workframe-ui/public/assets/project-logos/15.png +0 -0
  377. package/workframe-ui/public/assets/project-logos/16.png +0 -0
  378. package/workframe-ui/public/assets/project-logos/2.png +0 -0
  379. package/workframe-ui/public/assets/project-logos/3.png +0 -0
  380. package/workframe-ui/public/assets/project-logos/4.png +0 -0
  381. package/workframe-ui/public/assets/project-logos/5.png +0 -0
  382. package/workframe-ui/public/assets/project-logos/6.png +0 -0
  383. package/workframe-ui/public/assets/project-logos/7.png +0 -0
  384. package/workframe-ui/public/assets/project-logos/8.png +0 -0
  385. package/workframe-ui/public/assets/project-logos/9.png +0 -0
  386. package/workframe-ui/public/assets/project-logos/catalog.json +86 -0
  387. package/workframe-ui/public/assets/quadrantDiagram-W4KKPZXB-BrYDZX8q.js +7 -0
  388. package/workframe-ui/public/assets/radar-GUYGQ44K-BmWYPCds.js +1 -0
  389. package/workframe-ui/public/assets/requirementDiagram-4Y6WPE33-DwL9Mc8e.js +84 -0
  390. package/workframe-ui/public/assets/ringo-WhfUNOyY.png +0 -0
  391. package/workframe-ui/public/assets/rosie-CAtcIf87.png +0 -0
  392. package/workframe-ui/public/assets/rough.esm-CSKSodPl.js +1 -0
  393. package/workframe-ui/public/assets/sankeyDiagram-5OEKKPKP-DYIFsL8h.js +40 -0
  394. package/workframe-ui/public/assets/sequenceDiagram-3UESZ5HK-0-FPkFk8.js +162 -0
  395. package/workframe-ui/public/assets/src-B_od6b6h.js +1 -0
  396. package/workframe-ui/public/assets/stateDiagram-AJRCARHV-BQCiBk6u.js +1 -0
  397. package/workframe-ui/public/assets/stateDiagram-v2-BHNVJYJU-B89jAMFF.js +1 -0
  398. package/workframe-ui/public/assets/steve-CgXXJ9EZ.png +0 -0
  399. package/workframe-ui/public/assets/sun-BLNAhoZd.png +0 -0
  400. package/workframe-ui/public/assets/timeline-definition-PNZ67QCA-DS3tFcXj.js +120 -0
  401. package/workframe-ui/public/assets/treeView-BLDUP644-DSyUCKLY.js +1 -0
  402. package/workframe-ui/public/assets/treemap-LRROVOQU-CEZaNh5Y.js +1 -0
  403. package/workframe-ui/public/assets/vennDiagram-CIIHVFJN-CD-Vc9NF.js +34 -0
  404. package/workframe-ui/public/assets/wardley-L42UT6IY-Drq5w1Mc.js +1 -0
  405. package/workframe-ui/public/assets/wardleyDiagram-YWT4CUSO-DouXDJoF.js +78 -0
  406. package/workframe-ui/public/assets/warren-DIH7UKMY.png +0 -0
  407. package/workframe-ui/public/assets/woz-D2yleG-V.png +0 -0
  408. package/workframe-ui/public/assets/xychartDiagram-2RQKCTM6-DDf_Lol5.js +7 -0
  409. package/workframe-ui/public/assets/zaha-wersOEq9.png +0 -0
  410. package/workframe-ui/public/favicon.ico +0 -0
  411. package/workframe-ui/public/favicon.svg +7 -0
  412. package/workframe-ui/public/icons.svg +24 -0
  413. package/workframe-ui/public/index.html +50 -0
  414. package/workframe-ui/public/manifest.webmanifest +18 -0
  415. package/workframe-ui/public/workframe-config.json +4 -0
@@ -0,0 +1,390 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Dev/CI smoke test: generate all packs and verify required scaffold files.
4
+ * Canonical installer: bin/create-workframe.js
5
+ */
6
+ import fs from 'node:fs';
7
+ import os from 'node:os';
8
+ import path from 'node:path';
9
+ import { spawnSync } from 'node:child_process';
10
+ import { fileURLToPath } from 'node:url';
11
+
12
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
13
+ const PKG_ROOT = path.resolve(__dirname, '..');
14
+ const SYNC = path.join(PKG_ROOT, 'scripts', 'sync-canonical-to-package.mjs');
15
+ const CLI = path.join(PKG_ROOT, 'bin', 'create-workframe.js');
16
+
17
+ const syncRes = spawnSync(process.execPath, [SYNC], { encoding: 'utf8', cwd: PKG_ROOT });
18
+ if (syncRes.status !== 0) {
19
+ console.error(syncRes.stderr || syncRes.stdout);
20
+ process.exit(syncRes.status ?? 1);
21
+ }
22
+ const PACKS = ['native', 'core', 'product', 'engineering', 'vanilla'];
23
+ const REQUIRED = [
24
+ 'Agents/.gitkeep',
25
+ 'Files/AGENTS.md',
26
+ 'Files/.hermes.md',
27
+ 'Files/README.md',
28
+ 'SETUP.md',
29
+ 'README.md',
30
+ 'docker-compose.yml',
31
+ '.env.example',
32
+ '.env',
33
+ 'docs/PUBLIC_DEPLOY.md',
34
+ 'scripts/bootstrap-native.sh',
35
+ 'scripts/bootstrap-native.ps1',
36
+ 'scripts/bootstrap-profiles.sh',
37
+ 'scripts/bootstrap-profiles.ps1',
38
+ 'scripts/add-profile.sh',
39
+ 'scripts/add-profile.ps1',
40
+ 'scripts/open-setup.sh',
41
+ 'scripts/open-setup.ps1',
42
+ 'scripts/install.sh',
43
+ 'scripts/install.ps1',
44
+ 'scripts/start-install.sh',
45
+ 'scripts/start-install.ps1',
46
+ 'scripts/launch-install.ps1',
47
+ 'scripts/launch-install.sh',
48
+ 'scripts/open-chat.ps1',
49
+ 'scripts/open-chat.sh',
50
+ 'scripts/open-workframe-api.ps1',
51
+ 'scripts/open-workframe-api.sh',
52
+ 'scripts/open-workframe-ui.ps1',
53
+ 'scripts/open-workframe-ui.sh',
54
+ 'scripts/update-hermes.ps1',
55
+ 'scripts/update-hermes.sh',
56
+ 'scripts/setup-stack-secrets.sh',
57
+ 'scripts/agent-lifecycle.mjs',
58
+ 'scripts/lib/workframe-registry.mjs',
59
+ 'scripts/chat.sh',
60
+ 'scripts/chat.ps1',
61
+ 'scripts/verify-bootstrap.sh',
62
+ 'scripts/verify-bootstrap.ps1',
63
+ 'scripts/seed/agent-template/SOUL.md',
64
+ 'workframe-api/server.py',
65
+ 'workframe-api/public/index.html',
66
+ 'workframe-api/data/.gitkeep',
67
+ 'workframe-supervisor/server.py',
68
+ 'workframe-supervisor/Dockerfile',
69
+ 'workframe-ui/public/index.html',
70
+ 'workframe-ui/public/workframe-config.json',
71
+ 'workframe-ui/docker/nginx.conf',
72
+ 'docker/dashboard-proxy.conf',
73
+ 'workframe-manifest.json',
74
+ ];
75
+
76
+ function slugify(name) {
77
+ return name.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '') || 'workframe';
78
+ }
79
+
80
+ function nativeProfileSlug(name) {
81
+ return `${slugify(name)}-agent`;
82
+ }
83
+
84
+ function nativeAgentName(name) {
85
+ return `${name} Agent`;
86
+ }
87
+
88
+ function dockerStack(name) {
89
+ return slugify(name);
90
+ }
91
+
92
+ function fail(msg) {
93
+ console.error(`FAIL: ${msg}`);
94
+ process.exit(1);
95
+ }
96
+
97
+ function assertFile(root, rel) {
98
+ const file = path.join(root, rel);
99
+ if (!fs.existsSync(file)) fail(`missing ${rel} in ${root}`);
100
+ }
101
+
102
+ const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'wf-test-'));
103
+ console.log(`Scaffold test dir: ${tmp}`);
104
+
105
+ for (const pack of PACKS) {
106
+ const name = `Test_${pack}`;
107
+ const res = spawnSync(process.execPath, [CLI, name, '--pack', pack, '--out', tmp, '--ci', '--force'], {
108
+ encoding: 'utf8',
109
+ });
110
+ if (res.status !== 0) fail(`pack ${pack}: ${res.stderr || res.stdout}`);
111
+ const root = path.join(tmp, name);
112
+ for (const rel of REQUIRED) assertFile(root, rel);
113
+
114
+ const manifest = JSON.parse(fs.readFileSync(path.join(root, 'workframe-manifest.json'), 'utf8'));
115
+ const expectedSlug = nativeProfileSlug(name);
116
+ const expectedName = nativeAgentName(name);
117
+ const expectedStack = dockerStack(name);
118
+
119
+ if (manifest.native_agent?.profile_slug !== expectedSlug) {
120
+ fail(`pack ${pack}: expected native slug ${expectedSlug}, got ${manifest.native_agent?.profile_slug}`);
121
+ }
122
+ if (manifest.native_agent?.display_name !== expectedName) {
123
+ fail(`pack ${pack}: expected native name ${expectedName}, got ${manifest.native_agent?.display_name}`);
124
+ }
125
+ if (!manifest.package_version) fail(`pack ${pack}: manifest missing package_version`);
126
+ if (manifest.docker?.stack !== expectedStack) {
127
+ fail(`pack ${pack}: expected docker stack ${expectedStack}, got ${manifest.docker?.stack}`);
128
+ }
129
+ if (manifest.docker?.containers?.gateway !== `${expectedStack}-gateway`) {
130
+ fail(`pack ${pack}: unexpected gateway container name`);
131
+ }
132
+ if (manifest.docker?.containers?.workframe !== `${expectedStack}-workframe`) {
133
+ fail(`pack ${pack}: unexpected workframe container name`);
134
+ }
135
+ if (manifest.docker?.containers?.workframe_api !== `${expectedStack}-workframe-api`) {
136
+ fail(`pack ${pack}: unexpected workframe-api container name`);
137
+ }
138
+ if (!manifest.profiles.includes(expectedSlug)) {
139
+ fail(`pack ${pack}: profiles missing native slug ${expectedSlug}`);
140
+ }
141
+ if (pack === 'native') {
142
+ if (manifest.profiles.length !== 1 || manifest.profiles[0] !== expectedSlug) {
143
+ fail(`pack ${pack}: expected native-only bootstrap profiles, got ${manifest.profiles.join(', ')}`);
144
+ }
145
+ if (manifest.profiles_installed_after_native_bootstrap?.length !== 1 || manifest.profiles_installed_after_native_bootstrap?.[0] !== expectedSlug) {
146
+ fail(`pack ${pack}: expected native-only installed_after_native_bootstrap`);
147
+ }
148
+ }
149
+ if (!manifest.profiles_catalog?.length) fail(`pack ${pack}: manifest missing profiles_catalog`);
150
+ if (manifest.bootstrap?.default !== 'native') fail(`pack ${pack}: bootstrap.default should be native`);
151
+ if (!manifest.ports?.gateway || !manifest.ports?.dashboard || !manifest.ports?.ui || !manifest.ports?.api) {
152
+ fail(`pack ${pack}: manifest missing ports`);
153
+ }
154
+ if (manifest.layout?.workspace !== 'Files' || manifest.layout?.runtime !== 'Agents') {
155
+ fail(`pack ${pack}: manifest layout should stay Files/Agents`);
156
+ }
157
+
158
+ assertFile(root, `scripts/seed/profiles/${expectedSlug}/SOUL.md`);
159
+ assertFile(root, `scripts/seed/profiles/${expectedSlug}/SETUP.md`);
160
+
161
+ const nativeSoul = fs.readFileSync(path.join(root, `scripts/seed/profiles/${expectedSlug}/SOUL.md`), 'utf8');
162
+ if (!nativeSoul.includes('Setup gate')) fail(`pack ${pack}: native SOUL missing setup gate`);
163
+ const nativeSetup = fs.readFileSync(path.join(root, `scripts/seed/profiles/${expectedSlug}/SETUP.md`), 'utf8');
164
+ if (!nativeSetup.includes('Credential security')) fail(`pack ${pack}: native SETUP missing credential section`);
165
+
166
+ const compose = fs.readFileSync(path.join(root, 'docker-compose.yml'), 'utf8');
167
+ if (!compose.includes(`container_name: ${expectedStack}-gateway`)) {
168
+ fail(`pack ${pack}: compose missing named gateway container`);
169
+ }
170
+ if (!compose.includes(`container_name: ${expectedStack}-workframe`)) {
171
+ fail(`pack ${pack}: compose missing workframe UI container`);
172
+ }
173
+ if (!compose.includes(`container_name: ${expectedStack}-workframe-api`)) {
174
+ fail(`pack ${pack}: compose missing workframe-api container`);
175
+ }
176
+ if (!compose.includes(`container_name: ${expectedStack}-workframe-supervisor`)) {
177
+ fail(`pack ${pack}: compose missing workframe-supervisor container`);
178
+ }
179
+ if (!compose.includes('context: ./workframe-supervisor')) {
180
+ fail(`pack ${pack}: compose missing workframe-supervisor build context`);
181
+ }
182
+ if (!compose.includes('WORKFRAME_SUPERVISOR_URL=http://workframe-supervisor:8090')) {
183
+ fail(`pack ${pack}: compose missing supervisor URL for API`);
184
+ }
185
+ if (!compose.includes('internal: true')) {
186
+ fail(`pack ${pack}: compose missing internal control network`);
187
+ }
188
+ const gatewayBlock = compose.split(/^ (?=[a-z])/m).find((block) => block.startsWith('gateway:'));
189
+ if (gatewayBlock?.includes('env_file:')) {
190
+ fail(`pack ${pack}: gateway must not use env_file (secrets stay off Hermes container)`);
191
+ }
192
+ if (!compose.includes('workframe-proxy-token:/run/workframe-proxy')) {
193
+ fail(`pack ${pack}: compose missing shared proxy token volume`);
194
+ }
195
+ if (!compose.includes('WORKFRAME_PROXY_TOKEN')) {
196
+ fail(`pack ${pack}: compose missing WORKFRAME_PROXY_TOKEN`);
197
+ }
198
+ if (!compose.includes('gateway run') || !compose.includes(`-p ${expectedSlug}`)) {
199
+ fail(`pack ${pack}: compose gateway missing native profile ${expectedSlug}`);
200
+ }
201
+ if (!gatewayBlock?.includes('./Agents:/opt/data')) {
202
+ fail(`pack ${pack}: gateway must mount ./Agents:/opt/data (not host Hermes)`);
203
+ }
204
+ if (gatewayBlock?.includes('AppData/Local/hermes') || gatewayBlock?.includes('/.hermes')) {
205
+ fail(`pack ${pack}: gateway must not bind host Hermes into the stack`);
206
+ }
207
+ if (!compose.includes('./workframe-api/public:/app/public:ro')) {
208
+ fail(`pack ${pack}: compose missing workframe-api public mount`);
209
+ }
210
+ if (!compose.includes('WORKFRAME_UI_STATIC_DIR:-./workframe-ui/public') && !compose.includes('./workframe-ui/public:/usr/share/nginx/html:ro')) {
211
+ fail(`pack ${pack}: compose missing workframe-ui public mount`);
212
+ }
213
+ if (!compose.includes('./workframe-ui/docker/nginx.conf:/etc/nginx/conf.d/default.conf:ro')) {
214
+ fail(`pack ${pack}: compose missing workframe-ui nginx mount`);
215
+ }
216
+ if (!compose.includes('./docker/dashboard-proxy.conf:/etc/nginx/conf.d/default.conf:ro')) {
217
+ fail(`pack ${pack}: compose missing dashboard proxy mount`);
218
+ }
219
+ if (!compose.includes('./scripts:/opt/install/scripts:ro')) {
220
+ fail(`pack ${pack}: docker-compose must mount scripts`);
221
+ }
222
+ if (!compose.includes('HERMES_DASHBOARD_TUI=1')) {
223
+ fail(`pack ${pack}: compose missing dashboard TUI enablement`);
224
+ }
225
+ if (gatewayBlock?.includes('HERMES_DASHBOARD_INSECURE=1')) {
226
+ fail(`pack ${pack}: gateway must use dashboard basic auth, not HERMES_DASHBOARD_INSECURE`);
227
+ }
228
+ if (!gatewayBlock?.includes('HERMES_DASHBOARD_BASIC_AUTH_USERNAME')) {
229
+ fail(`pack ${pack}: gateway missing dashboard basic auth env`);
230
+ }
231
+ if (compose.includes('mission-control')) {
232
+ fail(`pack ${pack}: compose should not include mission-control in the default stack`);
233
+ }
234
+
235
+ const publicCompose = fs.readFileSync(path.join(root, 'docker-compose.public.yml'), 'utf8');
236
+ if (!fs.existsSync(path.join(root, 'docker-compose.host-bindings.yml'))) {
237
+ fail(`pack ${pack}: missing docker-compose.host-bindings.yml for supervisor apply`);
238
+ }
239
+ const hostBindings = fs.readFileSync(path.join(root, 'docker-compose.host-bindings.yml'), 'utf8');
240
+ if (!hostBindings.includes('WORKFRAME_HOST_PROJECT_ROOT')) {
241
+ fail(`pack ${pack}: host-bindings overlay must use WORKFRAME_HOST_PROJECT_ROOT`);
242
+ }
243
+ const publicApiBlock = publicCompose.split(/^ (?=[a-z])/m).find((block) => block.startsWith('workframe-api:'));
244
+ if (publicApiBlock?.includes('/var/run/docker.sock')) {
245
+ fail(`pack ${pack}: docker-compose.public.yml must not mount docker.sock on workframe-api`);
246
+ }
247
+ if (!publicCompose.includes('workframe-proxy-token:/run/workframe-proxy')) {
248
+ fail(`pack ${pack}: docker-compose.public.yml missing proxy token volume on API`);
249
+ }
250
+
251
+ const envExample = fs.readFileSync(path.join(root, '.env.example'), 'utf8');
252
+ if (!envExample.includes('WORKFRAME_PROXY_TOKEN')) {
253
+ fail(`pack ${pack}: .env.example missing WORKFRAME_PROXY_TOKEN`);
254
+ }
255
+ if (!envExample.includes('WORKFRAME_VAULT_KEK')) {
256
+ fail(`pack ${pack}: .env.example missing WORKFRAME_VAULT_KEK`);
257
+ }
258
+
259
+ const nginx = fs.readFileSync(path.join(root, 'workframe-ui/docker/nginx.conf'), 'utf8');
260
+ if (nginx.includes('/hermes-profiles/')) {
261
+ fail(`pack ${pack}: nginx should not include /hermes-profiles/ locations`);
262
+ }
263
+
264
+ const wfCfg = JSON.parse(fs.readFileSync(path.join(root, 'workframe-ui/public/workframe-config.json'), 'utf8'));
265
+ if (wfCfg.native_profile !== expectedSlug) {
266
+ fail(`pack ${pack}: workframe-config native_profile expected ${expectedSlug}, got ${wfCfg.native_profile}`);
267
+ }
268
+ if (wfCfg.project_name !== name) {
269
+ fail(`pack ${pack}: workframe-config project_name expected ${name}, got ${wfCfg.project_name}`);
270
+ }
271
+
272
+ const workspaceFiles = fs.readdirSync(path.join(root, 'Files')).sort();
273
+ const expectedWorkspaceFiles = ['.hermes.md', 'AGENTS.md', 'README.md'];
274
+ if (workspaceFiles.join('|') !== expectedWorkspaceFiles.join('|')) {
275
+ fail(`pack ${pack}: Files/ should stay lean, got ${workspaceFiles.join(', ')}`);
276
+ }
277
+
278
+ const agents = fs.readFileSync(path.join(root, 'Files/AGENTS.md'), 'utf8');
279
+ if (!agents.includes(expectedName)) fail(`pack ${pack}: AGENTS.md missing native agent name`);
280
+
281
+ const readme = fs.readFileSync(path.join(root, 'README.md'), 'utf8');
282
+ if (readme.includes('Workframe/scripts/')) fail(`pack ${pack}: README still references nested Workframe/scripts paths`);
283
+
284
+ const setup = fs.readFileSync(path.join(root, 'SETUP.md'), 'utf8');
285
+ if (!setup.includes('bootstrap-native')) fail(`pack ${pack}: SETUP.md missing native bootstrap`);
286
+ if (!setup.includes('add-profile')) fail(`pack ${pack}: SETUP.md missing add-profile`);
287
+ if (!setup.includes('start-install')) fail(`pack ${pack}: SETUP.md missing start-install`);
288
+ if (setup.includes('mission control')) fail(`pack ${pack}: SETUP.md should not position mission control in the main flow`);
289
+
290
+ const updateHermes = fs.readFileSync(path.join(root, 'scripts/update-hermes.ps1'), 'utf8');
291
+ if (updateHermes.includes('dashboard-')) {
292
+ fail(`pack ${pack}: update-hermes.ps1 should not recreate profile dashboard services`);
293
+ }
294
+
295
+ const chat = fs.readFileSync(path.join(root, 'scripts/chat.ps1'), 'utf8');
296
+ if (!chat.includes(`-p ${expectedSlug}`)) fail(`pack ${pack}: chat.ps1 missing native profile flag`);
297
+ if (!chat.includes(`${expectedStack}-chat`)) fail(`pack ${pack}: chat.ps1 missing named chat container`);
298
+
299
+ const bootstrapNative = fs.readFileSync(path.join(root, 'scripts/bootstrap-native.ps1'), 'utf8');
300
+ if (!bootstrapNative.includes(`profile use ${expectedSlug}`)) fail(`pack ${pack}: bootstrap-native missing profile use`);
301
+ if (!bootstrapNative.includes('routes.json')) fail(`pack ${pack}: bootstrap-native must write Agents/workframe/routes.json`);
302
+ if (!bootstrapNative.includes('SETUP.md')) fail(`pack ${pack}: bootstrap-native missing SETUP copy`);
303
+ if (!bootstrapNative.includes('Agents\\SOUL.md')) fail(`pack ${pack}: bootstrap-native must install Agents/SOUL.md`);
304
+ if (!bootstrapNative.includes('cwd: /workspace')) fail(`pack ${pack}: bootstrap-native must set terminal.cwd to /workspace`);
305
+
306
+ const startInstall = fs.readFileSync(path.join(root, 'scripts/start-install.ps1'), 'utf8');
307
+ if (!startInstall.includes('open-install-ui.ps1')) fail(`pack ${pack}: start-install.ps1 missing open-install-ui`);
308
+ const startInstallSh = fs.readFileSync(path.join(root, 'scripts/start-install.sh'), 'utf8');
309
+ if (!startInstallSh.includes('open-install-ui.sh')) fail(`pack ${pack}: start-install.sh missing open-install-ui`);
310
+ if (!fs.existsSync(path.join(root, 'scripts/apply-update-hermes.sh'))) {
311
+ fail(`pack ${pack}: missing scripts/apply-update-hermes.sh`);
312
+ }
313
+ if (!fs.existsSync(path.join(root, 'scripts/apply-update-workframe.sh'))) {
314
+ fail(`pack ${pack}: missing scripts/apply-update-workframe.sh`);
315
+ }
316
+ const installPs1 = fs.readFileSync(path.join(root, 'scripts/install.ps1'), 'utf8');
317
+ if (!installPs1.includes('open-workframe-ui.ps1')) fail(`pack ${pack}: install.ps1 missing open-workframe-ui`);
318
+ const installSh = fs.readFileSync(path.join(root, 'scripts/install.sh'), 'utf8');
319
+ if (!installSh.includes('open-workframe-ui.sh')) fail(`pack ${pack}: install.sh missing open-workframe-ui`);
320
+ const launchSh = fs.readFileSync(path.join(root, 'scripts/launch-install.sh'), 'utf8');
321
+ if (!launchSh.includes('start-install.sh')) fail(`pack ${pack}: launch-install.sh missing start-install`);
322
+
323
+ const addProfile = fs.readFileSync(path.join(root, 'scripts/add-profile.ps1'), 'utf8');
324
+ if (!addProfile.includes("'dev'")) fail(`pack ${pack}: add-profile missing dev in catalog`);
325
+
326
+ const verify = fs.readFileSync(path.join(root, 'scripts/verify-bootstrap.ps1'), 'utf8');
327
+ if (!verify.includes('bootstrap-native')) fail(`pack ${pack}: verify-bootstrap should mention bootstrap-native`);
328
+ if (!verify.includes('Agents\\SOUL.md')) fail(`pack ${pack}: verify-bootstrap must check Agents\\SOUL.md`);
329
+
330
+ const workframeApi = fs.readFileSync(path.join(root, 'workframe-api/server.py'), 'utf8');
331
+ if (!workframeApi.includes('active_id = persistent_id if persistent_valid else ""')) {
332
+ fail(`pack ${pack}: workframe-api bootstrap should not treat latest native session as active`);
333
+ }
334
+ if (workframeApi.includes('latest = _latest_session_id(prof)')) {
335
+ fail(`pack ${pack}: workframe-api should not fall back to latest session in profile_chat_session`);
336
+ }
337
+ if (!workframeApi.includes('binding_version = _binding_version(payload.get("binding_version"))')) {
338
+ fail(`pack ${pack}: workframe-api should version native UI bindings`);
339
+ }
340
+ if (!workframeApi.includes('"binding_version": binding_version')) {
341
+ fail(`pack ${pack}: workframe-api should persist binding_version in lane bindings`);
342
+ }
343
+ if (!workframeApi.includes('_wait_profile_api_healthy(profile: str, attempts: int = 60')) {
344
+ fail(`pack ${pack}: workframe-api must wait >=30s for cold u-* profile health`);
345
+ }
346
+ if (!workframeApi.includes('http://gateway:')) {
347
+ fail(`pack ${pack}: workframe-api profile health must probe gateway DNS from BFF container`);
348
+ }
349
+ if (!workframeApi.includes('for attempt in range(3)')) {
350
+ fail(`pack ${pack}: bootstrap_agent_dm_lane must retry gateway start up to 3 times`);
351
+ }
352
+
353
+ if (!workframeApi.includes('internal_proxy_auth')) {
354
+ fail(`pack ${pack}: workframe-api missing internal proxy auth`);
355
+ }
356
+ if (!workframeApi.includes('credential_vault.bootstrap_vault')) {
357
+ fail(`pack ${pack}: workframe-api missing vault envelope bootstrap`);
358
+ }
359
+ if (!workframeApi.includes('_invite_only_login_enforced')) {
360
+ fail(`pack ${pack}: workframe-api missing invite-only login gate`);
361
+ }
362
+
363
+ const supervisorPy = fs.readFileSync(path.join(root, 'workframe-supervisor/server.py'), 'utf8');
364
+ if (!supervisorPy.includes('for _ in range(60):')) {
365
+ fail(`pack ${pack}: workframe-supervisor must wait >=30s for profile gateway health`);
366
+ }
367
+
368
+ console.log(`OK pack=${pack} native=${expectedSlug} docker=${expectedStack}`);
369
+ }
370
+
371
+ const baRes = spawnSync(process.execPath, [CLI, 'BrandAuthority', '--pack', 'vanilla', '--out', tmp, '--ci', '--force'], {
372
+ encoding: 'utf8',
373
+ });
374
+ if (baRes.status !== 0) fail(`BrandAuthority scaffold: ${baRes.stderr || baRes.stdout}`);
375
+ const baManifest = JSON.parse(fs.readFileSync(path.join(tmp, 'BrandAuthority', 'workframe-manifest.json'), 'utf8'));
376
+ if (baManifest.native_agent.profile_slug !== 'brandauthority-agent') {
377
+ fail(`BrandAuthority slug expected brandauthority-agent, got ${baManifest.native_agent.profile_slug}`);
378
+ }
379
+ if (baManifest.docker.stack !== 'brandauthority') {
380
+ fail(`BrandAuthority docker stack expected brandauthority`);
381
+ }
382
+ console.log('OK BrandAuthority -> brandauthority-agent / brandauthority stack');
383
+
384
+ for (const bad of ['.', '..', '../escape', 'bad/name']) {
385
+ const res = spawnSync(process.execPath, [CLI, '--name', bad, '--out', tmp, '--ci', '--force'], { encoding: 'utf8' });
386
+ if (res.status === 0) fail(`expected rejection for name=${bad}`);
387
+ }
388
+ console.log('OK rejected unsafe project names');
389
+
390
+ console.log('All scaffold tests passed.');
@@ -0,0 +1,105 @@
1
+ #!/usr/bin/env bash
2
+ # Fail-closed preflight for WORKFRAME_DEPLOYMENT_MODE=public_multi_user.
3
+ # Usage: bash scripts/workframe/verify-public-deploy.sh [compose-dir]
4
+ set -euo pipefail
5
+
6
+ ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
7
+ COMPOSE_DIR="${1:-$ROOT/infra/compose/workframe}"
8
+ ENV_FILE="$COMPOSE_DIR/.env"
9
+ COMPOSE_FILE="$COMPOSE_DIR/docker-compose.yml"
10
+
11
+ fail() { echo "FAIL: $*" >&2; exit 1; }
12
+ warn() { echo "WARN: $*" >&2; }
13
+ ok() { echo "OK: $*"; }
14
+
15
+ [[ -f "$ENV_FILE" ]] || fail "missing $ENV_FILE"
16
+ [[ -f "$COMPOSE_FILE" ]] || fail "missing $COMPOSE_FILE"
17
+
18
+ env_val() {
19
+ local key="$1"
20
+ grep -E "^${key}=" "$ENV_FILE" | tail -n1 | cut -d= -f2- | tr -d '\r' || true
21
+ }
22
+
23
+ MODE="$(env_val WORKFRAME_DEPLOYMENT_MODE)"
24
+ MODE="${MODE:-trusted_team}"
25
+ if [[ "$MODE" != "public_multi_user" ]]; then
26
+ ok "WORKFRAME_DEPLOYMENT_MODE=$MODE (skipping public checks; pass nothing to force public)"
27
+ exit 0
28
+ fi
29
+
30
+ ok "checking public_multi_user preflight"
31
+
32
+ if [[ "$(env_val DEV_LOCAL_UNSAFE)" =~ ^(1|true|yes|on)$ ]]; then
33
+ fail "DEV_LOCAL_UNSAFE must be off for public_multi_user"
34
+ fi
35
+ if [[ "$(env_val SECURE_MODE)" != "true" ]]; then
36
+ fail "SECURE_MODE=true required"
37
+ fi
38
+
39
+ for key in WORKFRAME_SUPERVISOR_TOKEN WORKFRAME_API_TOKEN WORKFRAME_PROXY_TOKEN WORKFRAME_VAULT_KEK \
40
+ ZK_AUTH_HMAC_KEY ZK_AUTH_ENCRYPTION_KEY ZK_AUTH_SESSION_SECRET \
41
+ SMTP_HOST SMTP_USER SMTP_PASS EMAIL_FROM; do
42
+ [[ -n "$(env_val "$key")" ]] || fail "$key is empty"
43
+ done
44
+
45
+ APP_URL="$(env_val APP_BASE_URL)"
46
+ [[ "$APP_URL" == https://* ]] || fail "APP_BASE_URL must be https:// (got ${APP_URL:-<empty>})"
47
+
48
+ enc_key="$(env_val ZK_AUTH_ENCRYPTION_KEY)"
49
+ if [[ -n "$enc_key" ]]; then
50
+ python3 - "$enc_key" <<'PY' || fail "ZK_AUTH_ENCRYPTION_KEY must be base64-encoded 32 bytes (not hex)"
51
+ import base64, sys
52
+ raw = base64.b64decode(sys.argv[1].strip())
53
+ assert len(raw) == 32
54
+ PY
55
+ ok "ZK_AUTH_ENCRYPTION_KEY format"
56
+ fi
57
+
58
+ if [[ "$(env_val WORKFRAME_E2E)" =~ ^(1|true|yes|on)$ ]] && [[ "$APP_URL" == https://* ]]; then
59
+ fail "WORKFRAME_E2E must be off for public HTTPS deploy"
60
+ fi
61
+
62
+ if grep -A40 '^ gateway:' "$COMPOSE_FILE" | grep -q 'env_file:'; then
63
+ fail "gateway must not use env_file in docker-compose.yml"
64
+ fi
65
+ if ! grep -q 'control-net' "$COMPOSE_FILE"; then
66
+ fail "control-net missing from docker-compose.yml"
67
+ fi
68
+
69
+ UI_PORT="$(env_val WORKFRAME_UI_PORT)"
70
+ UI_PORT="${UI_PORT:-18644}"
71
+ API_PORT="$(env_val WORKFRAME_API_PORT)"
72
+ API_PORT="${API_PORT:-19120}"
73
+
74
+ if command -v curl >/dev/null 2>&1; then
75
+ health="$(curl -fsS "http://127.0.0.1:${API_PORT}/api/health" 2>/dev/null || true)"
76
+ if [[ -z "$health" ]]; then
77
+ warn "API health unreachable on 127.0.0.1:${API_PORT} (stack down?)"
78
+ else
79
+ echo "$health" | grep -q 'public_multi_user' || fail "API health missing deployment_mode public_multi_user"
80
+ echo "$health" | grep -q '"mode": "secure"' || fail "API not in secure mode"
81
+ echo "$health" | grep -q '"proxy_token_configured": true' || fail "API proxy_token_configured is false"
82
+ echo "$health" | grep -q '"vault_envelope": true' || fail "API vault_envelope is false"
83
+ echo "$health" | grep -q '"docker_sock_on_api": false' || fail "API still has docker.sock mounted"
84
+ echo "$health" | grep -q 'install_window_open' || warn "API health missing install_window_open"
85
+ echo "$health" | grep -q 'workframe_e2e' || warn "API health missing workframe_e2e"
86
+ echo "$health" | grep -q 'dev_local_unsafe' || warn "API health missing dev_local_unsafe"
87
+ ok "API health"
88
+ fi
89
+ dash_code="$(curl -sS -o /dev/null -w '%{http_code}' "http://127.0.0.1:${UI_PORT}/hermes-dashboard/" || true)"
90
+ [[ "$dash_code" == "403" ]] || warn "hermes-dashboard without session returned $dash_code (expected 403)"
91
+ else
92
+ warn "curl not found — skipping HTTP checks"
93
+ fi
94
+
95
+ if command -v docker >/dev/null 2>&1 && docker inspect workframe-gateway >/dev/null 2>&1; then
96
+ gw_env="$(docker inspect workframe-gateway --format '{{range .Config.Env}}{{println .}}{{end}}')"
97
+ for marker in WORKFRAME_SUPERVISOR_TOKEN ZK_AUTH_ SMTP_PASS; do
98
+ echo "$gw_env" | grep -q "$marker" && fail "gateway env contains $marker"
99
+ done
100
+ ok "gateway env allowlist"
101
+ else
102
+ warn "workframe-gateway not running — skipping docker inspect"
103
+ fi
104
+
105
+ ok "public_multi_user preflight passed"
@@ -0,0 +1,31 @@
1
+ # Workframe Agent Library
2
+
3
+ Model
4
+ - Main project agent (**{nativeAgentName}**) is concierge/orchestrator.
5
+ - Specialists are modular workers that can be installed/imported/removed.
6
+
7
+ Canonical behavior location
8
+ - Runtime: `Agents/profiles/{nativeProfileSlug}/SOUL.md`
9
+ - Bootstrap seed: `scripts/seed/profiles/{nativeProfileSlug}/SOUL.md`
10
+
11
+ Default specialist catalog
12
+ - visionary
13
+ - architect
14
+ - docs
15
+ - dev
16
+ - research
17
+ - designer
18
+
19
+ Install-time starter packs
20
+ - Recorded in `workframe-manifest.json` (`pack`, `profiles`, `native_agent`)
21
+ - Default scaffold pack is `native` (native agent only)
22
+ - Reference packs can still be chosen explicitly
23
+ - See `docs/SETUP.md` for the pack chosen at install
24
+
25
+ Extension pattern
26
+ - Add niche specialists only when recurring demand exists.
27
+ - Preferred path: spawn specialists on demand through botfather/lifecycle flows instead of preinstalling the whole crew.
28
+
29
+ Curation rule
30
+ - Keep role-specific skill/tool bundles lean.
31
+ - Avoid cloning massive identical bundles across all agents.
@@ -0,0 +1,29 @@
1
+ # Workframe Agent Operations
2
+
3
+ Goal
4
+ - keep the agent library dynamic but controlled.
5
+
6
+ Concierge responsibilities
7
+ - detect recurring specialist needs
8
+ - propose profile add/remove/swap
9
+ - route work through existing profiles until approved change lands
10
+ - spawn specialists only when a real role gap exists
11
+
12
+ Profile operations policy
13
+ - Add profile: when repeated tasks do not fit existing specialists.
14
+ - Remove profile: when low usage and overlapping role.
15
+ - Replace profile: when role remains but mission changes.
16
+
17
+ Approval
18
+ - owner/admin approves profile topology changes in team environments.
19
+
20
+ Preferred implementation path
21
+ 1) Update runtime profile SOUL under `Agents/profiles/`.
22
+ 2) Update bootstrap seeds under `scripts/seed/profiles/` when templates change.
23
+ 3) Spawn or update the runtime profile set through lifecycle/botfather flows.
24
+ 4) Announce changed routing behavior in docs and chat status.
25
+
26
+ Default topology policy
27
+ - Start native-only.
28
+ - Treat specialist packs as reference presets, not mandatory first boot state.
29
+ - Keep the installed crew as small as possible until real demand appears.
@@ -0,0 +1,64 @@
1
+ {
2
+ "version": 2,
3
+ "packs": {
4
+ "native": {
5
+ "description": "One native project agent only. Spawn specialists later through Workframe botfather flows.",
6
+ "profiles": [
7
+ "project-agent"
8
+ ]
9
+ },
10
+ "vanilla": {
11
+ "description": "Reference default crew pack (native project agent + all core specialists)",
12
+ "profiles": [
13
+ "project-agent",
14
+ "visionary",
15
+ "architect",
16
+ "docs",
17
+ "dev",
18
+ "research",
19
+ "designer"
20
+ ]
21
+ },
22
+ "core": {
23
+ "description": "Minimal operational baseline",
24
+ "profiles": [
25
+ "project-agent",
26
+ "docs",
27
+ "dev"
28
+ ]
29
+ },
30
+ "product": {
31
+ "description": "Product discovery and direction",
32
+ "profiles": [
33
+ "project-agent",
34
+ "docs",
35
+ "dev",
36
+ "visionary",
37
+ "research",
38
+ "designer"
39
+ ]
40
+ },
41
+ "engineering": {
42
+ "description": "Technical planning and delivery",
43
+ "profiles": [
44
+ "project-agent",
45
+ "docs",
46
+ "dev",
47
+ "architect",
48
+ "research"
49
+ ]
50
+ },
51
+ "full": {
52
+ "description": "Alias of vanilla for compatibility",
53
+ "profiles": [
54
+ "project-agent",
55
+ "visionary",
56
+ "architect",
57
+ "docs",
58
+ "dev",
59
+ "research",
60
+ "designer"
61
+ ]
62
+ }
63
+ }
64
+ }
@@ -0,0 +1,20 @@
1
+ version: 2
2
+ packs:
3
+ native:
4
+ description: One native project agent only. Spawn specialists later through Workframe botfather flows.
5
+ profiles: [project-agent]
6
+ vanilla:
7
+ description: Reference default crew pack (native project agent + all core specialists)
8
+ profiles: [project-agent, visionary, architect, docs, dev, research, designer]
9
+ core:
10
+ description: Minimal operational baseline
11
+ profiles: [project-agent, docs, dev]
12
+ product:
13
+ description: Product discovery and direction
14
+ profiles: [project-agent, docs, dev, visionary, research, designer]
15
+ engineering:
16
+ description: Technical planning and delivery
17
+ profiles: [project-agent, docs, dev, architect, research]
18
+ full:
19
+ description: Alias of vanilla for compatibility
20
+ profiles: [project-agent, visionary, architect, docs, dev, research, designer]
@@ -0,0 +1,20 @@
1
+ # Workframe Chat Permission Model
2
+
3
+ Purpose: keep chat collaboration simple, safe, and aligned with Workframe ontology.
4
+
5
+ - Concierge agent is primary chat-facing interface.
6
+ - Specialists are invoked through routing, not random direct control by default.
7
+ - Platform permissions (Telegram/Discord roles/channels/threads) are the first trust gate.
8
+
9
+ Trust model:
10
+ - Owner/admin = highest-trust operator.
11
+ - Team members = permitted by platform-level access policy.
12
+
13
+ Risk model:
14
+ - default allowed: docs + Kanban + status work
15
+ - explicit approval required: high-impact external actions and credential changes
16
+
17
+ Truth model:
18
+ - chat = intent and coordination
19
+ - Kanban = execution state
20
+ - files = canonical project truth