CLI 与 JSON 契约
面向对象:对接本知识库的外部 Agent(Codex / Claude Code / DSH 会话 / 任意脚本)。 本文档描述
validate、resolve与check的稳定、版本化、确定性机器接口。chat/eval是本地交互模式,不属于本契约。
1. 获取与运行
Section titled “1. 获取与运行”代码位于仓库默认分支 main(开发分支 codex/cli-agent 会合并回 main)。
# 正常环境(JDK 21+ 运行;JDK 21 编译工具链可由 Foojay resolver 下载):git clone https://github.com/lucasnotfound59/FTC-Knowledge-Bank.gitcd FTC-Knowledge-Bank./gradlew :apps:knowledge-cli:installDist # 产物在 apps/knowledge-cli/build/install/ftckb/bin/ftckb
# 受限环境(沙箱/CI 禁写 ~/.gradle):GRADLE_USER_HOME=/tmp/xxx ./gradlew :apps:knowledge-cli:installDist知识根目录:仓库内 knowledge/(43 条规则:37 条已批准 + 6 条候选,候选规则不会进入 resolve 结果)。
2. 命令与退出码
Section titled “2. 命令与退出码”| 命令 | 形式 | 说明 |
|---|---|---|
| validate | ftckb validate <knowledge-root> [--json] |
加载并校验全部规则;成功输出规则总数 |
| resolve | ftckb resolve <knowledge-root> --team N --season YYYY-YYYY [--json] |
按队伍+赛季裁决出全部生效规则;存在规则冲突时退出码为 2 |
| check | ftckb check <repo-root> --knowledge <knowledge-root> --team N --season YYYY-YYYY [--diff FILE] [--json] |
对当前 diff 执行硬检查,并返回 soft 提醒 |
选项约束:
--team:仅数字(如20827)。--season:严格YYYY-YYYY(如2025-2026)。--json可放在命令行的任意位置;出现--json时所有输出(包括错误)都是单行 JSON。resolve的--team/--season为必填,可重复出现时视为错误;validate不接受任何额外参数。
退出码(稳定,契约的一部分):
| 退出码 | 含义 |
|---|---|
| 0 | 成功(resolve 成功即无冲突) |
| 1 | check 存在硬违规(violations 非空) |
| 2 | 知识加载失败、规则校验失败(violations),或 resolve 存在冲突 |
| 64 | 用法错误(未知命令、缺/错参数) |
3. JSON 契约(schemaVersion = 1)
Section titled “3. JSON 契约(schemaVersion = 1)”所有 JSON 输出都是单行(无换行、无日志噪音)写往 stdout。顶层必有:
schemaVersion:整数,当前恒为 1;破坏性变更必须提升版本号。ok:布尔。command:"validate"、"resolve"或"check"(未知命令的用法错误没有此字段)。
3.1 validate 成功
Section titled “3.1 validate 成功”{"schemaVersion":1,"command":"validate","ok":true,"ruleCount":43,"violations":[]}ruleCount 为加载到的规则总数(含候选)。退出码 0。
3.2 resolve 成功
Section titled “3.2 resolve 成功”{ "schemaVersion": 1, "command": "resolve", "team": "20827", "season": "2025-2026", "ok": true, "activeRules": [ { "id": "official.keep-customizations-in-teamcode", "topic": "build-customization-location", "title": "Keep build customizations in TeamCode", "instruction": "Put legacy FTC SDK build customizations in TeamCode/build.gradle instead of build.common.gradle.", "rationale": "The official SDK reserves build.common.gradle for changes delivered with SDK updates.", "status": "approved", "authority": "official", "applicability": { "teams": [], "seasons": [] }, "evidence": [ { "type": "git", "repository": "FIRST-Tech-Challenge/FtcRobotController", "commit": "26cd1fdd2a3c4b26173d9ff33a3279c27d1c7ad1", "file": "build.common.gradle", "symbol": "build.common.gradle" } ] } ], "conflicts": []}activeRules 中每条规则的字段:
| 字段 | 类型 | 说明 |
|---|---|---|
| id | string | 全局唯一规则 id(official.* / shared.* / team-<编号>.*) |
| topic | string | 规则主题 slug;同一 topic 的多条规则构成冲突 |
| title / instruction / rationale | string | 规则正文(英文) |
| status | string | approved 或 candidate;resolve 结果只含 approved |
| authority | string | official / shared / team |
| applicability.teams / applicability.seasons | string[] | 空数组 = 对所有队伍/赛季生效 |
| evidence | array | 每条证据带 type 字段,见下 |
| checks | array | 规则附带的机器可执行检查(kind/pattern/appliesTo/note;可能为空数组;见 docs/standardizer-check.md 与 ftckb check) |
兼容细节:resolve 输出 checks[].kind 使用 path_forbidden、path_required、regex_required、regex_forbidden;知识 YAML 的 kind 与 check 违规字段 check 使用连字符(例如 path-forbidden)。消费者不要混淆这两种现有字段形式。
证据两种形态(按 type 区分):
{"type":"git","repository":"FIRST-Tech-Challenge/FtcRobotController","commit":"26cd1fdd…","file":"build.common.gradle","symbol":"build.common.gradle","line":12}{"type":"web","url":"https://acmerobotics.github.io/ftc-dashboard/gettingstarted.html","title":"FTC Dashboard Getting Started","publisher":"FTC Dashboard","accessedAt":"2026-08-13","section":"Basic Installation","version":"0.6.0"}- git:
symbol、line仅在有值时出现。 - web:
version、product、sku仅在有值时出现。
3.3 resolve 存在冲突
Section titled “3.3 resolve 存在冲突”冲突时 ok:false、conflicts 非空、退出码 2(仍输出完整 activeRules):
{"schemaVersion":1,"command":"resolve","team":"20827","season":"2025-2026","ok":false,"activeRules":[…],"conflicts":[{"topic":"same-topic","authority":"official","ruleIds":["official.first","official.second"]}]}conflicts 元素字段:topic(string)、authority(string,裁决层级)、ruleIds(string[])。
3.4 所有失败路径(统一错误形状)
Section titled “3.4 所有失败路径(统一错误形状)”只要命令行里出现 --json,任何失败都输出单行 JSON:
{"schemaVersion":1,"command":"resolve","ok":false,"error":{"code":"usage","message":"missing --season"}}error.code 取值:
| code | 退出码 | 含义 |
|---|---|---|
| usage | 64 | 用法错误;message 为具体原因(missing –team / unknown command / invalid value for –season …) |
| load-error | 2 | 知识目录加载失败;message 形如 error loading knowledge: … |
| invalid-knowledge | 2 | 规则校验失败;额外带 violations 数组 |
| conflict | 2 | check 所需的生效规则存在冲突,不执行 diff 检查 |
invalid-knowledge 示例:
{"schemaVersion":1,"command":"validate","ok":false,"violations":[{"ruleId":"shared.invalid-commit","field":"evidence[0].commit","message":"commit must be a Git SHA"}],"error":{"code":"invalid-knowledge","message":"1 rule violation(s)"}}外部 Agent 应联合校验退出码、JSON Schema、command、team/season 和 ok/违规数组的一致性。非 JSON、不支持的 schemaVersion 或字段错误应停止,不能按检查通过处理;项目接入包装器会执行这些检查。
3.5 check 成功或硬违规
Section titled “3.5 check 成功或硬违规”{"schemaVersion":1,"command":"check","team":"16093","season":"2025-2026","ok":true,"violations":[],"soft":[{"ruleId":"shared.example","note":"需要实际验证的提醒"}]}violations 每项必有 ruleId/check/pattern/detail,可选 path/line;soft 每项包含 ruleId/note。无硬违规退出 0,存在硬违规退出 1;错误形状同 3.4。soft 非空并不导致硬失败,也不是已完成硬件验证。
默认变化集合合并 HEAD→index 与 HEAD→工作区,覆盖非忽略 untracked 文件,避免“暂存了违规、只在工作区撤销”漏检。路径规则包括删除、只删行和重命名前后路径;regex 仅看新增行。--diff 替代默认变化集合,空补丁合法,无法解析的非空补丁失败。详见 standardizer-check.md。
4. 确定性保证
Section titled “4. 确定性保证”activeRules按id字典序排序;conflicts按topic排序,ruleIds排序;applicability.teams/seasons排序。- 相同输入(knowledge-root 内容 + team + season)必定产生逐字节相同的 stdout。
- 输出不含运行时间戳(
evidence.accessedAt来自规则数据本身)。 - 规则裁决优先级固定:OFFICIAL > TEAM > SHARED;同主题同层级冲突上报而不是静默覆盖。
5. 文本模式(给人看)
Section titled “5. 文本模式(给人看)”不带 --json 时输出人类可读文本:
$ ftckb validate knowledgevalidation=ok rules=43$ ftckb resolve knowledge --team 20827 --season 2025-2026active official.keep-customizations-in-teamcodeactive shared.dashboard-pin-stable-dependency…$ ftckb resolve knowledge --team 20827 --season 2025-2026 # 有冲突时conflict topic=build-customization-location rules=official.a,shared.b # 退出码 26. 变更策略
Section titled “6. 变更策略”- 只增不改:新增字段、新增 error.code 是向后兼容的;删除/改名/改类型必须提升
schemaVersion。 - 消费方应以
schemaVersion==1判断兼容性,未知字段一律忽略。 - 相关测试:
apps/knowledge-cli/src/test/kotlin/org/ftckb/cli/KernelJsonAcceptanceTest.kt(含契约、确定性、冲突、错误形状共 7 个用例),这是契约的可执行定义。
7. 边界与已知限制
Section titled “7. 边界与已知限制”- 候选规则(status=candidate)只出现在
validate的ruleCount里,不会进入resolve。 --team会改变结果:20827 已批准 6 条队伍风格规则(比 16093 多 6 条 active 规则);16093 的队伍规则仍全部是 candidate。对接方请按队号分别裁决。- 程序输出的错误消息为英文;规则正文(title/instruction/rationale)为英文,界面文案(web 会话等)另做中文化。
chat/eval/serve不在本契约内:它们基于同一内核构建,但不是给机器消费的接口。- 规则冲突目前只能检测(退出码 2),不能自动裁决;由上层 Agent 决定如何处理。
8. 当前快照
Section titled “8. 当前快照”- 知识规则:43 条(37 approved + 6 candidate;12 条 RookieBot 项目实践已批准,candidate 仍含 4 条 Control Hub LED 官方候选)。
- 契约测试随
./gradlew test执行;接入 Python 测试与本次验收结果见docs/project-integration.md。 - 机器可消费工件:
docs/kernel-contract.schema.json与fixtures/kernel/*.json;除 validate/resolve 示例外,包含 check-pass、check-hard、check-error-usage/load/conflict 的实际输出。 - 所有命令支持
--help(退出码 0);ftckb --version输出的 CLI 版本(当前 1.0.0)与契约schemaVersion(当前 1)互相独立。 - 知识规则快照更新:2026-09-07。