phase-barrier 0.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. phase_barrier-0.2.0/.gitattributes +5 -0
  2. phase_barrier-0.2.0/.github/workflows/ci.yml +75 -0
  3. phase_barrier-0.2.0/.github/workflows/release.yml +34 -0
  4. phase_barrier-0.2.0/.gitignore +31 -0
  5. phase_barrier-0.2.0/CHANGELOG.md +9 -0
  6. phase_barrier-0.2.0/LICENSE +21 -0
  7. phase_barrier-0.2.0/MANIFEST.in +5 -0
  8. phase_barrier-0.2.0/PKG-INFO +279 -0
  9. phase_barrier-0.2.0/README.md +251 -0
  10. phase_barrier-0.2.0/anti_shortcut/__init__.py +34 -0
  11. phase_barrier-0.2.0/anti_shortcut/__main__.py +107 -0
  12. phase_barrier-0.2.0/anti_shortcut/audit.py +109 -0
  13. phase_barrier-0.2.0/anti_shortcut/config.py +106 -0
  14. phase_barrier-0.2.0/anti_shortcut/integration.py +108 -0
  15. phase_barrier-0.2.0/anti_shortcut/interceptors.py +144 -0
  16. phase_barrier-0.2.0/anti_shortcut/skill.py +289 -0
  17. phase_barrier-0.2.0/anti_shortcut/state.py +159 -0
  18. phase_barrier-0.2.0/anti_shortcut/validators.py +243 -0
  19. phase_barrier-0.2.0/deploy/Dockerfile +15 -0
  20. phase_barrier-0.2.0/deploy/README.md +37 -0
  21. phase_barrier-0.2.0/deploy/docker-compose.yml +18 -0
  22. phase_barrier-0.2.0/deploy/probe.py +39 -0
  23. phase_barrier-0.2.0/deploy/seed_gate.py +92 -0
  24. phase_barrier-0.2.0/examples/anti_shortcut_config.yaml +56 -0
  25. phase_barrier-0.2.0/examples/demo.py +246 -0
  26. phase_barrier-0.2.0/phase_barrier.egg-info/PKG-INFO +279 -0
  27. phase_barrier-0.2.0/phase_barrier.egg-info/SOURCES.txt +41 -0
  28. phase_barrier-0.2.0/phase_barrier.egg-info/dependency_links.txt +1 -0
  29. phase_barrier-0.2.0/phase_barrier.egg-info/entry_points.txt +2 -0
  30. phase_barrier-0.2.0/phase_barrier.egg-info/requires.txt +6 -0
  31. phase_barrier-0.2.0/phase_barrier.egg-info/scm_file_list.json +37 -0
  32. phase_barrier-0.2.0/phase_barrier.egg-info/scm_version.json +8 -0
  33. phase_barrier-0.2.0/phase_barrier.egg-info/top_level.txt +1 -0
  34. phase_barrier-0.2.0/pyproject.toml +51 -0
  35. phase_barrier-0.2.0/setup.cfg +4 -0
  36. phase_barrier-0.2.0/tests/conftest.py +104 -0
  37. phase_barrier-0.2.0/tests/test_cli.py +65 -0
  38. phase_barrier-0.2.0/tests/test_config.py +43 -0
  39. phase_barrier-0.2.0/tests/test_integration.py +83 -0
  40. phase_barrier-0.2.0/tests/test_interceptors.py +63 -0
  41. phase_barrier-0.2.0/tests/test_skill.py +214 -0
  42. phase_barrier-0.2.0/tests/test_state.py +70 -0
  43. phase_barrier-0.2.0/tests/test_validators.py +190 -0
@@ -0,0 +1,5 @@
1
+ * text=auto eol=lf
2
+
3
+ *.png binary
4
+ *.jpg binary
5
+ *.ico binary
@@ -0,0 +1,75 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main, master]
6
+ pull_request:
7
+
8
+ concurrency:
9
+ group: ci-${{ github.ref }}
10
+ cancel-in-progress: true
11
+
12
+ jobs:
13
+ test:
14
+ name: pytest (Python ${{ matrix.python-version }})
15
+ runs-on: ubuntu-latest
16
+ strategy:
17
+ fail-fast: false
18
+ matrix:
19
+ python-version: ['3.10', '3.11', '3.12', '3.13', '3.14']
20
+ steps:
21
+ - uses: actions/checkout@v4
22
+ with:
23
+ fetch-depth: 0 # setuptools-scm 需要读取 tag
24
+
25
+ - uses: actions/setup-python@v5
26
+ with:
27
+ python-version: ${{ matrix.python-version }}
28
+ cache: pip
29
+ cache-dependency-path: pyproject.toml
30
+
31
+ - name: Install package and dev deps
32
+ run: |
33
+ python -m pip install --upgrade pip
34
+ pip install -e ".[dev]"
35
+
36
+ - name: Run test suite
37
+ run: python -m pytest
38
+
39
+ - name: Run end-to-end demo
40
+ run: python examples/demo.py
41
+
42
+ - name: Smoke-test CLI entry point
43
+ run: |
44
+ anti-shortcut --version
45
+ anti-shortcut inspect --json
46
+
47
+ package:
48
+ name: Build sdist and wheel
49
+ runs-on: ubuntu-latest
50
+ steps:
51
+ - uses: actions/checkout@v4
52
+ with:
53
+ fetch-depth: 0 # setuptools-scm 需要读取 tag
54
+
55
+ - uses: actions/setup-python@v5
56
+ with:
57
+ python-version: '3.12'
58
+
59
+ - name: Install build frontend
60
+ run: python -m pip install --upgrade build twine
61
+
62
+ - name: Build distributions
63
+ run: python -m build
64
+
65
+ - name: Check distributions (metadata + README)
66
+ run: twine check dist/*
67
+
68
+ - name: List artifacts
69
+ run: ls -l dist/
70
+
71
+ - uses: actions/upload-artifact@v4
72
+ with:
73
+ name: dist
74
+ path: dist/
75
+ if-no-files-found: error
@@ -0,0 +1,34 @@
1
+ name: Release to PyPI
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - 'v*'
7
+
8
+ permissions:
9
+ contents: read
10
+
11
+ jobs:
12
+ publish:
13
+ name: Build and publish
14
+ runs-on: ubuntu-latest
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+ with:
18
+ fetch-depth: 0 # setuptools-scm 需要读取 tag
19
+
20
+ - uses: actions/setup-python@v5
21
+ with:
22
+ python-version: '3.12'
23
+
24
+ - name: Install build frontend
25
+ run: python -m pip install --upgrade build
26
+
27
+ - name: Build sdist and wheel
28
+ run: python -m build
29
+
30
+ - name: Publish to PyPI
31
+ uses: pypa/gh-action-pypi-publish@release/v1
32
+ with:
33
+ packages-dir: dist/
34
+ password: ${{ secrets.PYPI_API_TOKEN }}
@@ -0,0 +1,31 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.egg-info/
5
+ build/
6
+ dist/
7
+ .pytest_cache/
8
+ .mypy_cache/
9
+ .ruff_cache/
10
+
11
+ # 虚拟环境
12
+ .venv/
13
+ venv/
14
+ env/
15
+
16
+ # 演示与临时产物
17
+ examples/demo_workspace/
18
+ .agent_gate/
19
+ _tmp_site/
20
+ _pytest_final/
21
+ _build_tmp/
22
+
23
+ # IDE / OS
24
+ .idea/
25
+ .vscode/
26
+ *.iml
27
+ .DS_Store
28
+ Thumbs.db
29
+
30
+ # 本地工具缓存
31
+ .workbuddy/
@@ -0,0 +1,9 @@
1
+ # Changelog
2
+
3
+ 版本号由 git tag 驱动(`setuptools-scm`):打 `vX.Y.Z` tag 后构建的发行包即为 `X.Y.Z`。
4
+
5
+ ## [0.1.0] - 2026-08-29
6
+
7
+ - 以 `phase-barrier` 作为发行名发布(与 GitHub 仓库同名);import 包名保持 `anti_shortcut`,CLI 命令保持 `anti-shortcut`。
8
+ - 功能:需求→spec→测试→实现→测试→修复→交付的阶段门禁;`write_file` / `execute_command` 工具拦截;spec / 测试 AST / 实现语法 / 测试运行 / 回归证据校验;JSON 状态机 + 审计日志;Docker 只读卷部署示例。
9
+ - 说明:更早的 0.1.0 曾以 `anti-shortcut-skill` 发布到 PyPI。PyPI 不支持项目改名或删除,旧项目将永久保留,建议在 PyPI 上将其 yank。
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Anti-Shortcut contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,5 @@
1
+ include README.md
2
+ include LICENSE
3
+ recursive-include deploy *.py *.yml *.md Dockerfile
4
+ recursive-include examples *.py *.yaml
5
+ prune examples/demo_workspace
@@ -0,0 +1,279 @@
1
+ Metadata-Version: 2.4
2
+ Name: phase-barrier
3
+ Version: 0.2.0
4
+ Summary: 阶段门禁反捷径校验 Skill:强制编码 Agent 遵循标准工程师 SOP(需求→spec→测试→实现→测试→修复→交付)
5
+ Author: Anti-Shortcut Team
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/Xuqing0415/phase-barrier
8
+ Project-URL: Repository, https://github.com/Xuqing0415/phase-barrier
9
+ Project-URL: Issues, https://github.com/Xuqing0415/phase-barrier/issues
10
+ Keywords: agent,code-agent,stage-gate,sop,validation,alpha-swe
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.10
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Programming Language :: Python :: 3.13
17
+ Classifier: Programming Language :: Python :: 3.14
18
+ Classifier: Topic :: Software Development :: Quality Assurance
19
+ Requires-Python: >=3.10
20
+ Description-Content-Type: text/markdown
21
+ License-File: LICENSE
22
+ Requires-Dist: pydantic>=2.0
23
+ Requires-Dist: PyYAML>=6.0
24
+ Requires-Dist: structlog>=23.0
25
+ Provides-Extra: dev
26
+ Requires-Dist: pytest>=7.0; extra == "dev"
27
+ Dynamic: license-file
28
+
29
+ # 反捷径校验 Skill(Anti-Shortcut Validation Skill)
30
+
31
+ [![CI](https://github.com/Xuqing0415/phase-barrier/actions/workflows/ci.yml/badge.svg)](https://github.com/Xuqing0415/phase-barrier/actions/workflows/ci.yml)
32
+ [![PyPI version](https://img.shields.io/pypi/v/phase-barrier.svg)](https://pypi.org/project/phase-barrier/)
33
+ [![Python versions](https://img.shields.io/pypi/pyversions/phase-barrier.svg)](https://pypi.org/project/phase-barrier/)
34
+
35
+ 强制编码 Agent(如 Alpha-SWE)遵循标准工程师 SOP 的**阶段门禁(Stage Gate)**组件:
36
+ 以“阶段状态机 + 证据校验 + 工具拦截”的组合,阻止 Agent 跳步、偷步或伪造产出。
37
+
38
+ > 流程:**需求 → spec 设计 → 测试用例 → 实现 → 测试 → 修复 → 交付**
39
+
40
+ ## 特性
41
+
42
+ - **不可绕过**:校验逻辑位于 Agent 工具调用层,Agent 无法通过自然语言指令绕过;状态文件由 Skill 独占原子写入。
43
+ - **最小侵入**:通过包装 `write_file` / `execute_command` 实现拦截,不改变核心工具接口。
44
+ - **证据明确**:每个阶段要求具体可验证的产物(文件、AST 统计、测试退出码与摘要)。
45
+ - **自动校验**:spec 章节检查、测试 AST 分析(函数数量 + 断言)、实现语法检查、测试结果解析,全部自动完成。
46
+ - **可配置**:YAML + Pydantic 配置,可自定义阶段要求、文件模式、测试命令,或关闭某些严格校验。
47
+
48
+ ## 架构
49
+
50
+ ```
51
+ Alpha-SWE Agent Core(思考 / 规划 / 调用工具)
52
+ │ 工具调用(write_file, execute_command, advance_stage)
53
+
54
+ 反捷径校验 Skill(中间件)
55
+ ├── 状态机 :阶段与证据持久化到 <workspace>/.agent_gate/state.json
56
+ ├── 证据校验 :每个阶段的校验函数(validators)
57
+ └── 工具拦截 :包装 write_file / execute_command,注入 advance_stage
58
+ │ 合法调用
59
+
60
+ 执行环境(文件系统 / Shell)
61
+ ```
62
+
63
+ ## 快速开始
64
+
65
+ ```bash
66
+ pip install phase-barrier # 从 PyPI 安装(发行名与仓库同名)
67
+ # 或本地构建后安装:
68
+ # python -m pip install --upgrade build
69
+ # python -m build
70
+ # pip install dist/phase_barrier-*.whl
71
+
72
+ pip install -e . # 开发模式安装(依赖 pydantic / pyyaml / structlog)
73
+ python examples/demo.py # 观看完整演示(含违规尝试被拦截)
74
+ python -m pytest # 运行测试套件
75
+ ```
76
+
77
+ ### 集成到 Agent(Alpha-SWE 等基于工具调用的 Agent)
78
+
79
+ ```python
80
+ from anti_shortcut import AntiShortcutSkill
81
+
82
+ # 1. 启动时创建 Skill(user_request 由系统传入,作为阶段 0 证据)
83
+ skill = AntiShortcutSkill(
84
+ workspace=".",
85
+ config="anti_shortcut_config.yaml", # 可选
86
+ user_request="实现一个计算斐波那契数列的函数",
87
+ )
88
+
89
+ # 2. 用包装后的工具替换 Agent 工具表中的原始工具,并注入 advance_stage
90
+ tools = skill.install(agent.tools)
91
+
92
+ # 3. Agent 后续只能调用 tools["write_file"] / tools["execute_command"] / tools["advance_stage"]
93
+ ```
94
+
95
+ ### 一键接入 + 插件加载
96
+
97
+ ```python
98
+ from anti_shortcut import bootstrap, register_integration
99
+
100
+ # 一步完成:创建 Skill -> 包装工具 -> 注入 advance_stage -> 加载插件
101
+ bootstrap(
102
+ agent_tools=agent.tools, # Agent 暴露的工具表
103
+ workspace=".",
104
+ user_request="实现一个计算斐波那契数列的函数",
105
+ agent=agent, # 透传给集成插件
106
+ )
107
+
108
+ # 进程内注册集成插件(宿主启动时注册,插件负责把包装后的工具装回 Agent)
109
+ def my_installer(agent, skill):
110
+ skill.install(agent.tools)
111
+
112
+ register_integration("alpha-swe-adapter", my_installer)
113
+ ```
114
+
115
+ 发布为独立包的插件可声明入口点组 `anti_shortcut.integrations`(`pyproject.toml`):
116
+
117
+ ```toml
118
+ [project.entry-points."anti_shortcut.integrations"]
119
+ alpha-swe = "alpha_swe_adapter:install"
120
+ ```
121
+
122
+ `load_plugins(agent, skill)` 会自动发现并执行入口点插件。
123
+
124
+ ### 命令行门禁检查(编排器 / 人工监督)
125
+
126
+ ```bash
127
+ python -m anti_shortcut inspect --workspace . # 查看当前阶段
128
+ python -m anti_shortcut inspect --workspace . --json # JSON 输出(便于自动化)
129
+ python -m anti_shortcut advance --workspace . --to 2 # 推进阶段(校验证据)
130
+ ```
131
+
132
+ `advance` 与 Agent 内部的 `advance_stage` 走同一套证据校验:通过返回退出码 0,被拒绝返回 1 并打印原因。
133
+
134
+ ## 阶段定义与证据要求
135
+
136
+ | 阶段 | 名称 | 必需证据 | 校验方式 |
137
+ |------|------|----------|----------|
138
+ | 0 | 需求接收 | 用户需求原文(系统传入) | 自动记录 |
139
+ | 1 | Spec 设计 | `spec.md`,含 `## 需求分析` / `## 设计方案` / `## 接口定义`,且足够详细 | 文件存在 + 章节匹配 + 最小长度 |
140
+ | 2 | 测试用例 | `test_*.py` 等,测试函数数量 ≥ 阈值,每个函数含断言 | 文件存在 + AST 解析 |
141
+ | 3 | 实现代码 | 非测试 `*.py` 源码 | 文件存在 + 语法编译检查 |
142
+ | 4 | 运行测试 | 测试命令执行记录(退出码 + 输出摘要) | 拦截器记录 `last_test_run` |
143
+ | 5 | 修复与回归 | 修复后的代码 + 重新运行的测试全部通过 | 测试通过且发生在最后一次代码修改之后 |
144
+ | 6 | 交付 | (可选)交付总结 | 达到阶段 6 即完成 |
145
+
146
+ 特殊分支:阶段 4 推进时,若最近一次测试**全部通过**且代码未被后续修改,则**跳过阶段 5 直接进入交付**;否则进入阶段 5 修复。
147
+
148
+ ## 工具拦截规则
149
+
150
+ | 工具 / 命令 | 拦截条件 | 提示 |
151
+ |-------------|----------|------|
152
+ | `write_file` 写实现代码 | 阶段 < 2(测试未完成) | 请先完成测试用例编写 |
153
+ | `write_file` 写测试文件 | 阶段 < 1(spec 未完成) | 请先完成 spec 设计 |
154
+ | `write_file` 写 `.agent_gate/` | 任意阶段 | 门禁目录由 Skill 独占 |
155
+ | `execute_command` 运行测试(pytest 等) | 阶段 < 3(实现未完成) | 请先完成实现代码 |
156
+ | shell 写入源码/测试(`>`、`sed -i`、`mv`、`rm`、`touch`…) | 同上按文件类型 | 与 `write_file` 相同的阶段限制 |
157
+ | 任何访问 `.agent_gate` 的命令 | 任意阶段 | 禁止通过 shell 访问门禁目录 |
158
+ | 只读命令(`ls` / `cat` / `dir` …) | 无 | 放行 |
159
+
160
+ `advance_stage(new_stage)` 是唯一合法的阶段推进入口:
161
+
162
+ - `new_stage` 必须等于当前阶段 + 1,否则返回“不允许跳跃阶段”;
163
+ - 推进前运行**当前阶段**的证据校验器,不通过则返回详细失败原因;
164
+ - 通过后写入状态机(原子写:临时文件 + `os.replace`),并记录证据哈希。
165
+
166
+ ## 状态与审计
167
+
168
+ - 状态文件:`<workspace>/.agent_gate/state.json` —— 当前阶段、阶段历史、证据哈希、最近测试结果。
169
+ - 审计日志:`<workspace>/.agent_gate/audit.log` —— 结构化 JSON,记录阶段变更、拦截事件、校验结果。
170
+
171
+ 示例状态:
172
+
173
+ ```json
174
+ {
175
+ "version": 1,
176
+ "current_stage": 2,
177
+ "completed_stages": [0, 1],
178
+ "stage_history": [
179
+ { "stage": 0, "name": "需求接收", "timestamp": "...", "evidence": {"user_request": "..."} },
180
+ { "stage": 1, "name": "Spec 设计", "timestamp": "...", "evidence": {"spec": {"sha256": "..."}} }
181
+ ],
182
+ "evidence": { "user_request": "...", "spec": {}, "tests": {}, "implementation": {}, "last_test_run": {} }
183
+ }
184
+ ```
185
+
186
+ ## 配置
187
+
188
+ 参考 [`examples/anti_shortcut_config.yaml`](examples/anti_shortcut_config.yaml)(缺省使用内置默认值):
189
+
190
+ ```yaml
191
+ min_test_functions: 2 # 测试函数数量阈值
192
+ spec_sections: ["## 需求分析", "## 设计方案", "## 接口定义"]
193
+ test_file_patterns: ["test_*.py", "tests/**/test_*.py"]
194
+ test_commands: ['^\\s*pytest\\b', '^\\s*npm\\s+test\\b', ...]
195
+ protect_gate_dir: true # 生产环境配合只读卷挂载
196
+ allow_other_files_any_stage: true # 其他文件类型(README 等)是否不限阶段
197
+ ```
198
+
199
+ ## 安全与防绕过
200
+
201
+ - **状态文件保护**:Agent 可用的工具全部被包装;`.agent_gate` 的任何写入 / shell 访问都被拦截。
202
+ - **生产部署**:将 `.agent_gate` 以只读卷挂载给 Agent 执行容器(`-v /host/path:/.agent_gate:ro`),实现进程级隔离——即使 Agent 绕过工具包装也无法篡改状态。
203
+ - **空壳防护**:测试文件经 AST 分析,要求测试函数数量 ≥ 阈值且每个函数含断言(`assert` / `pytest.raises`)。
204
+ - **伪造防护**:证据文件在推进时记录 SHA-256;阶段 5 要求测试运行发生在最后一次代码修改之后。
205
+ - **日志审计**:所有拦截与阶段变更写入 JSON 审计日志,便于事后分析“哪些请求被拦截”“跳过步骤的频率”。
206
+
207
+ ## Docker 只读卷部署(进程级防绕过)
208
+
209
+ 即使 Agent 绕过工具包装直接操作文件系统,也可通过“只读挂载”从文件系统层面锁死 `.agent_gate`:
210
+
211
+ ```bash
212
+ docker compose -f deploy/docker-compose.yml up --build
213
+ ```
214
+
215
+ - `gate-keeper` 服务:对 `/workspace/.agent_gate` **可写**,负责初始化状态并跑完整门禁流程;
216
+ - `agent` 服务:`/workspace` 可写(产出代码),但 `/workspace/.agent_gate` **只读挂载**(`:ro`);
217
+ - `agent` 侧探针验证:读状态正常、写门禁目录被拒绝(`PermissionError`)、写工作区源码正常。
218
+
219
+ 详见 [`deploy/README.md`](deploy/README.md)。
220
+
221
+ ## 模块结构
222
+
223
+ ```
224
+ anti_shortcut/
225
+ ├── __init__.py # 公共 API
226
+ ├── config.py # GateConfig(Pydantic)+ YAML 加载
227
+ ├── state.py # StateManager:JSON 原子持久化、阶段历史、证据
228
+ ├── validators.py # 各阶段证据校验器(spec / tests AST / implementation / test_run / retest)
229
+ ├── interceptors.py # 命令分类、门禁目录检测、shell 写路径提取、测试输出摘要
230
+ ├── audit.py # 结构化 JSON 审计日志(structlog,按文件独立实例)
231
+ ├── skill.py # AntiShortcutSkill:工具包装 + advance_stage + 权限检查
232
+ ├── integration.py # 集成层:bootstrap / 插件注册 / 入口点发现
233
+ └── __main__.py # CLI:python -m anti_shortcut inspect / advance
234
+ examples/
235
+ ├── demo.py # 模拟 Agent 完整演示(含违规拦截)
236
+ └── anti_shortcut_config.yaml # 示例配置
237
+ deploy/
238
+ ├── Dockerfile # 打包镜像(含 CLI)
239
+ ├── docker-compose.yml # gate-keeper(可写)+ agent(.agent_gate 只读)
240
+ ├── seed_gate.py # gate-keeper:初始化并跑完整门禁流程
241
+ ├── probe.py # agent 探针:验证只读挂载生效
242
+ └── README.md # 部署说明
243
+ tests/ # pytest 测试套件(64 个用例)
244
+ ```
245
+
246
+ ## 设计取舍
247
+
248
+ - **阶段 4 → 6 跳过修复**:测试一次通过时不必强制走修复阶段(见第 7 章工作流)。
249
+ - **修复后强制回归**:阶段 5 校验最近一次测试必须“通过”且“晚于最后一次代码修改”,防止改完不重测。
250
+ - **启发式 shell 解析**:`sed -i`、重定向等写路径提取是尽力而为;核心强制边界是工具包装 + 只读挂载,shell 解析用于纵深防御。
251
+ - **测试质量**:本 Skill 防“跳步”,不负责“测试写得好不好”;覆盖率与人工抽查可作为补充(见第 10 章)。
252
+
253
+ ## 环境说明
254
+
255
+ - 实现语言:Python 3.10+(已在 3.14 验证)
256
+ - 依赖:`pydantic>=2`、`PyYAML>=6`、`structlog>=23`(可选 `pytest` 用于测试)
257
+ - 跨平台:Windows / Linux / macOS(门禁目录权限建议在 Linux 容器 + 只读卷场景使用)
258
+
259
+ ## 构建与发布(PyPI)
260
+
261
+ 构建并检查发行包:
262
+
263
+ ```bash
264
+ python -m pip install --upgrade build twine
265
+ python -m build # 生成 dist/*.tar.gz 与 dist/*.whl
266
+ twine check dist/* # 校验元数据与 README 渲染
267
+ ```
268
+
269
+ 发布(需在 PyPI 注册账号,并配置 `~/.pypirc` 或 `TWINE_*` 环境变量):
270
+
271
+ ```bash
272
+ twine upload dist/* # 正式发布到 PyPI
273
+ # twine upload --repository testpypi dist/* # 先发 TestPyPI 验证
274
+ ```
275
+
276
+ - 版本号由 git tag 驱动(`setuptools-scm`):打 `vX.Y.Z` tag 后构建即为 `X.Y.Z`,无需再手工同步 `pyproject.toml` 与 `__init__.py`。发布流程:`git tag v0.1.1 && git push --tags`。
277
+ - CI(`.github/workflows/ci.yml`):push / PR 时在 Python 3.10–3.14 矩阵上运行 `pytest` + `examples/demo.py`;`package` job 构建 sdist/wheel 并执行 `twine check` 后上传为 artifact。
278
+ - 自动发布(`.github/workflows/release.yml`):打 `v*` tag 时自动构建并发布到 PyPI,使用仓库 Secret `PYPI_API_TOKEN`。
279
+ - 发行名说明:本项目发行名为 `phase-barrier`(与仓库同名),import 包名仍为 `anti_shortcut`。早期以 `anti-shortcut-skill` 发布过 0.1.0,PyPI 不允许项目改名/删除,旧项目会永久保留;若不想让旧名被误装,可在 PyPI 旧项目页将其 yank。