Skip to content
This repository was archived by the owner on Aug 25, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions decisions/ADR-0008-archetype-v2-ten.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# ADR-0008: archetype v2——补 planner/judge/researcher,十原型封顶

- status: accepted
- date: 2026-08-18
- deciders: owner 质询 + AI 独立回复

## 背景

owner 三个质询击穿 v1 七分类:
1. 工作任务的源头是谁?人类只给意图,谁定波次/设计测试/写工作卡?谁保证 `make check` 真有效?
2. 遇到决策分歧怎么办?不可能事事上升人类。
3. researcher 可加;且听说模型可专门作 tool 干"找代码翻文档",省 worker 上下文。

## 决策

### 1. planner(认同,从 orchestrator 拆出)

- 边界:**planner=设计时**(意图→波次计划+工作卡+测试规格),orchestrator=运行时(分派/监控/汇总)。混在一起会让"既排计划又管执行"失去制衡。
- 工作流位置:planner 产计划 → **计划须过 checker 评审**(防弱标准)→ checker 按规格**编写真测试代码**(测试作者权归 checker,builder 永不写自身验收——no-self-test 的组织级延伸)→ builder 实现 → checker 判决。
- checker 相应扩权:可写 tests/** 不可写实现(路径级权限分离,tiered_policy pattern 可执行)。
- **make check 有效性的元答案**:不靠"再多加一个审查者"(审查塔无限回归),靠客观指标短路——mutation score(testing.yaml T-10)验证测试杀变异能力,差分测试(T-09)验证行为等价。测试好不好,指标说话。
- 新约束:planner 与 builder 不得同一声明(标准制定者不可施工)。

### 2. judge(认同,但严格划界)

- 管辖权来自团队声明的授权域(枚举:测试抖动判定/评审分歧/规格歧义解释),**越域即改判"上升人类"**;治理/安全/生产动作永远人类(RL-1)。
- 独立性:validate 强制仲裁者模型别名与争议双方(builder/checker 成员)均不同——不能是任何一方同脑。
- 判决=结构化输出(decision+rationale+jurisdiction_basis),落 decision_made 事件形成判例库;owner 可推翻任何判决(破玻璃同哲学)。
- 升级阶梯:组内分歧 → judge(域内,自动)→ owner(域外/政策/生产,唯一人工口)。

### 3. researcher(认同,as_tool 是关键形态)

- 权限特征:读外部网络+读任意仓库,只产结构化报告(每条结论带 source 引用),不写仓库不碰生产。
- **上下文经济**:以 `expose.as_tool: true` 被 builder/planner 调用——全文留在 researcher 自己的上下文,worker 只收结论+引用。这正是"模型作为 tool 翻文档找代码"的机制化,schema 原生支持(io_contract 约束往返体积)。
- 修正一处设计错误:agent-as-tool 消费发生在 team 组装层(members.as_tool),agent 的 capabilities.tools 只收 tool: 注册项。

### 4. 克制:拒绝清单(十原型封顶)

| 拒绝加 | 理由 |
|---|---|
| critic | =checker(验收判决) |
| negotiator | =orchestrator 的协调协议,非信任边界 |
| memory-keeper | 记忆属 agent.memory + 事件流,非角色 |
| auditor | =curator(治理审计)+ judge(分歧裁决)组合 |
| teacher/trainer | 技能演进=Skill 自演进机制 + handoff.skill-extract,非角色 |

**封顶规则:提出第 11 个原型必须走 ADR,论证其权限/凭据/审计特征无法被现有十类覆盖。**

## 后果

- schema enum 十项;validate 增 judge 独立性强制;registry 增三个 proposed 条目(wave-planner/arbiter/researcher-code,未经实战,首引用时提级)+ web_search 工具。
- planner 用的 planning skill、judge 管辖域的正式枚举 → 留待 teams 轮(下一轮讨论)定义。
- GOVERNANCE AR-8 intent 同步更新。
36 changes: 36 additions & 0 deletions registry/agents/arbiter.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
id: arbiter
version: 0.1.0
status: proposed # 首个 team 引用时随 PR 提级
archetype: judge
role: "域内分歧仲裁:测试抖动判定/评审分歧/规格歧义解释;输出=判决+理由+管辖依据,可被 owner 推翻"
identity:
prompt_ref: identities/arbiter.md
model:
alias: coder-deep # 须与争议双方(builder/checker)别名不同——validate 强制
temperature: 0.1
reasoning_level: high
capabilities:
skills: []
tools: [tool:read_file] # 只读:看争议材料,不改任何东西
permissions:
inherit: org-default
mode: strict
overrides:
- {tools: [tool:read_file], pattern: "*", action: allow}
memory:
types: [semantic] # 判决理由入语义记忆形成判例库
retention: 365d
guardrails:
output_schema_strict: true # 判决 schema:{decision, rationale, jurisdiction_basis, reversible_by}
forbidden: [no-secret-output, no-bypass-gate]
post_conditions:
- "[llm] 每份判决注明管辖依据(团队授权域条目),越域即改判'上升人类'"
- "[ci] 判决写入 decision_made 事件(含双方主张摘要)"
io_contract:
input: {schema_ref: schemas/dispute-in.json}
output: {schema_ref: schemas/verdict.json}
expose:
as_tool: true
a2a_card: none
workspace:
scope: private
36 changes: 36 additions & 0 deletions registry/agents/researcher-code.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
id: researcher-code
version: 0.1.0
status: proposed # 首个引用时随 PR 提级
archetype: researcher
role: "检索即工具:找代码/翻文档/查资料,返回结构化结论+引用;全文留在自己上下文,worker 只收摘要(上下文经济)"
identity:
prompt_ref: identities/researcher-code.md
model:
alias: coder-fast # 检索是广度任务,用快档;结论质量靠引用可回溯保证
temperature: 0.2
reasoning_level: low
capabilities:
skills: []
tools: [tool:web_search, tool:read_file]
permissions:
inherit: org-default
mode: normal
overrides:
- {tools: [tool:read_file], pattern: "*", action: allow} # 只读任何仓库
memory:
types: [semantic] # 检索结论缓存,同题复用
retention: 30d
guardrails:
output_schema_strict: true # findings schema:每条结论必附 source 引用
forbidden: [no-secret-output]
post_conditions:
- "[llm] 无引用支撑的结论必须标注 confidence: low"
- "[ci] 输出过 findings schema(含 sources 数组非空校验)"
io_contract:
input: {schema_ref: schemas/question-in.json}
output: {schema_ref: schemas/findings.json}
expose:
as_tool: true # 核心用法:被 builder/planner 当工具调用
a2a_card: auto
workspace:
scope: private
39 changes: 39 additions & 0 deletions registry/agents/wave-planner.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
id: wave-planner
version: 0.1.0
status: proposed # 首个 team 引用时随 PR 提级 approved(本轮为定义落盘,未经实战)
archetype: planner
role: "工作源头:意图→波次计划+工作卡+测试规格;只写计划产物,不写实现"
identity:
prompt_ref: identities/wave-planner.md
model:
alias: coder-deep # 规划是重认知任务,用旗舰档
temperature: 0.3
reasoning_level: high
capabilities:
skills: [] # planning skill 待 teams 轮设计时随流程定义
tools: [tool:read_file, tool:write_file, tool:web_search]
# 检索增强(researcher-code)经 team 组装层以 as_tool 接入,不进本白名单(agent≠tool)
permissions:
inherit: org-default
mode: normal
overrides:
# 仅允许写顶层 plans/|cards/|specs/(相对本 agent 工作区根);其余显式 deny
# (normal 模式下 HIGH 仅 ask 不够;顶层锚定避免 src/plans/ 之类任意深度绕过)
- {tools: [tool:write_file], pattern: "re:^(?!(plans|cards|specs)/).*$", action: deny, severity: HIGH}
memory:
types: [semantic]
retention: 90d
guardrails:
output_schema_strict: true
forbidden: [no-secret-output]
post_conditions:
- "[llm] 每张工作卡含验收引用([ci] 优先,指向 testing.yaml 条目或 golden)"
- "[llm] 测试规格独立于实现描述(描述'验证什么'而非'怎么实现')"
io_contract:
input: {schema_ref: schemas/intent-in.json}
output: {schema_ref: schemas/wave-plan.json}
expose:
as_tool: true # orchestrator/judge 可调"补一个波次计划"
a2a_card: none
workspace:
scope: team
10 changes: 10 additions & 0 deletions registry/tools/web_search.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
id: web_search
version: 1.0.0
kind: builtin
severity: LOW
side_effects: [network]
input: {schema_ref: schemas/query-in.json}
output: {schema_ref: schemas/search-results.json}
implementation: {repo: openJiuwen-ai/jiuwenswarm, path: builtin/web_search}
status: approved
owner: team:governance-core
29 changes: 25 additions & 4 deletions scripts/validate.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ def fail(msg: str) -> None:
errors.append(msg)


def alias_of(a: dict):
"""读取 agent 的 model.alias;model 为 null/缺失 时返回 None(不抛异常)"""
return (a.get("model") or {}).get("alias")


def load_yaml(path: Path):
try:
with open(path, encoding="utf-8") as f:
Expand Down Expand Up @@ -58,7 +63,7 @@ def frontmatter(path: Path) -> dict:
ACTIVE = {"approved", "active"}

# ---- agent 校验 ----
ARCHETYPES = {"builder", "checker", "orchestrator", "curator", "interface", "observer", "operator"}
ARCHETYPES = {"builder", "planner", "checker", "judge", "orchestrator", "curator", "interface", "observer", "researcher", "operator"}
for aid, a in agents.items():
arch = a.get("archetype")
if arch not in ARCHETYPES:
Expand All @@ -80,7 +85,7 @@ def frontmatter(path: Path) -> dict:
fail(f"agent:{aid} 引用不存在的 tool:{tid}")
elif tools[tid].get("status") not in OK:
fail(f"agent:{aid} 引用未批准的 tool:{tid} (status={tools[tid].get('status')})")
alias = a.get("model", {}).get("alias")
alias = alias_of(a)
if alias and alias not in model_aliases:
fail(f"agent:{aid} 引用未注册的模型 alias: {alias}")

Expand All @@ -103,6 +108,22 @@ def frontmatter(path: Path) -> dict:
fail(f"team:{tid} 引用不存在的 agent:{aid}")
elif agents[aid].get("status") not in OK:
fail(f"team:{tid} 引用未批准的 agent:{aid}")
# AR-8 v2:judge 独立性——仲裁者模型别名不得与争议双方(builder/checker 成员)相同
judges = [a for a in member_ids if agents.get(a, {}).get("archetype") == "judge"]
disputants = [a for a in member_ids if agents.get(a, {}).get("archetype") in ("builder", "checker")]
for j in judges:
ja = alias_of(agents[j])
if not ja:
fail(f"team:{tid} 仲裁者 {j} 缺少 model.alias,无法验证裁决独立性(ADR-0008)")
for d in disputants:
if not alias_of(agents[d]):
fail(f"team:{tid} 争议方 {d} 缺少 model.alias,无法验证裁决独立性(ADR-0008)")
Comment thread
coderabbitai[bot] marked this conversation as resolved.
for j in judges:
ja = alias_of(agents[j])
for d in disputants:
da = alias_of(agents[d])
if ja and da and ja == da:
fail(f"team:{tid} 仲裁者 {j} 与争议方 {d} 模型别名相同({ja}),裁决不独立(ADR-0008)")
Comment thread
randypanding marked this conversation as resolved.
# AR-9 验证链:含 builder 的团队必须独立 checker 验收 + 外部审计
builders = [a for a in member_ids if agents.get(a, {}).get("archetype") == "builder"]
ver = t.get("verification", {})
Expand All @@ -118,9 +139,9 @@ def frontmatter(path: Path) -> dict:
fail(f"team:{tid} 的验收者 agent:{c} 不是 checker 原型(AR-8/9)")
if c in builders:
fail(f"team:{tid} 中 agent:{c} 既是 builder 又是验收者(利益分离)")
ca = agents[c].get("model", {}).get("alias")
ca = alias_of(agents[c])
for b in builders:
ba = agents[b].get("model", {}).get("alias")
ba = alias_of(agents[b])
if ca and ba and ca == ba:
fail(f"team:{tid} 验收者 {c} 与 builder {b} 使用相同模型别名 {ca}(独立性不足)")
ea = ver.get("external_audit", {})
Expand Down