跳转到内容

CLI 与 JSON 契约

面向对象:对接本知识库的外部 Agent(Codex / Claude Code / DSH 会话 / 任意脚本)。 本文档描述 validateresolvecheck稳定、版本化、确定性机器接口。 chat / eval 是本地交互模式,不属于本契约。

代码位于仓库默认分支 main(开发分支 codex/cli-agent 会合并回 main)。

终端窗口
# 正常环境(JDK 21+ 运行;JDK 21 编译工具链可由 Foojay resolver 下载):
git clone https://github.com/lucasnotfound59/FTC-Knowledge-Bank.git
cd 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 结果)。

命令 形式 说明
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 用法错误(未知命令、缺/错参数)

所有 JSON 输出都是单行(无换行、无日志噪音)写往 stdout。顶层必有:

  • schemaVersion:整数,当前恒为 1;破坏性变更必须提升版本号。
  • ok:布尔。
  • command"validate""resolve""check"(未知命令的用法错误没有此字段)。
{"schemaVersion":1,"command":"validate","ok":true,"ruleCount":43,"violations":[]}

ruleCount 为加载到的规则总数(含候选)。退出码 0。

{
"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 approvedcandidate;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_forbiddenpath_requiredregex_requiredregex_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:symbolline 仅在有值时出现。
  • web:versionproductsku 仅在有值时出现。

冲突时 ok:falseconflicts 非空、退出码 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 或字段错误应停止,不能按检查通过处理;项目接入包装器会执行这些检查。

{"schemaVersion":1,"command":"check","team":"16093","season":"2025-2026","ok":true,"violations":[],"soft":[{"ruleId":"shared.example","note":"需要实际验证的提醒"}]}

violations 每项必有 ruleId/check/pattern/detail,可选 path/linesoft 每项包含 ruleId/note。无硬违规退出 0,存在硬违规退出 1;错误形状同 3.4。soft 非空并不导致硬失败,也不是已完成硬件验证。

默认变化集合合并 HEAD→index 与 HEAD→工作区,覆盖非忽略 untracked 文件,避免“暂存了违规、只在工作区撤销”漏检。路径规则包括删除、只删行和重命名前后路径;regex 仅看新增行。--diff 替代默认变化集合,空补丁合法,无法解析的非空补丁失败。详见 standardizer-check.md

  • activeRulesid 字典序排序;conflictstopic 排序,ruleIds 排序;applicability.teams/seasons 排序。
  • 相同输入(knowledge-root 内容 + team + season)必定产生逐字节相同的 stdout。
  • 输出不含运行时间戳(evidence.accessedAt 来自规则数据本身)。
  • 规则裁决优先级固定:OFFICIAL > TEAM > SHARED;同主题同层级冲突上报而不是静默覆盖。

不带 --json 时输出人类可读文本:

$ ftckb validate knowledge
validation=ok rules=43
$ ftckb resolve knowledge --team 20827 --season 2025-2026
active official.keep-customizations-in-teamcode
active shared.dashboard-pin-stable-dependency
$ ftckb resolve knowledge --team 20827 --season 2025-2026 # 有冲突时
conflict topic=build-customization-location rules=official.a,shared.b # 退出码 2
  • 只增不改:新增字段、新增 error.code 是向后兼容的;删除/改名/改类型必须提升 schemaVersion
  • 消费方应以 schemaVersion==1 判断兼容性,未知字段一律忽略。
  • 相关测试:apps/knowledge-cli/src/test/kotlin/org/ftckb/cli/KernelJsonAcceptanceTest.kt(含契约、确定性、冲突、错误形状共 7 个用例),这是契约的可执行定义。
  • 候选规则(status=candidate)只出现在 validateruleCount 里,不会进入 resolve
  • --team 会改变结果:20827 已批准 6 条队伍风格规则(比 16093 多 6 条 active 规则);16093 的队伍规则仍全部是 candidate。对接方请按队号分别裁决。
  • 程序输出的错误消息为英文;规则正文(title/instruction/rationale)为英文,界面文案(web 会话等)另做中文化。
  • chat / eval / serve 不在本契约内:它们基于同一内核构建,但不是给机器消费的接口。
  • 规则冲突目前只能检测(退出码 2),不能自动裁决;由上层 Agent 决定如何处理。
  • 知识规则:43 条(37 approved + 6 candidate;12 条 RookieBot 项目实践已批准,candidate 仍含 4 条 Control Hub LED 官方候选)。
  • 契约测试随 ./gradlew test 执行;接入 Python 测试与本次验收结果见 docs/project-integration.md
  • 机器可消费工件:docs/kernel-contract.schema.jsonfixtures/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。