suimenqx/lua-nil-guard
GitHub: suimenqx/lua-nil-guard
面向 Lua 开发者的精准 nil 风险审查工具,结合静态分析与 LLM 推理检测运行时空指针隐患。
Stars: 0 | Forks: 0
# LuaNilGuard
`lua-nil-guard` 是一个面向开发者的 CLI 工具,用于审查 Lua 代码中可能存在的 nil 相关运行时错误。其支持的运行模式是源码树使用:保持此代码库完整,从检出目录运行,并将该工具指向您想要检查的 Lua 代码库。
中文文档:[README.zh-CN.md](./README.zh-CN.md)
## 环境要求
- Python 3.12+
- 本代码库的源码检出
- 在此检出目录运行 `pip install -e .`
## 快速入门
1. 创建并激活一个虚拟环境。
2. 以可编辑模式安装项目:
```
pip install -e .
```
每个 Python 环境只需运行一次。仅在切换环境或进行打包更改(如依赖项或 CLI 入口点更新)后才需要重新运行。
3. 在运行分析之前,验证 Tree-sitter 是否可用:
```
lua-nil-guard doctor
```
4. 初始化目标代码库配置:
```
lua-nil-guard init-config /path/to/target-repo
```
5. 默认情况下,LuaNilGuard 会在审查扫描和宏缓存解析中跳过 `id.lua` 和 `*_id.lua` 文件,因此巨大的生成字典不会影响响应时间。如果您想从选定文件中提取编译时事实,请配置 `config/preprocessor_files.json`,然后审计/缓存工具可提取的内容:
```
lua-nil-guard macro-audit /path/to/target-repo
lua-nil-guard macro-build-cache /path/to/target-repo
lua-nil-guard macro-cache-status /path/to/target-repo
```
配置的预处理器文件仅被视为预处理器输入:它们提供编译时的非 nil 事实,但不会作为普通的业务 Lua 代码被扫描审查。
LuaNilGuard 为这些配置的文件编译并重用本地宏缓存,因此重复运行不需要重新解析未更改的大型字典文件。
6. 如果代码库可能包含旧版编码的 Lua 文件,请先审计并规范化它们:
```
lua-nil-guard encoding-audit /path/to/target-repo
lua-nil-guard normalize-encoding --write /path/to/target-repo
```
7. 运行静态扫描:
```
lua-nil-guard scan /path/to/target-repo
```
8. 运行完整报告:
```
lua-nil-guard report /path/to/target-repo
```
## 持久运行工作流
对于支持恢复/状态/报告/导出的长时间运行代码库审查任务,请使用:
```
lua-nil-guard run-start [--trace-level summary|debug|forensic] /path/to/target-repo
lua-nil-guard run-status /path/to/target-repo [run_id]
lua-nil-guard run-report /path/to/target-repo [run_id]
lua-nil-guard run-export-json /path/to/target-repo [run_id] [output]
lua-nil-guard run-resume [--trace-level summary|debug|forensic] /path/to/target-repo
lua-nil-guard run-trace [--case-id CASE_ID] /path/to/target-repo [run_id]
lua-nil-guard run-trace-json [--case-id CASE_ID] /path/to/target-repo [run_id] [output]
lua-nil-guard case-replay /path/to/target-repo
lua-nil-guard case-replay-json /path/to/target-repo [output]
```
`run-status` 和 `run-report` 现在包含阶段指标和未知原因分布,包括:
- 候选/源计数器(`ast_exact`, `lexical_fallback`)
- 静态分析模式计数器(`ast_lite`, `domain_pruned`)
- 静态层计数器(`safe_static`, `unknown_static`)
- 生命周期计数器(`pruned_cases`, `llm_enqueued`, `llm_processed`, `llm_resolved`)
- 比率指标(`prune_rate`, `submission_rate`, `llm_resolution_rate`)
- 端到端延迟(`end_to_end_latency_seconds`)
- LLM 层计数器(`llm_enqueued`, `llm_processed`, `llm_second_hop`)
- 验证层计数器(`safe_verified`, `risky_verified`)
- `unknown_static` 情况的 `unknown_reason` 分布
有关完整的调优和候选级可观察性查询,请参阅 [`docs/run-tuning.md`](docs/run-tuning.md)。
### 后端交互跟踪与案例回放
当您需要可审计的后端交互时间线和单案例回放时,请使用此功能:
```
lua-nil-guard run-start --trace-level debug /path/to/target-repo
lua-nil-guard run-trace /path/to/target-repo [run_id]
lua-nil-guard case-replay /path/to/target-repo
lua-nil-guard clear-trace-artifacts /path/to/target-repo [run_id]
```
`case-replay-json` 包含一个规范化的 `decision_trace` 对象(`verdict`, `risk_path`, `safety_evidence`, `counterarguments_considered`, `missing_evidence`, `evidence_refs`, `uncertainty_reason`),用于下游审计仪表板。
跟踪级别:
- `summary`(默认):仅元数据/时间线
- `debug`:包含 prompt 和结构化响应负载
- `forensic`:包含 stderr/原始信封字段(必须通过 `--trace-level forensic` 显式启用)
默认跟踪行为由 `config/trace_policy.json` 控制:
```
{
"default_trace_level": "summary",
"max_inline_payload_bytes": 65536,
"redact_patterns": [
"(?i)(authorization\\s*[:=]\\s*)([^\\s,;]+)",
"(?i)(api[_-]?key\\s*[:=]\\s*)([^\\s,;]+)"
]
}
```
安全护栏:`config/trace_policy.json` 的 `default_trace_level` 不能设置为 `forensic`。请使用 `summary`/`debug` 作为默认值,并仅在显式审计运行时传递 `--trace-level forensic`。
当负载大小超过 `max_inline_payload_bytes` 时,跟踪负载会溢出存储在 `.lua_nil_guard/traces//...` 下,而数据库行保留描述符(路径/哈希/字节)。
`run-export-json` 现在导出一个结构化对象:
```
{
"run": {
"run_id": 12,
"stage_metrics": {
"static": {"total_cases": 120, "safe_static_cases": 80, "unknown_static_cases": 40},
"queue": {"llm_enqueued_cases": 40},
"llm": {"llm_processed_cases": 40, "llm_second_hop_cases": 7},
"verify": {"safe_verified_cases": 86, "risky_verified_cases": 21},
"finalize": {"completed_cases": 120, "failed_cases": 0}
},
"candidate_metrics": {
"ast_lite_cases": 120
},
"unknown_reason_distribution": [
{"reason": "no_bounded_ast_proof", "count": 31}
]
},
"findings": [
{
"case_id": "...",
"status": "risky_verified",
"confidence": "high"
}
]
}
```
如果您想要一个仅关注字符串库和字符串连接 nil 隐患的快速初次扫描,请使用:
```
lua-nil-guard scan --focus string /path/to/target-repo
lua-nil-guard report --focus string /path/to/target-repo
```
## 单文件审查
如果您只想检查一个 Lua 文件,请使用文件入口点。该文件仍需位于已通过 `init-config` 初始化的代码库中。
```
lua-nil-guard scan-file /path/to/target-repo/src/demo.lua
lua-nil-guard report-file /path/to/target-repo/src/demo.lua
lua-nil-guard report-file-json /path/to/target-repo/src/demo.lua
```
对于仅针对字符串的单文件检查:
```
lua-nil-guard scan-file --focus string /path/to/target-repo/src/demo.lua
lua-nil-guard report-file --focus string /path/to/target-repo/src/demo.lua
```
单文件审查保留代码库上下文,因此在裁决期间仍可使用跨文件函数摘要和相关函数源片段。
## 默认高风险覆盖范围
开箱即用,LuaNilGuard 优先处理通常会导致立即运行时错误的 Lua nil 隐患:
- 字符串库首个参数接收器,例如 `string.find`, `string.match`, `string.gsub`, `string.sub`, `string.len`, `string.byte`, `string.lower` 和 `string.upper`
- 使用 `..` 的字符串连接(两个操作数均独立检查)
- 通过 `pairs(...)` 和 `ipairs(...)` 进行的表迭代
- 使用 `#value` 的长度运算符
- 数字顺序比较:`<`, `<=`, `>`, `>=`(`==` 和 `~=` 被有意排除)
- 数字算术:`+`, `-`, `*`, `/`, `%`, `^`(两个操作数均独立检查)
这些模式是默认 `sink_rules.json` 模板的一部分,旨在成为试用期间首个对客户可见的价值面。`member_access.receiver` 有意默认不启用;如果您的代码库需要广泛的接收器 nil 检查,请手动添加。
## 推荐首次运行
对于首次试用,请勿从完整的代码库扫描开始。从一个有代表性的 Lua 文件开始,只有在结果过于不确定时才收紧配置。
1. 初始化目标代码库一次:
```
lua-nil-guard init-config /path/to/target-repo
```
2. 首先验证解析器环境:
```
lua-nil-guard doctor
```
3. 如果代码库是由较旧的 Windows 工具编辑的,请先运行编码检查:
```
lua-nil-guard encoding-audit /path/to/target-repo
lua-nil-guard normalize-encoding --write /path/to/target-repo
```
4. 选择一个包含已知 nil 敏感调用的真实文件并运行:
```
lua-nil-guard report-file /path/to/target-repo/src/demo.lua
```
5. 如果结果已经是 `risky` 或 `safe`,请在转向更广泛的扫描之前继续在小文件上迭代。
6. 如果结果大部分是 `uncertain`,请检查该文件是否依赖于当前代码库检出中未定义的辅助函数。在这种情况下,请向 `config/function_contracts.json` 添加窄契约,而不是立即扩大扫描范围。
典型示例:
- 一个证明其参数为非 nil 的防护辅助函数:
```
[
{
"qualified_name": "assert_present",
"ensures_non_nil_args": [1]
}
]
```
- 一个仅在使用已知回退值调用时才安全的规范化器:
```
[
{
"qualified_name": "normalize_name",
"returns_non_nil": true,
"applies_with_arg_count": 2,
"required_literal_args": {
"2": "''"
},
"applies_to_call_roles": ["assignment_origin", "sink_expression"]
}
]
```
7. 更新契约后重新运行同一文件。只有在几个有代表性的文件表现良好后,您才应该继续执行:
```
lua-nil-guard report /path/to/target-repo
```
8. 如果您想查看工具仍然无法证明的内容,请检查提案积压:
```
lua-nil-guard proposal-analytics /path/to/target-repo
```
此报告在您已经尝试了几次单文件运行后最有用。它有助于区分:
- 真正未解决的可能需要新的有界识别器的模式
- 可能需要显式契约的辅助函数
如果您的代码库使用巨大的预处理器样式宏字典文件(例如,在构建时使用的 `NAME = ""` 或 `Defaults.Name = 0` 文件),请在 `config/preprocessor_files.json` 中配置您想解析的文件,然后运行:
```
lua-nil-guard macro-audit /path/to/target-repo
lua-nil-guard macro-build-cache /path/to/target-repo
lua-nil-guard macro-cache-status /path/to/target-repo
```
`macro-audit` 显示:
- 加载了哪些配置的宏文件
- 哪些宏行被转换为编译时事实
- 哪些行因为超出了受支持的有界语法而未被解析
`macro-build-cache` 预构建编译好的宏缓存,`macro-cache-status` 告知您缓存是否新鲜或需要重建。当缓存新鲜时,正常的审查命令也会自动重用该缓存。当匹配的预处理器文件发生更改、有效的预处理器文件配置发生更改或缓存模式发生更改时,缓存会自动重建。
## 后端
代码库 CLI 命令现在在省略 `--backend` 时从 `config/backend.json` 解析默认后端:
```
{
"default_backend": "codex"
}
```
如果既未提供 `--backend` 也未提供 `config/backend.json`,命令将以显式设置提示退出。
您也可以使用 `--backend` 选择其他受支持的 CLI 集成:
- `gemini`
- `claude`
- `codex`
- `heuristic`(仅限调试/测试)
服务层 API(`run_repository_review`, `run_file_review`, `run_repository_review_job`, `benchmark_repository_review` 和 `draft_review_improvements`)在未编程提供 `backend` 时仍默认为 `codex`。
示例:
```
lua-nil-guard report --backend gemini /path/to/target-repo
lua-nil-guard report-file --backend gemini /path/to/target-repo/src/demo.lua
```
这些后端需要相应的本地 CLI 工具、凭据和机器上的网络访问已经正常工作。对于自定义提供商,请使用以下命令生成起始清单:
```
lua-nil-guard generate-backend-manifest my-provider stdout_envelope_cli
```
### Codex 审查手册
基于 Codex 的 Lua nil 风险审查的推荐命令路径:
1. 预检查:
```
codex exec --version
lua-nil-guard doctor
```
2. 首先在一个文件上验证:
```
lua-nil-guard report-file \
--backend codex \
--model gpt-5.1-codex-mini \
--backend-config 'model_reasoning_effort="high"' \
/path/to/target-repo/src/demo.lua
```
3. 扩展到代码库审查:
```
lua-nil-guard report \
--backend codex \
--model gpt-5.1-codex-mini \
--backend-config 'model_reasoning_effort="high"' \
/path/to/target-repo
```
4. 运行基准测试并检查质量/延迟:
```
lua-nil-guard benchmark \
--backend codex \
--model gpt-5.1-codex-mini \
--backend-config 'model_reasoning_effort="high"' \
/path/to/labeled-repo
```
基准测试说明:标记文件必须遵循 `provable_risky_*`, `provable_safe_*` 或 `provable_uncertain_*` 命名。
如果基准测试准确率意外较低且 `backend_fallbacks` 很高(或等于总案例数),请首先检查后端故障:
```
lua-nil-guard benchmark-json \
--backend codex \
--model gpt-5.1-codex-mini \
--backend-config 'model_reasoning_effort="high"' \
/path/to/labeled-repo \
build/benchmark_codex.json
```
然后检查 JSON 中的 `cases[*].backend_failure_reason`。一个常见问题是 `~/.codex/config.toml` 中存在不兼容的全局 Codex 设置,例如为仅支持 `low|medium|high` 的模型设置了 `model_reasoning_effort = "xhigh"`。每次运行时使用 `--backend-config 'model_reasoning_effort="high"'` 覆盖或更新您的全局 Codex 配置。
### Gemini 审查手册
基于 Gemini 的 Lua nil 风险审查的推荐命令路径:
1. 预检查:
```
gemini --version
lua-nil-guard doctor
```
2. 首先在一个文件上验证:
```
lua-nil-guard report-file \
--backend gemini \
--backend-timeout 90 \
--backend-attempts 1 \
/path/to/target-repo/src/demo.lua
```
3. 扩展到代码库审查:
```
lua-nil-guard report \
--backend gemini \
--backend-timeout 90 \
--backend-attempts 1 \
/path/to/target-repo
```
4. 基准测试并导出 JSON 以供诊断:
```
lua-nil-guard benchmark-json \
--backend gemini \
--backend-timeout 90 \
--backend-attempts 1 \
/path/to/labeled-repo \
build/benchmark_gemini.json
```
基准测试说明:标记文件必须遵循 `provable_risky_*`, `provable_safe_*` 或 `provable_uncertain_*` 命名。
实用调优指南:
- 如果 `backend_fallbacks` 或 `backend_timeouts` 很高,请首先增加 `--backend-timeout`(推荐范围:`60-120` 秒)。
- 保持 `--backend-attempts 1` 以获得稳定的链接和较低的延迟;当存在网络/API 抖动时使用 `2` 或 `3`。
- 如果您在 `cases[*].backend_failure_reason` 中看到 `ERR_STREAM_PREMATURE_CLOSE`,请将其视为瞬态后端传输故障,并使用更高的 `--backend-attempts` 重试。
- 首先使用默认的 Gemini 模型;如果您切换到更快的模型(例如 `--model gemini-2.5-flash`),请再次验证超时行为,因为延迟和响应稳定性可能不同。
在 `examples/mvp_cases/agent_semantic_suite` 上的本地实践观察(2026 年 3 月 7 日):
- `--backend-timeout 25 --backend-attempts 1`:所有案例回退,基准测试严重降级。
- `--backend-timeout 90 --backend-attempts 1`:`17/18` 精确匹配(`94.4%`),其中一个回退是由瞬态 `ERR_STREAM_PREMATURE_CLOSE` 引起的。
有关紧凑的分步指南(包括自定义后端清单设置和模型固定),请参阅 [`docs/gemini-playbook.md`](docs/gemini-playbook.md)。
## 代码库布局
目标代码库预期包含:
- `config/sink_rules.json`
- `config/confidence_policy.json`
- `config/function_contracts.json`
- `config/preprocessor_files.json`
- `config/domain_knowledge.json`
- `config/backend.json`
- `config/trace_policy.json`
`init-config` 将所有七个文件的默认版本写入目标代码库。`function_contracts.json` 允许您声明高置信度的包装函数(例如 `normalize_name` 总是返回非 nil 值)、通过 `ensures_non_nil_args` 实现的辅助防护(例如 `assert_profile(profile)`)、以及通过 `returns_non_nil_from_args` 声明的从特定参数返回默认非 nil 值的规范化器。对于多返回值辅助函数,您可以使用 `returns_non_nil_from_args_by_return_slot` 进一步按消耗的返回槽划分这些参数要求,这样槽 `1` 和槽 `2` 就不必共享相同的安全前提条件。您还可以通过使用 `requires_guarded_args_by_return_slot` 要求某些输入参数在信任特定返回槽之前已被防护,这使得防护辅助函数契约和后续的规范化器契约可以在一条证明链中协同工作您还可以使用 `applies_in_modules` 将契约限制为特定的调用方模块,使用 `applies_in_function_scopes` 限制为特定的调用方函数作用域,使用 `applies_to_scope_kinds`(`top_level`, `function_body`)限制作用域类型,使用 `applies_to_top_level_phases`(`init`, `post_definitions`)限制顶层阶段,使用 `applies_to_sinks` 限制特定的 sink 规则或 sink 名称,使用 `applies_to_call_roles`(`assignment_origin`, `sink_expression`, `guard_call`)限制特定的调用位置,使用 `applies_to_usage_modes`(`single_assignment`, `multi_assignment`, `direct_sink`)限制特定的返回值使用模式,使用 `applies_to_return_slots` 限制特定的选定返回槽(例如多返回辅助函数中的仅返回槽 `1`),使用 `applies_with_arg_count` 限制特定的调用元数,使用 `required_literal_args` 限制精确的字面量参数,使用 `required_arg_shapes`(`identifier`, `member_access`, `indexed_access`, `literal`, `call`, `expression`)限制参数源形状,使用 `required_arg_roots`(例如 `req`, `ngx` 或 `fallbacks`)限制参数根符号,使用 `required_arg_prefixes`(例如 `req.params` 或 `ngx.var`)限制点分访问路径前缀,以及当辅助函数仅对一条精确查找路径可信时,使用 `required_arg_access_paths`(例如 `req.params.user` 或 `req.params[1]`)限制精确的规范化访问链。带引号的字面量表键(如 `req.params["user"]`)会规范化为相同的 `req.params.user` 路径,而动态索引(如 `req.params[token]`)不计入精确匹配。这有助于在不依赖仅提示推理的情况下抑制误报。
`sink_rules.json` 故意默认不包含 `member_access.receiver`。当您的团队需要广泛的接收器检查时,请显式添加:
```
{
"id": "member_access.receiver",
"kind": "receiver",
"qualified_name": "member_access",
"arg_index": 0,
"nil_sensitive": true,
"failure_mode": "runtime_error",
"default_severity": "high",
"safe_patterns": ["assert(x)", "if x then ... end"]
}
```
`domain_knowledge.json` 支持对已知安全符号族进行确定性的零 AST 快速修剪。默认模板包含 `_name_*` 表、`_cmd_*` 表和全大写下划线宏的规则:
```
{
"rules": [
{
"id": "system_name_table_prefix",
"action": "skip_candidate",
"symbol_regex": "^_name_[A-Z0-9_]+(?:\\.[A-Za-z_][A-Za-z0-9_]*)*$",
"applies_to_sinks": ["member_access.receiver", "pairs.arg1", "ipairs.arg1", "length.operand"]
},
{
"id": "uppercase_macro_non_nil",
"action": "skip_candidate",
"symbol_regex": "^[A-Z][A-Z0-9]*(?:_[A-Z0-9]+)+$",
"applies_to_sinks": []
}
]
}
```
新代码库的快速入门配置流程:
1. 保留 `lua-nil-guard init-config` 的默认值。
2. 仅当您的团队需要接收器范围的检查时,才添加 `member_access.receiver`。
3. 首先为您的命名约定添加窄域规则,然后扩展。
示例:`_id_.*` 符号被视为稳定的非 nil 数字值:
```
{
"id": "id_numeric_non_nil",
"action": "skip_candidate",
"symbol_regex": "^_id_[A-Z0-9_]+$",
"applies_to_sinks": [
"compare.lt.left",
"compare.lt.right",
"compare.lte.left",
"compare.lte.right",
"compare.gt.left",
"compare.gt.right",
"compare.gte.left",
"compare.gte.right",
"arithmetic.add.left",
"arithmetic.add.right",
"arithmetic.sub.left",
"arithmetic.sub.right",
"arithmetic.mul.left",
"arithmetic.mul.right",
"arithmetic.div.left",
"arithmetic.div.right"
],
"assumed_non_nil": true,
"assumed_kind": "number"
}
```
示例:全局默认表变量始终存在:
```
{
"id": "global_default_tables",
"action": "skip_candidate",
"symbol_regex": "^_g_[A-Z0-9_]+(?:\\.[A-Za-z_][A-Za-z0-9_]*)*$",
"applies_to_sinks": [
"member_access.receiver",
"pairs.arg1",
"ipairs.arg1",
"length.operand"
],
"assumed_non_nil": true,
"assumed_kind": "table"
}
```
实用护栏:
- 从精确前缀(`^_name_`, `^_cmd_`, `^_id_`)开始,而不是宽泛的模式。
- 在使用通用作用域之前添加 sink 作用域(`applies_to_sinks`)。
- 首先使用一个文件进行验证(`report-file`),然后扩展到代码库扫描。
`preprocessor_files.json` 控制巨大生成 Lua 文件的分类:
- `preprocessor_files` / `preprocessor_globs`:作为宏字典解析(仅编译时事实,无普通候选扫描)
- `skip_review_files` / `skip_review_globs`:完全跳过(无扫描、无宏解析、无缓存工作)
默认模板:
```
{
"preprocessor_files": [],
"preprocessor_globs": [],
"skip_review_files": [],
"skip_review_globs": ["id.lua", "*_id.lua"]
}
```
如果您确实想将选定的 `id.lua` 样式文件作为宏字典解析,请将这些规则移至 `preprocessor_*` 并从 `skip_review_*` 中移除。
LuaNilGuard 可以提取有界事实,例如:
- `NAME = ""`
- `COUNT = 0`
- `AAA = 0x100`(规范化为十进制以进行数字检查)
- `Defaults.Name = ""`
- `cmd_id.dis = {0x14, "display"}`(被识别为非 nil 表字面量)
- `ALIAS = NAME`
对于点分赋值(例如 `a.b = 1`),LuaNilGuard 还推断父表存在(`a`)作为非 nil 表事实。然后,这些事实被用于抑制高价值 nil 隐患检查中的误报,同时保持报告锚定到开发人员编辑的原始源文件。
## 裁决模式
LuaNilGuard v3 始终使用单遍结构化裁决。
`--adjudication-mode` 已从 CLI 中移除。
`config/adjudication_policy.json` 也仅支持 `single_pass`。
## 校准
运行审查后,使用 `calibration-status` 检查离线校准数据:
```
lua-nil-guard calibration-status /path/to/target-repo
```
校准桶按 sink 类型和未知原因跟踪历史精度。当积累足够样本时,系统可以自动降级过度自信的 LLM 结论。
## 增量分析
对于 PR 级别的工作流,使用 `run-incremental` 仅重新分析受更改影响的文件:
```
lua-nil-guard run-incremental --changed-files src/a.lua,src/b.lua /path/to/target-repo
```
这需要之前的完整运行(`run-start`)已经填充了文件指纹和依赖数据。如果增量分析不可用,它将建议回退到完整运行。
## Nil Guard 注解
开发人员可以使用 `--- @nil_guard` 注解来声明 nil 契约:
```
--- @nil_guard: returns_non_nil
function normalize_name(raw)
return raw or ""
end
```
LuaNilGuard 使用注解作为跨函数推理的高优先级证据。有关完整的语法参考,请参阅 `docs/annotations.md`。
相关命令:
```
lua-nil-guard annotation-coverage /path/to/target-repo
lua-nil-guard annotation-suggest /path/to/target-repo/src/demo.lua
```
## 注意事项
- 此版本旨在供开发者试用。在大型代码库中使用之前,请先从几个真实文件或一个小模块开始。
- 正式分析命令(`scan`, `report`, `report-file`, `benchmark` 和提案命令)需要 Tree-sitter。如果 `doctor` 报告 Tree-sitter 不可用,请先修复解析器环境,而不是依赖降级模式。
- LuaNilGuard 仅使用通过 `cc`, `gcc` 或 `clang` 在本地编译的 vendored Lua 语法。它不会回退到外部安装的 `tree_sitter_lua` 包,因此解析器行为在不同机器间保持可复现。
- Lua 源文件应为 UTF-8。使用 `encoding-audit` 查找非 UTF-8 的 `.lua` 文件,并在审查前使用 `normalize-encoding --write` 转换受支持的旧版文件(`utf-8-sig`, `gb18030`)。
- 当重要的辅助函数要么存在于同一代码库中,要么在 `config/function_contracts.json` 中有表示时,单文件审查效果最佳。
- 缺少辅助定义不会阻止审查,但会降低跨文件证明强度,并可能增加 `uncertain` 结果。
- 裸全局 `require("module.name")` 声明在 nil 风险审查中被视为非 nil 模块符号,因此成员访问检查不会重复报告这些模块接收器为 nil 风险。
- 当前实现针对精度而非完整覆盖范围进行了优化。当无法证明有界的安全或有风险路径时,它将保持保守。
- 大型代码库性能工作(如全局 AST 缓存、增量 PR 分析和并发)已计划,但不包含在此版本中。目前,模块级或文件级试用是推荐的推广路径。
- 源码树或可编辑安装使用是受支持的路径。默认裁决器技能作为包数据打包,但 vendored Lua 语法构建仍依赖此代码库检出。
- `docs/` 下的内置文档更详细地涵盖了 prompt 结构和 sink 规则语义。
标签:Bug检测, Lua, Python, Roblox, Tree-sitter, 威胁情报, 开发者工具, 数据管道, 文档结构分析, 无后门, 游戏开发辅助, 空指针检查, 编码规范化, 软件工程, 运行时错误预防, 错误基检测, 静态代码分析, 静态分析器, 风险审查