钩子与脚本
一次无需凭据的发布准备会话。它证明的是两个最容易手工写错的契约:生成的钩子包装器,以及框架为编写好的 脚本套上的那层进程外壳。
- 在仓库根目录运行:
pnpm example:hooks - 包名:
@agent-bundle-example/hooks-and-scripts - 公开依赖:
agent-bundle(workspace:*) - Target:
portable、codex、claude - 凭据: 不需要,示例只读取
release/下签入的 JSON - 源码:
examples/hooks-and-scripts
它证明什么
- 钩子是写成处理函数,而不是宿主文档。
src/hooks/session-start.ts调用应用自有的releaseContext函数。构建把这个普通 Node 依赖捆入各宿主包装器,不启动 MCP 服务器或渲染 worker。见 钩子。 - 两种脚本声明方式都在。
verify-release按约定发布,src/scripts/下任何未被声明占用的普通脚本 都会被发现,而detect-risk保持显式配置,因为它要把自己的 target 限制为portable。示例故意让两种 方式都有覆盖。 - 进程外壳属于框架。 两个脚本都导出
main并返回退出码。argv 处理、等待与退出码采纳都归生成的外壳 所有,因此一个非零返回值会变成真正的阻断性退出,而不是被吞掉的返回值。见 脚本与资源。 - 输出的脚本自行解析自己的资源。
assets: ['release/*.json']把发布清单与风险登记表复制一份到产物 根目录的assets/中,由所有 target 共享,而每个输出脚本都相对自己所在的模块去读取它们,而不是相对 shell 的工作目录。 - 失败的重建保留上一个可用产物。 这就是下面那段可逆演练。
编写了什么
在 Workbench 中操作
- 页眉是“当前或已过期”epoch 状态的权威来源。在 Application → Events / Hooks 下选中
sessionStart,选择 Claude 夹具并运行。事件路由工作区会展示规范输入,其中包括"source": "workbench",以及投影后的结果。用它的 Replay 标签重跑绑定到该 epoch 的输入。 - 在 Application → Scripts 下为 Claude target 选中
verify-release并运行。输出的脚本 读取自己模块旁边打包好的release/release-manifest.json,并报告 2.4.0 版本已可打包。 - 把 target 换成 portable 并选择
detect-risk。它读取release/risk-register.json,报告高严重级别的REL-204,以退出码 2 结束,并定稿一条持久的阻断性轨迹。 - 在 Trace 中跟随这些运行,查看每次调用及其内核阶段;已附加宿主实际投递钩子时,其关联收据也会 出现在这里。使用 Open route 恢复已记录的快照。用 Advanced → Raw logs 查看未关联的 生产者细节,用 Advanced → Artifact 查看输出文件与 provenance,并在已有两次 eval 运行之后使用 Advanced → Evals → Compare。
可逆的诊断演练
签入的项目是健康的,所以要看到“上一个可用产物”的行为,就得故意把它弄坏。把
src/hooks/session-start.ts 的函数体临时替换为一个语法不完整的处理函数,按 Rebuild,并等待
Failed 这个已完成状态。从页眉失败计数打开 Problems:Workbench 会报告新的诊断,同时
Application 继续暴露上一个可用的树与产物。恢复签入的处理函数,
再按一次 Rebuild,等到 Idle:一个新的活跃 epoch 会替换过期目录并清除该诊断。
不要把 Building 状态读成修复已完成,新的活跃 epoch 才是证据。
非交互检查
在仓库级 pnpm build 之后:
pnpm check 是同一对“校验加构建”,只用一条命令。想在不打开 Workbench 的情况下检视输出的钩子包装器,
可以用命令行自身的钩子表面: