运行时治理
本页解释 spec-first init 背后的治理模型。它不只是“复制一些文件到项目里”,而是把 source assets、宿主差异、受管状态、预览计划和安全写入组合成一条可审查的 runtime 投递链路。
核心判断是:source 改动发生在 package 仓库,runtime mirrors 由 init 投递,managed state 只记录 spec-first 拥有什么,宿主入口只消费当前投影结果。
运行时资产分层
| 层 | 位置 | 角色 | 典型操作 |
|---|---|---|---|
| Source assets | skills/(含 skill-local references/agents)、templates/、src/cli/ | 行为真相源 | 修改 skill、agent、模板、CLI、contract |
| Projection logic | spec-first init、host adapter、manifest/governance filter | 确定性投影 | 过滤投递对象、改写宿主路径、生成 operation plan |
| Runtime mirrors | .claude/、.codex/、.agents/skills/ | 宿主加载副本 | 由 init 创建、刷新、清理 |
| Control-plane facts | .spec-first/config、.spec-first/workspace、.spec-first/sessions | 本机运行事实 | 由 setup/session/provider 命令维护 |
| Team knowledge | docs/brainstorms、docs/plans、docs/tasks、docs/solutions | 团队长期知识 | 由 workflow 生成并通常提交 |
这几层不能混用。修 workflow 文案、agent 引用或入口行为时,应回到 source assets;runtime mirror 漂移时,先确认 source,再重新 spec-first init。
Init Plan:先预览,再写入
init 的设计重点是 preview-first。它先构造计划,再执行副作用:
input: projectRoot / host / developer / lang
-> build init plan
-> preview next managed state
-> pre-sync old managed assets
-> write runtime mirrors and state
-> apply operation plan计划对象通常包含三类动作:
| 计划段 | 解决的问题 | 不是 |
|---|---|---|
preSyncPlan | 移除过时、退休或命名空间外的受管资产 | 不清理第三方或用户文件 |
writePlan | 写入本轮 runtime mirror、host instruction block、state | 不判断业务需求 |
destructiveResetPlan | legacy state 或 current runtime drift 下做受管硬重置 | 不是删除整个宿主目录 |
这让用户和工具可以在写入前看到将发生什么,也让错误计划在落盘前停止。
Managed State:ownership ledger
state.json 记录的是 spec-first 上一轮管理过的资产集合,不是 runtime 目录完整索引。
| 字段 | 含义 |
|---|---|
manifestVersion | 本轮 source manifest 版本 |
commands | 受管 command-backed workflow 文件 |
skills | 受管 standalone/internal skill mirrors |
workflowSkills | 受管 workflow skill mirrors |
agents | 受管 agent profiles |
agentSupportFiles | agent 支撑文件 |
因此,clean、init 和 drift 修复只应删除 spec-first 拥有的资产。宿主自身文件、第三方 provider 文件和用户手写文件不应因为位于同一 runtime root 就被当作 spec-first 资产。
原子写入与路径安全
Runtime 投递必须先保证文件系统边界:
| 风险 | 防线 |
|---|---|
| 相对路径逃出项目根 | operation target 解析时拒绝 |
| symlink 把 runtime root 指向仓库外 | realpath containment 检查 |
| 单文件写入半成品 | 同目录临时文件写入后 rename |
| destructive reset 中断 | reset 分支使用 runtime backup |
| 旧资产残留 | pre-sync 根据 managed state 清理 |
这不是为了把 init 变成复杂事务系统,而是为了让每个文件副作用都可解释、可限制、可失败退出。
多宿主投递矩阵
Claude Code 与 Codex 的 runtime 拓扑不同,init 不做同构复制。
| 投递面 | Claude Code | Codex |
|---|---|---|
| 命令入口 | .claude/commands/spec 与 .claude/commands/spec-*.md | 由 .agents/skills 承载 spec-* workflow skills |
| Workflow skills | .claude/spec-first/workflows | .agents/skills |
| Standalone skills | .claude/skills | .agents/skills |
| Agents | .claude/agents | .codex/agents |
| Managed state | .claude/spec-first/state.json | .codex/spec-first/state.json |
| Host instruction | CLAUDE.md managed block | AGENTS.md managed block |
Codex 侧还会把共享文本中的 Claude 路径、agent 调度语义和入口名称改写到 Codex 可消费的形态。这个改写属于 adapter 责任,不应由用户手工在 .agents/skills 里批量替换。
Preview 宿主的投影边界
当前 source catalog 还登记了四个显式 opt-in 宿主。它们共享 source assets 和 spec-* workflow 名称,但 runtime 拓扑与验证声明不能与 Claude Code / Codex 混为一谈:
| 宿主 | 主要投影 | 当前边界 |
|---|---|---|
| Cursor | .cursor/skills/、.cursor/agents/、.cursor/spec-first/ | generated_runtime_preview;仅证明生成,不声明完整 loader/user journey |
| Kiro | .kiro/skills/、.kiro/agents/、.kiro/spec-first/、.kiro/settings/ | opt-in preview;IDE 实机 smoke 仍需单独取证 |
| Qoder | .qoder/commands/spec-*.md、.qoder/skills/、.qoder/agents/、.qoder/spec-first/ | opt-in degraded preview;CLI 与 agent 工具能力取决于本机宿主 |
| OpenCode | .opencode/commands/spec-*.md、.opencode/skills/、.opencode/agents/、.opencode/spec-first/ | opt-in preview;宿主发现与完整 user journey 需单独验证 |
因此,init --cursor、init --kiro、init --qoder、init --opencode 的成功只证明对应 projection / contract 层面完成;是否适合生产 workflow,仍以对应宿主的真实 smoke、user journey 和 field evidence 为准。
Developer Profile 与语言策略
init 会使用 developer profile 写入项目级语言与作者信息。常见来源顺序是:
- 显式
--user/--lang - 全局
~/.spec-first/.developer git config user.name
Profile 主要影响两件事:默认生成语言,以及 CHANGELOG.md 这类需要作者字段的变更记录。它不是权限系统,也不是 workflow state。
正确修复路径
| 现象 | 正确处理 | 反模式 |
|---|---|---|
spec-* 文案错 | 修改 source skill / template,重新 init | 手改 generated runtime mirror |
| agent 名称或引用错 | 修改 skill-local skills/**/references/agents/ 或 adapter transform | 在 runtime mirror 里补丁 |
doctor 报 runtime drift | 确认 source 与版本,再 spec-first init | 删除 state 后手工拼 runtime |
| Codex 入口仍带 Claude 路径 | 检查 Codex adapter 与 path rewrite | 批量搜索替换 generated mirror |
| 旧版本资产残留 | 用 init/clean 的受管删除路径 | 手删整个宿主目录导致第三方文件丢失 |
阅读下一步
- 运行模型:从 CLI、runtime mirror、control-plane facts 的角度理解整体拓扑。
- 产物目录与 Git 边界:判断哪些目录应提交、忽略或重建。
- 契约与质量门禁:理解 runtime 治理如何进入 workflow contract、verification 和 release gate。
