create-workframe 0.1.0 → 0.1.1
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.
- package/LICENSE +201 -201
- package/NOTICE +12 -12
- package/README.md +8 -92
- package/SECURITY.md +40 -40
- package/bin/workframe.js +329 -329
- package/docs/workspace-instructions/WORKFRAME_ONBOARDING.md +1 -1
- package/docs/workspace-instructions/WORKFRAME_ROUTING.md +8 -8
- package/package.json +3 -6
- package/profiles/architect/AGENTS.md +29 -29
- package/profiles/architect/SOUL.md +2 -2
- package/profiles/architect/skills/devops/kanban-worker/SKILL.md +27 -27
- package/profiles/designer/AGENTS.md +26 -26
- package/profiles/designer/skills/devops/kanban-worker/SKILL.md +27 -27
- package/profiles/dev/AGENTS.md +28 -28
- package/profiles/dev/skills/devops/kanban-worker/SKILL.md +27 -27
- package/profiles/docs/AGENTS.md +27 -27
- package/profiles/docs/skills/devops/kanban-worker/SKILL.md +27 -27
- package/profiles/research/AGENTS.md +26 -26
- package/profiles/research/skills/devops/kanban-worker/SKILL.md +27 -27
- package/profiles/visionary/AGENTS.md +25 -25
- package/profiles/visionary/skills/devops/kanban-worker/SKILL.md +27 -27
- package/profiles/workframe-agent/AGENTS.md +37 -37
- package/profiles/workframe-agent/skills/devops/botfather/SKILL.md +85 -85
- package/profiles/workframe-agent/skills/devops/kanban-handoff-pattern/SKILL.md +58 -58
- package/profiles/workframe-agent/skills/devops/workframe-cohort/SKILL.md +54 -54
- package/rules/workspace-README.md +5 -5
- package/scripts/apply-update-hermes.sh +17 -17
- package/scripts/apply-update-workframe.sh +77 -77
- package/scripts/bootstrap-workspace-link.sh +8 -8
- package/scripts/bundle-workframe-ui.mjs +3 -3
- package/scripts/compose-docker-host.sh +37 -37
- package/scripts/ensure-compose-host-paths.mjs +51 -51
- package/scripts/fix-zk-encryption-key.sh +35 -35
- package/scripts/lib/install-identity.mjs +212 -212
- package/scripts/restart-gateway-hermes.sh +12 -12
- package/scripts/set-compose-public-url.mjs +92 -92
- package/scripts/setup-stack-secrets.sh +50 -50
- package/scripts/sync-canonical-to-package.mjs +8 -7
- package/scripts/verify-public-deploy.sh +105 -105
- package/shared/WORKFRAME_AGENT_LIBRARY.md +17 -17
- package/shared/WORKFRAME_AGENT_OPERATIONS.md +15 -15
- package/shared/WORKFRAME_AGENT_PACKS.json +18 -18
- package/shared/WORKFRAME_AGENT_PACKS.yaml +8 -8
- package/shared/WORKFRAME_SKILL_CURATION.md +4 -4
- package/workframe-api/README.md +28 -28
- package/workframe-api/action_proxy.py +131 -131
- package/workframe-api/auth_rate_limit.py +49 -49
- package/workframe-api/credential_vault.py +445 -445
- package/workframe-api/data/avatar-catalog.json +41 -41
- package/workframe-api/email_sender.py +220 -220
- package/workframe-api/google_auth.py +90 -90
- package/workframe-api/install_api.py +359 -359
- package/workframe-api/internal_proxy_auth.py +150 -150
- package/workframe-api/llm_proxy.py +277 -277
- package/workframe-api/oidc_jwt.py +108 -108
- package/workframe-api/package.json +12 -13
- package/workframe-api/public/assets/index-DPXu_lGn.css +1 -1
- package/workframe-api/public/assets/index-DYnLrCZZ.js +8 -8
- package/workframe-api/requirements.txt +2 -2
- package/workframe-api/site_meta.py +271 -271
- package/workframe-api/stack_config.py +427 -427
- package/workframe-api/time-bind-chat.py +99 -99
- package/workframe-api/turn_credentials.py +226 -226
- package/workframe-api/updates.py +417 -417
- package/workframe-api/vault_kek.py +159 -159
- package/workframe-api/zk_auth.py +633 -633
- package/workframe-supervisor/Dockerfile +11 -11
- package/workframe-supervisor/server.py +787 -787
- package/workframe-ui/docker/nginx.conf +85 -85
- package/workframe-ui/public/assets/{arc-CBDYvkAF.js → arc-COAT3laO.js} +1 -1
- package/workframe-ui/public/assets/architecture-7EHR7CIX-DUyH3hWG.js +1 -0
- package/workframe-ui/public/assets/{architectureDiagram-3BPJPVTR-XnBRKeW0.js → architectureDiagram-3BPJPVTR-BFjWV24l.js} +1 -1
- package/workframe-ui/public/assets/{blockDiagram-GPEHLZMM-VYHUfVhd.js → blockDiagram-GPEHLZMM-DSQLPfrj.js} +1 -1
- package/workframe-ui/public/assets/{c4Diagram-AAUBKEIU-BTjUcJpm.js → c4Diagram-AAUBKEIU-DKEHv1t2.js} +1 -1
- package/workframe-ui/public/assets/channel-g7r_RGaY.js +1 -0
- package/workframe-ui/public/assets/{chunk-2J33WTMH-w7uu7R-b.js → chunk-2J33WTMH-DHZg-DUi.js} +1 -1
- package/workframe-ui/public/assets/{chunk-3OPIFGDE-Cb9LtnDX.js → chunk-3OPIFGDE-BB-OYTfp.js} +1 -1
- package/workframe-ui/public/assets/{chunk-4BX2VUAB-DiQ-qCwH.js → chunk-4BX2VUAB-C93q0YIm.js} +1 -1
- package/workframe-ui/public/assets/{chunk-55IACEB6-C-mLFr7z.js → chunk-55IACEB6-MAYniqik.js} +1 -1
- package/workframe-ui/public/assets/{chunk-5ZQYHXKU-DOesfiCI.js → chunk-5ZQYHXKU-ChgN6YJs.js} +1 -1
- package/workframe-ui/public/assets/{chunk-727SXJPM-BJ3oBZuz.js → chunk-727SXJPM-B_FYwdAv.js} +1 -1
- package/workframe-ui/public/assets/{chunk-AQP2D5EJ-CCA6xpGs.js → chunk-AQP2D5EJ-1_Hw_h1A.js} +1 -1
- package/workframe-ui/public/assets/{chunk-BSJP7CBP-a0cMNFb2.js → chunk-BSJP7CBP-CFiDQ1Rv.js} +1 -1
- package/workframe-ui/public/assets/{chunk-CSCIHK7Q-kuqN8EIY.js → chunk-CSCIHK7Q-DZ9UMTlB.js} +1 -1
- package/workframe-ui/public/assets/{chunk-FMBD7UC4-DyPgYHCg.js → chunk-FMBD7UC4-DlMlyFgw.js} +1 -1
- package/workframe-ui/public/assets/{chunk-KSCS5N6A-CdUuvR0V.js → chunk-KSCS5N6A-DHXtQ_Hf.js} +1 -1
- package/workframe-ui/public/assets/{chunk-L5ZTLDWV-Dq9NoWmK.js → chunk-L5ZTLDWV-CuQzg-QG.js} +1 -1
- package/workframe-ui/public/assets/{chunk-LZXEDZCA-p74rddlO.js → chunk-LZXEDZCA-BHzjzCGg.js} +2 -2
- package/workframe-ui/public/assets/{chunk-ND2GUHAM-DBD2u1Gz.js → chunk-ND2GUHAM-DHXx05n2.js} +1 -1
- package/workframe-ui/public/assets/{chunk-NZK2D7GU-BeIeYFnd.js → chunk-NZK2D7GU-CV5pmDM_.js} +1 -1
- package/workframe-ui/public/assets/{chunk-O5CBEL6O-ClHc56ib.js → chunk-O5CBEL6O-6tkCHxsV.js} +1 -1
- package/workframe-ui/public/assets/chunk-QZHKN3VN-C5UQehWY.js +1 -0
- package/workframe-ui/public/assets/chunk-WU5MYG2G-DhWllrI8.js +1 -0
- package/workframe-ui/public/assets/{chunk-XPW4576I-EFr8R_1p.js → chunk-XPW4576I-BClwIiCp.js} +1 -1
- package/workframe-ui/public/assets/classDiagram-4FO5ZUOK-BBM_8T8E.js +1 -0
- package/workframe-ui/public/assets/classDiagram-v2-Q7XG4LA2-BBM_8T8E.js +1 -0
- package/workframe-ui/public/assets/{cose-bilkent-S5V4N54A-C7aPBODd.js → cose-bilkent-S5V4N54A-DOrGV6DQ.js} +1 -1
- package/workframe-ui/public/assets/{dagre-BM42HDAG-BdU1Rv-H.js → dagre-BM42HDAG-DXTPvJkX.js} +1 -1
- package/workframe-ui/public/assets/{diagram-2AECGRRQ-DWowSo85.js → diagram-2AECGRRQ-xX_v-pbf.js} +1 -1
- package/workframe-ui/public/assets/{diagram-5GNKFQAL-MnxBbceO.js → diagram-5GNKFQAL-Cd2pXbBe.js} +1 -1
- package/workframe-ui/public/assets/{diagram-KO2AKTUF-DQaLRXFf.js → diagram-KO2AKTUF-Df3XvUtk.js} +1 -1
- package/workframe-ui/public/assets/{diagram-LMA3HP47-CQaBud9k.js → diagram-LMA3HP47-CsijIPaD.js} +1 -1
- package/workframe-ui/public/assets/{diagram-OG6HWLK6-D8bAXbY9.js → diagram-OG6HWLK6-aq5fmfHd.js} +1 -1
- package/workframe-ui/public/assets/{dist-DGpTLHr_.js → dist-D1c0mkbB.js} +1 -1
- package/workframe-ui/public/assets/{erDiagram-TEJ5UH35-1E-xSvBK.js → erDiagram-TEJ5UH35-DnFysVRY.js} +1 -1
- package/workframe-ui/public/assets/eventmodeling-FCH6USID-Ci8mdb44.js +1 -0
- package/workframe-ui/public/assets/{flowDiagram-I6XJVG4X-CgOVD5hu.js → flowDiagram-I6XJVG4X-C6Ebi3su.js} +1 -1
- package/workframe-ui/public/assets/{ganttDiagram-6RSMTGT7-JFYAIauo.js → ganttDiagram-6RSMTGT7-BQXQtUpa.js} +1 -1
- package/workframe-ui/public/assets/{gitGraph-WXDBUCRP-B9REenIl.js → gitGraph-WXDBUCRP-Dt0zIs_M.js} +1 -1
- package/workframe-ui/public/assets/{gitGraphDiagram-PVQCEYII-BQ7NcMSn.js → gitGraphDiagram-PVQCEYII-BF8gHzRn.js} +1 -1
- package/workframe-ui/public/assets/index-DpoUZAxh.css +1 -0
- package/workframe-ui/public/assets/{index-Dnw6vjqb.js → index-lRpzpNPT.js} +2 -2
- package/workframe-ui/public/assets/{info-J43DQDTF-CL6-eTjH.js → info-J43DQDTF-CSmszQJT.js} +1 -1
- package/workframe-ui/public/assets/{infoDiagram-5YYISTIA-LJTODW4W.js → infoDiagram-5YYISTIA-CVTKGW6p.js} +1 -1
- package/workframe-ui/public/assets/{ishikawaDiagram-YF4QCWOH-bchrQVuo.js → ishikawaDiagram-YF4QCWOH-Z8pT09Lv.js} +1 -1
- package/workframe-ui/public/assets/{journeyDiagram-JHISSGLW-DkrvYuxP.js → journeyDiagram-JHISSGLW-r3wD68_T.js} +1 -1
- package/workframe-ui/public/assets/{kanban-definition-UN3LZRKU-DFRbj0IG.js → kanban-definition-UN3LZRKU-Il8VglqN.js} +1 -1
- package/workframe-ui/public/assets/{line-Vd48P7-O.js → line-oyjpfz2A.js} +1 -1
- package/workframe-ui/public/assets/{linear-Ckizh2G7.js → linear-Cf7p5tVp.js} +1 -1
- package/workframe-ui/public/assets/{mermaid-parser.core-Bkimsnqj.js → mermaid-parser.core-YmbZ-AfY.js} +2 -2
- package/workframe-ui/public/assets/{mermaid.core-x0TvVuPo.js → mermaid.core-BFdCAqCo.js} +3 -3
- package/workframe-ui/public/assets/{mindmap-definition-RKZ34NQL-6ykAFPEz.js → mindmap-definition-RKZ34NQL-Cy2iCtEl.js} +1 -1
- package/workframe-ui/public/assets/{packet-YPE3B663-Dw3xgMDt.js → packet-YPE3B663-DwOBZL6K.js} +1 -1
- package/workframe-ui/public/assets/{pie-LRSECV5Y-DATysawG.js → pie-LRSECV5Y-04PPhnKK.js} +1 -1
- package/workframe-ui/public/assets/{pieDiagram-4H26LBE5-SJKD1S0S.js → pieDiagram-4H26LBE5-LxIpgHqi.js} +1 -1
- package/workframe-ui/public/assets/{quadrantDiagram-W4KKPZXB-BrYDZX8q.js → quadrantDiagram-W4KKPZXB-0nBYfYm4.js} +1 -1
- package/workframe-ui/public/assets/{radar-GUYGQ44K-BmWYPCds.js → radar-GUYGQ44K-D2-vBqps.js} +1 -1
- package/workframe-ui/public/assets/{requirementDiagram-4Y6WPE33-DwL9Mc8e.js → requirementDiagram-4Y6WPE33-DbuU0nlu.js} +1 -1
- package/workframe-ui/public/assets/{sankeyDiagram-5OEKKPKP-DYIFsL8h.js → sankeyDiagram-5OEKKPKP-B2hQ6B2x.js} +1 -1
- package/workframe-ui/public/assets/{sequenceDiagram-3UESZ5HK-0-FPkFk8.js → sequenceDiagram-3UESZ5HK-BBrU30e1.js} +1 -1
- package/workframe-ui/public/assets/{src-B_od6b6h.js → src-BJEDmV70.js} +1 -1
- package/workframe-ui/public/assets/{stateDiagram-AJRCARHV-BQCiBk6u.js → stateDiagram-AJRCARHV-7FGO4kkH.js} +1 -1
- package/workframe-ui/public/assets/stateDiagram-v2-BHNVJYJU-DLTSizMg.js +1 -0
- package/workframe-ui/public/assets/{timeline-definition-PNZ67QCA-DS3tFcXj.js → timeline-definition-PNZ67QCA-ptDm4rCN.js} +1 -1
- package/workframe-ui/public/assets/{treeView-BLDUP644-DSyUCKLY.js → treeView-BLDUP644-CS6Z-0q8.js} +1 -1
- package/workframe-ui/public/assets/{treemap-LRROVOQU-CEZaNh5Y.js → treemap-LRROVOQU-DqV4Y2VA.js} +1 -1
- package/workframe-ui/public/assets/{vennDiagram-CIIHVFJN-CD-Vc9NF.js → vennDiagram-CIIHVFJN-C0UrZJYt.js} +1 -1
- package/workframe-ui/public/assets/{wardley-L42UT6IY-Drq5w1Mc.js → wardley-L42UT6IY-bNDN3_Sa.js} +1 -1
- package/workframe-ui/public/assets/{wardleyDiagram-YWT4CUSO-DouXDJoF.js → wardleyDiagram-YWT4CUSO-jWiJsefM.js} +1 -1
- package/workframe-ui/public/assets/{xychartDiagram-2RQKCTM6-DDf_Lol5.js → xychartDiagram-2RQKCTM6-Dsh_fLCy.js} +1 -1
- package/workframe-ui/public/favicon.svg +7 -7
- package/workframe-ui/public/index.html +50 -50
- package/workframe-ui/public/workframe-config.json +3 -3
- package/scripts/security_audit.py +0 -156
- package/scripts/test-scaffold.mjs +0 -390
- package/workframe-api/tests/__init__.py +0 -0
- package/workframe-api/tests/db_setup.py +0 -13
- package/workframe-api/tests/test_admin_updates_gated.py +0 -30
- package/workframe-api/tests/test_agent_dm_bootstrap.py +0 -196
- package/workframe-api/tests/test_agent_profile_sync.py +0 -76
- package/workframe-api/tests/test_auth_email.py +0 -222
- package/workframe-api/tests/test_auth_hole_fix_selfcheck.py +0 -99
- package/workframe-api/tests/test_auth_rate_limit.py +0 -19
- package/workframe-api/tests/test_avatar_resolve.py +0 -77
- package/workframe-api/tests/test_child_soul_template.py +0 -71
- package/workframe-api/tests/test_credential_canary.py +0 -135
- package/workframe-api/tests/test_credential_isolation.py +0 -448
- package/workframe-api/tests/test_credential_resolution.py +0 -206
- package/workframe-api/tests/test_device_oauth.py +0 -108
- package/workframe-api/tests/test_doctor_repair.py +0 -103
- package/workframe-api/tests/test_ensure_profile_api.py +0 -77
- package/workframe-api/tests/test_gateway_compose_security.py +0 -136
- package/workframe-api/tests/test_install_secure_host.py +0 -39
- package/workframe-api/tests/test_internal_proxy_auth.py +0 -125
- package/workframe-api/tests/test_invite_runtime_bootstrap.py +0 -72
- package/workframe-api/tests/test_kanban_delegation.py +0 -185
- package/workframe-api/tests/test_llm_proxy.py +0 -155
- package/workframe-api/tests/test_login_access_policy.py +0 -183
- package/workframe-api/tests/test_mvp_model_bootstrap.py +0 -75
- package/workframe-api/tests/test_onboarding_bootstrap.py +0 -248
- package/workframe-api/tests/test_platform_auth.py +0 -47
- package/workframe-api/tests/test_profile_config_path.py +0 -56
- package/workframe-api/tests/test_profile_config_yaml_repair.py +0 -63
- package/workframe-api/tests/test_profile_create.py +0 -72
- package/workframe-api/tests/test_profile_identity_overlay.py +0 -61
- package/workframe-api/tests/test_profile_install_health.py +0 -45
- package/workframe-api/tests/test_profile_secret_policy.py +0 -57
- package/workframe-api/tests/test_profile_workspace_cwd.py +0 -34
- package/workframe-api/tests/test_provider_bootstrap.py +0 -75
- package/workframe-api/tests/test_provider_connect.py +0 -54
- package/workframe-api/tests/test_room_crud.py +0 -192
- package/workframe-api/tests/test_room_tenancy.py +0 -701
- package/workframe-api/tests/test_runtime_identity_backfill.py +0 -34
- package/workframe-api/tests/test_site_meta.py +0 -81
- package/workframe-api/tests/test_soul_stub.py +0 -42
- package/workframe-api/tests/test_space_member_sync.py +0 -99
- package/workframe-api/tests/test_stripe_stack_config.py +0 -37
- package/workframe-api/tests/test_supervisor_lifecycle.py +0 -52
- package/workframe-api/tests/test_turn_credential_vault.py +0 -125
- package/workframe-api/tests/test_updates.py +0 -176
- package/workframe-api/tests/test_user_cohort.py +0 -113
- package/workframe-api/tests/test_vault_envelope.py +0 -110
- package/workframe-api/tests/test_workspace_members.py +0 -183
- package/workframe-api/tests/test_workspace_messaging_sync.py +0 -125
- package/workframe-api/tests/test_workspace_provider_list.py +0 -57
- package/workframe-supervisor/tests/test_exec_guard.py +0 -42
- package/workframe-supervisor/tests/test_server_import.py +0 -21
- package/workframe-ui/public/assets/architecture-7EHR7CIX-CtbQKTuT.js +0 -1
- package/workframe-ui/public/assets/channel-Dy4Z4-jn.js +0 -1
- package/workframe-ui/public/assets/chunk-QZHKN3VN-CtBEchFK.js +0 -1
- package/workframe-ui/public/assets/chunk-WU5MYG2G-B9pBtriN.js +0 -1
- package/workframe-ui/public/assets/classDiagram-4FO5ZUOK-BMAEA8jI.js +0 -1
- package/workframe-ui/public/assets/classDiagram-v2-Q7XG4LA2-BMAEA8jI.js +0 -1
- package/workframe-ui/public/assets/eventmodeling-FCH6USID-D75cstNT.js +0 -1
- package/workframe-ui/public/assets/index-DpAGxump.css +0 -1
- package/workframe-ui/public/assets/stateDiagram-v2-BHNVJYJU-B89jAMFF.js +0 -1
|
@@ -1,50 +1,50 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
# Append production stack secrets to a Workframe .env (idempotent).
|
|
3
|
-
# Usage: bash scripts/workframe/setup-stack-secrets.sh path/to/.env
|
|
4
|
-
set -euo pipefail
|
|
5
|
-
|
|
6
|
-
ENV_FILE="${1:-/workspace/.env}"
|
|
7
|
-
|
|
8
|
-
append_if_missing() {
|
|
9
|
-
local key="$1"
|
|
10
|
-
local value="$2"
|
|
11
|
-
local comment="${3:-}"
|
|
12
|
-
if [[ -f "$ENV_FILE" ]] && grep -q "^${key}=" "$ENV_FILE"; then
|
|
13
|
-
echo "${key} already exists in ${ENV_FILE}"
|
|
14
|
-
return 0
|
|
15
|
-
fi
|
|
16
|
-
mkdir -p "$(dirname "$ENV_FILE")"
|
|
17
|
-
{
|
|
18
|
-
[[ -n "$comment" ]] && printf '\n# %s\n' "$comment"
|
|
19
|
-
printf '%s=%s\n' "$key" "$value"
|
|
20
|
-
} >>"$ENV_FILE"
|
|
21
|
-
echo "${key} generated and appended to ${ENV_FILE}"
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
rand_hex() {
|
|
25
|
-
openssl rand -hex 32 2>/dev/null || python3 - <<'PY'
|
|
26
|
-
import secrets
|
|
27
|
-
print(secrets.token_hex(32))
|
|
28
|
-
PY
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
rand_b64() {
|
|
32
|
-
python3 - <<'PY'
|
|
33
|
-
import base64, os
|
|
34
|
-
print(base64.b64encode(os.urandom(32)).decode())
|
|
35
|
-
PY
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
rand_proxy() {
|
|
39
|
-
python3 - <<'PY'
|
|
40
|
-
import secrets
|
|
41
|
-
print(secrets.token_urlsafe(32))
|
|
42
|
-
PY
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
append_if_missing WORKFRAME_SUPERVISOR_TOKEN "${WORKFRAME_SUPERVISOR_TOKEN:-$(rand_hex)}" \
|
|
46
|
-
"Workframe supervisor token. Keep this secret."
|
|
47
|
-
append_if_missing WORKFRAME_PROXY_TOKEN "${WORKFRAME_PROXY_TOKEN:-$(rand_proxy)}" \
|
|
48
|
-
"Internal LLM/action proxy secret — gateway + API must match."
|
|
49
|
-
append_if_missing WORKFRAME_VAULT_KEK "${WORKFRAME_VAULT_KEK:-$(rand_b64)}" \
|
|
50
|
-
"Credential vault KEK (32-byte base64). Required for public_multi_user."
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Append production stack secrets to a Workframe .env (idempotent).
|
|
3
|
+
# Usage: bash scripts/workframe/setup-stack-secrets.sh path/to/.env
|
|
4
|
+
set -euo pipefail
|
|
5
|
+
|
|
6
|
+
ENV_FILE="${1:-/workspace/.env}"
|
|
7
|
+
|
|
8
|
+
append_if_missing() {
|
|
9
|
+
local key="$1"
|
|
10
|
+
local value="$2"
|
|
11
|
+
local comment="${3:-}"
|
|
12
|
+
if [[ -f "$ENV_FILE" ]] && grep -q "^${key}=" "$ENV_FILE"; then
|
|
13
|
+
echo "${key} already exists in ${ENV_FILE}"
|
|
14
|
+
return 0
|
|
15
|
+
fi
|
|
16
|
+
mkdir -p "$(dirname "$ENV_FILE")"
|
|
17
|
+
{
|
|
18
|
+
[[ -n "$comment" ]] && printf '\n# %s\n' "$comment"
|
|
19
|
+
printf '%s=%s\n' "$key" "$value"
|
|
20
|
+
} >>"$ENV_FILE"
|
|
21
|
+
echo "${key} generated and appended to ${ENV_FILE}"
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
rand_hex() {
|
|
25
|
+
openssl rand -hex 32 2>/dev/null || python3 - <<'PY'
|
|
26
|
+
import secrets
|
|
27
|
+
print(secrets.token_hex(32))
|
|
28
|
+
PY
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
rand_b64() {
|
|
32
|
+
python3 - <<'PY'
|
|
33
|
+
import base64, os
|
|
34
|
+
print(base64.b64encode(os.urandom(32)).decode())
|
|
35
|
+
PY
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
rand_proxy() {
|
|
39
|
+
python3 - <<'PY'
|
|
40
|
+
import secrets
|
|
41
|
+
print(secrets.token_urlsafe(32))
|
|
42
|
+
PY
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
append_if_missing WORKFRAME_SUPERVISOR_TOKEN "${WORKFRAME_SUPERVISOR_TOKEN:-$(rand_hex)}" \
|
|
46
|
+
"Workframe supervisor token. Keep this secret."
|
|
47
|
+
append_if_missing WORKFRAME_PROXY_TOKEN "${WORKFRAME_PROXY_TOKEN:-$(rand_proxy)}" \
|
|
48
|
+
"Internal LLM/action proxy secret — gateway + API must match."
|
|
49
|
+
append_if_missing WORKFRAME_VAULT_KEK "${WORKFRAME_VAULT_KEK:-$(rand_b64)}" \
|
|
50
|
+
"Credential vault KEK (32-byte base64). Required for public_multi_user."
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
3
|
* Copy canonical Workframe BFF into create-workframe package tree before npm pack.
|
|
4
|
-
* Run from
|
|
4
|
+
* Run from repository root: node packages/create-workframe/scripts/sync-canonical-to-package.mjs
|
|
5
5
|
*/
|
|
6
6
|
import fs from 'node:fs';
|
|
7
7
|
import path from 'node:path';
|
|
@@ -9,14 +9,15 @@ import { fileURLToPath } from 'node:url';
|
|
|
9
9
|
|
|
10
10
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
11
11
|
const PKG_ROOT = path.resolve(__dirname, '..');
|
|
12
|
-
const
|
|
13
|
-
const CANONICAL_API = path.join(
|
|
12
|
+
const REPO_ROOT = path.resolve(PKG_ROOT, '../..');
|
|
13
|
+
const CANONICAL_API = path.join(REPO_ROOT, 'services/workframe-api');
|
|
14
14
|
const PKG_API = path.join(PKG_ROOT, 'workframe-api');
|
|
15
|
-
const CANONICAL_SUPERVISOR = path.join(
|
|
15
|
+
const CANONICAL_SUPERVISOR = path.join(REPO_ROOT, 'services/workframe-supervisor');
|
|
16
16
|
const PKG_SUPERVISOR = path.join(PKG_ROOT, 'workframe-supervisor');
|
|
17
17
|
|
|
18
18
|
const SKIP_DIRS = new Set([
|
|
19
19
|
'data',
|
|
20
|
+
'tests',
|
|
20
21
|
'__pycache__',
|
|
21
22
|
'.pytest_cache',
|
|
22
23
|
'.venv',
|
|
@@ -103,7 +104,7 @@ const applyScripts = [
|
|
|
103
104
|
'ensure-compose-host-paths.mjs',
|
|
104
105
|
];
|
|
105
106
|
for (const name of applyScripts) {
|
|
106
|
-
const src = path.join(
|
|
107
|
+
const src = path.join(REPO_ROOT, 'scripts/workframe', name);
|
|
107
108
|
const dst = path.join(PKG_ROOT, 'scripts', name);
|
|
108
109
|
if (!fs.existsSync(src)) throw new Error(`Missing apply script: ${src}`);
|
|
109
110
|
fs.mkdirSync(path.dirname(dst), { recursive: true });
|
|
@@ -111,7 +112,7 @@ for (const name of applyScripts) {
|
|
|
111
112
|
console.log(`Synced ${name} -> package/scripts/`);
|
|
112
113
|
}
|
|
113
114
|
|
|
114
|
-
const publicDeploySrc = path.join(
|
|
115
|
+
const publicDeploySrc = path.join(REPO_ROOT, 'infra/compose/workframe/PUBLIC_DEPLOY.md');
|
|
115
116
|
const publicDeployDst = path.join(PKG_ROOT, 'docs/PUBLIC_DEPLOY.md');
|
|
116
117
|
if (fs.existsSync(publicDeploySrc)) {
|
|
117
118
|
fs.mkdirSync(path.dirname(publicDeployDst), { recursive: true });
|
|
@@ -120,7 +121,7 @@ if (fs.existsSync(publicDeploySrc)) {
|
|
|
120
121
|
}
|
|
121
122
|
|
|
122
123
|
for (const name of ['LICENSE', 'NOTICE', 'SECURITY.md']) {
|
|
123
|
-
const src = path.join(
|
|
124
|
+
const src = path.join(REPO_ROOT, name);
|
|
124
125
|
const dst = path.join(PKG_ROOT, name);
|
|
125
126
|
if (!fs.existsSync(src)) throw new Error(`Missing publish file: ${src}`);
|
|
126
127
|
fs.copyFileSync(src, dst);
|
|
@@ -1,105 +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"
|
|
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"
|
|
@@ -8,23 +8,23 @@ Canonical behavior location
|
|
|
8
8
|
- Runtime: `Agents/profiles/{nativeProfileSlug}/SOUL.md`
|
|
9
9
|
- Bootstrap seed: `scripts/seed/profiles/{nativeProfileSlug}/SOUL.md`
|
|
10
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.
|
|
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
28
|
|
|
29
29
|
Curation rule
|
|
30
30
|
- Keep role-specific skill/tool bundles lean.
|
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
Goal
|
|
4
4
|
- keep the agent library dynamic but controlled.
|
|
5
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
|
|
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
11
|
|
|
12
12
|
Profile operations policy
|
|
13
13
|
- Add profile: when repeated tasks do not fit existing specialists.
|
|
@@ -17,13 +17,13 @@ Profile operations policy
|
|
|
17
17
|
Approval
|
|
18
18
|
- owner/admin approves profile topology changes in team environments.
|
|
19
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.
|
|
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.
|
|
@@ -1,17 +1,17 @@
|
|
|
1
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",
|
|
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
15
|
"architect",
|
|
16
16
|
"docs",
|
|
17
17
|
"dev",
|
|
@@ -48,11 +48,11 @@
|
|
|
48
48
|
"research"
|
|
49
49
|
]
|
|
50
50
|
},
|
|
51
|
-
"full": {
|
|
52
|
-
"description": "Alias of vanilla for compatibility",
|
|
53
|
-
"profiles": [
|
|
54
|
-
"project-agent",
|
|
55
|
-
"visionary",
|
|
51
|
+
"full": {
|
|
52
|
+
"description": "Alias of vanilla for compatibility",
|
|
53
|
+
"profiles": [
|
|
54
|
+
"project-agent",
|
|
55
|
+
"visionary",
|
|
56
56
|
"architect",
|
|
57
57
|
"docs",
|
|
58
58
|
"dev",
|
|
@@ -1,11 +1,11 @@
|
|
|
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]
|
|
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
9
|
core:
|
|
10
10
|
description: Minimal operational baseline
|
|
11
11
|
profiles: [project-agent, docs, dev]
|
|
@@ -21,7 +21,7 @@ Tool curation rules
|
|
|
21
21
|
3) Add a skill only after repeated need.
|
|
22
22
|
4) Remove stale skills quarterly.
|
|
23
23
|
|
|
24
|
-
Install-time selection
|
|
25
|
-
- default to the `native` starter pack unless a larger reference pack is explicitly requested
|
|
26
|
-
- reference packs remain available (`core` / `product` / `engineering` / `full`)
|
|
27
|
-
- concierge can request profile add/remove later with owner approval.
|
|
24
|
+
Install-time selection
|
|
25
|
+
- default to the `native` starter pack unless a larger reference pack is explicitly requested
|
|
26
|
+
- reference packs remain available (`core` / `product` / `engineering` / `full`)
|
|
27
|
+
- concierge can request profile add/remove later with owner approval.
|
package/workframe-api/README.md
CHANGED
|
@@ -1,28 +1,28 @@
|
|
|
1
|
-
# Workframe API Service
|
|
2
|
-
|
|
3
|
-
**Version:** `0.1.0` (`workframe-api-0.1.0`). See `docs/VERSION.md`.
|
|
4
|
-
|
|
5
|
-
Active backend service for the transplanted Workframe vertical slice.
|
|
6
|
-
|
|
7
|
-
This is intentionally preserved as the current Python BFF instead of being rewritten into `apps/api`.
|
|
8
|
-
|
|
9
|
-
## Local
|
|
10
|
-
|
|
11
|
-
```bash
|
|
12
|
-
cd services/workframe-api
|
|
13
|
-
python3 -m venv .venv
|
|
14
|
-
. .venv/bin/activate
|
|
15
|
-
pip install -r requirements.txt
|
|
16
|
-
HOST=0.0.0.0 PORT=8080 HERMES_DATA=/opt/data WORKSPACE=/workspace python3 server.py
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
## Runtime state
|
|
20
|
-
|
|
21
|
-
Runtime files are intentionally not committed:
|
|
22
|
-
|
|
23
|
-
- `data/*.db`
|
|
24
|
-
- `data/.auth_keys`
|
|
25
|
-
- Hermes `Agents/`
|
|
26
|
-
- workspace `Files/`
|
|
27
|
-
|
|
28
|
-
For VPS deployment, mount clean persistent volumes into `/opt/data` and `/workspace`.
|
|
1
|
+
# Workframe API Service
|
|
2
|
+
|
|
3
|
+
**Version:** `0.1.0` (`workframe-api-0.1.0`). See `docs/VERSION.md`.
|
|
4
|
+
|
|
5
|
+
Active backend service for the transplanted Workframe vertical slice.
|
|
6
|
+
|
|
7
|
+
This is intentionally preserved as the current Python BFF instead of being rewritten into `apps/api`.
|
|
8
|
+
|
|
9
|
+
## Local
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
cd services/workframe-api
|
|
13
|
+
python3 -m venv .venv
|
|
14
|
+
. .venv/bin/activate
|
|
15
|
+
pip install -r requirements.txt
|
|
16
|
+
HOST=0.0.0.0 PORT=8080 HERMES_DATA=/opt/data WORKSPACE=/workspace python3 server.py
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Runtime state
|
|
20
|
+
|
|
21
|
+
Runtime files are intentionally not committed:
|
|
22
|
+
|
|
23
|
+
- `data/*.db`
|
|
24
|
+
- `data/.auth_keys`
|
|
25
|
+
- Hermes `Agents/`
|
|
26
|
+
- workspace `Files/`
|
|
27
|
+
|
|
28
|
+
For VPS deployment, mount clean persistent volumes into `/opt/data` and `/workspace`.
|