Skip to content

Commit dba7dc5

Browse files
committed
refactor(contract): 契约字段统一 lowerCamelCase(硬切无兼容层)并固化命名规则
- CLAUDE.md 新增 Contract Field Naming 强制规则:序列化边界一律 lowerCamelCase,proto 字段名仅限 .proto 内部;禁止为旧键保留兼容解析/双读/别名 - docs: spec 级文档契约键统一 camelCase;v2 descriptor 增加命名约定小节;SDK 指南同步(python/cpp 保留语言惯用名并标注契约键) - go sdk: 描述符与配置结构 json tag 全量改 camel,校验消息同步 - js sdk: FunctionDescriptor 接口/protobuf 编码映射/manifest 输出键改 camel - java sdk: provider manifest 输出键改 camel - python sdk: manifest 输出键改 camel(dataclass 字段保留 PEP8 snake) - assignment REST: game_id/target_env 改 gameId/targetEnv,web 调用点同 PR 硬切
1 parent 8de0a17 commit dba7dc5

52 files changed

Lines changed: 472 additions & 395 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CLAUDE.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,3 +390,34 @@ rg -n '^\s+[A-Z][A-Za-z0-9]*:' configs/*.yaml configs/**/*.yaml
390390
```
391391

392392
If a change introduces new uppercase YAML keys, it is a review failure unless the file is explicitly a legacy compatibility fixture.
393+
394+
## Contract Field Naming (Mandatory)
395+
396+
FunctionContract 及所有对外暴露的 JSON/SDK 契约字段名必须统一 `lowerCamelCase`。此仓库此前因 proto 字段名(snake_case)被直接透传为 SDK/JSON 键名而产生漂移(如 `input_schema`),该做法已废弃。
397+
398+
规范来源:`docs/architecture/openapi-sdk-descriptor-v2.md` 的「命名约定」小节。
399+
400+
### 1) Canonical Rules
401+
402+
- 契约字段(`inputSchema`、`outputSchema`、`approvalRequired`、`policyKey` 等)在所有文档、示例、REST payload、SDK 表层一律 `lowerCamelCase`。
403+
- proto 字段名的 snake_case 仅允许出现在 `.proto` 文件内部(protobuf 官方风格);其生成 `json_name` 必须为 `lowerCamelCase`,文档引用时禁止把 proto 字段名当作契约键名(允许显式的「对应 proto 字段名 X」对照注释)。
404+
- 序列化边界必须输出 lowerCamelCase 契约键:REST payload、SDK 产出的 JSON/manifest、proto `json_name`。语言原生标识符遵循各自惯例(Go 导出字段 PascalCase 配 lowerCamelCase json tag;Python dataclass/kwargs 按 PEP8 snake_case;C++ 成员 snake_case;TS/JS 与 Java/C# 属性即契约键本身,用 lowerCamelCase),不得把语言的内部命名直接透传为契约键。
405+
- 业务 payload 内部(JSON Schema properties、游戏业务数据)不属于平台契约,命名由游戏方自行决定。
406+
- 枚举字符串值(如 `input_schema_stale`)是机器标识符,不属于本规则范围。
407+
408+
### 2) Implementation Rules
409+
410+
- 新增 REST DTO、SDK descriptor 字段时禁止 `json:"snake_case"` 形式的契约键。
411+
- **禁止兼容旧键**:发现漂移时直接改名为 canonical 键,并在同一变更内更新全部调用方(含 web 子模块、SDK 示例与测试);不得为旧键保留兼容解析、双读或别名映射。兼容层只会让错误命名永久化。
412+
- 更新 SDK 字段名时,同 PR 内必须同步更新对应 `docs/sdks/<lang>/` 指南,保持文档与代码一致。
413+
414+
### 3) Review Checklist
415+
416+
Before merge, scan for snake_case contract keys leaking to JSON/SDK surfaces or docs:
417+
418+
```bash
419+
rg -n 'json:"[a-z]+_[a-zA-Z]+"' internal sdks --glob '!**/*_test.go' --glob '!**/generated/**' --glob '!**/_pb2*' --glob '!gen/**' --glob '!**/pkg/pb/**'
420+
rg -n '`input_schema`|`output_schema`|`approval_required`|`approval_policy_key`' docs --glob '!docs/archive/**' --glob '!docs/sdks/**'
421+
```
422+
423+
New occurrences are review failures unless they are explicit legacy compatibility code or annotated proto-name references.

docs/api/function.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ type OpenAPIOperation = json.RawMessage
1111

1212
说明:
1313

14-
- `JSONValue` 仅表示业务 payload 或函数返回值,结构必须由函数 `input_schema` / `output_schema` 约束。
14+
- `JSONValue` 仅表示业务 payload 或函数返回值,结构必须由函数 `inputSchema` / `outputSchema` 约束。
1515
- `JSONSchema` 仅表示 JSON Schema / OpenAPI Schema。
1616
- `FormPresentationSpec` 表示 JSON Schema 表单的受控展示配置,不能承载页面布局、菜单或任意组件 props。
1717
- `OpenAPIOperation` 只用于契约查看,不用于运行控制台直接生成页面。

docs/architecture/openapi-sdk-descriptor-v2.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,10 @@ OpenAPI operation / SDK descriptor
4949
| `enabled` / `deprecated` | 标准字段 | 同名字段 | 目录与执行开关;disabled 合同持久化保留但不可执行、不可发布 |
5050
| `tags` | 标准字段 | `tags` | 目录与检索用途,非菜单事实 |
5151

52+
### 命名约定
53+
54+
FunctionContract 对外暴露的 SDK / JSON 字段名统一使用 lowerCamelCase(如 `inputSchema``outputSchema``approvalRequired`)。proto 字段名按 protobuf 规范保留 snake_case,其生成的 `json_name` 即 lowerCamelCase;文档、示例与 SDK 对外表层一律以 lowerCamelCase 指代契约字段,禁止把 proto 字段名直接透传为 JSON/SDK 键名。语言原生标识符遵循各自惯例(如 Python kwargs 为 snake_case),但 SDK 序列化到 JSON/wire 时必须使用本表的 lowerCamelCase 契约键。
55+
5256
`capability` 只允许:
5357

5458
```text

docs/architecture/sdk-agent-transport-redesign.md

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -252,14 +252,14 @@ SDK 与 Agent 建连后,应在该连接上建立 provider session,而不是
252252

253253
推荐保留 `0x05xx` 分组,但重定义为:
254254

255-
| MsgID | 建议名称 | 说明 |
256-
|------:|-----------|------|
257-
| `0x050101` | `ProviderConnectRequest` | SDK 建立 provider session |
258-
| `0x050102` | `ProviderConnectResponse` | 返回 `session_id` / 能力协商结果 |
259-
| `0x050103` | `ProviderHeartbeatRequest` | SDK 心跳 |
260-
| `0x050104` | `ProviderHeartbeatResponse` | Agent 心跳响应 |
261-
| `0x050105` | `ProviderDrainRequest` | Agent 主动要求 SDK 停止接新请求 |
262-
| `0x050106` | `ProviderDrainResponse` | SDK 确认 drain 状态 |
255+
| MsgID | 建议名称 | 说明 |
256+
| ---------: | --------------------------- | -------------------------------- |
257+
| `0x050101` | `ProviderConnectRequest` | SDK 建立 provider session |
258+
| `0x050102` | `ProviderConnectResponse` | 返回 `session_id` / 能力协商结果 |
259+
| `0x050103` | `ProviderHeartbeatRequest` | SDK 心跳 |
260+
| `0x050104` | `ProviderHeartbeatResponse` | Agent 心跳响应 |
261+
| `0x050105` | `ProviderDrainRequest` | Agent 主动要求 SDK 停止接新请求 |
262+
| `0x050106` | `ProviderDrainResponse` | SDK 确认 drain 状态 |
263263

264264
说明:
265265

@@ -424,7 +424,7 @@ SDK-Agent v1 的默认业务负载规则为:
424424

425425
### Schema 规则
426426

427-
`input_schema` / `output_schema` 应定义为可选增强项,而不是默认前置条件。
427+
`inputSchema` / `outputSchema` 应定义为可选增强项,而不是默认前置条件。
428428

429429
v1 约束:
430430

@@ -558,20 +558,20 @@ SDK 收到这些信号后,可以:
558558

559559
所有 SDK 建议统一收敛到以下字段语义:
560560

561-
| Field | 说明 |
562-
|---|---|
563-
| `transport.kind` | 固定优先为 `tcp` |
564-
| `transport.address` | Agent 地址 |
565-
| `transport.connect_timeout_ms` | 连接超时 |
566-
| `transport.request_timeout_ms` | 请求超时 |
567-
| `transport.tls` | TLS 配置 |
568-
| `reconnect.enabled` | 是否自动重连 |
569-
| `reconnect.initial_delay_ms` | 初始退避 |
570-
| `reconnect.max_delay_ms` | 最大退避 |
571-
| `reconnect.backoff_multiplier` | 指数退避倍率 |
572-
| `reconnect.jitter_factor` | 抖动因子 |
573-
| `backpressure.max_concurrency` | 本地并发上限 |
574-
| `backpressure.max_queue_size` | 本地排队上限 |
561+
| Field | 说明 |
562+
| ------------------------------ | ---------------- |
563+
| `transport.kind` | 固定优先为 `tcp` |
564+
| `transport.address` | Agent 地址 |
565+
| `transport.connect_timeout_ms` | 连接超时 |
566+
| `transport.request_timeout_ms` | 请求超时 |
567+
| `transport.tls` | TLS 配置 |
568+
| `reconnect.enabled` | 是否自动重连 |
569+
| `reconnect.initial_delay_ms` | 初始退避 |
570+
| `reconnect.max_delay_ms` | 最大退避 |
571+
| `reconnect.backoff_multiplier` | 指数退避倍率 |
572+
| `reconnect.jitter_factor` | 抖动因子 |
573+
| `backpressure.max_concurrency` | 本地并发上限 |
574+
| `backpressure.max_queue_size` | 本地排队上限 |
575575

576576
### 废弃字段
577577

docs/architecture/sdk-wire-protocol.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ v1 默认规则:
267267

268268
## Schema 规则
269269

270-
`input_schema` / `output_schema` 在默认路径下描述的是 JSON payload 的 JSON Schema。
270+
`inputSchema` / `outputSchema`(对应 proto 字段名 `input_schema` / `output_schema`在默认路径下描述的是 JSON payload 的 JSON Schema。
271271

272272
规则:
273273

docs/development/repository-guidelines.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ title: 仓库规范
4747

4848
游戏方在 function spec / OpenAPI 里定义的枚举(哪怕字段也叫 status)是**用户数据**,不是平台状态:
4949

50-
- 平台只做三件事:透传(schema 原文存 `input_schema`/`output_schema`,无损)、渲染(property 带 `enum` → 表单生成 Select)、校验(运行时按 schema 拒绝非法值)。
50+
- 平台只做三件事:透传(schema 原文存 `inputSchema`/`outputSchema`,无损)、渲染(property 带 `enum` → 表单生成 Select)、校验(运行时按 schema 拒绝非法值)。
5151
- 词表随用户 spec 版本漂移,平台代码不得预知、不得转换为 Go 枚举、不得在 DB 层加 CHECK 约束。
5252
- 用户改 enum 不需要平台发版。
5353

docs/guide/concepts/function-management.md

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ Croupier 的核心模型仍然是“函数注册驱动”,但注册与调用
2323
- 资源 `resource`
2424
- 业务动作 `operation`
2525
- 风险等级 `risk`
26-
- 输入 `input_schema`
27-
- 输出 `output_schema`
26+
- 输入 `inputSchema`
27+
- 输出 `outputSchema`
2828
- 能力语义 `capability`
2929

3030
## 当前注册模型
@@ -70,7 +70,7 @@ sequenceDiagram
7070
"tags": ["player", "moderation"],
7171
"summary": "封禁玩家",
7272
"description": "封禁指定玩家账号",
73-
"input_schema": {
73+
"inputSchema": {
7474
"type": "object",
7575
"properties": {
7676
"player_id": { "type": "string" },
@@ -79,7 +79,7 @@ sequenceDiagram
7979
},
8080
"required": ["player_id", "duration"]
8181
},
82-
"output_schema": {
82+
"outputSchema": {
8383
"type": "object",
8484
"properties": {
8585
"success": { "type": "boolean" },
@@ -91,12 +91,12 @@ sequenceDiagram
9191

9292
**风险等级 (`risk`):**
9393

94-
| 等级 | 说明 | 审批要求 | 允许角色 |
95-
|------|------|----------|----------|
96-
| `low` | 低风险操作 | 无需审批 | user, operator |
97-
| `medium` | 中风险操作 | 无需审批,需审计 | operator |
98-
| `high` | 高风险操作 | 单管理员审批 + 审计 | admin |
99-
| `danger` | 危险操作 | 双人审批 + 审计 | super_admin |
94+
| 等级 | 说明 | 审批要求 | 允许角色 |
95+
| -------- | ---------- | ------------------- | -------------- |
96+
| `low` | 低风险操作 | 无需审批 | user, operator |
97+
| `medium` | 中风险操作 | 无需审批,需审计 | operator |
98+
| `high` | 高风险操作 | 单管理员审批 + 审计 | admin |
99+
| `danger` | 危险操作 | 双人审批 + 审计 | super_admin |
100100

101101
函数注册时会根据风险等级自动创建对应的默认政策,也可以通过 API 覆盖。详见[权限控制](./permissions.md)文档。
102102

@@ -111,7 +111,7 @@ sequenceDiagram
111111

112112
这意味着 SDK 用户不需要先定义自己的 `.proto` 才能接入。
113113

114-
Server 根据 `input_schema` 或 OpenAPI request schema 为 PageProposal 生成表单展示候选。Dashboard 表单 renderer 使用 JSON Schema validation 和 FormPresentationSpec,不在运行时猜测页面业务语义。
114+
Server 根据 `inputSchema` 或 OpenAPI request schema 为 PageProposal 生成表单展示候选。Dashboard 表单 renderer 使用 JSON Schema validation 和 FormPresentationSpec,不在运行时猜测页面业务语义。
115115

116116
完整业务页面由 Resource Catalog 与 Page Studio 管理。Server 会先把函数归一化为 FunctionContract / ResourceCapability / CapabilitySemantics,再生成 PageProposal。PageSpec 是强类型页面 DSL,负责分页、表格、详情、弹窗、任务状态和图表等页面级能力,由 ProComponents renderer 显示。
117117

@@ -162,8 +162,8 @@ stateDiagram-v2
162162
## 最佳实践
163163

164164
1. 函数 ID 应稳定且可读,例如 `player.ban`
165-
2. `summary``description``input_schema``output_schema` 建议补齐
166-
3. 需要自动加入 CRUD Resource 时补齐 `resource``capability``input_schema``output_schema`;SDK 没有 REST 语义时由 Resource Catalog 审核 identity/collection 能力
165+
2. `summary``description``inputSchema``outputSchema` 建议补齐
166+
3. 需要自动加入 CRUD Resource 时补齐 `resource``capability``inputSchema``outputSchema`;SDK 没有 REST 语义时由 Resource Catalog 审核 identity/collection 能力
167167
4. 动态菜单多语言、页面标题和按钮文案只能在 Page Studio / PageSpec 中配置
168168
5. 需要平台理解的字段必须放在协议层
169169
6. 只属于具体业务的参数放到 JSON payload

docs/guide/concepts/function-registration-ui.md

Lines changed: 33 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -29,29 +29,32 @@ FunctionContract
2929

3030
## 注册信息
3131

32-
| 字段 | 作用 | 是否页面 UI |
33-
| --- | --- | --- |
34-
| `id``version` | 稳定函数身份与变更追踪 ||
35-
| `summary``description``tags` | 函数目录、搜索、诊断 ||
36-
| `input_schema``output_schema` | 表单字段、验证、候选列和详情字段 ||
37-
| `resource``operation` | 业务资源与动作归属 ||
38-
| `capability` | `collection_query/item_query/create/update/delete/action/task/report` ||
39-
| `execution``approval``risk``permission` | 调度、审批与治理;审批可与同步/异步组合 ||
40-
| 分类、标题、列、动作位置、mapping、页面类型 | PageProposal/PageSpec | 是,不能注册 |
32+
| 字段 | 作用 | 是否页面 UI |
33+
| --------------------------------------------- | --------------------------------------------------------------------- | ------------ |
34+
| `id``version` | 稳定函数身份与变更追踪 | |
35+
| `summary``description``tags` | 函数目录、搜索、诊断 | |
36+
| `inputSchema``outputSchema` | 表单字段、验证、候选列和详情字段 | |
37+
| `resource``operation` | 业务资源与动作归属 | |
38+
| `capability` | `collection_query/item_query/create/update/delete/action/task/report` | |
39+
| `execution``approval``risk``permission` | 调度、审批与治理;审批可与同步/异步组合 | |
40+
| 分类、标题、列、动作位置、mapping、页面类型 | PageProposal/PageSpec | 是,不能注册 |
4141

4242
示例:
4343

4444
```ts
45-
client.registerFunction({
46-
id: 'player.update',
47-
version: '1.0.0',
48-
resource: 'player',
49-
operation: 'update',
50-
capability: 'update',
51-
risk: 'warning',
52-
input_schema: PlayerUpdateSchema,
53-
output_schema: PlayerSchema,
54-
}, updatePlayer);
45+
client.registerFunction(
46+
{
47+
id: "player.update",
48+
version: "1.0.0",
49+
resource: "player",
50+
operation: "update",
51+
capability: "update",
52+
risk: "warning",
53+
inputSchema: PlayerUpdateSchema,
54+
outputSchema: PlayerSchema,
55+
},
56+
updatePlayer,
57+
);
5558
```
5659

5760
`capability` 是能力语义,不是 UI:它只说明 `player.update` 可以参与玩家资源的更新生命周期,不说明它显示为行按钮、详情弹窗还是独立页。这些由 PageProposal 生成,随后由 Page Studio 确定。
@@ -60,12 +63,12 @@ client.registerFunction({
6063

6164
JSON Schema 是自动界面的基础,但不是完整页面定义:
6265

63-
| JSON Schema 信息 | 平台可自动生成 |
64-
| --- | --- |
66+
| JSON Schema 信息 | 平台可自动生成 |
67+
| ---------------------------------------- | ------------------------------------------------------ |
6568
| 输入字段、required、enum、format、默认值 | SchemaFormRenderer 字段与校验;Modal/Drawer 仅作为容器 |
66-
| 输出对象字段 | 详情字段、结果字段候选 |
67-
| 输出 collection item schema | ProTable 列候选 |
68-
| REST path + method + path parameter | CRUD capability 与 identity 高置信度建议 |
69+
| 输出对象字段 | 详情字段、结果字段候选 |
70+
| 输出 collection item schema | ProTable 列候选 |
71+
| REST path + method + path parameter | CRUD capability 与 identity 高置信度建议 |
6972

7073
JSON Schema 不能自行判断:
7174

@@ -95,12 +98,12 @@ POST /players/{playerId}/ban -> action -> 行操作候选
9598

9699
### 非 CRUD 函数
97100

98-
| 函数 | 默认 Proposal | 直接发布条件 |
99-
| --- | --- | --- |
100-
| `mail.send` | OperationPage | 有可执行 binding、输入表单、风险/权限与导航默认值 |
101-
| `player.ban` | Resource action 或 OperationPage | identity/context 明确时为资源动作,否则独立操作页 |
102-
| `reward.batchGrant` | TaskPage | 真实 task 状态、事件和结果语义完整 |
103-
| `analytics.retention` | ReportPage | dataset、维度、指标和图表/表格语义完整 |
101+
| 函数 | 默认 Proposal | 直接发布条件 |
102+
| --------------------- | -------------------------------- | ------------------------------------------------- |
103+
| `mail.send` | OperationPage | 有可执行 binding、输入表单、风险/权限与导航默认值 |
104+
| `player.ban` | Resource action 或 OperationPage | identity/context 明确时为资源动作,否则独立操作页 |
105+
| `reward.batchGrant` | TaskPage | 真实 task 状态、事件和结果语义完整 |
106+
| `analytics.retention` | ReportPage | dataset、维度、指标和图表/表格语义完整 |
104107

105108
页面质量:
106109

docs/guide/integrations/openapi-registration.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@ OpenAPI
3232
| `id` | `operationId` | 稳定函数 ID |
3333
| `version` | `x-version` | 契约版本 |
3434
| `summary` / `description` | 标准字段 | 目录和诊断说明 |
35-
| `input_schema` | request body schema | 输入 JSON Schema |
36-
| `output_schema` | response schema | 输出 JSON Schema |
35+
| `inputSchema` | request body schema | 输入 JSON Schema |
36+
| `outputSchema` | response schema | 输出 JSON Schema |
3737
| `resource` | REST path 推导或 `x-resource` | 资源 key |
3838
| `operation` | method/path 推导或 `x-operation` | 动作 key |
3939
| `capability` | REST 推导或 `x-capability` | 受控能力语义 |

docs/sdks/cpp/api/resources-and-operations.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@
1616
- `operation`
1717
- `capability`
1818
- `risk`
19-
- `input_schema`
20-
- `output_schema`
19+
- `input_schema`(成员名;契约键 `inputSchema`
20+
- `output_schema`(成员名;契约键 `outputSchema`
2121

2222
SDK descriptor 不提供页面 schema、组件树、页面 mapping、菜单、分类显示名、页面标题、按钮文案或页面位置。
2323

0 commit comments

Comments
 (0)