跳转到内容

检查语义与已知限制

本仓库核心目的:规范和统一代码库,让所有 Agent 写出同一标准的代码。 知识库不只是“给 Agent 看规则的资料库”,而是规范器:

  • resolve = 告知:把生效规则(OFFICIAL > GLOBAL > LOCAL > SHARED 确定性裁决)交给任何 Agent;
  • check = 执法(本设计新增):对 Agent/队员的代码改动做确定性机器检查,违规即报, 通过才算符合标准。

闭环:任何 Agent 写码前 resolve 拿规则 → 写码 → 提交前 check 验证 → 报告附 check 结果。 规则作者在写规则的同时定义“怎么验证它”——检查引擎数据驱动,不硬编码规则内容。

终端窗口
# 默认合并 HEAD→index 与 HEAD→工作区(含非忽略 untracked)的变化
ftckb check <repo-root> --team 20827 --season 2025-2026 --generic-profile [--json]
# 或检查一个补丁/任意 diff(外部 Agent 常用:提交前自检)
ftckb check <repo-root> --team 20827 --season 2025-2026 --generic-profile --diff <file.patch> [--json]
# 显式 test/dev 工作模式(逐任务临时参数;用户明确指定时才使用)
ftckb resolve knowledge --team 20827 --season 2025-2026 --profile ftclib-command --work-mode test --json
ftckb check <repo-root> --team 20827 --season 2025-2026 --profile command-based --diff <file.patch> --work-mode dev --json

JSON 契约(沿用 kernel 风格,退出码扩展):

{
"schemaVersion": 2,
"command": "check",
"team": "20827", "season": "2025-2026", "profiles": [],
"ok": true,
"violations": [],
"soft": [
{"ruleId": "shared.limelight-check-result-validity",
"note": "Check that the latest Limelight result exists and is valid before using target or pose fields."}
]
}
  • 退出码:0 无硬违规;1 存在硬违规(violations 非空);2 知识/仓库加载、校验、上下文或规则冲突失败;64 参数错误。
  • 确定性:violations 按 ruleId+path+line 排序;soft 按 ruleId 排序;同输入同输出。
  • 判定范围:路径 checks 检查所有触及路径(含删除、只删行、空文件、重命名前后路径)。regex checks 只检查新增行,不报全库历史债;regex-required 按单条新增行匹配,regex-forbidden 先按单条新增行匹配,再可在连续新增行组成的同一块中跨行匹配。--diff 使用同样的路径/新增行语义;非空坏补丁报错,不静默通过。
  • 默认同时检查 HEAD→index 和 HEAD→工作区并去重,避免暂存违规仅在工作区撤销后漏检;仅存在于 index 的行号可能与当前文件不同,应结合 staged diff 阅读。
  • check 使用与 resolve 完全相同的生效规则集(含冲突检测),保证“告知什么就执法什么”。
  • --work-mode normal|test|dev 是逐任务临时参数,省略等同 normal,不写入项目配置、不改变 team/season/profile,也不能按文件名、路径或依赖推断;只有用户明确指定测试代码或 dev 代码时才选择。test 只把 global.command-responsibilities 与 shared.ftclib-command-candidate 移入 excludedRules(原因 work-mode-test),其余规则和硬检查(含 tests/utils 路径与 JUnit)继续执法。check --work-mode dev 必须提供本次改动的 --diff FILE(否则 usage/64),把每个 hard 命中连 ruleId/check/path/line/detail 转成 soft、violations 为空并退出 0,原有 soft 保留;加载/校验/冲突/坏补丁错误仍为 2/64。不能把 dev 输出描述为符合正式规则。

规则 YAML 可含 checks:(schema v3/v4;有 checks 的规则是硬检查)或 v4 的 reviewTriggers:(审阅触发元数据):

kind 语义 判定
path-forbidden 禁止改动命中路径 diff 触及 pattern 匹配的路径 → violation
path-required 改动必须包含命中路径 diff 未触及任何匹配路径 → violation(本身没有“改 X 才触发”的条件)
regex-required 新增行必须含模式 匹配 appliesTo 路径的已加行中没有任何一行命中 pattern → violation
regex-forbidden 新增行不得含模式 先检查每条已加行,再检查连续新增行块;任一命中 pattern → violation(行号=首次命中)

字段:kind、pattern(glob 或正则,见下)、appliesTo(可选 glob,限定路径)、note(人类可读说明)。 path-* 的 pattern 是 glob;regex-* 的 pattern 是 Java 正则,appliesTo 是路径 glob。

path-required 本身没有“改 X 才触发”的条件字段;它要求本次变化集合包含匹配路径。regex-required 在匹配文件的新增行集合中寻找模式,并非 Java 控制流分析。resolve JSON 的 kind 使用下划线形式,check 输出违规种类使用连字符形式。

YAML 示例:

- id: shared.limelight-check-result-validity
# ...既有字段...
reviewTriggers:
- paths: ["**/*.java"]
addedLinePatterns:
- '\b(?:Limelight3A|LLResult)\b'
- '\.(?:getLatestResult|getBotpose(?:_[A-Za-z0-9]+)?|getTargetTimestamp|getStaleness)\s*\('
- id: official.keep-customizations-in-teamcode
checks:
- kind: path-forbidden
pattern: "build.common.gradle"
note: "SDK 保留 build.common.gradle,定制放 TeamCode/build.gradle"
- id: global.vendor-documented-build-dependencies
checks: []
reviewTriggers:
- paths: ["build.dependencies.gradle"]
addedLinePatterns: []

规则校验器同步扩展:checks 字段的 kind 必须合法、pattern 必须可编译、note 非空; 非法 checks 让 validate 失败(规则作者写错会立刻被发现)。

硬检查(可机判,写进 checks):

规则 检查
official.keep-customizations-in-teamcode path-forbidden build.common.gradle
shared.ftc-sdk-pin-release regex-forbidden 依赖行含 +/SNAPSHOT(RobotCore/Hardware/Inspection)
shared.ftc-sdk-preserve-build-tooling path-forbidden gradle/wrapper/*、gradlew、gradlew.bat
shared.dashboard-pin-stable-dependency regex-forbidden dashboard 依赖行含 +/SNAPSHOT
global.test-utility-layout 跨赛季 path-forbidden 非规范 TeamCode tests/utils/source set 路径,及 regex-forbidden TeamCode JUnit import/dependency

软提示(行为/结构类,机器无法验证,check 输出 soft):

dependency-verify-sync-build-run、ftc-sdk-separate-toolchain-versions、 gobilda 四条(SKU/档位/伺服/PID)、limelight-back-up-before-os-update、limelight-configure-camera-pose、 limelight-synchronize-pipeline-dependent-reads、pedro 三条(坐标转换/定位先行/实机调参),以及由 reviewTriggers 命中时才输出的 Limelight validity/freshness 与 global.vendor-documented-build-dependencies 条件式 soft。

诚实声明:机器只对“能从 diff 文本确定性判定”的事项执法;行为类规则一律走 soft + 人工确认,不假装全能。

无 checks/无 trigger 的生效规则始终输出 soft;无 checks/有 reviewTriggers 的规则为条件式 soft,同一 trigger 的路径和新增行模式都匹配才输出一项 soft;有 checks 才产生硬 violations。两条 Limelight validity/freshness 规则保留 approved,使用第二种模式:无关 Java 不产生 Limelight soft,命中后若没有其他硬违规仍为退出码 0。仓库 V0.9.0 当前 5 条生效规则带硬检查;跨赛季 global.test-utility-layout 对可确定的错误路径/JUnit 新增以退出码 1 阻止,机器人侧 OpMode 的规范路径为 TeamCode/src/main/java/org/firstinspires/ftc/teamcode/tests/,复用工具的规范路径为 TeamCode/src/main/java/org/firstinspires/ftc/teamcode/utils/。完整 Agent instruction 仍负责不能可靠机判的语义分类;目标 TeamCode 禁用 JUnit/source set 不影响 Knowledge Bank 自身的 Kotlin/CLI JUnit 测试。global.vendor-documented-build-dependencies 是第三条路径触发的条件式 soft:任何对根目录 build.dependencies.gradle 的新增、修改、删除或重命名都只输出一项 soft 并要求 Agent 提供第一方厂商文档/固定 commit、精确依赖版本和 diff 逐项对应,但规则引擎不联网、不鉴别域名、不验证证据真伪,soft 不代表机器已证明合规或违规,也不会把该文件改动变成静默通过。soft 只请求人工/模型审阅,不是机器已证明违规或真机验证,Agent 必须向用户报告每个 soft。

4. 分阶段计划(M1–M4 已交付,M5 即文档合并)

Section titled “4. 分阶段计划(M1–M4 已交付,M5 即文档合并)”

状态:M1 schema v3 + checks 模型 ✅;M2 检查引擎 + ftckb check + 离线测试 ✅; M3 硬检查规则落地(历史 V0.5.0 为 4 条生效规则含 checks,Limelight 改为条件式 soft)+ 正反例冒烟 ✅;V0.6.0 已加入第 5 条 global.test-utility-layout;V0.7.0 收窄 official build-file 硬保护到 build.common.gradle,并为 build.dependencies.gradle 加入 global.vendor-documented-build-dependencies 条件式 soft;M4 standardizer 模块(CLI 与 AS 插件共用)+ 插件 Edit 后自动检查 + scripts/check-gate.sh CI 门禁 ✅;已合并 main。

  • M1 schema v3 + 领域模型:Checks 模型、RuleYamlCodec/RuleValidator 扩展、resolve –json 增量输出 checks(契约只增不改);全部既有测试绿。
  • M2 检查引擎 + ftckb check:diff 解析(jgit 默认 + --diff 补丁)、四类检查、JSON 契约、退出码、 确定性排序;离线单测覆盖四类检查与边界(空 diff、坏补丁、冲突规则)。
  • M3 覆盖落地:为硬检查规则写 checks + 负例/正例 fixture;validate 全绿; 真实仓库上 check 冒烟(对一份违规 diff 与一份合规 diff)。
  • M4 接入面:CI 示例(PR gate 脚本)、AS 插件 Edit 后自动 check 并在 diff viewer 标注、 eval 增加 check 场景、README/AGENTS.md 更新“规范器”定位。
  • M5 文档合并:docs/standardizer-check.md(本文件)+ kernel-contract.md 契约章节 + 推送合并。
  • kernel JSON v2 返回 normalized profiles;resolve/check 必须选择同一 profile(generic 是显式空集)。两者不需要 API key。

  • YAML v4 的 reviewTriggers 是审阅触发元数据,不是新增硬检查类型,也不能替代 checks 或人工审阅;它只让无 checks 的规则成为条件式 soft。

  • 来源 authority 不等于 policyLevel;official 来源最高,其余按 global/local/shared 裁决。candidate、队号/赛季/profile 不匹配不执法。

  • check 不执行任何代码/构建/测试;只做静态文本判定。

  • 只对 diff 判定;全库历史债不在 v1 范围(后续可加 --full 扫描)。

  • 规则冲突时 check 与 resolve 行为一致:先报冲突(退出码 2),不猜测裁决。