中央工作台

把 /onboarding.md 这个链接交给 AI 终端(Claude Code、Codex),它会按步骤把当前项目接入 workhub。人需要做的准备见首页的《接入一个项目》。

接入要求版本
v1
发布者
workhub
发布时间
1 小时前
更新说明
初始版本

workhub 接入剧本 v1

给 AI 终端(Claude Code、Codex)的执行说明。人把这个链接交给你,你读完后按步骤把当前项目接入中央工作台 workhub。 新项目、已在建的项目都适用;已经接入过的项目,重新执行一遍就会按最新要求更新。

  • 中央地址:https://workhub.qianba.cc。如果你打开这份剧本用的地址与它不同(比如内网地址),以你实际打开的地址为准,下文的地址都相应替换。
  • 版本:v1,即中央当前的接入要求版本。接入后记在 .workhub/lock.yaml 的 onboarding;以后接入要求更新了,重新执行一遍就会按新版本更新项目。
  • 在项目仓库的根目录执行。命令以 bash 为例;Windows PowerShell 里用 curl.exe(curl 是 Invoke-WebRequest 的别名),环境变量写成 $env:WORKHUB_KEY。
  • 在 Windows 上用 Python 处理含中文的内容时加 -X utf8(如 python -X utf8 script.py),否则输出可能是乱码。

你要做成什么

接入完成后,项目仓库的标尺分支(main 或 master)上会有:

文件 作用
.workhub/progress.yaml 项目进度。中央从 Git 读取它,这是项目对外公开的全部内容
.workhub/loop.md Loop 视图(loop-engineering 流程图)的本地副本。所有接入项目都按它干活
.workhub/capabilities/ 视图里用到的 agent 及其依赖的 skill,已解压
.workhub/standards.md 项目规范的副本:目录、设计文件、脚本、知识库怎么放
.workhub/layout.yaml 选择“映射”方式时才有:规范的各角色在本项目对应哪个目录
.workhub/lock.yaml 接入状态:接入要求版本、项目 ID、分支、视图版本、规范版本、已装能力。重跑剧本时据此判断要做什么
AGENTS.md 里的 workhub 规则块 以后每次会话都要遵守的规则。Codex 直接读 AGENTS.md
CLAUDE.md 第一行的 @AGENTS.md 让 Claude Code 读到同一份规则
.gitattributes 里的一行 让 .workhub/ 下的文件不做换行转换,避免签出后出现无意义的改动

中央 workhub 只从 Git 读取进度,不会向仓库提交任何东西。

原则

从哪一步开始

先做第 0 步,再按第 1 步的结果走:

情况 依次执行
A. 中央没有登记这个仓库 2 → 3 → 4 → 5 → 6 → 7 → 8
B. 已登记,但项目里没有 .workhub/lock.yaml 2(分支以中央记录的为准)→ 4 → 5 → 6 → 7 → 8
C. 已有 .workhub/lock.yaml(重跑) 4(只检查)→ 5 → 6 →(前面有任何改动,或 onboarding 小于 1,就执行 7)→ 8

第 0 步:准备

  1. 读取环境变量 WORKHUB_KEY。没有的话,请人提供本端的 workhub 密钥(whk_ 开头)。建议人自己在终端设置环境变量后重启会话;如果人直接在对话里给出,只在本次会话的 shell 里设置(bash:export WORKHUB_KEY=...;PowerShell:$env:WORKHUB_KEY="..."),不写进任何文件。
  2. 校验密钥:
curl -s -w "\n%{http_code}\n" https://workhub.qianba.cc/v1/whoami -H "Authorization: Bearer $WORKHUB_KEY"
# 200 → {"client": "build-server-02", ...}   401 表示密钥无效或已过期,请人确认

AI 终端的每条命令往往在新的 shell 里执行,环境变量不会保留。最好请人在启动 AI 终端之前就设置好 WORKHUB_KEY;否则每条命令前都要重新设置。

  1. 确认当前目录是 Git 仓库,并有远端:git remote get-url origin。
    • 没有远端的新项目:请人先在 Gitee、GitHub、Gogs 等创建仓库(或在 gh 已登录时用 gh repo create),设为 origin 并推送一次。
    • 远端是 file:// 或本地路径:中央在另一台服务器上,通常访问不到,请人确认(只有中央和项目在同一台机器上的测试环境才能这样登记,此时 git_credential 随便填一个令牌即可)。

第 1 步:识别项目状态

  1. 有 .workhub/lock.yaml:读出 project_id,GET https://workhub.qianba.cc/v1/projects/<project_id>。
    • 200:走情况 C。
    • 404:中央已没有这个项目。告诉人,人同意后删掉 lock.yaml,按下面第 2 条重新判断。
  2. 没有 lock.yaml,按仓库地址查询:
curl -s -G https://workhub.qianba.cc/v1/projects/lookup --data-urlencode "repo_url=$(git remote get-url origin)" \
  -H "Authorization: Bearer $WORKHUB_KEY"
# 200 → 情况 B,记下 project_id 和 status_ref
# 404(not_registered)→ 情况 A

第 2 步:确认标尺分支

前期每个项目只用一个分支(main 或 master),中央也读这个分支。

  1. 情况 B:用 lookup 返回的 status_ref。
  2. 情况 A:查远端默认分支 git ls-remote --symref origin HEAD(输出 ref: refs/heads/main HEAD),取不到就看有没有 main 或 master。
  3. 问人确认:“标尺分支用 <分支>,进度文件和 workhub 文件都提交到这个分支,可以吗?”之后的工作都在这个分支上做。

第 3 步:登记项目

中央需要一份只读凭据来拉取仓库。选一种,告诉人你要怎么做:

ssh-keygen -t ed25519 -N "" -C "workhub-readonly" -f "<临时目录>/workhub_deploy"

把公钥 workhub_deploy.pub 加到仓库的“部署公钥 / Deploy keys”(只读):

仓库地址用 SSH 形式(如 git@gitee.com:team/order.git)。私钥全文放进请求体 JSON 时用脚本读取文件生成(换行要正确转义),登记完成后删除私钥、公钥和请求体文件。

请求体(用脚本生成 UTF-8 文件 <临时目录>/register.json):

{
  "repo_url": "git@gitee.com:team/order.git",
  "status_ref": "main",
  "name": "订单服务",
  "git_credential": {"auth": "ssh_key", "private_key": "-----BEGIN OPENSSH PRIVATE KEY-----\n...\n-----END OPENSSH PRIVATE KEY-----\n"}
}

git_credential 也可以是 {"auth": "https_token", "token": "<令牌>"}。name 用项目名称(不超过 40 字)。问人确认后登记:

curl -sX POST https://workhub.qianba.cc/v1/projects -H "Authorization: Bearer $WORKHUB_KEY" \
  -H "Content-Type: application/json; charset=utf-8" --data-binary @"<临时目录>/register.json"
# 201 → {"project_id": "prj_...", "status_ref": "main", "webhook_url": "...", ...}

第 4 步:进度文件

按附录 A 的格式写 .workhub/progress.yaml(先建好 .workhub/ 目录),project_id 用登记得到的。已有这个文件时(情况 C、D),只检查格式和 project_id,不改内容。

提交前校验(请求体同样用脚本生成):

# <临时目录>/progress.json 的内容:{"project_id": "<project_id>", "content": "<progress.yaml 全文>"}
curl -sX POST https://workhub.qianba.cc/v1/progress/validate -H "Authorization: Bearer $WORKHUB_KEY" \
  -H "Content-Type: application/json; charset=utf-8" --data-binary @"<临时目录>/progress.json"
# → {"ok": true, ...} 或 {"ok": false, "error": "..."}

首次写入时把内容给人确认(这个文件对外网公开)。

第 5 步:项目规范、AI 规则和换行设置

项目规范规定干活的产出放在哪、怎么留存(目录、设计文件、脚本、知识库);AI 规则块写进 AGENTS.md,让以后每次会话都按规范和 Loop 视图干活。两者在中央同属一个版本。

  1. 下载规范:
curl -s -o "<临时目录>/standards.md" -D "<临时目录>/standards.headers" https://workhub.qianba.cc/standards.md
# 版本号在响应头 X-Standards-Version

复制到 .workhub/standards.md。

  1. 目录适配(lock.yaml 里已经有 standards_version 的项目跳过这一条,除非规范的目录要求变了):

    • 新项目:按规范的默认位置建目录(docs/design/、docs/knowledge/、scripts/ 等,空目录可以先不建,用到时再建),并按范本写一个 docs/knowledge/index.md。
    • 已在建的项目:问人选映射还是改造。
      • 映射:读现有目录,按规范“已在建的项目”一节写 .workhub/layout.yaml,列出各角色在本项目对应的目录,给人确认。
      • 改造:对照规范末尾的范本,列出迁移计划(哪些文件移到哪里、要新建哪些文件),给人确认后执行。改造单独提交一次,不和接入的其他改动混在一起。
  2. 写 AI 规则块(已填好项目 ID、分支、地址):

curl -s "https://workhub.qianba.cc/standards/agents.md?project_id=<project_id>"
  1. .gitattributes 里没有 .workhub/** -text 这一行就加上(没有这个文件就新建),避免换行转换让 .workhub/ 下的文件在签出后出现无意义的改动。

内容与原来一致就算没有改动。

第 6 步:Loop 视图、agent 和 skill

所有接入项目都必须按 Loop 视图干活。视图和其中用到的 agent、skill 来自 workhub 能力库,由团队的各个端发布。它们会写进项目,以后的会话会按它们执行,所以安装前要给人看。

  1. 下载视图到临时文件,检查状态码:
curl -s -o "<临时目录>/loop.md" -D "<临时目录>/loop.headers" -w "%{http_code}" https://workhub.qianba.cc/v1/loop/content
# 200 → 版本号在响应头 X-Loop-Version
# 404 → 中央还没有视图:跳过本步,lock.yaml 的 loop_version 记 0、capabilities 记 []
  1. 取视图用到的全部 agent 和 skill(已去重):
curl -s https://workhub.qianba.cc/v1/loop/resolve -H "Authorization: Bearer $WORKHUB_KEY"
# → {"loop_version": 2, "items": [{"id": "public/backend-dev", "type": "agent", "version": 1, "status": "active",
#     "content_sha256": "...", "content_path": "/v1/capabilities/public/backend-dev/versions/1/content"}, ...]}
# 410 → 视图引用了已下架的版本:停下来告诉人
  1. 与 lock.yaml 对比,找出要新装或更新的项(id、version、content_sha256 有一个不同,或目录不存在)和要删除的项(lock 里有、清单里没有)。没有任何变化、视图版本也没变,就跳到第 5 条。

  2. 把要新装或更新的包下载到临时目录,校验并只读查看:

    • 下载:curl -s -o "<临时目录>/<名称>.zip" https://workhub.qianba.cc<content_path> -H "Authorization: Bearer $WORKHUB_KEY";
    • 校验 SHA-256 与 content_sha256 一致(sha256sum、shasum -a 256、certutil -hashfile <文件> SHA256 或 Python),不一致就停止并告诉人;
    • 列出包里的文件:python -X utf8 -m zipfile -l <zip>,读出 manifest.yaml。中央在发布时已经拒绝了路径穿越、绝对路径和符号链接,这里再看一眼文件名即可。

    给人看并确认:视图版本和更新说明(GET https://workhub.qianba.cc/v1/loop 的 note),要安装、更新、删除的能力清单,每个包的 manifest.yaml 和文件列表;status 为 deprecated 的一并告诉人。人同意后:

    • 解压到临时目录(python -X utf8 -m zipfile -e <zip> <目录>、PowerShell Expand-Archive 或 unzip),再替换到 .workhub/capabilities/<id>/(如 .workhub/capabilities/public/backend-dev/,先删除旧目录);
    • 删除清单里已经没有的能力目录,以及因此变空的范围目录;
    • 把视图从临时文件复制到 .workhub/loop.md。

    人不同意就停在这里,不改动项目里的视图和能力。

  3. 上报本项目在用的全部能力(清单里的每一项,包括 skill)。每次执行本步都上报一次:

# 请求体:{"project_id": "<project_id>", "items": [{"id": "public/backend-dev", "version": 1}, ...]}
curl -sX POST https://workhub.qianba.cc/v1/capabilities/installed -H "Authorization: Bearer $WORKHUB_KEY" \
  -H "Content-Type: application/json; charset=utf-8" --data-binary @"<临时目录>/installed.json"

第 7 步:写接入状态并提交

  1. 写 .workhub/lock.yaml(capabilities 与 .workhub/capabilities/ 下的目录一一对应,顺序与 /v1/loop/resolve 的清单一致;sha256 是 zip 包的 content_sha256,不是解压后文件的):
# 由 workhub 接入剧本维护,不要手改
onboarding: 1
project_id: prj_01JB8XQ2M4
status_ref: main
loop_version: 2
standards_version: 1
capabilities:
  - {id: public/backend-dev, version: 1, sha256: "<64 位>"}
  1. 把改动清单给人确认(git status、git diff --stat),确认没有把密钥、私钥、令牌、webhook 地址、密码箱内容加进去,然后在标尺分支上提交并推送:
git add .workhub AGENTS.md CLAUDE.md .gitattributes
git commit -m "接入 workhub(接入剧本 v1)"   # 首次接入
# 重跑时写明改了什么,如:git commit -m "更新 workhub 接入:Loop 视图 v2,新增 public/doc-writer"
# 你的工具自带的署名行可以照常附加
git push origin <标尺分支>

第 8 步:验收并汇报

curl -sX POST "https://workhub.qianba.cc/v1/projects/<project_id>/sync?wait=true" -H "Authorization: Bearer $WORKHUB_KEY"
# updated / file_unchanged / unchanged:成功
# parse_error:看 error,修正进度文件后回到第 7 步
# error:中央拉取失败,GET /v1/projects/<project_id>/sync-log 看原因

向人汇报:项目 ID、项目页面 https://workhub.qianba.cc/projects/<project_id>、视图版本、装了哪些能力、本次改动了什么,以及需要人处理的事(如配置 webhook;中央无法判断 webhook 是否已配置,只能问人)。


附录 A:进度文件 .workhub/progress.yaml

schema: workhub/progress/v1
project_id: prj_01JB8XQ2M4        # 登记时分配,必须一致
name: 订单服务
summary: 退款功能开发中,预计本周完成联调   # 一句话现状
phase: 实现                        # 当前阶段,自由文本
progress: 60                       # 整体进度 0–100,可选
updated_at: 2026-10-20T16:00:00+08:00

items:                             # 计划中、进行中、阻塞或刚结束的工作,最多 20 条
  - id: refund                     # 项目内稳定标识
    title: 订单退款
    state: blocked                 # planned / running / blocked / done / failed / cancelled
    stage: 前后端实现
    progress: 60
    blocked_reason: 等待接口字段确认  # state 为 blocked 时必填
    updated_at: 2026-10-20T15:40:00+08:00

milestones:                        # 近期里程碑,最多 20 条,新的在前
  - date: 2026-10-18
    title: 退款接口设计评审通过
字段 必填 规则
schema 是 固定为 workhub/progress/v1
project_id 是 与登记返回的一致
name 是 不超过 40 字
summary 是 不超过 200 字
phase 否 不超过 20 字
progress 否 0–100 的整数
updated_at 是 ISO 8601,带时区
items[].id、title、state 是 id 为字母数字和 _.-;title 不超过 100 字
items[].stage 否 不超过 20 字
items[].blocked_reason blocked 时必填 不超过 200 字
milestones[].date、title 是 date 为 YYYY-MM-DD

文件不超过 64 KB;对外网公开,只写可以公开的概括;标尺分支禁止 force push 和删除。不合规时中央保留上一份合规内容,页面上显示解析错误。

附录 B:密码箱

一条凭据 = 标题和说明(公开)+ 内容(任意文本,加密)。默认私有(只有本端能取用),public 则所有端都能取用。只有创建它的端能修改和撤销。

# 存(请求体用脚本生成):{"title": "订单服务测试环境管理员", "description": "测试后台登录", "project_id": "<project_id>", "visibility": "public", "content": "..."}
curl -sX POST https://workhub.qianba.cc/v1/secrets -H "Authorization: Bearer $WORKHUB_KEY" \
  -H "Content-Type: application/json; charset=utf-8" --data-binary @"<临时目录>/secret.json"
# 列出本端能取用的(只有公开字段),可加 &project_id=... 过滤
curl -s "https://workhub.qianba.cc/v1/secrets?mine=true" -H "Authorization: Bearer $WORKHUB_KEY"
# 一次取回多条内容(最多 50 条)
curl -sX POST https://workhub.qianba.cc/v1/secrets/values -H "Authorization: Bearer $WORKHUB_KEY" -H "Content-Type: application/json" \
  -d '{"ids": ["sec_xxxxxxxxxx", "sec_yyyyyyyyyy"]}'

创建者还可以 PATCH /v1/secrets/{sid}、PUT /v1/secrets/{sid}/content(版本加 1)、POST /v1/secrets/{sid}/revoke。GET /v1/audit-log 看本端的取用和本端凭据被谁取用。

附录 C:能力库

能力是 Skill 或 Agent 的 zip 包,根目录必须有 manifest.yaml。标识 public/<名称> 为公共能力,<project_id>/<名称> 为项目私有能力。

curl -s https://workhub.qianba.cc/v1/capabilities                                                   # 浏览
curl -s https://workhub.qianba.cc/v1/capabilities/public/backend-dev/versions/latest/resolve -H "Authorization: Bearer $WORKHUB_KEY"
# 推送自己封装的能力
curl -sX POST https://workhub.qianba.cc/v1/capabilities -H "Authorization: Bearer $WORKHUB_KEY" -H "Content-Type: application/json" \
  -d '{"id": "<project_id>/refund-checker", "type": "skill"}'
curl -sX POST https://workhub.qianba.cc/v1/capabilities/<project_id>/refund-checker/versions \
  -H "Authorization: Bearer $WORKHUB_KEY" -H "Content-Type: application/zip" --data-binary @refund-checker.zip
# manifest.yaml
type: skill            # skill 或 agent
name: 退款校验
description: 校验退款规则
scenarios: [退款开发]   # 适用场景,可选
# agent 才有:依赖的 skill 及版本。公共能力只能依赖公共能力
# skills:
#   - {id: public/api-impl, version: 2}

版本发布后不可修改,单包不超过 10 MB。创建者可以废弃(.../versions/{v}/deprecate)或下架(.../versions/{v}/yank,需填原因)。

附录 D:Loop 视图

全局一张,md 文件,开头是 YAML 头:

---
schema: workhub/loop/v1
name: 后端需求交付
entry: design
nodes:
  - id: design                        # 小写字母、数字、_、-;不能叫 done
    name: 接口设计
    agent: public/api-designer        # 默认用最新版;写 @版本号 锁定
    rules:
      - 输出接口文档,评审通过才进入下一步
    next:
      - to: implement
  - id: implement
    name: 编码实现
    agent: public/backend-dev
    next:
      - {to: done, when: 测试通过}                     # done 表示结束
      - {to: implement, when: 测试失败, max_loops: 3}   # 回到前面的节点就是 loop
---

## 说明

(自由文本)

并行:to: [a, b] 表示分叉,a、b 同时开始;各分支最后汇到同一个标了 join: all 的节点,所有分支完成后才开始它。分支里不能再分叉、不能回环、不能直接到 done。执行到分叉时,按视图正文的说明启动并行子任务。

要改进视图:基于最新版修改后发布,base_version 填下载时的版本号;期间有别的端发布了新版本会返回 409(version_conflict),先下载最新版覆盖本地再改。请求体 {"base_version": 3, "content": "<整个 md 文件的内容>", "note": "更新说明"} 用脚本生成:

curl -sX POST https://workhub.qianba.cc/v1/loop -H "Authorization: Bearer $WORKHUB_KEY" \
  -H "Content-Type: application/json; charset=utf-8" --data-binary @"<临时目录>/loop.json"

附录 E:错误

状态码 含义
400 / 422 参数不合法,message 里有原因
401 密钥无效、已删除或已过期
403 不是创建者,或取用别的端的私有凭据
404 不存在
409 仓库已登记(already_registered,带 project_id);Loop 视图或接入要求的版本冲突(version_conflict)
410 已撤销或已下架
429 请求过多
502 中央访问 Git 仓库失败

完整接口文档:https://workhub.qianba.cc/v1/docs

附录 F:维护接入要求

本剧本和首页的《接入一个项目》说明合在一起,是中央的“接入要求”,按版本维护,任何端都能发布新版本:

# 取当前版本的原文:{"version": 3, "guide": "<首页说明 md>", "playbook": "<本剧本 md>", "note": ..., ...}
curl -s https://workhub.qianba.cc/v1/onboarding
# 基于它修改后发布。请求体(用脚本生成):{"base_version": 3, "guide": "...", "playbook": "...", "note": "更新说明"}
curl -sX POST https://workhub.qianba.cc/v1/onboarding -H "Authorization: Bearer $WORKHUB_KEY" \
  -H "Content-Type: application/json; charset=utf-8" --data-binary @"<临时目录>/onboarding.json"

附录 G:维护项目规范

项目规范(standards.md,含对照范本)和 AI 规则块(agents_rules.md)同属一个版本,任何端都能发布新版本,规则与接入要求相同:

curl -s https://workhub.qianba.cc/v1/standards          # 当前版本原文:{"version": 2, "standards": "...", "agents_rules": "...", ...}
# 请求体:{"base_version": 2, "standards": "...", "agents_rules": "...", "note": "更新说明"}
curl -sX POST https://workhub.qianba.cc/v1/standards -H "Authorization: Bearer $WORKHUB_KEY" \
  -H "Content-Type: application/json; charset=utf-8" --data-binary @"<临时目录>/standards.json"

两个文件里可以用占位符 {{ base_url }}、{{ version }};规则块另有 {{ project_id }}、{{ branch }}。

历史版本

首页说明和本剧本同属一个版本,任何端都能发布新版本(见附录 F)。

版本发布者时间更新说明
v1 workhub 2026-10-21 00:20 初始版本