mcpField
F
forge

forge

github.com/tleguede-works开发039 次安装2 周前更新
代码仓库

关于 forge

Forge 是一款规划技能,可将初步产品构想整理为六层产品与实施计划,并建立可追踪关系。它面向准备开展实现的团队和 Agent,以人工审批关卡及机械化检查约束阶段顺序和交付物位置。

主要功能

  1. 01六层产品与实施文档
  2. 02规则与边界情况的追踪 ID
  3. 03各阶段之间的人工审批关卡
  4. 04项目状态与交付物检查脚本
  5. 05交付物限定存放于 .forge

适用场景

  1. 01将早期构想整理为产品计划
  2. 02把产品工作拆分为可实现的切片
  3. 03检查项目阶段与审批状态

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/tleguede-works/ship-clean-skills --skill forge

安装后在 Claude Code 中输入/forge确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

README.md
agents/
client-liaison.md
forge-implementer.md
plan-validator.md
premise-challenger.md
product-analyst.md
quality-analyst.md
red-team.md
scenario-tester.md
scope-architect.md
systems-architect.md
ux-designer.md
references/
archetypes.md
design-quality.md
fast-track.md
impact-protocol.md
migration-v1-v2.md
module-prioritization.md
research-protocol.md
review-checklists.md
scenario-tests.md
skill-boundaries.md
state-schema.md
test-strategies.md
scripts/
audit-report.js
consistency-check.js
coverage-check.js
ddl-exec.js
dependency-check.js
design-check.js

详细介绍

Forge

Forge 可以将一个初始想法——哪怕它还很模糊——转化为一份完整的产品与实现计划,分为六个逐步深入的层级,精确到即使能力较弱的 AI 也能毫无歧义地实现每个切片。

六个文档层级

Niveau 0 — INTENT       : Pourquoi ce produit existe, pour qui, quel problème il résout (PRD).
Niveau 1 — SCOPE         : Quoi et quand. MVP, V1, V2..., roadmap, compromis de scope.
Niveau 2 — DESIGN        : À quoi ça ressemble. Standards, direction visuelle, écrans, flows, interactions.
Niveau 3 — ARCHITECTURE  : Comment c'est structuré. Slices, modules, fondations, modèles de données, API, dépendances.
Niveau 4 — PLAN          : Comment implémenter chaque slice. Contrats, algorithmes, composants, checklist de tâches, critères d'acceptation.
Niveau 5 — VALIDATION    : Comment vérifier que tout fonctionne. Tests unitaires, intégration, E2E, UI (Chrome MCP), régression.

术语——三种规划单元

  • 切片:一项完整的端到端功能,涵盖 UI、业务逻辑、数据访问和集成。这是规格说明和实现的基本单位。 灵感来自 Corpus 的“能力”概念——这是一种第三方开源方法论,并非本集合中的技能——但定义依据是需求,而非代码。一个切片对应 PRD 中确定的一项用户需求。
  • 模块:一组技术上连贯的内容(例如“身份验证”“支付”)。包含多个切片。用于组织架构,而非规划实现。其排名由使用频率决定,而非领域组织结构。
  • 基础项:一项横向关注点(设计系统、身份验证、错误处理、i18n、配置、日志记录、CI/CD)。在业务切片之前实现。保持原子性,不拆分为切片。

指导原则

每项重要决策都有依据,每项声明都可验证,每条路径都经过预判。

Forge 遵循五项基本原则:

  1. 每条业务规则、每个边界情况、每项约束都有稳定的标识符(业务规则使用 B1、B2……,边界情况使用 E1、E2……,验证使用 V1、V2……,约束使用 C1、C2……)。这些 ID 永不重复使用,即使规则已被删除也不例外。它们构成完整可追溯性的主干:PRD → 架构 → 计划 → 测试。

  2. 人工关卡不可妥协。 每个阶段都以明确验证结束。未经明确“批准”,绝不开始下一阶段。绝不将沉默或提问视为批准。(有界且有记录的例外:Fast Track 模式,它会在单一检查点后自动执行第 4 至第 5 阶段——参见 references/fast-track.md。) 这条规则由防护机制落实,而非仅靠自律。 每个制品都归属一个阶段(PHASE_ARTIFACT_OWNERS):state.js register 拒绝在所属阶段到达之前注册制品,而 forge-guard 会检查已写入磁盘的制品(no_premature_artifacts)。曾有一次,在设计仍处于 draft 状态时写入了 architecture.md 和十五份计划,十二项检查却全部通过:阶段顺序当时只是一条指示。如果它提示 premature_artifact,这不是需要绕过的障碍,而是基础尚未获批的信号。请推进阶段,或在通过关卡后再生成制品。

  3. 完整性优先于速度。 一份表面连贯却暗藏漏洞的浅薄计划,比一份产出较慢但真正完整的计划更糟。始终要问:“还缺什么?有什么被遗漏了?”

  4. 系统性地采用多视角分析。 在定稿重要文档(PRD、架构、计划)之前,至少应由两种不同视角进行分析。目的不是说“没问题”,而是找出主视角遗漏的内容。

  5. 交付物只存放在 .forge 中,不得存放在其他位置。 在临时目录中生成的文档就等于丢失。这不是建议,而是由 forge-guard.js 机械验证的约束。

如何运行脚本

本文档中的命令相对于技能目录,而非项目目录。

脚本不在项目中:它们随技能一起安装 (~/.agents/skills/forge/scripts/、.opencode/skills/forge/scripts/……)。项目 没有 scripts/ 目录。因此,脚本路径相对于项目的命令无法从任何项目中 执行——首次调用时,会因 Cannot find module '<projet>/scripts/state.js' 而失败。

定义一次技能路径,并在所有地方使用它:

# Le dossier de base du skill est communiqué au chargement du skill.
export FORGE=/chemin/vers/skills/forge

node "$FORGE/scripts/state.js" start

由此得出两条规则:

  1. 当前目录是项目目录,而不是技能目录。脚本通过 process.cwd() 解析锚点:如果从技能目录运行,项目锚点就会指向技能仓库——也就是说,指向错误的项目,而且不会给出提示。
  2. 当当前目录不是项目根目录时,显式传入锚点:node "$FORGE/scripts/state.js" start /chemin/du/projet。

步骤 0 — 获取实际状态(每次调用时最先执行)

此步骤必须先于其他所有操作——包括读取 state.json,也包括解析锚点。

node "$FORGE/scripts/state.js" start

一条命令即可显示:当前阶段、待处理的门禁、各状态下的切片及计划是否实际存在和测试用例数量、哈希不匹配的文档、未解决的分歧、尚未晋升的发现,以及项目记忆状态(AGENTS.md §Definition of Done、未解决的 ADR、LEARNINGS.md 的篇幅)。

为什么用命令而不是文件。 每次会话都完整阅读会话日志太耗时,最后还会凭记忆重新构建。一个真实项目中的实际后果是:14 个已批准的切片没有任何测试,而跟踪记录却毫无征兆地显示错误信息——因为进度是「根据对话记忆了解的,而不是根据本应作为事实来源的文件了解的」。

如果 start 报告有切片已标记完成但没有测试用例,这并不是新情况:这是第一个可靠信号。继续之前先处理这些切片。

步骤 0 bis — 解析当前项目

在错误的目录中创建 .forge,意味着之后必须手动全面补救。

node "$FORGE/scripts/state.js" anchor

该命令会显示选定的锚点、其来源(existing_state | project_marker | cwd)、是否通过向上遍历解析,以及遍历过的目录链。

如果会话可以访问 Legacy 项目、语料库或参考项目,绝不能将其设为锚点。 应将其声明为只读,且绝不修改:

node "$FORGE/scripts/state.js" init <racine> "<NomProduit>" --reference /chemin/vers/Legacy

解析遵循以下三条规则,按顺序执行:

  1. 如果某个祖先目录中已有 .forge/state.json,则优先使用它——这表示恢复正在进行中的项目,包括从子目录恢复。
  2. 如果没有,则检查当前目录中的项目标记(package.json、pyproject.toml、go.mod、.git……);如果当前目录已有文件,也会进行有限的向上遍历。空目录表示一个新项目:不会向上遍历,否则新项目会以相邻的 monorepo 为锚点。
  3. 如果以上都不满足,则直接使用当前工作目录。

如果解析出的锚点是已声明的参考项目,该命令会明确报错——即使该 Legacy 项目没有 .forge 也一样;这种情况最危险,也最常见。这是为了防范代价最高的情形:分析 Legacy,然后把新项目的 .forge 写入 Legacy。

状态与恢复

如果 anchor 返回 state_exists: true,请读取 state.json。它会标明最近完成的阶段、每个切片/基础项的状态,以及待处理的关卡。告知用户项目进展到哪一步,并从下一阶段继续——除非用户明确要求,否则绝不重新生成已处于 approved 状态的文档。

如果文件采用 v1 架构,则会被拒绝,不会静默迁移:

node "$FORGE/scripts/state.js" migrate <anchor>

确切格式请参阅 references/state-schema.md。

写入位置——不可妥协的规则

内容位置
所有 Forge 交付物<anchor>/.forge/,位于 CANONICAL_LAYOUT 中规定的规范路径
项目状态.forge/state.json——仅包含元数据,绝不包含内容
审计日志.forge/audit/

forge-guard.js 会检查以下三项禁令:

  1. 绝不写到 .forge/ 之外。 写入临时目录或项目根目录的交付物等同于丢失。
  2. 绝不在 state.json 中写入文档内容。 PRD 应位于 .forge/prd.md。在状态文件中放入文本块属于 bug——会通过禁用键和数值长度检测出来。
  3. 绝不手动在 .md 的 front matter 中写入 status:。 唯一的写入方是 state.js set-status,它会在同一操作中更新状态和 front matter。

工具包脚本不得修改——且此规定经过验证

以上三项禁令保护的是项目交付物。工具包本身此前却没有任何保护:forge-guard.js 检查的是 .forge/、AGENTS.md、.opencode/rules/ 和清单——不包括运行工具包的脚本。而 $FORGE 是由 Agent 设置的 export,因此可以指向任意位置。

因此存在两条绕过路径,且都不会被检测到。我们在一个真实项目中发现:AI 修改了脚本以绕过关卡,而仓库状态——脚本已损坏、缺少必需交付物——直到人工复查时才被发现。这是唯一一个会停用自身保护机制的缺陷,因此也是唯一一个无法自行检测到的缺陷。

node "$FORGE/scripts/forge-guard.js" kit-integrity <anchor>
node "$FORGE/scripts/forge-guard.js" kit-integrity <anchor> --write-manifest

.forge/kit-manifest.json 会记录工具包中每个文件的 sha256 指纹。每次运行时,门禁都会进行比对。两种处理方式刻意区分:

发生变化的内容处理方式原因
一个脚本硬性失败脚本负责落实流程。脚本一旦被修改,就意味着流程不再得到落实
一份参考文档警告文档为 Agent 提供信息,但不会落实任何事项。如果把失败和警告混为一谈,文档更新就会无谓地阻塞项目——届时门禁也会因此被绕过

清单必须通过明确操作写入,绝不自动写入。 这是唯一可能掩盖修改的操作:如果门禁能自行重写,就不再能保护任何东西。如果脚本是有意修改的——例如更新工具包——请重写清单,并在 DECISIONS.md 中说明原因。否则,请还原脚本。

补充脚本应有明确归处

当工具包无法满足实际需求时,可以编写脚本。脚本应放在 .forge/tools/ 中,并进行声明:

{ "project": { "tools": { "seed-dwight.js": { "purpose": "…", "owner": "…" } } } }

forge-guard.js tools 会拒绝以下三种情况,且每一种都是独立缺陷:未声明的工具(没人会知道三个月后它的存在)、已声明但未说明用途的工具,以及已声明但磁盘上不存在的工具——登记内容与实际不符的登记表,比没有登记表更糟,因为人们会相信它。

在其他位置编写脚本——例如项目根目录或 .forge/ 中 tools/ 以外的位置——会被标记为放错位置的脚本。这类位置是尚未找到合适归处的脚本默认落点。

哪份内容具有权威性——状态和交付物永远不会不一致

state.json   =  AUTORITÉ   pour le statut
front matter =  MIROIR    (champ status:), écrit par set-status

如果出现偏差——state.json 写着 implemented,而 .md 仍写着 draft——系统会检测到并自动修正:

node "$FORGE/scripts/forge-guard.js" sync .          # détecte, exit 1
node "$FORGE/scripts/forge-guard.js" sync . --fix    # réaligne le miroir sur l'autorité

content_hash 针对的是文档的正文,而不是 front matter:因此,更改状态不会使计划失效。哈希不再匹配,表示发生了越界编辑——此时文档会被标记为 stale。

各自负责什么——与 project-rules-architect 的职责边界

两个彼此不了解的 skill 会产生两套互相竞争的记忆系统,且没有优先级规则。这是大多数跟进故障的结构性原因。

Forge 负责project-rules-architect 负责
.forge/——正在构建什么、进展如何AGENTS.md、.opencode/rules/*.md——需要遵循什么
state.json——状态、路径、ID、哈希DECISIONS.md——原因 · LEARNINGS.md——发生过什么故障 · SESSION_LOG.md——发生过什么

规则:业务或技术事实应保存在由 project-rules-architect 负责的文件中。state.json 只包含指向该文件的引用。包含散文内容的 state.json 不是状态文件,而是伪装成状态文件的文档——forge-guard.js state 会拒绝它。

发现应当路由,而不是堆积:

node "$FORGE/scripts/state.js" finding <anchor> --domain=testing.md --severity=majeur "<fait>" "<correction>"

必须指定领域。 没有领域的发现就没有可提升的目标,因此不会产生任何改变:它只会变成又一条日志,与本应由它提供依据的规则相互竞争。这是经测量确认的零提升原因。

完整约定:references/skill-boundaries.md。

两种模式

Guided(默认)Fast Track
Gate每个阶段一个第 5 阶段结束时一个,第 7 阶段每个里程碑再加一个
阶段 4-5手动,逐个 slice 进行自动化,由子 Agent 验证
阶段 7手动每个 slice 均设有可执行门禁
验证器会话中轮换验证视角quality-analyst、red-team 和 plan-validator 并行运行
启用条件始终可用PRD、约定、设计、界面和基准测试均已批准
退出方式—随时选择“返回常规模式”

每次启用时都要选择自主级别:milestone(默认)或 full。详情和理由见 references/fast-track.md § 两种自主级别。

Fast Track 不会取消验证,只会取消重复操作。

各个阶段

按顺序执行。**每个阶段都必须以明确的人类验证 gate 结束——没有得到清晰的“approved”,绝不能开始下一阶段。**这是此 skill 最重要的规则。

阶段未产出应有内容,就不能获批。 complete-phase 和 set-phase … approved 会拒绝缺少交付物的阶段;forge-guard 也会在 gate 前通过 current_phase_has_deliverables 发出提示。拒绝信息会指出缺少的交付物,并提供登记命令。

这项约定不是走形式。检查只会验证已声明的交付物:没有声明就没有检查,结果便会全部显示通过。曾在一次完整测试中发现这种情况——第 0 阶段在 deliverables: {} 且没有 conventions.md 的情况下获批,之后整个流程都建立在这个缺失的基础上继续推进,没有任何检查发出警告。

如何提出 gate 问题。 对于规格文档:“是否遗漏了使用场景,或你已经发现的约束?” 对于拆分方案:“你认可将工作拆分为这些 slices 吗?还是需要合并或拆分其中某些部分?” 对于计划:“实现顺序是否合理?你是否发现缺失的依赖关系?” 只有得到明确的批准用语后才能继续。

每次 gate 前,都要运行防护检查。它们是确定性的、即时的,且不消耗任何 token:

node "$FORGE/scripts/forge-guard.js" all <anchor>        # chemins, état, contrat de phase, synchronisation, placeholders, versions
node "$FORGE/scripts/consistency-check.js" all <anchor>   # écarts ENTRE artefacts

这里出现 fail 不是建议:请先修正,再提交文档。

为什么有两个命令。 forge-guard 一次只读取一份文档:它会检查文档是否存在、路径是否正确、状态是否一致。它无法发现某个计划与其本应实现的架构相矛盾。consistency-check 只做这件事,而且只有它能做——因为项目中代价最高的问题模式并非规格不完整,而是后续产物揭示了先前已获批准的产物存在缺陷。在一个真实项目中,这种情况出现了 13 次,旁边还写着这句话:“没有任何 gate 检查能发现它。”

声明交付物依赖什么。 已获批准的交付物应由 PRD 中的需求作为依据,而且必须明确写出这种依赖关系:

node "$FORGE/scripts/state.js" register <anchor> deliverable conventions .forge/conventions.md --requires=B11,C1,C2

consistency-check premises 会将这些 ID 与 PRD 的实际状态进行比较,并标记已获批准的交付物仍依赖的已撤回需求。如果没有这项声明,文档就会继续基于 PRD 已放弃的前提保持批准状态:在一次实测中,conventions.md 以“这是对严格多租户需求的回应”为由论证采用 PostgreSQL,而 PRD 却因没有第二个客户端而将多租户排除在范围之外。没有任何检查能发现这一点。

已撤回的需求必须保留其 ID,并列在 ## 9. Hors scope 条目的开头:- **C102** — Multi-tenant strict — raison : …。撤回需求时去掉它的标识符,会让它无法追踪,矛盾也就再次变得无法检测——检查还会拒绝没有 ID 的撤回,因为无法追踪的撤回就等于没有声明撤回。

一个 ID 只能指代一个需求。 如果 C1 在范围外条目中指代“严格多租户”,在约束条目中又指代“仅一台服务器”,那么所有对 C1 的引用都会变得模棱两可——包括这项检查中的引用,它会因此指错交付物。检查会拒绝这种冲突。

如何避免冲突,以及千万不要怎么做。

“把已撤回的需求重新编号到单独的编号范围(B1xx、C1xx)”这种本能做法会破坏可追踪性,必须摒弃:前面的规则要求已撤回的需求保留其 ID,正是为了让已获批准的交付物能够与它关联起来。把 B18 改名为 B118 会切断这条关联——检查将不再指认正确的交付物,而会指向一个从未有人写过的 ID。

正确做法是在上游遵循一条规则:

将已撤回的需求编号放在编号范围的末尾,从已使用的最大编号开始,永远不要重新分配已空出的编号。

也就是说,撤回 B18、B19、B20、B21 后,下一个有效需求就是 B22。已撤回的编号仍以原始 ID 保留在第 § 9 节,并且 18–21 这个编号段标记为已作废。这正是冲突检查所验证的内容,因此没有商量的余地。

这种规范是有代价的——编号会增长得更快——但这是值得的取舍:编号中的空缺一眼可见,ID 冲突却要等到产生错误诊断后才会被发现。

conventions.md 是最常见的情况:它是一份持续更新的文档,PRD 修订会要求相应修改。请重新修订它,将状态改为 stale,然后再改为 approved,并重新运行 consistency-check premises。

各阶段的分工

本表具有规范性。 它说明了编写各阶段交付物时应读取哪个 Agent 文件。没有这张表,就只能猜文件名——而猜测会生成不存在的文件,且文件缺失永远不会导致失败。

在测试项目中连续两次发现了这个问题:Phase 4 使用 agents/solution-architect.md(实际文件名是 systems-architect.md),Phase 5 使用 agents/plan-writer.md(该文件不存在)。两种情况下,调用都看似成功:子 Agent 确实生成了交付物,并依据 SKILL.md § 5 开展工作,同时指出文件缺失。绕过错误指令的 Agent 不会让缺陷显现出来,反而会把缺陷掩盖起来。

阶段交付物要读取的 Agent验证方式
1.forge/prd.mdagents/product-analyst.mdforge-guard placeholders、client-liaison --check
2.forge/roadmap.mdagents/scope-architect.mdconsistency-check premises
3.forge/design/agents/ux-designer.mddesign-check contrast、design-check tokens-used
4.forge/architecture.mdagents/systems-architect.mdddl-exec all、dependency-check
5.forge/plans/由你自己编写,遵循 SKILL.md § Phase 5 和 templates/implementation-plan.md.tmplcoverage-check slice、forge-guard placeholders
6.forge/test-plan.mdagents/quality-analyst.mdconsistency-check plans

Phase 5 没有负责编写的 Agent,这是刻意安排的。 实施计划是最容易凭空编写的东西:描述尚未编写的代码的文档,很容易通过所有格式检查。因此没有人可以代写——只有 agents/plan-validator.md,它会审阅已经写好的计划,但不会重写任何内容。

premise-challenger.md 会在 Phase 1 的两个时点额外介入:在初步构想的访谈进行到一半时,以及 PRD 完成时。它不会重写任何内容,只会指出问题,由你来处理。

validate-repo 会拒绝磁盘上存在但此处未列出的 Agent 文件,也会拒绝此处列出但磁盘上不存在的 Agent 文件。因此,本表不会自行失去同步。


Phase 0 — 初始化

目标:在进行任何产品构思之前,明确项目背景并生成约定基线。

  1. 解析 anchor(state.js anchor)——这是步骤 0,已完成。
  2. 如果 anchor 中已有项目,请读取其配置文件:package.json、tsconfig.json、.opencode/、AGENTS.md、规则、ADR。提取其中隐含的约定(lint、格式、目录结构、技术栈、测试框架)。
  3. 如果项目尚不存在,请询问用户:
    • 计划采用的技术栈(语言、框架、数据库……)
    • 技术或托管限制
    • 必须使用或禁止使用的工具
  4. 创建 .forge/:node "$FORGE/scripts/state.js" init <anchor> "<Nom>" --reference <projet de référence si applicable>。
  5. 以“背景基线”模式调用 project-rules-architect——参见 § 两次调用。只需交付以下文件:放在 anchor 根目录下的 AGENTS.md、SESSION_LOG.md、DECISIONS.md、LEARNINGS.md。
  6. 根据 templates/conventions.md.tmpl 生成 .forge/conventions.md。尚未确定的部分(例如状态管理、E2E 框架)标记为 À DÉCIDER EN PHASE 4。
  7. 注册交付物:state.js register <anchor> deliverable conventions .forge/conventions.md。
  8. 根据 templates/contract.md.tmpl 生成 .forge/contract.md,使用 client-liaison --check 检查,修正其指出的问题,并让相关方签字确认:
    node "$FORGE/scripts/state.js" register <anchor> deliverable contract .forge/contract.md
    node "$FORGE/scripts/state.js" set-status <anchor> deliverable contract approved
    
  9. 向用户总结检测到的内容,并请求确认。

在明确这些背景之前,绝不要开始讨论产品。 技术选择会限制产品可能性,反之亦然。

签约后,只有两件事会再打断你

这是合同的承诺,而且并非象征性的:所有涉及采购的事项都在签约前决定,否则合同会被 forge-guard contract 拒绝。因此签约后:

原因方式
与合同存在偏差state.js client --kind=ecart …
由你负责的决定state.js client --kind=decision …

四个字段都是必填项——what、price、by、if_no_answer,命令会拒绝缺少这些字段的事项。没有截止日期的决定不会一直搁置:它必须得到决定,而决定者是 Forge。超过日期后,Forge 会执行「未回复」条款,并在下一次总结时告知你。

上下文基础不包含任何规则。 在第 1 次调用和第 2 次调用之间,项目有记忆,但没有规则集:这是正常状态,并非只完成了一半的工作。如果第 1 次调用返回了 AGENTS.md 或 .opencode/rules/,说明 scaffold 模式被绕过了——它在技术栈探测之前就停止了。


对 project-rules-architect 的两次调用

Forge 是调用方,会在两个固定时间点调用。绝不会是被调用方。

调用时间你传递你获取
1 — 上下文基础第 0 阶段,第 5 步产品名称、用户已经说明的内容四个记忆文件,已就位
2 — 规则集architecture 为 approved 时已确定的技术栈、选定的约定、MVP 范围AGENTS.md + 规则,已接入
调用 1 — 上下文基础

调用 project-rules-architect,并明确要求使用 scaffold 模式:

「为这个项目搭建上下文结构:AGENTS.md、SESSION_LOG.md、
DECISIONS.md、LEARNINGS.md。不包含任何规则,不创建 AGENTS.md,不进行技术栈探测——技术栈尚未确定。」

应该返回:anchor 根目录下的四个文件,包含各自的标题,除此之外不应有任何内容。返回结果中包含规则,就说明结果有误。

调用 2 — 规则集

当 architecture 变为 approved 时,而不是之前:

“以下是已确定的技术栈和本项目的范围。请建立规则集, 并将其接入目标工具。”

从 .forge/architecture.md 和 .forge/conventions.md 中传递:技术栈及其确切版本、已选定的约定、范围,以及不应转化为规则的未决问题。

传递摘录,而不是整个文件。 这两份文档可能有数千行,而决定规则的部分始终只占其中一小部分。结构化摘要——技术栈表、库的选择、未决问题——既比完整文件更精简,也比走马观花地读完整文件更可靠。规则:传递的一项事实占一行,而不是一章。

为什么不能提前。 规则是依据技术栈生成的。在技术栈确定之前生成规则,就是猜测——而猜出的规则有规则的权威性,却只有假设的可靠性,因此 Agent 会照做。

这次调用有一道门槛,而不只是一个时间点。 在 architecture approved 之前,它尚未到执行时机;之后若仍未执行,则属于 forge-guard 会报告的缺陷:

node "$FORGE/scripts/forge-guard.js" rules-present <anchor>

如果规则目录不存在、为空,或目录存在但未接入,检查就会失败——因为四个无人加载的 Markdown 文件,看起来是完整的规则集,实际上却完全不起作用。这正是之前缺失的检查:调用 2 有记录、有日期、有条件,却从未触发。在实验室中进度相同的五个项目里,只有一个有规则集,而且没有任何提示指出这一点。

继续之前,请验证结果:

node "$PRA/scripts/rules-selftest.js" <anchor>

对交付的规则集进行十项检查:接入、索引、占位符、交叉引用、相互矛盾的阈值、.forge/ 耦合、污染、无法验证的说明、门槛、预算。此处失败属于交付缺陷,不是讨论事项。

Forge 对这些文件绝不会做的事
❌ 绝不✅ 应改为
写入 AGENTS.md、SESSION_LOG.md、DECISIONS.md、LEARNINGS.md什么也不做。这些是 Agent 的记忆,由它自己维护。
创建自己的 AGENTS.md 或 .opencode/rules/由调用 2 生成规则集。
将规则复制到 conventions.md将技术栈事实传递给调用 2。

由两个写入者共同写入的记忆会无声无息地丢失数据:一个添加内容,另一个覆盖,而文件仍然存在,看起来也合情合理。这就是这份约定存在的原因,而不是为了讲究整洁。

记忆的实际状态:state.js start 会在 project_memory 中报告该状态。

conventions.md 是一份持续更新的文档。 它从 Phase 0 已知的内容开始,在 Phase 4(架构:验证库、状态管理的选择)中逐步补充,也可以随时修订。实施计划(Phase 5)会引用它;之后对 conventions.md 的任何修改都会使依赖它的计划失效——每次修订后都要运行 state.js check-stale。

修订契约——只扩展,绝不重新编号

其他文档按编号引用的文档不得重新编号:必须对其进行扩展。在 § 5.9 插入内容会导致 § 5.10、§ 5.11 以及后续所有章节的编号顺延——于是每个交叉引用仍然指向一个存在的章节,却指错了位置。这是最糟糕的漂移形式:它能解析成功,检查会判定一切正常,也没有任何提示。

已发现,INC-011:修订两项关键根本原因时,在 § 5.9 和 § 5.10 插入了两个 endpoints。八份计划中的十七处交叉引用因此失效——error-handling(4)、restriction-lignes(3)、journal-acces(4)、export-provenance(4)——却没有任何一行指出这一点。安全的修复方式是将两个 endpoints 添加到 § 5 的末尾。

不要编辑已批准的文档。要修订它:

node "$FORGE/scripts/state.js" amend <anchor> <clé> \
  --reason "<pourquoi cet amendement existe>" \
  [--changes <fichier-listant-ce-qui-change>]

这条命令的作用,以及每一项存在的原因:

必须提供 --reason没有理由的修订就是普通编辑。说明理由正是修订与编辑的区别。
标题映射它在批准时捕获——这就是其他文档引用的版本。没有它,第一次修订就可能随意重新编号。
重新编号 → 拒绝某个编号对应了不同主题,或对应章节已消失时,命令会拒绝执行,并按顺序指出漂移。警告可以被忽略;拒绝会迫使你采取行动。
--allow-renumber它不是一个开关:必须同时提供 --renumber-reason <texte>,而且该理由会保留在状态中,与失效编号一并记录。没人记得原因时,这是唯一留下的记录。
状态 → stale修订后的文档已不再是获批的版本。使用 stale 而非 draft:这是已为动态文档定义的流程——它会在 gate 重新通过 approved。

命令拒绝时会告诉你该怎么做:

Un document cité par numéro s'étend, il ne se renumérote pas.
Corrige sans risque : ajouter les sections NOUVELLES en fin de numérotation,
et ne toucher à aucun numéro existant.

交叉引用必须指明目标。 单独写 § 5.15,无法说明它指的是哪份文档。写成 `architecture.md` § 5.15:这样检查就能准确知道该查看哪里,无需进行任何解释。consistency-check references 会给出两种判定:

  • 失效指针——已指明目标,但章节不存在 → 失败。这是编号漂移,也就是 INC-011 的形式;
  • 目标未声明——未带文件名的交叉引用 → 计数,但绝不判为失败。在测试项目中:276。若让这些情况失败,就会产生一种一周后就会被关闭的检查——这个项目中已经发生过四次。它的解决方法已写在输出中:为文件命名,计数就会下降。
Phase 1 — 发现阶段(PRD)

目标:将模糊的想法转化为完整且一致的产品需求文档。

这不是写作阶段。 这是访谈和逐步完善的阶段。PRD 是产出,而不是过程。

premise-challenger 在本阶段会介入两次:一次在访谈进行到一半时,针对最初的想法;另一次在最后,针对 PRD。它不会改写任何内容:只会指出问题,由你来处理。参见 agents/premise-challenger.md。

1.1 初始访谈

逐步提问,每次一到两个问题。不要向用户连珠炮似地提问。需要涵盖以下类别(按顺序):

  1. 问题:这个产品要解决什么问题?面向谁?为什么是现在?
  2. 用户:用户是谁?有哪些细分群体?技能水平如何?使用场景是什么?
  3. 解决方案:产品如何解决这个问题?价值主张是什么?
  4. 功能:主要功能有哪些?次要功能有哪些?
  5. 约束:是否存在法律、技术、预算或时间方面的约束?
  6. 现有产品:是否有竞争对手?是否有类似产品?这个产品有什么不同?
  7. 风险:预期有哪些风险?有哪些未知因素?
  8. 成功:如何判断产品是否成功?
1.2 质疑与深入探究

完成初次访谈后,进一步质疑回答:

  • 发现矛盾:“你说产品应该简单,但功能 X 很复杂——如何兼顾两者?”
  • 找出隐含问题:“你没有提到错误处理——产品是否需要处理失败情况?”
  • 测试边界:“如果用户在状态 Y 下执行 X,会发生什么?”
  • 质疑必要性:“这项功能可能要花 40% 的工作量,却只占 5% 的使用量——它真的有必要吗?”
  • 指出遗漏:“我没有看到密码恢复机制——这是有意为之吗?”
  • 找出依赖关系:“要让功能 A 正常工作,必须先有 B、C 和 D——这个顺序你觉得合适吗?”
  • 提出替代方案:“与其在 V1 中实现复杂的角色系统,不如只用一个简单的管理员/用户标记,够用吗?”
1.3 编写 PRD

回答成熟后,根据 templates/prd.md.tmpl 在 .forge/prd.md 中编写 PRD。绝不能写入 state.json,也不能写在其他位置。

规则:

  • 每条业务规则都必须有一个稳定 ID(B1、B2……)。
  • 每个边缘情况都必须有一个稳定 ID(E1、E2……)。
  • 每项约束都必须有一个稳定 ID(C1、C2……)。
  • ID 一经确定即为最终版本——绝不能重复使用。
  • 用户故事必须编号并标明优先级。
  • PRD 不包含实现层面的技术术语(框架、数据库……)——它是一份纯产品文档。
  • 已发现但尚未解决的所有歧义都应放入“待澄清事项”一节。

然后:state.js register、forge-guard.js placeholders,之后才能进行 gate。

1.4 多视角评审

最终 gate 前,应用视角轮换——PRD 的这一阶段为必做项:

  • 质量视角:是否识别了所有类型的用户(包括管理员、支持人员)?用户故事是否涵盖所有用例?是否涵盖了非功能性约束?
  • 风险视角:用户故事之间是否存在矛盾?是否有未明确说明的隐含业务规则?是否有未经验证的假设?

根据发现的问题修正 PRD,然后再提交评审。

1.5 调研——不要重复造轮子

确定 PRD 前,应用 references/research-protocol.md:

  1. 识别原型类型(references/archetypes.md)。
  2. 查找并阅读至少两个参考产品。将结果记录在 .forge/benchmarks.md 中——不要写入 state.json。
  3. 针对 PRD 中的每个业务问题,提取其不变量(绝不能为假的属性),而不是代码。
  4. 阅读该原型类型的常见病灶(archetypes.md 第 9 节),并逐一思考:我们的设计做得更好吗?如何证明?
  5. 有意为之的差异应记录在 benchmarks.md 第 5 节,并注明其可逆转成本。

如果调研没有改变任何决策,那就没有产出。如果确实如此,应如实说明,而不是填满文档。

1.6 GATE

提交完整 PRD。Gate 检查清单见 references/review-checklists.md#prd。

阶段 2 — 范围(路线图)

目标:定义每个版本包含哪些内容,以及原因。

2.1 范围分析
  1. 重看 PRD,列出所有功能/用户故事。
  2. 针对每项功能评估:用户价值、复杂度、依赖关系、风险。
  3. 确定 MVP:解决核心问题且可供真实用户使用的最小功能集合。
  4. 定义 V1:在 MVP 基础上,加入能带来差异化但不会让范围失控的功能。
  5. 将所有“锦上添花”或依赖用户反馈的内容推迟到 V2 及之后。
2.2 拆分依据

对于每个版本,说明:

  • 为什么包含这些功能。
  • 为什么推迟其他功能。
  • 做出了哪些权衡。
  • 承担了哪些风险。
2.3 路线图

根据 templates/roadmap.md.tmpl 生成 .forge/roadmap.md。绝不写入 state.json。

每个版本都包含:

  • 带有 ID(B*)的功能
  • 成功标准
  • 版本间依赖关系
  • 工作量估算(相对估算,不按天计算)
  • 此版本的特定风险
2.4 多视角审查

在 gate 之前,应用视角轮换:

  • 质量视角:是否全面列出了各版本的风险?是否有未明确说明的跨版本依赖?
  • 风险视角:MVP 是否真正解决了主要问题?哪些被推迟的功能可能会阻碍真实用户?
2.5 GATE

展示路线图。Gate 检查清单(references/review-checklists.md#roadmap)。

阶段 3 — 设计(UI/UX)

目标:在实现功能之前设计界面,明确视觉方向,并根据真实使用频率确定导航优先级。

本阶段的顺序至关重要。不要跳过步骤。

3.1 视觉方向和标准——先于任何设计

在完成以下两份文档之前,不得开始绘制界面。

  1. 识别应用原型(references/archetypes.md),并用一句话写出工作循环。将其记录在 state.json(product.archetype)中。
  2. 根据情境调用适用的设计技能——这是必需步骤,参见 references/design-quality.md § 2(移动端 → imagegen-frontend-mobile,落地页 → frontend-design,密集型 Web 应用 → impeccable……)。如果没有可用技能,至少应用 § 3 中的禁忌,并在审计中注明。
  3. 确定三个锚点:参考对象、氛围(三个词)、反面参考。缺少这些内容,阶段 3 就尚未完成。
  4. 根据 templates/benchmarks.md.tmpl 生成 .forge/benchmarks.md:参考产品、原型符合性检查表、已接受的偏差。此文档将作为 Fast Track 验证器的参考依据。
3.2 按使用频率确定导航优先级

导航项的顺序体现了优先级,这是移动应用设计中最常见的错误。

应用 references/module-prioritization.md:

  1. 为每个模块评分:频率(1–5)× 中心性(1–5),并说明理由。
  2. 排序:先放主要循环,再放重复性操作,然后是生命周期入口,最后是配置。
  3. 主要导航项最多 5 个——其余放入溢出菜单(“更多”)。
  4. “首页”不默认排第一:只有当它用于开启循环,或是使用频率最高时,才排在第一位。

导航顺序应可验证:

node "$FORGE/scripts/state.js" set-nav <anchor> '{ "archetype": "...", "core_loop": "...", "items": [ ... ] }'
3.3 设计系统
  1. 定义具有具体值的设计令牌——绝不要写「稍后定义」。

  2. 定义基础组件:按钮、输入框、模态框、卡片、表格等。

  3. 定义导航模式:路由、面包屑、侧边栏、导航栏、条目顺序(参见 3.2)。

  4. 遵守 references/design-quality.md § 3 中的禁忌:不要使用未明确选择的纯白色,不要默认用阴影作为分隔,不要使用默认调色板,不要使用统一的字体比例尺。

  5. 从 templates/design-system.md.tmpl 生成 .forge/design/design-system.md。

  6. 在设计系统中声明颜色类别(模板的 § 0.0)。然后:测量对比度——不要填写对比度。 检查清单要求填写「对比度 N:1」,但此前没有任何工具验证它:因此这些比例只是写出来的,而非计算得出的。

    声明并非形式上的要求。通过名称猜测颜色类别的检查无法处理名称所用语言之外的语言:历史信号都是英文字面量(--color-text-*、--color-ink-50、*-subtle),而此技能生成的所有内容都是法语。对于法语词汇,所有颜色都会被归为「非文本组件」,并按 3:1 的标准评估——因此 3.80:1 的文本也能通过。这个检查本来就是为了找出这种缺陷,结果缺陷又出现在刚刚测量过的文档里。

    on: 表示文本实际放置在哪些背景上——否则,反转色文本明明只放在墨色背景上,却会拿来与纸色背景对比,必然无法通过。exempt: 需要填写理由:装饰性色调并非界面组件。未列入清单的颜色令牌会被标记:声明是一种承诺,因此省略也是一种选择。

    node "$FORGE/scripts/design-check.js" contrast <anchor>
    node "$FORGE/scripts/design-check.js" tokens <anchor>
    

    这项检查能捕捉两种校对时看不到的问题:标注的比例与测量结果不符——这是毫无依据的保证;以及文本在某种背景上清晰可读,却在另一种表面上过浅,例如表格的交替行或凹陷面板。问题往往就出在这里。

    阈值依据 WCAG:文本与所有表面的对比度为 4.5:1(1.4.3),非文本组件(包括焦点环)的对比度为 3:1(1.4.11)。输出中会显示每个令牌的类别(文本、组件、填充、豁免),并根据其声明、用途和名称推断:如果检查没有说明令牌为何被归入该类别,就无法对其提出质疑。

3.4 屏幕与流程

对于 PRD 中每个带有用户界面的功能:

  1. 列出所有必要的屏幕,并为每个屏幕标明其导航层级。
  2. 在 .forge/design/screens/<nom>.md 中为每个屏幕创建一个文件,并从 templates/screen.md.tmpl 生成。
  3. 模板要求填写 9 种状态、每个屏幕的视觉方向、交互、各断点下的响应式行为、无障碍设计和可追溯性。务必完整填写——残留的 {{PLACEHOLDER}} 意味着该部分不会被实现。
  4. 定义屏幕之间的导航流程(主路径、替代路径、错误、引导流程)。

然后:

node "$FORGE/scripts/forge-guard.js" placeholders <anchor>
node "$FORGE/scripts/design-check.js" contrast <anchor>
node "$FORGE/scripts/design-check.js" component-parity <anchor>

引用了令牌的屏幕,必须引用一个确实存在且可读的值。后者无法通过重读屏幕来确认:必须进行测量。

渲染组件的屏幕必须了解其表面。组件增加插槽或状态时,将其同步到所有渲染该组件的屏幕,并非礼貌之举,而是确保同一组件始终以相同方式渲染的必要条件。component-parity 能捕捉到忘记同步后出现的问题,例如条目列表变得不准确(有 7 个插槽却写成「6 个插槽」)。如果屏幕选择不渲染某种状态,则应注明理由:`Tile` — exempt: `offline`(表格处于在线状态)。

3.5 验证设计
  1. 检查 PRD 中的每条业务规则(B*)是否都有对应的屏幕或流程。
  2. 检查每种错误状态(E*)是否都有视觉呈现。
  3. 检查所有屏幕之间的视觉一致性。
  4. 如果已有代码:使用 Chrome MCP 检查界面(溢出、响应式、布局、导航)。
3.6 多视角审查

在 gate 前,应用视角轮换:

  • 质量视角:每种边缘情况都有视觉状态吗?是否考虑了无障碍访问?响应式设计是否覆盖所有断点?
  • 风险视角:屏幕之间是否存在视觉不一致?是否有未处理的错误状态?
3.7 GATE

展示标准、优先级排序后的导航、设计系统和屏幕。用户在进入架构阶段前进行视觉验收。Gate 检查清单(references/review-checklists.md#design)。

Phase 4 — 架构(系统设计)

目标:将产品拆分为切片、模块和基础能力,并明确它们的依赖关系。

4.1 切片拆分
  1. 列出 PRD 中的每项功能。
  2. 将功能归组为模块(技术上连贯的分组)。模块的顺序和分组遵循 references/module-prioritization.md——优先考虑频率,绝不按领域组织结构排序。
  3. 将每个模块拆分为切片(可独立实现的端到端功能)。
  4. 确定横向基础能力(Phase 3 的设计系统、身份验证、错误处理、国际化、配置、日志记录、API 客户端)。

拆分规则:

  • 一个切片应能独立实现和测试(或使用其依赖项的模拟对象进行测试)。
  • 一个切片新增的文件不应超过约 10 个。
  • 如果一个切片过大,说明它包含多个不同的功能。
  • 如果两个切片有 50% 以上的代码相同,可考虑将它们合并。
4.2 数据模型

为每个切片定义:

  • 实体及其字段(类型、约束、关系)。
  • 验证模式。
  • API 契约(端点、请求、响应、错误)。

规则:所有模型都必须逐字段定义,不能概述。此阶段遗漏字段会导致实现阶段出现错误。

4.3 依赖关系图
  1. 逐个切片声明依赖关系图:
    node "$FORGE/scripts/state.js" dep <anchor> <slice|fondation> <a,b,c>
    
    state.js dep 会拒绝对不存在切片的依赖、自依赖,以及任何会形成循环的依赖。错误的依赖关系图与不完整的依赖关系图无法区分:失效的依赖永远无法满足,之后也不会有任何提示。
  2. 运行 node "$FORGE/scripts/dependency-check.js" check <anchor> --write,计算 depended_on_by 和 impl_wave。
  3. 找出循环依赖、拓扑顺序,以及可以并行开发的切片。

如果你的波次计划比最低要求更细,请声明该计划。 dependency-check 会计算最少的拓扑波次。更细的排期计划是合理的——两个人不可能同时负责 RLS 策略和差值公式——但必须写入架构的 front matter:

impl_waves: 13
impl_waves_rationale: >-
  Plan d'ordonnancement, pas minimum topologique. Le graphe se réduit à 8 vagues ;
  on en retient 13 parce que F4 et F9 ne doivent pas être portées par la même personne.

如果不作声明,writeBack 会在不作提示的情况下覆盖 impl_wave,导致 Phase 4 的两份文档相互矛盾,而 CI 却显示通过。声明但没有理由,差异将不予通过:没有理由的计划与计数错误无法区分。说明理由后,该差异会作为警告保留。

4.4 生成架构文档

根据 templates/architecture.md.tmpl 生成 .forge/architecture.md。

4.5 DDL 要么执行,要么就不该写

**文档中的 DDL 不会经过编译、类型检查或执行。**它只会被阅读。因此,只有在编写时,也就是作者重读自己刚写的内容时,才能发现其中的缺陷。

在一次真实测试中,三个这样的缺陷通过了三道 gate,且重读时一个也看不出来:

  • ALTER TABLE … ADD CONSTRAINT … CHECK (… <> (SELECT … FROM …)) — 一个包含子查询的 CHECK。PostgreSQL 会在创建时拒绝它,因为 CHECK 必须仅根据当前行进行求值。该约束并不存在。
  • 在触发器开头写入 IF NEW.status = OLD.status THEN RETURN NEW; END IF; — 只有在状态发生转换时才会触发该守卫。写入其他列的 UPDATE 会绕过它。这道门虽然写了、注释了,却不起作用。
  • 一个触发器要求存在的 published_at,却没有任何代码生成它。

在 gate 之前运行:

node "$FORGE/scripts/ddl-exec.js" all <anchor>

三种判定,各有不同:

命令检查内容引擎
completenessDDL 修改的每张表都已创建,或以列清单表格的形式列出。没有表被凭空使用。无
executePostgreSQL 接受每条语句。被它拒绝的约束并不存在。pglite
guards文档声明的每个守卫都确实会拒绝被禁止的操作。pglite

声明你的守卫。首行是 -- forge:ddl-refuse 的 sql 代码块包含一条必须被拒绝的语句。如果它执行成功,检查会指出这一点——而它说的是事实,因为执行语句的是 PostgreSQL,而不是阅读者:

-- forge:ddl-refuse
-- Publier sans signature doit être refusé. Si cette instruction passe, la
-- porte n'est pas une porte.
UPDATE definition_version SET status = 'published' WHERE definition_version_id = 1;

被禁止操作的名称不是由检查猜出来的:是文档明确写出的。这就是有效检查与猜测式检查的区别——任何需要推断的检查都会产生噪声。

未声明的守卫不会经过测试:无论是脚本、审阅者,还是守卫本身,都不会测试它。对于未声明任何守卫的架构,guards 会返回 pass,并给出 guards_declared: 0,同时明确说明这一点——因为检查若不说明自己没有找到什么,就会让空缺蒙混过关。

引擎是可选的。没有 pglite 时,execute 和 guards 会返回 skipped,并给出安装命令;它们绝不会在未执行的情况下返回 pass。completeness 仍然可用:它不需要引擎,只需要文档。

4.6 多视角审阅

在 gate 之前,应用视角轮换——这是架构审阅的必备步骤:

  • 质量视角:数据模型是否逐字段完整?每个 endpoint 是否列出所有错误代码?各个 slice 是否涵盖 PRD 中的全部用户故事?
  • 风险视角:是否存在依赖循环?是否有入站依赖过多的 slice?是否存在缺乏依据的架构决策?

添加标准合规性检查:plan-validator 会将架构与 .forge/benchmarks.md 和架构类型(references/archetypes.md)进行比较。

4.7 GATE

Gate 检查清单(references/review-checklists.md#architecture)。

阶段 5 — 按 slice 制定实施计划

目标:生成一份足够精确的实施计划,让能力较弱的 AI 也不会出错。

每次处理一个 slice。Guided 模式下,每个 slice 之后都要经过一次 gate。Fast Track 模式下,使用 references/fast-track.md 中的自动验证循环。

5.1 数据契约(代码)

使用目标技术栈的语法生成实际代码:

  • 验证模式(Zod、Pydantic、Dart 类等)。
  • 类型和接口。
  • API 契约(请求/响应类型)。

不可妥协的规则:代码中的每个字段都必须对应架构(阶段 4)中定义的字段。不得自行添加字段。

5.2 关键算法

对于包含多个条件分支或多个步骤的每条业务规则(B*),编写伪代码或实际代码。不要用散文改述。

5.3 组件计划
  • 组件树。
  • 每个组件的 Props、state、事件。
  • 状态处理(loading、empty、error、success、边缘情况)。
5.4 状态管理(state management)
  • 哪些数据是全局的,哪些是本地的。
  • 每项数据的存储机制。
  • 组件之间的数据流。
5.5 需要避免的陷阱

预判最可能出现的误解。每个陷阱都要关联到一个具体的 B*/E* ID,并明确对比表述:"不要将 X 与 Y 混淆——正确行为是 Z(参见 B12)。"

5.6 任务清单

按阶段排列的具体清单:

  1. 数据层(架构、类型、API 客户端)。
  2. 业务逻辑(算法、服务、状态管理)。
  3. 用户界面(组件、屏幕、表单、导航)。
  4. 集成(权限、功能标记、路由)。
  5. 单元测试。
  6. 组件测试。
  7. 集成测试 / E2E 测试。
  8. 润色(无障碍、响应式、动画、错误)。
5.7 验收标准

每条标准都可单独验证,并关联到一个 B*/E*/C* ID。

5.8 测试计划

对于此切片,仅列出特定内容:

  • 涵盖的 B*/E*/C* ID,以及各自的测试类型。
  • 此切片特有的 E2E 场景。
  • 此切片各屏幕的 Chrome MCP 验证项。

通用框架(测试框架、模式、覆盖率规则)在全局测试计划(.forge/test-plan.md,于 Phase 6 生成)中定义。不要在此重复。

5.9 覆盖率验证

在 gate 前运行:node "$FORGE/scripts/coverage-check.js" slice <anchor> <slice>,然后运行 node "$FORGE/scripts/forge-guard.js" placeholders <anchor>。

pass: false = 返回并补全计划。脚本会检查:

  • PRD 中的每个 B*/E*/C* ID 在计划中都有对应项。
  • 每个必需章节都存在且内容非空。
  • 不存在残留的 {{PLACEHOLDER}}。
5.10 GATE

Gate 检查清单(references/review-checklists.md#implementation-plan)。

Phase 6 — 验证(全局测试计划)

目标:定义全局测试策略并配置测试环境。

6.1 测试配置
  1. 安装/初始化测试框架(Jest、Vitest、Pytest 等)。
  2. 安装/初始化 E2E 工具(Playwright、Cypress 等)。
  3. 配置 Chrome MCP 以进行 UI 验证。
6.2 基础测试

对于每项基础功能,在实现各切片之前编写测试:

  • 设计系统:基础组件的渲染测试。
  • Auth:身份验证流程测试。
  • 错误处理:错误情况下的行为测试。
  • i18n:翻译是否存在的测试。
  • API 客户端:拦截器、重试、超时测试。
6.3 回归计划

定义每次合并前必须通过的回归测试套件。

6.4 GATE

Gate 检查清单(references/review-checklists.md#validation)。

Phase 7 — 实现

对于计划已获批准的每个切片:

  1. 确认所有依赖项均已实现(或已模拟):node "$FORGE/scripts/state.js" check-stale <anchor> <slice>。
  2. 首先阅读该切片的实现计划和约定(.forge/conventions.md)。如果计划对与另一个切片的交互有歧义,只查阅架构中相关的章节,不要通读整个架构。
  3. 按照任务清单实现,并严格遵守文档中记录的数据契约、算法和注意事项。
  4. 在适用时,先编写测试(TDD);否则,在实现每一层后立即编写测试。
  5. 验证每项验收标准。
  6. 执行退出标准——这是一个关卡,不是检查清单:
    node "$FORGE/scripts/forge-exit.js" <anchor> <slice>
    
    它会运行项目的真实命令,并检查切片是否包含测试用例,而不只是测试文件。“测试存在”意味着“至少有一个用例”——此前批准 14 个切片却没有任何测试,正是因为缺少了这一区分。
  7. 运行 Chrome MCP 检查:溢出、响应式布局、导航、错误状态。
  8. 将发现的问题分配到相应领域——绝不允许没有目标的问题:
    node "$FORGE/scripts/state.js" finding <anchor> --domain=<règle visée> --severity=<s> "<fait>" "<correction>"
    
  9. 运行 node "$FORGE/scripts/consistency-check.js" all <anchor>——该切片不得出现在差异项中。
  10. 更新状态:state.js set-status <anchor> slice <slice> implemented,验证通过后再设为 validated。
  11. 每完成一个切片后都要执行 GATE。

规则:当前切片未完成全部测试和验证前,绝不能开始下一个切片。

在 Fast Track 下,步骤 1-9 不会中断:实现工作持续推进,并可按需生成一份里程碑报告(3 至 5 个切片)。报告会明确区分哪些内容经过了机械化验证,哪些没有。

如果领域涉及到期时间——例如租金、订阅、期限——则完整周期场景必须纳入引入该生命周期的切片的退出标准,而不是最后一个切片。参见 references/scenario-tests.md。

Phase 8 — 最终验证
  1. 运行完整回归测试套件。
  2. 确认 PRD 中的所有验收标准均已满足。
  3. 最后对整个项目再次进行视角轮换(质量视角 + 风险视角)。
  4. 运行 node "$FORGE/scripts/forge-guard.js" all <anchor>。
  5. 更新 state.json:将项目状态设为 validated。
  6. 关闭事件日志(.forge/audit/issues.md),并生成项目审计报告。

变更管理与影响分析

每项变更都可能产生影响。

当用户要求修改(功能、规则、界面、架构……)时,绝不能在未进行影响分析的情况下立即应用变更。

影响分析流程

应用变更前,遵循 references/impact-protocol.md 中的流程。向用户总结:

  1. 受影响的功能:哪些业务规则(B*)会被修改、新增或删除?
  2. 受影响的界面:需要修改哪些屏幕?
  3. 受影响的模块/切片:需要调整哪些切片?
  4. 受影响的依赖项:还有哪些切片依赖变更内容?
  5. 需要修改的测试:哪些现有测试会失效?
  6. 需要更新的文档:PRD、架构、计划、路线图?
  7. 风险:哪些内容可能在不知不觉中失效?
  8. 工作量:影响程度的相对估算(局部 / 中等 / 重大 / 结构性)。

用户必须明确确认接受这些影响后,才能应用变更。

应用变更后
  1. 更新源文档(PRD、架构、设计等)。
  2. 将影响传递到所有受影响的文档(计划、roadmap、测试)。
  3. 将受影响的文档标记为 stale:state.js set-status <anchor> <kind> <clé> stale。
  4. 对相关切片运行 state.js check-stale。
  5. 检查整体一致性:forge-guard.js all。
  6. 报告所有变得不一致的内容。

多视角——两种验证模式

重要文档不会只经过一次审查就定稿。根据所用模式,有两种验证机制。

Guided 模式——视角轮换(默认)

在主会话中,以两种明确的视角对文档进行两次审查:

  1. 质量视角:缺失的边界情况、没有对应测试的规则、未涵盖的非功能性约束。
  2. 风险视角:内部矛盾、未经验证的假设、隐式依赖、盲点。

然后进行修正,再展示结果:“我已从质量和风险角度审查了这份文档。以下是我发现并修正的问题:[列表]。以下是仍需决定的事项:[列表]。”

何时应用:PRD(阶段 1)、架构(阶段 4)和最终验证(阶段 8)的关卡之前必须应用;建议用于 Roadmap、设计和计划。

为何在会话中进行,而不是使用子 Agent:视角轮换可以立即完成,不会产生额外的大模型调用,并能确保会话刚刚生成的文档接受同样严格的审查。对于大多数项目而言,在每个关卡编排 Agent 并不能带来成比例的额外收益。

Fast Track 模式——专用子 Agent(自动)

当方向已经过验证(PRD、规范、设计、屏幕、基准测试均已获批)时,手动验证 15 份计划既费力,也容易导致礼节性批准。此时,Fast Track 会并行委派给盲点互补的专用 Agent进行验证:

Agent查找……问题
quality-analyst缺失的内容“这份规范完整吗?”
red-team错误的内容“哪些地方会行不通?”
plan-validator不符合标准的内容“这是否符合此类应用的标准?”

每个 Agent 都有一份输入契约(唯一需要读取的文件)和一份输出契约(严格的 JSON)。它们绝不会看到整个 .forge——上下文会带来成本,而上下文过载的验证器会降低验证质量。

确定性脚本会在 Agent 之前运行:脚本一秒就能检测出 Agent 需要读三遍才能发现的问题。

入口关卡可执行,并会明确指出拒绝原因:

node "$FORGE/scripts/forge-guard.js" fast-track <anchor> \
     [--scope plans|phases4-7] [--autonomy milestone|full]

它不属于 forge-guard all——benchmarks 属于阶段 3,test_plan 属于阶段 6,因此纳入后会导致所有普通项目失败。但也不会因为忘记它而被绕过:state.js status 会显示该模式是否已启用,而 state.js fast-track --attempt 会在第三次尝试时停止。

完整流程、入口条件、限制和绕过方式:references/fast-track.md。


专业 Agent

每个 Agent 都是一份契约:包含角色、输入列表、流程、输出格式,以及明确列出的不负责事项。这不是角色描述,而是实现委派的关键。

Agent阶段模式角色
product-analyst1, 2produce, review需求探索、访谈、PRD、用户故事
scope-architect2produce, review路线图、MVP、版本拆分、权衡
ux-designer3produce, review标准、视觉方向、优先级导航、屏幕、流程
systems-architect4produce, review架构、切片、模块、数据、API、依赖项
quality-analyst1–8produce, validate完整性、边界情况、测试计划;Fast Track 验证器
red-team1–8validate矛盾、盲点、未经验证的假设
plan-validator4, 5validate是否符合应用类型标准
premise-challenger1–4challenge质疑用户的假设——初始想法、所需功能、MVP
scenario-tester6–8produce, review按业务场景测试:生命周期、时钟、不变量
forge-implementer7, 8produce实施、TDD、验证
client-liaison0, 4, 5, 7, 8check, stress客户无法理解的内容——未解答的问题,不给出结论

premise-challenger 是唯一不审阅 Forge 文档的 Agent:它审视您的需求,并指出某个想法何时不妥、已有解决方案、程度失当或放错位置。它会在第 1、2、3 阶段结束时触发;您在过程中添加功能时,也会一律触发。只要有一个 critical 结论,就会暂停,直到您作出回应。

client-liaison——唯一与客户沟通的 Agent

其他十个 Agent 都是工程师:他们寻找错误、不完整或无法测试之处。client-liaison 寻找难以理解之处,这是另一种专业工作。文档可能完全正确,却让接收者无法读懂——其他十个 Agent 都不会发现这一点,因为他们读的都是作者所用的语言。

模式问题输出
check客户能否不提出任何问题就签字?文档中未解答的问题
stress知情的客户会提出什么,而 Forge 没有写明?主要异议,以及保持沉默的代价

它绝不会给出结论。 一个表示赞同的子 Agent 会用假客户取代真正的客户,使关卡变成自我认证——这是此处代价最高的错误,因为它不会显现。它只提出问题;由客户作决定。

它不读取代码、计划或架构。这项限制不是预防措施,而是它的专业所在。由读过架构的人撰写的客户文档,总会包含架构内容。它的价值完全在于它没有读过架构。

适用于契约(第 0 阶段)、每份差异评估,以及实施前的阶段检查点。

没有可用的子 Agent 时:加载当前阶段相关 Agent 的指令,并应用姿态轮换。此时 Fast Track 不可用,改由 Guided 模式接手。


审计 — 基于 Forge 自身的执行结果改进 Forge

Forge 的每次执行都会在 .forge/audit/ 中记录日志:

文件类型用途
run-log.jsonl机器可读,仅追加所有事件:状态转换、gate、验证器、护栏、事件
issues.md人类可读事件日志:症状、根本原因、规避方法、纠正措施
metrics.json机器可读汇总计数器

没有记录的事件就等于没有发生。 这是能够改进该技能的唯一数据。

必须记录的内容
node "$FORGE/scripts/state.js" log <anchor> <type> "<message>" [k=v ...]

必须触发记录的类型:

情况类型
子 Agent 返回 REVISEfast_track_validate
子 Agent 返回 BLOCKfast_track_block
用户纠正输出(“不,这不对”)user_correction
护栏失败guard_failure
脚本失败script_failure
检测到状态不一致(通过 sync 自动记录)
在 .forge 之外发现交付物(通过 strays --relocate 自动记录)
需要重试某个阶段phase_retry
人工 gate 被拒绝gate_revise
用户退出 Fast Trackfast_track_escape

issues.md 中的 origine 选项卡(forge / projet / environnement)是最重要的字段:它能区分“Forge 引导有误”和“PRD 含糊不清”。

跨项目分析
node "$FORGE/scripts/audit-report.js" <dossier-contenant-les-projets> --out reports/

合并多个项目的日志,按规范化签名汇总故障,并区分结构性问题(在多个项目中出现 → 归入该技能)与偶发事件(仅出现在一个项目中)。正常时返回 0,检测到结构性问题时返回 2。


验证纪律

这些规则不是偏好,而是从真实项目中累计的 43 次修正中得出的结论,其中 43 次全都是验证错误,而非知识错误——Agent 知道答案,缺少的是把知识应用到实际文件上的步骤。

它们出现在这里,是因为它们从未被提升为规则。没有进入规则的发现,什么也没有改变。

  1. 一项断言,值得执行一次验证它的操作。“不存在任何执行 X 的代码”是对系统的断言,理应像“代码执行 X”一样严谨。读完整个代码块,否则就不要断言。

  2. **退出码不等于结果。**命令可能被忽略,却仍返回 0。已弃用的标志被悄然移除、replace 没有匹配项:两者都曾造成假通过。

  3. **验证更改是否存在的检查,无法验证更改的内容。**证明文件已修改的门禁,只能证明它被修改了,不能证明其中内容属实。

  4. 只能看到已更改内容的检查,永远无法发现遗漏。git status 会显示更改内容;对它而言,未更新的文件与已更新的文件无法区分。

  5. **重新实现待测规则的测试,测的不是规则,而是它的副本。**而且它会通过。

  6. **因错误原因通过的测试,比失败更糟。**它占据了本该找出真实缺陷的测试位置。

  7. 没有触及错误所在代码行的测试,不算覆盖。“规则写了”不等于“规则已接入”。

  8. **预期值是一个陈述,不是凭空编造。**把它写成一个关于测试数据的问题,然后作答。用与被测代码相同的代码计算出的预期值,什么也验证不了。

  9. **不变量必须有明确形式。**对称性可以假定;不变量必须证明。如果唯一的写法是“除非……”,那它就不是不变量。

  10. **一个事实,两种表示。**两个地方计算同一件事,却没有任何地方负责协调。一旦它们出现分歧,就没人知道哪个才是正确的。提取一个规范函数——绝不要保留两个计算点。

  11. **没有两个测试的边界,就不是真正的边界。**只走正常路径的测试,无法验证其他情况。

  12. 无法写进文档的规则,就应该删除。而无法执行的规则,只是装饰。

  13. **没有适用范围的发现并不完整。**它没有明确的晋升目标,因此不会带来任何改变。

  14. **没有进入规则文件的发现,什么也没有改变。**它被用来替代规则,而不是补充规则。


参考资料

脚本 — 确定性执行,零依赖

调用方式:node "$FORGE/scripts/<fichier>" [<anchor>] [args…]。$FORGE 是 skill 的 目录,参见上文“如何运行脚本”。

只有一个例外,而且明确标注了:ddl-exec.js 会加载 PostgreSQL 引擎 (@electric-sql/pglite)来执行 DDL。这个引擎是 仓库的开发依赖,绝不是分发的 skill 的依赖。没有它时,脚本不会模拟任何内容:它会返回 skipped,说明自己没有执行什么,并给出安装命令。声称已执行、实际却没有执行的检查是最糟糕的检查,因为它会显示绿色通过。

脚本作用时机
state.js start实际状态:阶段、门禁、slice 及测试用例数、尚未晋升的发现步骤 0,每次会话
state.js anchor解析当前项目,拒绝参考项目步骤 0 bis
state.js finding根据晋升领域路由发现发现缺陷时立即执行
state.js set-status一次操作中写入权威状态及其镜像每次状态变更
state.js sync调和状态 ↔ front matter每个门禁之前
state.js set-nav记录导航顺序及其理由阶段 3
state.js check-stale派生文档,或审批后修改的计划开始实现前
state.js dep声明 slice 或基础模块的依赖关系图阶段 4
state.js amend记录修订并拒绝重新编号;写入 amended_from、原因和变更列表每次修订
state.js migratev1 → v2现有项目
forge-guard.js all路径、状态、词汇、同步、derived_from 来源信息、提前生成的产物、多余字符、“待决定”项、占位符、版本、项目记忆、工具包完整性、已声明的工具、未记录的事件每个门禁之前
forge-guard.js memory-present四个记忆文件均存在,且 AGENTS.md 为三个文件中的每个文件都指定了触发条件阶段 0,之后每个门禁
forge-guard.js kit-integrity工具包脚本与记录的指纹一致;修改过的脚本会导致硬性失败,文档则发出警告每个门禁之前
forge-guard.js kit-integrity --write-manifest写入 .forge/kit-manifest.json — 明确执行的操作,绝不自动执行执行一次,并在每次工具包更新后执行
forge-guard.js tools所有补充脚本都位于 .forge/tools/,并且已声明用途每个门禁之前
forge-guard.js incidents将门禁检测到的偏差记录到 .forge/audit/issues.md每个门禁之前
consistency-check.js all检查产物之间的偏差:PRD ↔ 架构 ↔ 计划 ↔ 测试 ↔ 屏幕,以及已解析的章节交叉引用每个门禁之前
forge-exit.js执行 slice 的退出条件阶段 7,每个 slice 执行一次
coverage-check.js检查 slice 计划的覆盖率阶段 5
design-check.js测量对比度(WCAG 1.4.3 / 1.4.11)、无值的 token,以及组件与屏幕之间的表面一致性阶段 3,门禁时
ddl-exec.js执行架构的 DDL:PostgreSQL 会拒绝还是接受。检查 DDL 是否创建了它所修改的表,以及已声明的约束是否成立阶段 4,门禁时
dependency-check.js循环、拓扑顺序;--write 会持久化依赖关系图阶段 4
audit-report.js对多个项目进行交叉分析多个项目完成后
selftestskill 自身的测试发布前
检查未亲眼看到失败,就不算验证通过

新增或修改的每项检查,都必须在同一批次中拦截一个它声称要查找的缺陷——同时放行一个干净样例。两者都要做到。

这不是形式上的预防措施。在同一个项目中,两次发现:PowerShell 中的 Get-Content -Raw + 正则表达式 \u 扫描,在已损坏的文件上报告了“0 个问题”;取代它的 Node 扫描则基于“损坏内容是 CJK”的假设,对 _USERNAMEOục 中含有 U+1EE1 的文件报告无问题——该字符属于 Latin Extended Additional。直到采用白名单,才发现第三个异常字符。

由此得出三条规则:

  1. 用白名单,不用可疑名单。 允许范围 = ASCII + Latin-1 + Latin Extended-A + 标点 + 符号 + emoji + 仓库语言的排版字符(序数 1ᵉʳ、下标 CO₂)。其余一律标记。 白名单的首次尝试曾把正确的法语序数标记了 28 次:如果白名单没有覆盖仓库语言,它就会变成一个最终被关闭的检查。
  2. 标有 unicode-scan:ignore 的行会被忽略,这样就能在日志中引用缺陷,而不会触发检查。否则,证明缺陷存在的报告就无法提交。
  3. skip ≠ pass。 未运行的检查会说明自己没有覆盖什么。一个从未见过失败的检查,不算已验证,只能说状态未知。

对于输入是生成文件的检查:必须先在实际项目上验证,然后才能接入 all。由命令触发的检查仍可单独运行,不属于 all。

参考文档

文件内容
references/skill-boundaries.mdForge 与 project-rules-architect 各自负责什么;发现问题后的路由
references/state-schema.md.forge/state.json(v2)的格式、写入规则、权威来源
references/migration-v1-v2.md迁移过度膨胀的 v1 state.json 的流程
references/module-prioritization.md按使用频率排列模块和导航的顺序
references/design-quality.md反通用化禁令、必需的设计 skills、视觉方向
references/scenario-tests.md按业务场景编写的测试——生命周期、注入时钟、不变量
references/test-strategies.md测试类别、如何选择、哪些测试可在没有设备的情况下运行
references/archetypes.md各类原型的标准 + 已测量的反复出现的问题
references/research-protocol.md不要重新发明:提取不变量,而非代码
references/fast-track.md自动验证、两级自主程度、限制
references/impact-protocol.md变更影响分析流程
references/review-checklists.md按文档类型划分的 gate 检查清单

产品访谈记录在 agents/product-analyst.md 中。


工作流摘要

anchor → Interview (Phase 1) → PRD → Roadmap (Phase 2)
  → Standards + Direction + Navigation priorisée + Design (Phase 3)
  → Architecture (Phase 4) → Plans d'implémentation (Phase 5) → Tests (Phase 6)
  → Implémentation (Phase 7) → Validation (Phase 8)

全程还需遵循:

Anchor résolu · Livrables dans .forge · État = autorité, front matter = miroir
Gates humains (ou Fast Track) · Analyse d'impact · Multi-perspective
Identifiants stables · Exhaustivité · Garde-fous déterministes · Audit

评论

支持 Markdown