Skip to content

Commit cfe5cb5

Browse files
committed
docs(spec): hook-protocol 调用形态归因 delta + openspec 校验债清零
- hook-protocol MODIFIED delta:非 Shell 间接按 exec/subprocess 调用形态归因(5 场景) - dot-prefix change 三条 requirement 补 RFC2119 规范句 - gate-full-scan-excludes 补 skip_specs(工具类修正先例) - 7 份主规格 Purpose 占位符换成真实描述(openspec 1.13.1 strict 要求) - openspec validate --all --strict 全绿(门禁同款二进制 exit=0)
1 parent 75e49b8 commit cfe5cb5

10 files changed

Lines changed: 45 additions & 10 deletions

File tree

  • openspec
    • changes
      • 2026-09-22-gate-full-scan-excludes
      • 2026-09-23-dot-prefix-default-skip/specs/scan-scope-policy
      • 2026-09-23-fix-release-chain-and-gate-attribution/specs/hook-protocol
    • specs
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
schema: spec-driven
2+
created: 2026-09-22
3+
skip_specs: true

‎openspec/changes/2026-09-23-dot-prefix-default-skip/specs/scan-scope-policy/spec.md‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
### Requirement: Check and save faces MUST skip dot-prefixed paths by default
1010

11-
相对项目根,任一路径段以 `.` 开头(`.`、`..` 段除外)的目录与文件为点前缀路径,默认忽略:不扫描、不检查、不报告。适用于 PostToolUse 保存面、提交门禁 delta 面、语言发现面,以及全量扫描的 ruff 与 `find` 型 gate 通道。项目根本身位于点前缀父目录下(如 `~/.config/proj/`)不构成点前缀命中。
11+
点前缀路径的默认忽略 MUST 作用于全部检查面。相对项目根,任一路径段以 `.` 开头(`.`、`..` 段除外)的目录与文件为点前缀路径,默认忽略:不扫描、不检查、不报告。适用于 PostToolUse 保存面、提交门禁 delta 面、语言发现面,以及全量扫描的 ruff 与 `find` 型 gate 通道。项目根本身位于点前缀父目录下(如 `~/.config/proj/`)不构成点前缀命中。
1212

1313
#### Scenario: PostToolUse skips dot-prefixed files
1414

@@ -37,7 +37,7 @@
3737

3838
### Requirement: Commit safety face MUST NOT be weakened by dot-prefix skipping
3939

40-
点前缀默认忽略只作用于检查面。入库安全检查独立收集拟入库路径:密钥/凭据类文件模式(`.env`、`*.pem`、`.DS_Store` 等)无论点前缀与否照常拦截;点前缀目录(宿主插件清单与第一方配置)照常可入库。
40+
入库安全检查 MUST NOT 因点前缀忽略而放宽。点前缀默认忽略只作用于检查面。入库安全检查独立收集拟入库路径:密钥/凭据类文件模式(`.env`、`*.pem`、`.DS_Store` 等)无论点前缀与否照常拦截;点前缀目录(宿主插件清单与第一方配置)照常可入库。
4141

4242
#### Scenario: Secret files remain blocked
4343

@@ -51,7 +51,7 @@
5151

5252
### Requirement: Config discovery MUST keep matching dot-prefixed config files
5353

54-
linter 配置发现(`requiresConfig`、`linter_config_files` 项目级匹配)不受点前缀忽略影响:点前缀配置文件照常使语言判定为已接入。
54+
配置发现 MUST NOT 受点前缀忽略影响。linter 配置发现(`requiresConfig`、`linter_config_files` 项目级匹配)不受点前缀忽略影响:点前缀配置文件照常使语言判定为已接入。
5555

5656
#### Scenario: requiresConfig matches dot files
5757

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# hook-protocol(增量):非 Shell 间接正文按调用形态归因
2+
3+
## MODIFIED Requirements
4+
5+
### Requirement: The guard SHALL treat one-level interpreter indirection as guarded
6+
7+
`is_guarded()` MUST 覆盖直接命令与一层解释器间接。**Shell 解释器(bash/sh/zsh)**:脚本文件文本或 `-c` 内联代码按与直接命令相同的分隔符切段规则扫描到 `git commit|git push` 段首命令词时 MUST 判为拦截;切段扫描前 MUST 先展开 `$(...)` 与反引号内层文本(shell 语义下它们会被真实执行;`ro=$(git push …)` 曾静默放行),段首归一化 MUST 覆盖 shell 控制引导词(`if`/`then`/`else`/`elif`/`while`/`until`/`do`/`!`——`if git push; then`、`for x; do git push; done` 曾静默放行)。**非 Shell 解释器(python/node 等)**:正文 MUST NOT 按 shell 切段归因——模板字符串/帮助文本里的 git 命令字面量样例不是调用(bump-plugin.mjs:164-165 帮助文本实测误报、发版工具被不可绕过地锁死);归因 MUST 只认 subprocess/exec 调用形态(`execFileSync("git", …)`、`subprocess.run(["git", …])`、`os.system("…")` 等调用点的 git 参数位),命中调用形态时 MUST 判为拦截并在 resolve 阶段按「不可建模」UNVERIFIED 阻断。`resolve_project_roots()` MUST 用同一套归一化判定收集仓库边界(含 `git -C <path>` 显式仓边界)——判定不同源时会出现"命中拦截但 roots=[] → 静默放行"的击穿(0.8.2 实测)。更深的动态构造(如 subprocess 参数拼接)MUST 在文档中声明为能力边界而非承诺。
8+
9+
#### Scenario: A wrapper script performs the commit
10+
11+
- **WHEN** 调用形如 `bash runner.sh` 且脚本体内含 `git commit` 或 `git push`
12+
- **THEN** 判定命中,硬门禁按正常流程跑 linter 并可能 exit 2
13+
14+
#### Scenario: Command substitution or shell control structure hides the git call
15+
16+
- **WHEN** 调用形如 `ro=$(git push origin b 2>&1)`、`` x=`git commit` ``、`for x; do git push; done` 或 `if git push; then …; fi`
17+
- **THEN** 展开/归一化后命中拦截,且 `resolve_project_roots` 解析出正确仓库边界(不为 [])
18+
19+
#### Scenario: Text mentioning git push in an echo is not guarded
20+
21+
- **WHEN** 调用为 `echo "git push 是危险命令"` 或脚本内容仅为 `echo hi`
22+
- **THEN** 判定不命中,钩子静默放行
23+
24+
#### Scenario: Help text samples in a non-shell script are not guarded
25+
26+
- **WHEN** `node scripts/tool.mjs` 的正文含模板字符串帮助文本 `cd <root> && git add -A && git commit -m "x" && git push`
27+
- **THEN** 判定不命中(字面量样例不是调用),钩子放行
28+
29+
#### Scenario: A non-shell script really invokes git via subprocess
30+
31+
- **WHEN** `python3 work.py` 的正文含 `subprocess.run(["git", "push"])` 或 `node run.mjs` 的正文含 `execFileSync("git", ["git commit" …])` 形态的调用
32+
- **THEN** 判定命中,且 resolve 阶段按「间接 Git 操作不能可靠建模」UNVERIFIED 阻断(不静默放行)

‎openspec/specs/asset-canonicalization/spec.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# asset-canonicalization Specification
22

33
## Purpose
4-
TBD - created by archiving change consolidate-marketing-assets. Update Purpose after archive.
4+
定义营销资产的正典化契约:零引用资产必须移除、保留资产必须在 assets/README.md 逐个登记,使资产面始终可审计、可追溯,不积累无主文件。
55
## Requirements
66
### Requirement: Zero-reference marketing assets SHALL be removed
77

‎openspec/specs/bilingual-docs-consistency/spec.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# bilingual-docs-consistency Specification
22

33
## Purpose
4-
TBD - created by archiving change add-readme-parity-gate. Update Purpose after archive.
4+
定义 README.md 与 README.zh-CN.md 的结构一致性契约:标题层级、本地链接目标与版本串必须镜像,由 tests/test_readme_parity.py 门禁强制,保证双语用户入口同步演进、任一边漏改即失败。
55
## Requirements
66
### Requirement: README structural parity SHALL be enforced by tests/test_readme_parity.py
77

‎openspec/specs/gate-trigger-policy/spec.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# gate-trigger-policy Specification
22

33
## Purpose
4-
TBD - created by archiving change 2026-09-22-fix-gate-trigger-and-mcp. Update Purpose after archive.
4+
定义 UserPromptSubmit 门禁的触发策略:只有真实提交意图才启动 lint 门禁的精确判据(词边界、疑问句识别、否定式排除、可识别语言收窄),消除日常对话的误触发与无关全量检查。
55
## Requirements
66
### Requirement: The UserPromptSubmit hook SHALL run the lint gate only when intent is commit-like
77
The `UserPromptSubmit` hook MUST evaluate the user's prompt for commit intent using word-boundary matching of trigger words (`commit|push|deploy|发布|部署`) and a separate action-verb check. The hook SHALL exit silently when either (a) no trigger word is present, (b) the only trigger occurrence is followed by `?`, or (c) a trigger word appears in an interrogative sentence identified by `QUESTION_MARKERS` (`?`, `?`, `么`, `吗`, `如何`, `怎么`, `有没有`, `是不是`, `什么是`, `哪些`).

‎openspec/specs/idiomatic-runner/spec.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# idiomatic-runner Specification
22

33
## Purpose
4-
TBD - created by archiving change add-run-per-language. Update Purpose after archive.
4+
定义按语言执行的运行器契约:per-language 子进程执行收口在 scripts/run_per_language.py,入口(run_check.py/fix.py)不再自建 subprocess 运行器,退出码统一归一化,避免同一执行语义多处漂移。
55
## Requirements
66
### Requirement: Per-language execution SHALL live in scripts/run_per_language.py
77

‎openspec/specs/languages-registry-contract/spec.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# languages-registry-contract Specification
22

33
## Purpose
4-
TBD - created by archiving change add-languages-schema-validator. Update Purpose after archive.
4+
定义 languages.json 注册表契约:语言清单的单一事实源由 scripts/validate_languages_json.py 的结构与一致性规则校验并在 CI 强制,任何字段缺失、命令形态错误或命名冲突在入库前被拦截。
55
## Requirements
66
### Requirement: languages.json SHALL be validated by scripts/validate_languages_json.py
77

‎openspec/specs/plugin-manifest-contracts/spec.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# plugin-manifest-contracts Specification
22

33
## Purpose
4-
TBD - created by archiving change add-manifest-bundle-dynamic. Update Purpose after archive.
4+
定义插件清单族的一致性契约:四端 manifest 与市场清单的版本链一致、发布物中的 skills bundle 必须等于 skills.lock 与 plugin-local 声明的并集,安装面不出现缺技能或多技能。
55
## Requirements
66
### Requirement: Released manifest skills bundle SHALL equal the lock+local union
77

‎openspec/specs/registry-driven-config/spec.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# registry-driven-config Specification
22

33
## Purpose
4-
TBD - created by archiving change add-linter-config-from-registry. Update Purpose after archive.
4+
定义注册表驱动的 linter 配置契约:各语言 linter 配置文件清单只在 languages.json 声明,env_check 等消费方从注册表派生配置事实而非硬编码字典,保证新增语言只改一处。
55
## Requirements
66
### Requirement: Per-language linter config files SHALL live in scripts/languages.json
77

0 commit comments

Comments
 (0)