create-workframe 0.1.5 → 0.1.7

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 (185) hide show
  1. package/.dockerignore +22 -22
  2. package/.gitignore +73 -73
  3. package/LICENSE +201 -201
  4. package/NOTICE +12 -12
  5. package/README.md +40 -40
  6. package/SECURITY.md +38 -38
  7. package/bin/create-workframe.js +2816 -2814
  8. package/bin/workframe.js +329 -329
  9. package/docs/workspace-instructions/WORKFRAME_DISCORD.md +20 -20
  10. package/docs/workspace-instructions/WORKFRAME_DOCUMENTS_AND_ARTIFACTS.md +20 -20
  11. package/docs/workspace-instructions/WORKFRAME_KANBAN.md +20 -20
  12. package/docs/workspace-instructions/WORKFRAME_ONBOARDING.md +21 -21
  13. package/docs/workspace-instructions/WORKFRAME_ROUTING.md +29 -29
  14. package/docs/workspace-instructions/WORKFRAME_TELEGRAM.md +19 -19
  15. package/package.json +64 -64
  16. package/profiles/README.md +15 -15
  17. package/profiles/architect/AGENTS.md +29 -29
  18. package/profiles/architect/SOUL.md +44 -44
  19. package/profiles/architect/skills/devops/kanban-worker/SKILL.md +27 -27
  20. package/profiles/designer/AGENTS.md +26 -26
  21. package/profiles/designer/SOUL.md +31 -31
  22. package/profiles/designer/skills/devops/kanban-worker/SKILL.md +27 -27
  23. package/profiles/dev/AGENTS.md +28 -28
  24. package/profiles/dev/SOUL.md +31 -31
  25. package/profiles/dev/skills/devops/kanban-worker/SKILL.md +27 -27
  26. package/profiles/docs/AGENTS.md +27 -27
  27. package/profiles/docs/SOUL.md +30 -30
  28. package/profiles/docs/skills/devops/kanban-worker/SKILL.md +27 -27
  29. package/profiles/research/AGENTS.md +26 -26
  30. package/profiles/research/SOUL.md +31 -31
  31. package/profiles/research/skills/devops/kanban-worker/SKILL.md +27 -27
  32. package/profiles/visionary/AGENTS.md +25 -25
  33. package/profiles/visionary/SOUL.md +31 -31
  34. package/profiles/visionary/skills/devops/kanban-worker/SKILL.md +27 -27
  35. package/profiles/workframe-agent/AGENTS.md +37 -37
  36. package/profiles/workframe-agent/SETUP.md +185 -185
  37. package/profiles/workframe-agent/SOUL.md +61 -61
  38. package/profiles/workframe-agent/skills/devops/botfather/SKILL.md +85 -85
  39. package/profiles/workframe-agent/skills/devops/kanban-handoff-pattern/SKILL.md +58 -58
  40. package/profiles/workframe-agent/skills/devops/workframe-cohort/SKILL.md +54 -54
  41. package/prompts/WORKFRAME_PROMPT_TEMPLATES.md +16 -16
  42. package/rules/.hermes.md +11 -11
  43. package/rules/AGENTS.md +22 -22
  44. package/rules/workspace-README.md +5 -5
  45. package/scripts/apply-update-workframe.sh +91 -21
  46. package/scripts/bundle-workframe-ui.mjs +83 -83
  47. package/scripts/create_workframe_scaffold.py +648 -648
  48. package/scripts/ensure-compose-host-paths.mjs +51 -51
  49. package/scripts/lib/install-identity.mjs +212 -212
  50. package/scripts/lib/workframe-registry.mjs +290 -290
  51. package/scripts/new-project.mjs +68 -68
  52. package/scripts/select_agent_pack.py +31 -31
  53. package/scripts/set-compose-public-url.mjs +92 -92
  54. package/scripts/sync-canonical-to-package.mjs +164 -164
  55. package/shared/WORKFRAME_AGENT_LIBRARY.md +31 -31
  56. package/shared/WORKFRAME_AGENT_OPERATIONS.md +29 -29
  57. package/shared/WORKFRAME_AGENT_PACKS.json +64 -64
  58. package/shared/WORKFRAME_AGENT_PACKS.yaml +20 -20
  59. package/shared/WORKFRAME_CHAT_PERMISSION_MODEL.md +20 -20
  60. package/shared/WORKFRAME_HANDOFF_SCHEMA.md +25 -25
  61. package/shared/WORKFRAME_SKILL_CURATION.md +27 -27
  62. package/workframe-api/Dockerfile +14 -14
  63. package/workframe-api/README.md +24 -24
  64. package/workframe-api/action_proxy.py +131 -131
  65. package/workframe-api/auth_rate_limit.py +49 -49
  66. package/workframe-api/credential_vault.py +445 -445
  67. package/workframe-api/data/avatar-catalog.json +41 -41
  68. package/workframe-api/data/logo-catalog.json +14 -14
  69. package/workframe-api/data/user-avatar-catalog.json +18 -18
  70. package/workframe-api/email_sender.py +220 -220
  71. package/workframe-api/google_auth.py +90 -90
  72. package/workframe-api/install_api.py +359 -359
  73. package/workframe-api/internal_proxy_auth.py +150 -150
  74. package/workframe-api/llm_proxy.py +280 -280
  75. package/workframe-api/oidc_jwt.py +108 -108
  76. package/workframe-api/package.json +12 -12
  77. package/workframe-api/platform_auth.py +194 -194
  78. package/workframe-api/profile_secret_policy.py +86 -86
  79. package/workframe-api/public/assets/index-DPXu_lGn.css +1 -1
  80. package/workframe-api/public/assets/index-DYnLrCZZ.js +8 -8
  81. package/workframe-api/public/assets/index-DglUqFB_.js +8 -8
  82. package/workframe-api/public/index.html +12 -12
  83. package/workframe-api/requirements.txt +2 -2
  84. package/workframe-api/server.py +20295 -19866
  85. package/workframe-api/site_meta.py +271 -271
  86. package/workframe-api/stack_config.py +435 -427
  87. package/workframe-api/test_ensure_native_profile.py +29 -0
  88. package/workframe-api/test_oauth_llm.py +58 -0
  89. package/workframe-api/test_provider_model_surface.py +31 -0
  90. package/workframe-api/test_stack_config_install_smtp.py +51 -0
  91. package/workframe-api/time-bind-chat.py +99 -99
  92. package/workframe-api/turn_credentials.py +226 -226
  93. package/workframe-api/updates.py +506 -506
  94. package/workframe-api/vault_kek.py +159 -159
  95. package/workframe-api/zk_auth.py +633 -633
  96. package/workframe-supervisor/Dockerfile +11 -11
  97. package/workframe-supervisor/profile_secret_policy.py +76 -76
  98. package/workframe-supervisor/server.py +860 -860
  99. package/workframe-ui/docker/nginx.conf +85 -85
  100. package/workframe-ui/public/assets/{arc-CnriPN3G.js → arc-Cn-lt9fT.js} +1 -1
  101. package/workframe-ui/public/assets/architecture-7EHR7CIX-CCMNXHod.js +1 -0
  102. package/workframe-ui/public/assets/{architectureDiagram-3BPJPVTR-DYYB1Ic2.js → architectureDiagram-3BPJPVTR-qXoGCqfH.js} +1 -1
  103. package/workframe-ui/public/assets/{blockDiagram-GPEHLZMM-Bn-fFOyj.js → blockDiagram-GPEHLZMM-DoopFlWj.js} +1 -1
  104. package/workframe-ui/public/assets/{c4Diagram-AAUBKEIU-BPPDtAnD.js → c4Diagram-AAUBKEIU-BRa7hfzE.js} +1 -1
  105. package/workframe-ui/public/assets/channel-CtFV3sE3.js +1 -0
  106. package/workframe-ui/public/assets/{chunk-2J33WTMH-Bz2CJiC3.js → chunk-2J33WTMH-Cl33E2hh.js} +1 -1
  107. package/workframe-ui/public/assets/{chunk-3OPIFGDE-B8aMeE1B.js → chunk-3OPIFGDE-BRywYZQO.js} +1 -1
  108. package/workframe-ui/public/assets/{chunk-4BX2VUAB-bLFHQTuT.js → chunk-4BX2VUAB-CI3xzp-0.js} +1 -1
  109. package/workframe-ui/public/assets/{chunk-55IACEB6-BRxhx-lG.js → chunk-55IACEB6-Bkf3Ye3F.js} +1 -1
  110. package/workframe-ui/public/assets/{chunk-5ZQYHXKU-BLyOgEJ8.js → chunk-5ZQYHXKU-C5RN3hUT.js} +1 -1
  111. package/workframe-ui/public/assets/{chunk-727SXJPM-DiuvBl7G.js → chunk-727SXJPM-BaY0yDwt.js} +1 -1
  112. package/workframe-ui/public/assets/{chunk-AQP2D5EJ-BE1_aBdC.js → chunk-AQP2D5EJ-VMMBaDqd.js} +1 -1
  113. package/workframe-ui/public/assets/{chunk-BSJP7CBP-BicGsmBs.js → chunk-BSJP7CBP-DlNZ1UV3.js} +1 -1
  114. package/workframe-ui/public/assets/{chunk-CSCIHK7Q-C3VTns3d.js → chunk-CSCIHK7Q-tT2HyVy0.js} +1 -1
  115. package/workframe-ui/public/assets/{chunk-FMBD7UC4-DSiXY3bY.js → chunk-FMBD7UC4-CyACRaUT.js} +1 -1
  116. package/workframe-ui/public/assets/{chunk-KSCS5N6A-Cvw5s3fR.js → chunk-KSCS5N6A-seK5WAZs.js} +1 -1
  117. package/workframe-ui/public/assets/{chunk-L5ZTLDWV-jJifGdIQ.js → chunk-L5ZTLDWV-r5cyG5AH.js} +1 -1
  118. package/workframe-ui/public/assets/{chunk-LZXEDZCA-Maee1aqo.js → chunk-LZXEDZCA-SnbeVxsJ.js} +2 -2
  119. package/workframe-ui/public/assets/{chunk-ND2GUHAM-C77N3VAM.js → chunk-ND2GUHAM-zbFgEXSJ.js} +1 -1
  120. package/workframe-ui/public/assets/{chunk-NZK2D7GU-BY68lrPB.js → chunk-NZK2D7GU-UhZc8kOk.js} +1 -1
  121. package/workframe-ui/public/assets/{chunk-O5CBEL6O-D_c4kWzh.js → chunk-O5CBEL6O-DHvu2iZ-.js} +1 -1
  122. package/workframe-ui/public/assets/chunk-QZHKN3VN-B1g7l1_B.js +1 -0
  123. package/workframe-ui/public/assets/chunk-WU5MYG2G-B_qfZ6QP.js +1 -0
  124. package/workframe-ui/public/assets/{chunk-XPW4576I-DlQgvqBp.js → chunk-XPW4576I-CCPNKbzG.js} +1 -1
  125. package/workframe-ui/public/assets/classDiagram-4FO5ZUOK-CJoeCNq6.js +1 -0
  126. package/workframe-ui/public/assets/classDiagram-v2-Q7XG4LA2-CJoeCNq6.js +1 -0
  127. package/workframe-ui/public/assets/{cose-bilkent-S5V4N54A-CHCOHDSd.js → cose-bilkent-S5V4N54A-D1CLe6Y0.js} +1 -1
  128. package/workframe-ui/public/assets/{dagre-BM42HDAG-CKPcSYwU.js → dagre-BM42HDAG-DYHcGVs_.js} +1 -1
  129. package/workframe-ui/public/assets/{diagram-2AECGRRQ-C6qe0jP-.js → diagram-2AECGRRQ-DVUkJ-II.js} +1 -1
  130. package/workframe-ui/public/assets/{diagram-5GNKFQAL-DhQhrieU.js → diagram-5GNKFQAL-C9Y1Acc2.js} +1 -1
  131. package/workframe-ui/public/assets/{diagram-KO2AKTUF-Bqf6Iw1r.js → diagram-KO2AKTUF-Db3zez-n.js} +1 -1
  132. package/workframe-ui/public/assets/{diagram-LMA3HP47-Bt1ms2D2.js → diagram-LMA3HP47-BaOR5sIr.js} +1 -1
  133. package/workframe-ui/public/assets/{diagram-OG6HWLK6-C0Rrxe1i.js → diagram-OG6HWLK6-fLBzMY5W.js} +1 -1
  134. package/workframe-ui/public/assets/{dist-BLcLhTn6.js → dist-uZYeD3o1.js} +1 -1
  135. package/workframe-ui/public/assets/{erDiagram-TEJ5UH35-Cy1GbZVu.js → erDiagram-TEJ5UH35-BoCxDSyE.js} +1 -1
  136. package/workframe-ui/public/assets/eventmodeling-FCH6USID-Bw910jho.js +1 -0
  137. package/workframe-ui/public/assets/{flowDiagram-I6XJVG4X-DL3ALqDG.js → flowDiagram-I6XJVG4X-BnYa3CAj.js} +1 -1
  138. package/workframe-ui/public/assets/{ganttDiagram-6RSMTGT7-CMpwBhXQ.js → ganttDiagram-6RSMTGT7-Dm_e_Kaa.js} +1 -1
  139. package/workframe-ui/public/assets/{gitGraph-WXDBUCRP-C0mwHUXL.js → gitGraph-WXDBUCRP-CBAj8ntv.js} +1 -1
  140. package/workframe-ui/public/assets/{gitGraphDiagram-PVQCEYII-6gzhWaF0.js → gitGraphDiagram-PVQCEYII-D5auJjJh.js} +1 -1
  141. package/workframe-ui/public/assets/index-DHLQNAXd.js +129 -0
  142. package/workframe-ui/public/assets/index-auJ0bLMU.css +1 -0
  143. package/workframe-ui/public/assets/{info-J43DQDTF-Bb_wZTxU.js → info-J43DQDTF-BNMADxE2.js} +1 -1
  144. package/workframe-ui/public/assets/{infoDiagram-5YYISTIA-601evYFV.js → infoDiagram-5YYISTIA-C8c45T4J.js} +1 -1
  145. package/workframe-ui/public/assets/{ishikawaDiagram-YF4QCWOH-BYtF-wHm.js → ishikawaDiagram-YF4QCWOH-CyWuHB4e.js} +1 -1
  146. package/workframe-ui/public/assets/{journeyDiagram-JHISSGLW-BMizyHzC.js → journeyDiagram-JHISSGLW-B43pCuDT.js} +1 -1
  147. package/workframe-ui/public/assets/{kanban-definition-UN3LZRKU-CLLJsdnh.js → kanban-definition-UN3LZRKU-Dyn480BI.js} +1 -1
  148. package/workframe-ui/public/assets/{line-BFiSvu-q.js → line-CNtIbnmt.js} +1 -1
  149. package/workframe-ui/public/assets/{linear-D6HYZ18_.js → linear-pmSg_4uV.js} +1 -1
  150. package/workframe-ui/public/assets/{mermaid-parser.core-Cid5yDBQ.js → mermaid-parser.core-BX4tnojE.js} +2 -2
  151. package/workframe-ui/public/assets/{mermaid.core-DqIiju5Z.js → mermaid.core-BtpBva5o.js} +3 -3
  152. package/workframe-ui/public/assets/{mindmap-definition-RKZ34NQL-Bg7xJdsz.js → mindmap-definition-RKZ34NQL-DcMcB_69.js} +1 -1
  153. package/workframe-ui/public/assets/{packet-YPE3B663-1ebGt86D.js → packet-YPE3B663-KSzK9WlD.js} +1 -1
  154. package/workframe-ui/public/assets/{pie-LRSECV5Y-DJ9wOBC_.js → pie-LRSECV5Y-DLOH6Mg8.js} +1 -1
  155. package/workframe-ui/public/assets/{pieDiagram-4H26LBE5-BmK96Aus.js → pieDiagram-4H26LBE5-BhrX2aGk.js} +1 -1
  156. package/workframe-ui/public/assets/{quadrantDiagram-W4KKPZXB-ByUqtWPZ.js → quadrantDiagram-W4KKPZXB-B5dDjbTX.js} +1 -1
  157. package/workframe-ui/public/assets/{radar-GUYGQ44K-DN-Hkt96.js → radar-GUYGQ44K-BPdjqZiu.js} +1 -1
  158. package/workframe-ui/public/assets/{requirementDiagram-4Y6WPE33-ByU2r8gb.js → requirementDiagram-4Y6WPE33-21Dq5e0N.js} +1 -1
  159. package/workframe-ui/public/assets/{sankeyDiagram-5OEKKPKP-elyWa0GK.js → sankeyDiagram-5OEKKPKP-CiA99dbO.js} +1 -1
  160. package/workframe-ui/public/assets/{sequenceDiagram-3UESZ5HK-CzZwsAiK.js → sequenceDiagram-3UESZ5HK-Bwpui7_x.js} +1 -1
  161. package/workframe-ui/public/assets/{src-5vgsM_dl.js → src-B3Axsi1U.js} +1 -1
  162. package/workframe-ui/public/assets/{stateDiagram-AJRCARHV-B0O5w5lJ.js → stateDiagram-AJRCARHV-C76qwtE8.js} +1 -1
  163. package/workframe-ui/public/assets/stateDiagram-v2-BHNVJYJU-Dn0CDWJD.js +1 -0
  164. package/workframe-ui/public/assets/{timeline-definition-PNZ67QCA-oyqa5w5y.js → timeline-definition-PNZ67QCA-CufInOyk.js} +1 -1
  165. package/workframe-ui/public/assets/{treeView-BLDUP644-MCV12-eP.js → treeView-BLDUP644-C4sxh0R-.js} +1 -1
  166. package/workframe-ui/public/assets/{treemap-LRROVOQU-DiA1P9n5.js → treemap-LRROVOQU-BjV72ANV.js} +1 -1
  167. package/workframe-ui/public/assets/{vennDiagram-CIIHVFJN-CO_4x7OR.js → vennDiagram-CIIHVFJN-DgsdR0Rl.js} +1 -1
  168. package/workframe-ui/public/assets/{wardley-L42UT6IY-CmQNv6Xv.js → wardley-L42UT6IY-DZ279G_t.js} +1 -1
  169. package/workframe-ui/public/assets/{wardleyDiagram-YWT4CUSO-CJxDkbIj.js → wardleyDiagram-YWT4CUSO-Bde25kvz.js} +1 -1
  170. package/workframe-ui/public/assets/{xychartDiagram-2RQKCTM6-B02MxgzG.js → xychartDiagram-2RQKCTM6-B8VnS2Pb.js} +1 -1
  171. package/workframe-ui/public/favicon.svg +7 -7
  172. package/workframe-ui/public/icons.svg +24 -24
  173. package/workframe-ui/public/index.html +47 -47
  174. package/workframe-ui/public/manifest.webmanifest +18 -18
  175. package/workframe-ui/public/workframe-config.json +3 -3
  176. package/workframe-ui/public/assets/architecture-7EHR7CIX-CFhr7xAe.js +0 -1
  177. package/workframe-ui/public/assets/channel-Dok_-T0o.js +0 -1
  178. package/workframe-ui/public/assets/chunk-QZHKN3VN-C3wwLrTa.js +0 -1
  179. package/workframe-ui/public/assets/chunk-WU5MYG2G-GFFSg2kf.js +0 -1
  180. package/workframe-ui/public/assets/classDiagram-4FO5ZUOK-DKbGfT5Z.js +0 -1
  181. package/workframe-ui/public/assets/classDiagram-v2-Q7XG4LA2-DKbGfT5Z.js +0 -1
  182. package/workframe-ui/public/assets/eventmodeling-FCH6USID-C_PrceHe.js +0 -1
  183. package/workframe-ui/public/assets/index-DyO6K0TD.css +0 -1
  184. package/workframe-ui/public/assets/index-yvpSUs8T.js +0 -133
  185. package/workframe-ui/public/assets/stateDiagram-v2-BHNVJYJU-RXZRaSgT.js +0 -1
@@ -1,85 +1,85 @@
1
- ---
2
- name: botfather
3
- description: Native Workframe agent crew control — create/tune child agents via the BFF API. Child agents must never load this skill.
4
- version: 2.0.0
5
- platforms: [linux, macos, windows]
6
- metadata:
7
- hermes:
8
- tags: [workframe, botfather, crew, profiles, vault]
9
- ---
10
-
11
- # Botfather — Native Agent Crew Control
12
-
13
- You are the **native Workframe agent** (concierge / botfather / PM). Only you orchestrate the crew. Child specialists cannot create agents or read the credential vault.
14
-
15
- ## Architecture (current — do not guess older models)
16
-
17
- | Layer | What it is |
18
- |---|---|
19
- | **Template profile** | Shared Hermes profile (`architect`, `dev`, …) — identity, SOUL, skills |
20
- | **Runtime profile** | Per-user chat profile `u-{user}-{template}` — this is what answers in DMs |
21
- | **API vault** | Raw BYOK keys live in Workframe API storage — **never** in profile `config.yaml` or `.env` |
22
- | **LLM access** | Runtime profiles call `/internal/llm/` with short-lived lease tokens per turn |
23
-
24
- **Never** write `model.api_key`, provider secrets, or raw tokens into Hermes profile files. Users connect keys in Workframe UI (onboarding / Settings → Connect).
25
-
26
- ## Primary path — same as the UI
27
-
28
- Create agents through the Workframe BFF (fastest, correct tenancy):
29
-
30
- ```bash
31
- curl -s -X POST http://workframe-api:8080/api/hermes/profiles/create \
32
- -H "Content-Type: application/json" \
33
- -H "Cookie: <session>" \
34
- -d '{
35
- "name": "architect",
36
- "display_name": "Architect",
37
- "model": "openrouter/anthropic/claude-sonnet-4",
38
- "workspace_id": "<workspace-uuid>"
39
- }'
40
- ```
41
-
42
- This creates the template (if needed), provisions `u-{user}-architect`, sets the model on the **runtime**, opens a DM room, and binds a session.
43
-
44
- Other BFF endpoints you may use (with user session):
45
-
46
- | Intent | Endpoint |
47
- |---|---|
48
- | Bootstrap DM only | `POST /api/hermes/profiles/{template}/bootstrap-dm` |
49
- | Delete child | `POST /api/hermes/profiles/delete` `{"profile":"slug"}` |
50
- | Set SOUL | `POST /api/hermes/profiles/{slug}/soul` |
51
-
52
- ## Fallback — CLI inside gateway container
53
-
54
- When the BFF is unreachable, use Hermes CLI for **child** profiles only (not native):
55
-
56
- ```bash
57
- /opt/hermes/bin/hermes profile create --clone-from architect my-specialist
58
- /opt/hermes/bin/hermes -p my-specialist gateway start
59
- ```
60
-
61
- Do **not** hand-edit `config.yaml` to embed API keys. Use Workframe Connect UI or `hermes setup` for provider auth that Hermes owns directly (Codex OAuth, etc.).
62
-
63
- ## `agent-lifecycle.mjs` (Docker-only fallback)
64
-
65
- ```bash
66
- node /workspace/scripts/agent-lifecycle.mjs create --slug dev --from-seed --spawn
67
- ```
68
-
69
- Requires Docker on the host. Prefer the BFF path above when the API is up.
70
-
71
- ## Child birth checklist
72
-
73
- 1. Slug + display name + role
74
- 2. SOUL (purpose-specific — no empty shells)
75
- 3. Model (optional — MVP default applies; lands on **runtime**)
76
- 4. Skills (preset clone or `--clone-from`)
77
- 5. DM lane is auto-created by `profiles/create` — user lands in chat
78
-
79
- ## Rules
80
-
81
- 1. **Vault is off-limits** — no reading/exporting other users' or agents' keys
82
- 2. **Never delete native profile** (`workframe-agent`)
83
- 3. **Confirm** before destructive external actions
84
- 4. **Route work** to specialists — you orchestrate, not impersonate
85
- 5. Load this skill before crew changes
1
+ ---
2
+ name: botfather
3
+ description: Native Workframe agent crew control — create/tune child agents via the BFF API. Child agents must never load this skill.
4
+ version: 2.0.0
5
+ platforms: [linux, macos, windows]
6
+ metadata:
7
+ hermes:
8
+ tags: [workframe, botfather, crew, profiles, vault]
9
+ ---
10
+
11
+ # Botfather — Native Agent Crew Control
12
+
13
+ You are the **native Workframe agent** (concierge / botfather / PM). Only you orchestrate the crew. Child specialists cannot create agents or read the credential vault.
14
+
15
+ ## Architecture (current — do not guess older models)
16
+
17
+ | Layer | What it is |
18
+ |---|---|
19
+ | **Template profile** | Shared Hermes profile (`architect`, `dev`, …) — identity, SOUL, skills |
20
+ | **Runtime profile** | Per-user chat profile `u-{user}-{template}` — this is what answers in DMs |
21
+ | **API vault** | Raw BYOK keys live in Workframe API storage — **never** in profile `config.yaml` or `.env` |
22
+ | **LLM access** | Runtime profiles call `/internal/llm/` with short-lived lease tokens per turn |
23
+
24
+ **Never** write `model.api_key`, provider secrets, or raw tokens into Hermes profile files. Users connect keys in Workframe UI (onboarding / Settings → Connect).
25
+
26
+ ## Primary path — same as the UI
27
+
28
+ Create agents through the Workframe BFF (fastest, correct tenancy):
29
+
30
+ ```bash
31
+ curl -s -X POST http://workframe-api:8080/api/hermes/profiles/create \
32
+ -H "Content-Type: application/json" \
33
+ -H "Cookie: <session>" \
34
+ -d '{
35
+ "name": "architect",
36
+ "display_name": "Architect",
37
+ "model": "openrouter/anthropic/claude-sonnet-4",
38
+ "workspace_id": "<workspace-uuid>"
39
+ }'
40
+ ```
41
+
42
+ This creates the template (if needed), provisions `u-{user}-architect`, sets the model on the **runtime**, opens a DM room, and binds a session.
43
+
44
+ Other BFF endpoints you may use (with user session):
45
+
46
+ | Intent | Endpoint |
47
+ |---|---|
48
+ | Bootstrap DM only | `POST /api/hermes/profiles/{template}/bootstrap-dm` |
49
+ | Delete child | `POST /api/hermes/profiles/delete` `{"profile":"slug"}` |
50
+ | Set SOUL | `POST /api/hermes/profiles/{slug}/soul` |
51
+
52
+ ## Fallback — CLI inside gateway container
53
+
54
+ When the BFF is unreachable, use Hermes CLI for **child** profiles only (not native):
55
+
56
+ ```bash
57
+ /opt/hermes/bin/hermes profile create --clone-from architect my-specialist
58
+ /opt/hermes/bin/hermes -p my-specialist gateway start
59
+ ```
60
+
61
+ Do **not** hand-edit `config.yaml` to embed API keys. Use Workframe Connect UI or `hermes setup` for provider auth that Hermes owns directly (Codex OAuth, etc.).
62
+
63
+ ## `agent-lifecycle.mjs` (Docker-only fallback)
64
+
65
+ ```bash
66
+ node /workspace/scripts/agent-lifecycle.mjs create --slug dev --from-seed --spawn
67
+ ```
68
+
69
+ Requires Docker on the host. Prefer the BFF path above when the API is up.
70
+
71
+ ## Child birth checklist
72
+
73
+ 1. Slug + display name + role
74
+ 2. SOUL (purpose-specific — no empty shells)
75
+ 3. Model (optional — MVP default applies; lands on **runtime**)
76
+ 4. Skills (preset clone or `--clone-from`)
77
+ 5. DM lane is auto-created by `profiles/create` — user lands in chat
78
+
79
+ ## Rules
80
+
81
+ 1. **Vault is off-limits** — no reading/exporting other users' or agents' keys
82
+ 2. **Never delete native profile** (`workframe-agent`)
83
+ 3. **Confirm** before destructive external actions
84
+ 4. **Route work** to specialists — you orchestrate, not impersonate
85
+ 5. Load this skill before crew changes
@@ -1,58 +1,58 @@
1
- ---
2
- name: kanban-handoff-pattern
3
- description: Kanban task handoff from Workframe concierge to user-scoped specialist runtime profiles — workspace_kind, assignee slugs, worker protocol, failure modes.
4
- ---
5
-
6
- # Kanban handoff pattern
7
-
8
- **Prerequisite:** Read `WORKFRAME_COHORT.md` and use **runtime_slug** as `--assignee`, never bare template names (`architect`, `dev`).
9
-
10
- ## Kanban vs delegate_task
11
-
12
- | Use kanban when | Use delegate_task when |
13
- |-----------------|------------------------|
14
- | Durable work, audit trail, human review | Quick parallel subtasks in one turn |
15
- | Specialist may take minutes | Parent turn bounds the work |
16
-
17
- ## Create a task (CLI)
18
-
19
- ```bash
20
- /opt/hermes/.venv/bin/hermes -p <your-runtime-slug> kanban create "Title" \
21
- --assignee <specialist-runtime-slug-from-cohort> \
22
- --workspace-kind scratch \
23
- --body "Goal…\n\nOutput: /workspace/docs/…"
24
- ```
25
-
26
- ### workspace_kind (only these)
27
-
28
- - `scratch` — default, isolated temp dir (safest)
29
- - `dir:/absolute/path` — e.g. `dir:/workspace`
30
- - `worktree` — git worktree
31
-
32
- Using `project`, `repo`, or anything else → `spawn_failed: unknown workspace_kind`.
33
-
34
- ## Worker protocol (specialists)
35
-
36
- 1. `kanban_show` — orient
37
- 2. Do the work; write outputs to paths in task body
38
- 3. `kanban_comment` — handoff notes for reviewer
39
- 4. **`kanban_complete(summary=…)`** or **`kanban_block(reason=…)`** before exit
40
-
41
- Clean exit without complete/block → protocol violation → auto-block after `failure_limit` (default 2).
42
-
43
- ## Failure modes
44
-
45
- | Symptom | Cause | Fix |
46
- |---------|-------|-----|
47
- | empty API key | assignee is template slug, not runtime | cohort runtime_slug |
48
- | unknown workspace_kind | invalid kind in DB/CLI | recreate with `scratch` |
49
- | protocol violation | worker died without complete/block | fix credentials + skills |
50
- | task blocked | failure_limit tripped | fix root cause, `kanban unblock` |
51
-
52
- ## Verify
53
-
54
- ```bash
55
- /opt/hermes/.venv/bin/hermes -p <profile> kanban list
56
- /opt/hermes/.venv/bin/hermes -p <profile> kanban show <task_id>
57
- /opt/hermes/.venv/bin/hermes -p <profile> kanban log <task_id>
58
- ```
1
+ ---
2
+ name: kanban-handoff-pattern
3
+ description: Kanban task handoff from Workframe concierge to user-scoped specialist runtime profiles — workspace_kind, assignee slugs, worker protocol, failure modes.
4
+ ---
5
+
6
+ # Kanban handoff pattern
7
+
8
+ **Prerequisite:** Read `WORKFRAME_COHORT.md` and use **runtime_slug** as `--assignee`, never bare template names (`architect`, `dev`).
9
+
10
+ ## Kanban vs delegate_task
11
+
12
+ | Use kanban when | Use delegate_task when |
13
+ |-----------------|------------------------|
14
+ | Durable work, audit trail, human review | Quick parallel subtasks in one turn |
15
+ | Specialist may take minutes | Parent turn bounds the work |
16
+
17
+ ## Create a task (CLI)
18
+
19
+ ```bash
20
+ /opt/hermes/.venv/bin/hermes -p <your-runtime-slug> kanban create "Title" \
21
+ --assignee <specialist-runtime-slug-from-cohort> \
22
+ --workspace-kind scratch \
23
+ --body "Goal…\n\nOutput: /workspace/docs/…"
24
+ ```
25
+
26
+ ### workspace_kind (only these)
27
+
28
+ - `scratch` — default, isolated temp dir (safest)
29
+ - `dir:/absolute/path` — e.g. `dir:/workspace`
30
+ - `worktree` — git worktree
31
+
32
+ Using `project`, `repo`, or anything else → `spawn_failed: unknown workspace_kind`.
33
+
34
+ ## Worker protocol (specialists)
35
+
36
+ 1. `kanban_show` — orient
37
+ 2. Do the work; write outputs to paths in task body
38
+ 3. `kanban_comment` — handoff notes for reviewer
39
+ 4. **`kanban_complete(summary=…)`** or **`kanban_block(reason=…)`** before exit
40
+
41
+ Clean exit without complete/block → protocol violation → auto-block after `failure_limit` (default 2).
42
+
43
+ ## Failure modes
44
+
45
+ | Symptom | Cause | Fix |
46
+ |---------|-------|-----|
47
+ | empty API key | assignee is template slug, not runtime | cohort runtime_slug |
48
+ | unknown workspace_kind | invalid kind in DB/CLI | recreate with `scratch` |
49
+ | protocol violation | worker died without complete/block | fix credentials + skills |
50
+ | task blocked | failure_limit tripped | fix root cause, `kanban unblock` |
51
+
52
+ ## Verify
53
+
54
+ ```bash
55
+ /opt/hermes/.venv/bin/hermes -p <profile> kanban list
56
+ /opt/hermes/.venv/bin/hermes -p <profile> kanban show <task_id>
57
+ /opt/hermes/.venv/bin/hermes -p <profile> kanban log <task_id>
58
+ ```
@@ -1,54 +1,54 @@
1
- ---
2
- name: workframe-cohort
3
- description: Per-user Workframe agent cohort — runtime profile slugs, kanban assignees, credential boundaries, and orchestration rules for the concierge.
4
- ---
5
-
6
- # Workframe cohort (read first)
7
-
8
- On every session start, read **`WORKFRAME_COHORT.md`** in your profile home (`/opt/data/profiles/<your-runtime-slug>/`). Workframe regenerates it when you bind a chat session.
9
-
10
- ## You are a per-user runtime instance
11
-
12
- Your Hermes profile slug looks like `u-<user-part>-workframe-agent`. You are **not** the shared template `workframe-agent`. Introduce yourself using the display name from `WORKFRAME_COHORT.md` (e.g. "Fab's Workframe Agent").
13
-
14
- ## Specialists — always use runtime slugs
15
-
16
- | Wrong (fails) | Right |
17
- |---------------|-------|
18
- | kanban `--assignee architect` | `--assignee u-…-architect` from cohort table |
19
- | delegate to `dev` | delegate to `u-…-dev` |
20
- | read `/opt/data/profiles/architect/.env` | only your cohort's `u-…-*` profiles |
21
-
22
- Template profiles share disk but **lack the triggering user's API keys**. Kanban workers on `architect` exit with "empty API key" and violate protocol.
23
-
24
- ## Kanban orchestration
25
-
26
- Load **kanban-handoff-pattern** before creating or dispatching tasks.
27
-
28
- ```bash
29
- /opt/hermes/.venv/bin/hermes -p <your-runtime-slug> kanban create "Title" \
30
- --assignee <cohort-runtime-slug> \
31
- --workspace-kind scratch \
32
- --body "…"
33
- ```
34
-
35
- - `workspace_kind`: `scratch` | `dir:/workspace` | `worktree` only
36
- - Workers must call `kanban_complete` or `kanban_block` before exit
37
- - After `failure_limit` failures, `kanban unblock <task_id>` after fixing root cause
38
-
39
- ## Cron & delegation
40
-
41
- - Cron jobs that invoke agents: target **runtime_slug** from cohort
42
- - `delegate_task`: pass the specialist's **runtime_slug**, not template name
43
- - Your cohort is **only your user's agents** — never other users' `u-*` profiles
44
-
45
- ## Tools in browser chat
46
-
47
- - Use **terminal** (not `execute_code`) for `hermes kanban`, `hermes cron`, shell
48
- - Full CLI: `/opt/hermes/.venv/bin/hermes -p <profile> …`
49
- - Docker socket is unavailable inside the gateway container
50
-
51
- ## Privacy
52
-
53
- - User LLM keys are overlaid per-turn into **your** runtime profile `.env`
54
- - Do not read or exfiltrate keys; do not access profiles outside `WORKFRAME_COHORT.md`
1
+ ---
2
+ name: workframe-cohort
3
+ description: Per-user Workframe agent cohort — runtime profile slugs, kanban assignees, credential boundaries, and orchestration rules for the concierge.
4
+ ---
5
+
6
+ # Workframe cohort (read first)
7
+
8
+ On every session start, read **`WORKFRAME_COHORT.md`** in your profile home (`/opt/data/profiles/<your-runtime-slug>/`). Workframe regenerates it when you bind a chat session.
9
+
10
+ ## You are a per-user runtime instance
11
+
12
+ Your Hermes profile slug looks like `u-<user-part>-workframe-agent`. You are **not** the shared template `workframe-agent`. Introduce yourself using the display name from `WORKFRAME_COHORT.md` (e.g. "Fab's Workframe Agent").
13
+
14
+ ## Specialists — always use runtime slugs
15
+
16
+ | Wrong (fails) | Right |
17
+ |---------------|-------|
18
+ | kanban `--assignee architect` | `--assignee u-…-architect` from cohort table |
19
+ | delegate to `dev` | delegate to `u-…-dev` |
20
+ | read `/opt/data/profiles/architect/.env` | only your cohort's `u-…-*` profiles |
21
+
22
+ Template profiles share disk but **lack the triggering user's API keys**. Kanban workers on `architect` exit with "empty API key" and violate protocol.
23
+
24
+ ## Kanban orchestration
25
+
26
+ Load **kanban-handoff-pattern** before creating or dispatching tasks.
27
+
28
+ ```bash
29
+ /opt/hermes/.venv/bin/hermes -p <your-runtime-slug> kanban create "Title" \
30
+ --assignee <cohort-runtime-slug> \
31
+ --workspace-kind scratch \
32
+ --body "…"
33
+ ```
34
+
35
+ - `workspace_kind`: `scratch` | `dir:/workspace` | `worktree` only
36
+ - Workers must call `kanban_complete` or `kanban_block` before exit
37
+ - After `failure_limit` failures, `kanban unblock <task_id>` after fixing root cause
38
+
39
+ ## Cron & delegation
40
+
41
+ - Cron jobs that invoke agents: target **runtime_slug** from cohort
42
+ - `delegate_task`: pass the specialist's **runtime_slug**, not template name
43
+ - Your cohort is **only your user's agents** — never other users' `u-*` profiles
44
+
45
+ ## Tools in browser chat
46
+
47
+ - Use **terminal** (not `execute_code`) for `hermes kanban`, `hermes cron`, shell
48
+ - Full CLI: `/opt/hermes/.venv/bin/hermes -p <profile> …`
49
+ - Docker socket is unavailable inside the gateway container
50
+
51
+ ## Privacy
52
+
53
+ - User LLM keys are overlaid per-turn into **your** runtime profile `.env`
54
+ - Do not read or exfiltrate keys; do not access profiles outside `WORKFRAME_COHORT.md`
@@ -1,16 +1,16 @@
1
- # Workframe Reusable Prompt Templates
2
-
3
- ## 1) Concierge onboarding
4
- "You are the {projectName} Agent concierge. Interview for mission, scope, constraints, success criteria. Select a starter agent pack, then route first tasks via Kanban and persist outcomes to files."
5
-
6
- ## 2) Starter-pack selection
7
- "Given this project description, choose one starter pack (core/product/engineering/full). Explain why and list profiles included."
8
-
9
- ## 3) Specialist routing
10
- "Decompose this request into specialist lanes. Keep roles pure. Use Kanban dependencies only when required."
11
-
12
- ## 4) Library expansion proposal
13
- "If this workload is recurring and not well-covered, propose a new specialist profile with mission, minimal skills/tools, and expected artifacts."
14
-
15
- ## 5) Handoff quality check
16
- "Validate task handoff against `WORKFRAME_HANDOFF_SCHEMA.md` and suggest minimal fixes."
1
+ # Workframe Reusable Prompt Templates
2
+
3
+ ## 1) Concierge onboarding
4
+ "You are the {projectName} Agent concierge. Interview for mission, scope, constraints, success criteria. Select a starter agent pack, then route first tasks via Kanban and persist outcomes to files."
5
+
6
+ ## 2) Starter-pack selection
7
+ "Given this project description, choose one starter pack (core/product/engineering/full). Explain why and list profiles included."
8
+
9
+ ## 3) Specialist routing
10
+ "Decompose this request into specialist lanes. Keep roles pure. Use Kanban dependencies only when required."
11
+
12
+ ## 4) Library expansion proposal
13
+ "If this workload is recurring and not well-covered, propose a new specialist profile with mission, minimal skills/tools, and expected artifacts."
14
+
15
+ ## 5) Handoff quality check
16
+ "Validate task handoff against `WORKFRAME_HANDOFF_SCHEMA.md` and suggest minimal fixes."
package/rules/.hermes.md CHANGED
@@ -1,11 +1,11 @@
1
- # .hermes — {projectName}
2
-
3
- Chat **must** use profile **`{nativeProfileSlug}`** ({nativeAgentName}):
4
-
5
- ```powershell
6
- ..\scripts\chat.ps1
7
- ```
8
-
9
- Bootstrap (after `hermes setup`): `..\scripts\bootstrap-profiles.ps1`
10
-
11
- Bare `docker run ... hermes-agent:latest` without `-p {nativeProfileSlug}` is generic Hermes — not this Workframe install.
1
+ # .hermes — {projectName}
2
+
3
+ Chat **must** use profile **`{nativeProfileSlug}`** ({nativeAgentName}):
4
+
5
+ ```powershell
6
+ ..\scripts\chat.ps1
7
+ ```
8
+
9
+ Bootstrap (after `hermes setup`): `..\scripts\bootstrap-profiles.ps1`
10
+
11
+ Bare `docker run ... hermes-agent:latest` without `-p {nativeProfileSlug}` is generic Hermes — not this Workframe install.
package/rules/AGENTS.md CHANGED
@@ -1,22 +1,22 @@
1
- # AGENTS — {projectName}
2
-
3
- Shared project workspace (`/workspace` → `/opt/data/workspace`). Hermes mounts host `Files/` at `/opt/data/workspace`; `/workspace` is a symlink so writes pass `HERMES_WRITE_SAFE_ROOT`.
4
-
5
- ## Native agent
6
-
7
- **{nativeAgentName}** (`{nativeProfileSlug}`) — concierge and orchestrator. Chat via `../scripts/chat.sh` or `../scripts/chat.ps1`, or browser `/chat` after Phase B.
8
-
9
- ## Layout
10
-
11
- | Path | Role |
12
- |------|------|
13
- | `Files/` (here) | Project source of truth — keep lean until you add real work |
14
- | `Agents/` | Hermes runtime — profiles, skills, memory (never commit) |
15
-
16
- ## Rules
17
-
18
- - Do not use Hermes `default` profile for project work.
19
- - Put deliverables here; keep Workframe/Hermes doctrine in agent SOUL under `Agents/profiles/`.
20
- - **Credentials never in chat** — API keys and bot tokens go through Hermes setup, dashboard, or Workframe secure UI only.
21
- - **{nativeAgentName}** is the PM/concierge — cross-lane work routes through them unless you are bound to a dedicated Discord/TG channel for this profile.
22
- - Outcomes live in `/workspace` (this folder); chat is intake, not the system of record.
1
+ # AGENTS — {projectName}
2
+
3
+ Shared project workspace (`/workspace` → `/opt/data/workspace`). Hermes mounts host `Files/` at `/opt/data/workspace`; `/workspace` is a symlink so writes pass `HERMES_WRITE_SAFE_ROOT`.
4
+
5
+ ## Native agent
6
+
7
+ **{nativeAgentName}** (`{nativeProfileSlug}`) — concierge and orchestrator. Chat via `../scripts/chat.sh` or `../scripts/chat.ps1`, or browser `/chat` after Phase B.
8
+
9
+ ## Layout
10
+
11
+ | Path | Role |
12
+ |------|------|
13
+ | `Files/` (here) | Project source of truth — keep lean until you add real work |
14
+ | `Agents/` | Hermes runtime — profiles, skills, memory (never commit) |
15
+
16
+ ## Rules
17
+
18
+ - Do not use Hermes `default` profile for project work.
19
+ - Put deliverables here; keep Workframe/Hermes doctrine in agent SOUL under `Agents/profiles/`.
20
+ - **Credentials never in chat** — API keys and bot tokens go through Hermes setup, dashboard, or Workframe secure UI only.
21
+ - **{nativeAgentName}** is the PM/concierge — cross-lane work routes through them unless you are bound to a dedicated Discord/TG channel for this profile.
22
+ - Outcomes live in `/workspace` (this folder); chat is intake, not the system of record.
@@ -1,5 +1,5 @@
1
- # {projectName}
2
-
3
- Welcome to Workframe — your team's social AI collaboration space.
4
-
5
- Use this file to keep a living record of what this project is, who is on the team, sub-projects, agents, kanban guidelines, and anything else newcomers should know. Your Workframe Agent can help you evolve it over time.
1
+ # {projectName}
2
+
3
+ Welcome to Workframe — your team's social AI collaboration space.
4
+
5
+ Use this file to keep a living record of what this project is, who is on the team, sub-projects, agents, kanban guidelines, and anything else newcomers should know. Your Workframe Agent can help you evolve it over time.
@@ -5,8 +5,82 @@ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
5
5
  # shellcheck source=compose-docker-host.sh
6
6
  source "$SCRIPT_DIR/compose-docker-host.sh"
7
7
 
8
+ # ponytail: npm integrity via python3 — Alpine supervisor has no xxd
9
+ _wf_npm_integrity_ok() {
10
+ local tarball="$1" pkg="$2" ver="${3:-latest}"
11
+ local expected actual
12
+ expected="$(npm view "${pkg}@${ver}" dist.integrity --silent 2>/dev/null || true)"
13
+ [[ -n "$expected" ]] || return 0
14
+ if ! command -v python3 >/dev/null 2>&1; then
15
+ echo "warn: python3 missing — skipping npm integrity check" >&2
16
+ return 0
17
+ fi
18
+ actual="$(python3 -c 'import base64, hashlib, sys
19
+ p = sys.argv[1]
20
+ d = hashlib.sha512(open(p, "rb").read()).digest()
21
+ print("sha512-" + base64.b64encode(d).decode())' "$tarball")"
22
+ [[ "$actual" == "$expected" ]]
23
+ }
24
+
25
+ # Host path in .env may not exist inside supervisor — use compose mount when it does not.
26
+ _wf_resolve_project_root() {
27
+ local host="${WORKFRAME_HOST_PROJECT_ROOT:-}"
28
+ local proj="${WORKFRAME_PROJECT_ROOT:-}"
29
+ if [[ -n "$host" && -d "$host" ]]; then
30
+ printf '%s' "$host"
31
+ return
32
+ fi
33
+ if [[ -n "$host" ]]; then
34
+ printf '%s' "$compose_cd"
35
+ return
36
+ fi
37
+ printf '%s' "${proj:-$compose_cd}"
38
+ }
39
+
40
+ _wf_sync_tree() {
41
+ local src="$1" dest="$2"
42
+ mkdir -p "$dest"
43
+ cp -a "${src}/." "${dest}/"
44
+ }
45
+
46
+ _wf_install_paths() {
47
+ local root="$1"
48
+ if [[ -d "$root/services/workframe-api" ]]; then
49
+ API_DIR="$root/services/workframe-api"
50
+ SUP_DIR="$root/services/workframe-supervisor"
51
+ UI_DIR="$root/apps/web/dist"
52
+ if [[ -d "$root/scripts/workframe" ]]; then
53
+ SCRIPTS_DIR="$root/scripts/workframe"
54
+ else
55
+ SCRIPTS_DIR="$root/scripts"
56
+ fi
57
+ else
58
+ API_DIR="$root/workframe-api"
59
+ SUP_DIR="$root/workframe-supervisor"
60
+ UI_DIR="$root/workframe-ui/public"
61
+ if [[ -d "$root/scripts/workframe" ]]; then
62
+ SCRIPTS_DIR="$root/scripts/workframe"
63
+ else
64
+ SCRIPTS_DIR="$root/scripts"
65
+ fi
66
+ fi
67
+ }
68
+
69
+ if [[ "${WF_APPLY_UPDATE_SELF_CHECK:-}" == "1" ]]; then
70
+ TMP="$(mktemp -d)"
71
+ trap 'rm -rf "$TMP"' EXIT
72
+ echo test > "$TMP/t"
73
+ if ! _wf_npm_integrity_ok "$TMP/t" create-workframe latest 2>/dev/null; then
74
+ : # empty file won't match registry integrity — exercise python path only
75
+ fi
76
+ command -v python3 >/dev/null || { echo "self-check: python3 required" >&2; exit 1; }
77
+ echo "apply-update-workframe self-check ok"
78
+ exit 0
79
+ fi
80
+
8
81
  workframe_compose_prepare
9
- PROJECT_ROOT="${WORKFRAME_HOST_PROJECT_ROOT:-${WORKFRAME_PROJECT_ROOT:-$compose_cd}}"
82
+ PROJECT_ROOT="$(_wf_resolve_project_root)"
83
+ _wf_install_paths "$PROJECT_ROOT"
10
84
 
11
85
  echo "=== Workframe update (API + supervisor + UI) ==="
12
86
  echo "Project root: $PROJECT_ROOT"
@@ -28,33 +102,29 @@ elif command -v npm >/dev/null 2>&1; then
28
102
  (cd "$TMP" && npm pack "${NPM_PACKAGE}@${TARGET_VERSION:-latest}" --silent)
29
103
  TARBALL="$(ls -1 "$TMP"/${NPM_PACKAGE}-*.tgz 2>/dev/null | head -n1 || true)"
30
104
  if [[ -n "$TARBALL" ]]; then
31
- EXPECTED="$(npm view "${NPM_PACKAGE}@${TARGET_VERSION:-latest}" dist.integrity --silent 2>/dev/null || true)"
32
- if [[ -n "$EXPECTED" ]]; then
33
- ACTUAL="sha512-$(sha512sum "$TARBALL" | awk '{print $1}' | xxd -r -p | base64 | tr -d '\n')"
34
- if [[ "$ACTUAL" != "$EXPECTED" ]]; then
35
- echo "integrity mismatch for ${NPM_PACKAGE}@${TARGET_VERSION:-latest}" >&2
36
- exit 1
37
- fi
38
- echo "integrity ok: ${NPM_PACKAGE}@${TARGET_VERSION:-latest}"
105
+ if ! _wf_npm_integrity_ok "$TARBALL" "$NPM_PACKAGE" "${TARGET_VERSION:-latest}"; then
106
+ echo "integrity mismatch for ${NPM_PACKAGE}@${TARGET_VERSION:-latest}" >&2
107
+ exit 1
39
108
  fi
109
+ echo "integrity ok: ${NPM_PACKAGE}@${TARGET_VERSION:-latest}"
40
110
  tar -xf "$TARBALL" -C "$TMP"
41
111
  PKG="$TMP/package"
42
- for dir in workframe-api workframe-supervisor; do
43
- if [[ -d "$PKG/$dir" ]]; then
44
- echo "Syncing $dir/"
45
- mkdir -p "$PROJECT_ROOT/$dir"
46
- cp -a "$PKG/$dir/." "$PROJECT_ROOT/$dir/"
47
- fi
48
- done
112
+ if [[ -d "$PKG/workframe-api" ]]; then
113
+ echo "Syncing workframe-api -> $API_DIR"
114
+ _wf_sync_tree "$PKG/workframe-api" "$API_DIR"
115
+ fi
116
+ if [[ -d "$PKG/workframe-supervisor" ]]; then
117
+ echo "Syncing workframe-supervisor -> $SUP_DIR"
118
+ _wf_sync_tree "$PKG/workframe-supervisor" "$SUP_DIR"
119
+ fi
49
120
  if [[ -d "$PKG/workframe-ui/public" ]]; then
50
- echo "Syncing workframe-ui/public/"
51
- mkdir -p "$PROJECT_ROOT/workframe-ui/public"
52
- cp -a "$PKG/workframe-ui/public/." "$PROJECT_ROOT/workframe-ui/public/"
121
+ echo "Syncing workframe-ui/public -> $UI_DIR"
122
+ _wf_sync_tree "$PKG/workframe-ui/public" "$UI_DIR"
53
123
  fi
54
124
  for script in apply-update-hermes.sh apply-update-workframe.sh restart-gateway-hermes.sh compose-docker-host.sh update-hermes.sh; do
55
125
  if [[ -f "$PKG/scripts/$script" ]]; then
56
- cp -a "$PKG/scripts/$script" "$PROJECT_ROOT/scripts/workframe/$script"
57
- chmod +x "$PROJECT_ROOT/scripts/workframe/$script" 2>/dev/null || true
126
+ cp -a "$PKG/scripts/$script" "$SCRIPTS_DIR/$script"
127
+ chmod +x "$SCRIPTS_DIR/$script" 2>/dev/null || true
58
128
  fi
59
129
  done
60
130
  else