Skip to content

docs(skill): Path B 三处针对性 fix — haiku 4.5 dogfood 数据驱动 #427

docs(skill): Path B 三处针对性 fix — haiku 4.5 dogfood 数据驱动

docs(skill): Path B 三处针对性 fix — haiku 4.5 dogfood 数据驱动 #427

Workflow file for this run

name: ci
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
python-version: ["3.11", "3.12"]
steps:
- uses: actions/checkout@v4
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install
run: |
python -m pip install --upgrade pip
pip install -e ".[dev]"
- name: Lint (ruff)
run: ruff check pinrule/ tests/
- name: Dead code scan (vulture, min-confidence 60)
run: vulture pinrule/ whitelist.py --min-confidence 60
- name: Type check (mypy)
run: |
mypy pinrule/
mypy tests/
- name: Test
run: pytest tests/ -q
- name: Windows GBK default-console smoke test (zh-CN user 真路径)
# 用户 dogfood (2026-05-18) 撞 issue: PYTHONIOENCODING=utf-8 让 CI 真
# 漏测中文 Windows 默认 GBK 控制台. 这个 step 真不设 UTF-8 env, 模拟
# 真中文 Windows 用户跑 pinrule init / hook 的 default state.
if: runner.os == 'Windows'
run: |
chcp 936
python -m pinrule --version
# 跑 init 真验证不崩溃 (用户 issue Bug 1)
$env:PINRULE_HOME = "$env:RUNNER_TEMP\pinrule-gbk-smoke"
python -m pinrule init --no-minimal
# hook smoke: import + main() 不该 UnicodeEncodeError
$payload = '{"session_id":"smoke","hook_event_name":"PreToolUse","tool_name":"Bash","tool_input":{"command":"echo hi"}}'
$payload | python -c "from pinrule.hooks import pre_tool_use; pre_tool_use.main()"
- name: Build wheel
run: |
pip install build
python -m build --wheel
- name: Verify wheel contains JSON templates AND signal data
env:
# Windows PowerShell 默认 cp1252 codec 不能 encode 中文 print 输出.
# force utf-8 跨平台一致.
PYTHONIOENCODING: utf-8
run: |
python -c "
import glob, zipfile, sys
wheels = glob.glob('dist/pinrule-*-py3-none-any.whl')
if not wheels: sys.exit('wheel build 失败 — dist/ 无 wheel')
z = zipfile.ZipFile(wheels[0])
names = z.namelist()
# v0.6.0 BREAKING: sticky.* → rules.* 重命名 (v0.9.6 修)
# v0.9.15 critical: data/signals/ 整个目录之前漏 force-include
# → wheel 缺 signals 导致 compile_alternation() never-match →
# evidence / keep_pushing / non_blocking 等 keyword 层失效.
# codex GPT-5.5 cross-model audit 抓到. 影响所有 pip install 用户.
expected = [
# v0.17.0: PyYAML drop, 全部资产改 JSON / Python 模块. 0 runtime deps.
'data/rules.dev.example.json',
'data/rules.dev.example.zh.json',
'data/locales/en.json',
'data/locales/zh.json',
'data/config.example.json',
'skills/pinrule/SKILL.md',
# v0.9.15: 7 个 signal type * 2 lang = 14 文件
# 用 sampling 而非全列:每个 signal type 至少 1 个 lang 在
'data/signals/weak_claims/en.txt',
'data/signals/completion_words/en.txt',
# v0.17.0: push_signals 从 yaml 转 Python 模块 (cartesian 嵌套语义)
'data/signals/push_signals/en.py',
'data/signals/stop_hints/en.txt',
'data/signals/agent_saturation/zh.txt',
'data/signals/explicit_handoff/zh.txt',
'data/signals/user_stop_hints/zh.txt',
]
missing = [n for n in expected if n not in names]
if missing: sys.exit(f'wheel 缺文件: {missing}')
print(f'{wheels[0]} 含全部 {len(expected)} 个关键模板 + signals ✓')
"
- name: Wheel smoke test - signals compile_alternation truly works
# v0.9.15 critical: 即便 wheel 含 signal 文件,也要 functional 验证
# 真能编译出 non-empty regex(防 packaging path 错 / load 失败).
# codex GPT-5.5 推荐 smoke test pattern.
# v0.16.17: 跨平台 — Windows venv binaries 在 Scripts/, Unix 在 bin/.
env:
PYTHONIOENCODING: utf-8
shell: bash
run: |
python -m venv smoke-venv
if [ "$RUNNER_OS" = "Windows" ]; then
VENV_PY="smoke-venv/Scripts/python"
else
VENV_PY="smoke-venv/bin/python"
fi
"$VENV_PY" -m pip install dist/pinrule-*-py3-none-any.whl
"$VENV_PY" -c "
from pinrule.signals import compile_alternation
# 验证 4 个关键 signal 真编译成 working regex
for sig in ('weak_claims', 'completion_words', 'push_signals', 'stop_hints'):
pat = compile_alternation(sig)
# never-match pattern '(?!)' 长度 4,真 pattern 应 >> 50
assert pat.pattern != '(?!)', f'{sig}: signals 没 load → never-match'
assert len(pat.pattern) > 50, f'{sig}: pattern 太短可能漏字眼 ({len(pat.pattern)} chars)'
print(f' ✓ {sig}: pattern {len(pat.pattern)} chars')
print('signals compile_alternation smoke test ✓')
"