# 规则配置正确设置规范

> 适用范围：规则配置详情页、规则 YAML、规则版本保存/发布、历史规则迁移。
> 核心原则：页面配置必须最终落成可被 DSL 校验和执行引擎直接消费的正式 YAML，不能只维护前端临时字段。

## 1. 总体对象关系

规则配置只有三类核心对象：

| 对象 | 作用 | 由谁引用 | 正确落点 |
|------|------|----------|----------|
| 抽取字段 | 从文本中抽取业务值，例如 `合同金额`、`甲方`、`技术指标` | 规则 stage / AI prompt | `extract` |
| 视觉要素 | 从 OCR/版面视觉中识别签章、签名、骑缝章 | 视觉规则 stage | `visual_elements` |
| 评查规则 | 判断合同/案卷是否合规 | 执行引擎 | `rules[].rules[].stages` |

禁止把视觉要素当普通抽取字段使用。也就是说，不能生成：

```yaml
dependencies:
- visual.骑缝章
```

也不能生成：

```yaml
stages:
- id: '1'
  check: required
  field: visual.骑缝章
```

正确做法是先定义视觉要素，再在视觉 stage 中引用。

## 2. 抽取字段正确设置

抽取字段用于文本抽取，配置在 `extract` 下。

```yaml
extract:
- group: 基础信息
  fields:
  - name: 合同名称
    type: verbatim
    required_from: draft
    desc: 合同标题或合同名称
  - name: 合同金额
    type: money
    required_from: draft
    desc: 合同总金额
  - name: 质量等级
    type: enum
    required_from: draft
    allowed:
    - 合格
    - 优良
    desc: 工程质量等级
```

字段设置规则：

| 字段 | 正确口径 |
|------|----------|
| `name` | 业务字段名，必须稳定，AI prompt 和规则 stage 都会引用它 |
| `type` | 字段类型，常见为 `verbatim`、`string`、`money`、`date`、`integer`、`enum` |
| `required_from` | 只允许 `draft` 或 `executed`，不能写 `-` |
| `allowed` | 仅 `enum` 必填，用于枚举候选项 |
| `desc` | 抽取说明，要写清楚正向/负向边界 |

抽取字段可以被确定性规则引用：

```yaml
stages:
- id: '1'
  check: required
  field: 合同名称
- id: '2'
  check: required
  field: 合同金额
logic: 1 AND 2
```

抽取字段也可以被 AI 规则引用：

```yaml
stages:
- id: '1'
  check: ai
  prompt: '请检查合同金额是否明确。

    合同金额：{{合同金额}}

    请以 JSON 格式回答：{"passed": true/false, "reason": "简要说明"}
    '
```

## 3. 视觉要素正确设置

视觉要素用于签章、签名、骑缝章，不属于文本抽取字段。

```yaml
visual_elements:
  seals:
  - id: 发包人公章
    name: 发包人公章或合同专用章
    required: true
    required_from: executed
    allowed_types:
    - 公章
    - 合同专用章
    expected_text_match:
      field: 发包人名称
  signatures:
  - id: 法定代表人签名
    name: 法定代表人手写签名
    required: true
    required_from: executed
  cross_page_seals:
  - id: 骑缝章
    name: 合同骑缝章
    required: true
    required_from: executed
```

视觉要素字段含义：

| 字段 | 正确口径 |
|------|----------|
| `id` | 视觉要素稳定编码，建议直接用业务名，例如 `骑缝章`、`发包人公章` |
| `name` | 页面展示名，可比 `id` 更详细 |
| `required` | 是否必需，布尔值 |
| `required_from` | 生效阶段，通常签章/签名/骑缝章为 `executed` |
| `allowed_types` | 可接受的章类型，例如 `公章`、`合同专用章` |
| `expected_text_match.field` | 印章文字需要匹配的抽取字段，例如 `发包人名称` |

页面交互要求：

| 页面字段 | 正确行为 |
|----------|----------|
| 视觉要素编码 | 可选；不填时用视觉要素名称作为 `id` |
| 视觉要素名称 | 必填；业务人员可理解的名称 |
| 要素类型 | 三选一：`签章`、`签名`、`骑缝章` |
| 签章类型 | 写入 `allowed_types`，不是 `signature_types` |
| 签署角色 | 当前兼容写入 `expected_text_match.field` 的第一个值 |

禁止默认生成 `visual-时间戳` 作为业务配置。如果历史数据已经存在，可以保留兼容，但新增配置不应再制造这类不可读编码。

## 4. 视觉规则正确设置

视觉规则必须使用视觉 stage，不使用 `dependencies`。

签章存在：

```yaml
stages:
- id: '1'
  type: seal.present
  seal_id: 发包人公章
logic: '1'
```

签章文字匹配：

```yaml
stages:
- id: '1'
  type: seal.text_match
  seal_id: 发包人公章
logic: '1'
```

签章类型命中：

```yaml
stages:
- id: '1'
  type: seal.type_in
  seal_id: 发包人公章
logic: '1'
```

签名存在：

```yaml
stages:
- id: '1'
  type: signature.present
  signature_id: 法定代表人签名
logic: '1'
```

骑缝章完整：

```yaml
stages:
- id: '1'
  type: cross_page_seal.complete
  seal_id: 骑缝章
logic: '1'
```

## 5. 确定性规则正确设置

确定性规则用于非 AI 的固定判断，例如必填、格式、金额一致、数量检查。

```yaml
- rule_id: GC-000
  name: 基础信息完整性
  risk: high
  score: 10
  type: deterministic
  stages:
  - id: '1'
    check: required
    fields:
    - 发包人名称
    - 承包人名称
    - 工程名称
    - 合同金额
    logic: and
  logic: '1'
  messages:
    pass: 基础信息完整
    fail: 缺少发包人/承包人/工程名称/合同金额
```

设置规则：

| 项 | 正确口径 |
|----|----------|
| `rule_id` | 稳定规则编码，不随版本变化 |
| `name` | 业务名称 |
| `risk` | `high`、`medium`、`low` |
| `score` | 分值，必须有值 |
| `stages` | 至少一条 |
| `logic` | 多 stage 时必须表达 stage 组合关系 |
| `messages` | 建议保留，用于结果展示 |

## 6. AI 规则正确设置

AI 规则必须配置 `check: ai` 和 prompt。Prompt 中引用的 `{{字段名}}` 必须来自 `extract` 或可解析的子文档字段。

```yaml
- rule_id: JS-TECH-008
  name: 技术标准与质量条款
  risk: medium
  score: 3
  type: ai_rule
  stages:
  - id: '1'
    check: ai
    prompt: '请检查技术合同中技术标准与质量条款的完整性和明确性。

      技术规范：{{技术标准规范}}
      质量要求：{{质量要求}}

      请以 JSON 格式回答：{"passed": true/false, "reason": "简要说明"}
      '
    schema:
      type: object
      required:
      - passed
      - reason
      properties:
        passed:
          type: boolean
        reason:
          type: string
    pass_when: passed == True
  logic: '1'
```

AI 规则设置要求：

| 项 | 正确口径 |
|----|----------|
| `prompt` | 必须包含评查目标、输入字段、判断标准、输出格式 |
| `{{字段名}}` | 必须能在抽取字段中找到 |
| `schema` | 建议配置，保证输出可解析 |
| `pass_when` | 建议配置，避免返回结构无法判定 |

## 7. 规则组合正确设置

规则组合不直接检查字段，而是组合已有规则结果。

```yaml
- rule_id: GC-GROUP-QUALITY
  name: 质量条款综合评查
  type: rule_group
  risk: high
  score: 20
  rules:
  - GC-QUALITY-001
  - GC-QUALITY-002
  logic: GC-QUALITY-001 AND GC-QUALITY-002
```

规则组合要求：

| 项 | 正确口径 |
|----|----------|
| `type` | 必须为 `rule_group` |
| `rules` | 子规则 ID 列表，必须存在 |
| `logic` | 组合表达式，引用子规则 ID |
| `stages` | 不应配置 |

## 8. 子文档/案卷字段正确设置

案卷类规则可能有子文档配置。

```yaml
sub_documents:
- id: 处罚决定书
  name: 行政处罚决定书
  required: true
  extract:
  - group: 当事人信息
    fields:
    - name: 当事人名称
      type: verbatim
      desc: 被处罚对象名称
```

引用方式：

```yaml
stages:
- id: '1'
  check: required
  field: 处罚决定书.当事人名称
```

子文档设置要求：

| 项 | 正确口径 |
|----|----------|
| `id` | 稳定文书编码 |
| `name` | 文书展示名 |
| `required` | 是否必需 |
| `extract.fields` | 子文档内部字段 |

## 9. 版本保存与发布正确流程

规则编辑必须区分“保存草稿”和“发布生效”。

1. 编辑页面内容。
2. 前端序列化为正式 YAML。
3. 后端执行 DSL schema 校验。
4. 点击“保存规则配置”只生成草稿版本。
5. 点击“发布版本”后才成为当前租户生效版本。
6. 其他租户不应看到该租户未发布或已发布的私有版本。

版本状态口径：

| 状态 | 含义 | 是否生效 | 是否可回滚 |
|------|------|----------|------------|
| `draft` | 草稿 | 否 | 否 |
| `validated` | 校验通过但未发布 | 否 | 否 |
| `published` | 当前生效版本 | 是 | 否，当前版本不能回滚到自己 |
| `rollback` | 历史回滚版本 | 作为历史候选 | 是 |
| `deprecated` | 废弃版本 | 否 | 通常否 |

## 10. 租户下规则配置正确口径

当前采用方案 A：业务树共享，规则版本按租户隔离。

| 层级 | 是否共享 | 说明 |
|------|----------|------|
| 业务树/规则包分类 | 共享 | 例如合同、案卷、技术合同分类 |
| 规则 YAML 版本 | 租户隔离 | 梅州、揭阳可以有不同发布版本 |
| 公共规则模板 | 共享来源 | 新租户可从公共模板复制初始版本 |
| 角色权限 | 控制谁能看/编辑/发布 | 不决定规则数据归属 |

正确行为：

- 揭阳编辑并发布 `JS-TECH-032` 的 V10，梅州仍应看到梅州自己的当前版本。
- 新建租户时，应从公共模板或指定来源物化一份租户规则版本。
- 规则编辑接口必须带当前用户租户上下文，不能只按 `rule_type` 查全局版本。

## 11. 历史旧写法迁移规则

### 11.1 `check: visual + element`

旧写法：

```yaml
stages:
- id: '1'
  check: visual
  element: 骑缝章
```

如果 `element` 是 `骑缝章` 或 `cross_page_seal`，迁移为：

```yaml
visual_elements:
  cross_page_seals:
  - id: 骑缝章
    name: 合同骑缝章
    required: true
    required_from: executed

stages:
- id: '1'
  type: cross_page_seal.complete
  seal_id: 骑缝章
```

如果 `element` 是 `seal` 或具体公章名，迁移为：

```yaml
visual_elements:
  seals:
  - id: 发包人公章
    name: 发包人公章
    required: true
    required_from: executed

stages:
- id: '1'
  type: seal.present
  seal_id: 发包人公章
```

如果 `element` 是 `signature` 或具体签名名，迁移为：

```yaml
visual_elements:
  signatures:
  - id: 法定代表人签名
    name: 法定代表人签名
    required: true
    required_from: executed

stages:
- id: '1'
  type: signature.present
  signature_id: 法定代表人签名
```

### 11.2 `dependencies: visual.xxx`

旧写法：

```yaml
dependencies:
- visual.骑缝章
```

迁移原则：

- 不再输出 `dependencies`。
- 根据视觉要素类型生成正式视觉 stage。
- 如果找不到对应 `visual_elements`，页面应提示先补视觉要素，不能静默保存。

### 11.3 `field: visual.xxx`

旧写法：

```yaml
stages:
- id: '1'
  check: required
  field: visual.骑缝章
```

迁移原则：

- 删除这个错误 stage。
- 改成 `cross_page_seal.complete + seal_id`、`seal.present + seal_id` 或 `signature.present + signature_id`。

## 12. 页面正确交互设计

规则详情页应按当前规则实际引用展示：

| 区块 | 展示内容 | 新增行为 |
|------|----------|----------|
| 抽取字段 | 当前规则引用的文本字段 | 新增后自动挂到当前规则普通字段依赖 |
| 子文档 | 当前规则引用的子文档或子文档字段 | 新增后按子文档字段引用 |
| 视觉要素 | 当前规则引用的签章/签名/骑缝章 | 新增后生成视觉 stage |
| 当前 YAML 片段 | 正式序列化后的当前规则 YAML | 不显示前端临时 `dependencies` |
| 版本管理 | 草稿、发布、回滚 | 回滚必须选择非当前、非草稿版本 |

新增视觉要素的页面逻辑：

1. 用户填写“视觉要素名称”，例如 `骑缝章`。
2. “视觉要素编码”可不填。
3. 不填编码时，系统用名称作为 `id`。
4. 类型选择 `骑缝章` 后，保存当前规则时生成 `cross_page_seal.complete`。
5. YAML 片段显示正式 stage。

## 13. `JS-TECH-032` 正确配置

当前旧配置：

```yaml
- rule_id: JS-TECH-032
  name: 骑缝章检查
  risk: medium
  score: 2
  applies_in:
  - executed
  stages:
  - id: '1'
    check: visual
    element: 骑缝章
  logic: '1'
```

正确配置：

```yaml
visual_elements:
  cross_page_seals:
  - id: 骑缝章
    name: 合同骑缝章
    required: true
    required_from: executed

rules:
- group: 默认规则组
  rules:
  - rule_id: JS-TECH-032
    name: 骑缝章检查
    risk: medium
    score: 2
    type: deterministic
    applies_in:
    - executed
    stages:
    - id: '1'
      type: cross_page_seal.complete
      seal_id: 骑缝章
    logic: '1'
    messages:
      pass: 已加盖骑缝章
      fail: 未检测到骑缝章
```

页面上应表现为：

- 视觉要素区显示 `骑缝章 / 骑缝章 / executed 必需`。
- 检查方法显示 `cross_page_seal.complete` 或中文 `骑缝章完整性检查`。
- YAML 片段显示 `type: cross_page_seal.complete` 和 `seal_id: 骑缝章`。
- 不再显示 `dependencies: visual.骑缝章`。

## 14. 保存前验收清单

每次保存规则配置前必须满足：

| 检查项 | 验收标准 |
|--------|----------|
| YAML schema | `RulesFile.model_validate` 通过 |
| DSL validator | `validate(rules_file)` 通过 |
| 字段引用 | 所有 `field / fields / prompt {{}}` 都能找到抽取字段 |
| 视觉引用 | 所有 `seal_id / signature_id` 都能找到视觉要素 |
| 规则组合 | 子规则 ID 存在 |
| 租户边界 | 保存和发布只影响当前租户 |
| 预览一致 | 页面 YAML 片段与实际保存 YAML 一致 |

## 15. 禁止项

禁止以下配置继续进入新版本：

- `visual-时间戳` 作为新增视觉要素默认编码。
- `dependencies: visual.xxx`。
- `check: required + field: visual.xxx`。
- `required_from: -`。
- `enum` 字段没有 `allowed`。
- AI prompt 引用不存在的字段。
- 规则发布不带租户上下文。
- 当前版本可以回滚到自己。

