pinrule 0.16.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.
- pinrule-0.16.0/.github/ISSUE_TEMPLATE/bug_report.md +35 -0
- pinrule-0.16.0/.github/ISSUE_TEMPLATE/bug_report.zh.md +35 -0
- pinrule-0.16.0/.github/ISSUE_TEMPLATE/feature_request.md +26 -0
- pinrule-0.16.0/.github/ISSUE_TEMPLATE/feature_request.zh.md +26 -0
- pinrule-0.16.0/.github/PULL_REQUEST_TEMPLATE.md +26 -0
- pinrule-0.16.0/.github/PULL_REQUEST_TEMPLATE.zh.md +26 -0
- pinrule-0.16.0/.github/workflows/ci.yml +101 -0
- pinrule-0.16.0/.gitignore +28 -0
- pinrule-0.16.0/CHANGELOG.md +3127 -0
- pinrule-0.16.0/CHANGELOG.zh.md +5366 -0
- pinrule-0.16.0/CLAUDE.md +103 -0
- pinrule-0.16.0/CLAUDE.zh.md +103 -0
- pinrule-0.16.0/CODE_OF_CONDUCT.md +29 -0
- pinrule-0.16.0/CODE_OF_CONDUCT.zh.md +29 -0
- pinrule-0.16.0/LICENSE +21 -0
- pinrule-0.16.0/PKG-INFO +487 -0
- pinrule-0.16.0/README.md +456 -0
- pinrule-0.16.0/README.zh.md +475 -0
- pinrule-0.16.0/SECURITY.md +47 -0
- pinrule-0.16.0/SECURITY.zh.md +47 -0
- pinrule-0.16.0/assets/demo-en.svg +80 -0
- pinrule-0.16.0/assets/demo-zh.svg +80 -0
- pinrule-0.16.0/data/config.example.yaml +34 -0
- pinrule-0.16.0/data/locales/en.yaml +167 -0
- pinrule-0.16.0/data/locales/zh.yaml +164 -0
- pinrule-0.16.0/data/rules.dev.example.yaml +175 -0
- pinrule-0.16.0/data/rules.dev.example.zh.yaml +143 -0
- pinrule-0.16.0/data/rules.dev.minimal.example.yaml +109 -0
- pinrule-0.16.0/data/rules.dev.minimal.example.zh.yaml +92 -0
- pinrule-0.16.0/data/signals/agent_saturation/en.txt +57 -0
- pinrule-0.16.0/data/signals/agent_saturation/zh.txt +52 -0
- pinrule-0.16.0/data/signals/completion_words/en.txt +27 -0
- pinrule-0.16.0/data/signals/completion_words/zh.txt +21 -0
- pinrule-0.16.0/data/signals/explicit_handoff/en.txt +25 -0
- pinrule-0.16.0/data/signals/explicit_handoff/zh.txt +24 -0
- pinrule-0.16.0/data/signals/push_signals/en.yaml +114 -0
- pinrule-0.16.0/data/signals/push_signals/zh.yaml +156 -0
- pinrule-0.16.0/data/signals/stop_hints/en.txt +45 -0
- pinrule-0.16.0/data/signals/stop_hints/zh.txt +41 -0
- pinrule-0.16.0/data/signals/user_stop_hints/en.txt +77 -0
- pinrule-0.16.0/data/signals/user_stop_hints/zh.txt +66 -0
- pinrule-0.16.0/data/signals/weak_claims/en.txt +28 -0
- pinrule-0.16.0/data/signals/weak_claims/zh.txt +41 -0
- pinrule-0.16.0/docs/ARCHITECTURE.md +448 -0
- pinrule-0.16.0/docs/ARCHITECTURE.zh.md +470 -0
- pinrule-0.16.0/docs/CODEX_BACKEND.md +146 -0
- pinrule-0.16.0/docs/CODEX_BACKEND.zh.md +146 -0
- pinrule-0.16.0/docs/HANDOFF.md +94 -0
- pinrule-0.16.0/docs/HANDOFF.zh.md +861 -0
- pinrule-0.16.0/docs/HOOK_CONFIGURATION_GUIDE.md +139 -0
- pinrule-0.16.0/docs/HOOK_PROTOCOL_RESEARCH.md +115 -0
- pinrule-0.16.0/docs/PRD.md +249 -0
- pinrule-0.16.0/docs/PRD.zh.md +254 -0
- pinrule-0.16.0/docs/REFACTOR_PLAN_RULE_AND_I18N.md +114 -0
- pinrule-0.16.0/docs/REFACTOR_PLAN_RULE_AND_I18N.zh.md +263 -0
- pinrule-0.16.0/docs/RULES_REDESIGN_PROPOSAL.md +118 -0
- pinrule-0.16.0/docs/RULES_REDESIGN_PROPOSAL.zh.md +334 -0
- pinrule-0.16.0/docs/V0_6_0_PLAN.md +99 -0
- pinrule-0.16.0/docs/V0_6_0_PLAN.zh.md +99 -0
- pinrule-0.16.0/pinrule/__init__.py +10 -0
- pinrule-0.16.0/pinrule/__main__.py +6 -0
- pinrule-0.16.0/pinrule/backends/HOWTO.md +181 -0
- pinrule-0.16.0/pinrule/backends/HOWTO.zh.md +196 -0
- pinrule-0.16.0/pinrule/backends/__init__.py +42 -0
- pinrule-0.16.0/pinrule/backends/_base.py +147 -0
- pinrule-0.16.0/pinrule/backends/_json_hooks.py +210 -0
- pinrule-0.16.0/pinrule/backends/claude_code.py +65 -0
- pinrule-0.16.0/pinrule/backends/codex.py +1016 -0
- pinrule-0.16.0/pinrule/backends/cursor.py +218 -0
- pinrule-0.16.0/pinrule/backends/native_capabilities.py +59 -0
- pinrule-0.16.0/pinrule/backends/protocol_adapter.py +155 -0
- pinrule-0.16.0/pinrule/checks/__init__.py +88 -0
- pinrule-0.16.0/pinrule/checks/_types.py +28 -0
- pinrule-0.16.0/pinrule/checks/bypass_pinrule.py +202 -0
- pinrule-0.16.0/pinrule/checks/chinese_plain.py +200 -0
- pinrule-0.16.0/pinrule/checks/common.py +237 -0
- pinrule-0.16.0/pinrule/checks/description_context.py +121 -0
- pinrule-0.16.0/pinrule/checks/evidence.py +133 -0
- pinrule-0.16.0/pinrule/checks/keep_pushing.py +174 -0
- pinrule-0.16.0/pinrule/checks/long_term.py +224 -0
- pinrule-0.16.0/pinrule/checks/non_blocking.py +186 -0
- pinrule-0.16.0/pinrule/checks/read_first.py +77 -0
- pinrule-0.16.0/pinrule/checks/testset.py +110 -0
- pinrule-0.16.0/pinrule/cli.py +1628 -0
- pinrule-0.16.0/pinrule/config.py +85 -0
- pinrule-0.16.0/pinrule/cursor_rules_sync.py +95 -0
- pinrule-0.16.0/pinrule/cursor_visibility.py +119 -0
- pinrule-0.16.0/pinrule/hooks/__init__.py +1 -0
- pinrule-0.16.0/pinrule/hooks/_payload.py +40 -0
- pinrule-0.16.0/pinrule/hooks/_tool_gate.py +152 -0
- pinrule-0.16.0/pinrule/hooks/_transcript.py +63 -0
- pinrule-0.16.0/pinrule/hooks/after_agent_response.py +45 -0
- pinrule-0.16.0/pinrule/hooks/before_mcp_execution.py +72 -0
- pinrule-0.16.0/pinrule/hooks/before_read_file.py +32 -0
- pinrule-0.16.0/pinrule/hooks/before_shell_execution.py +36 -0
- pinrule-0.16.0/pinrule/hooks/post_tool_use.py +323 -0
- pinrule-0.16.0/pinrule/hooks/pre_compact.py +131 -0
- pinrule-0.16.0/pinrule/hooks/pre_tool_use.py +30 -0
- pinrule-0.16.0/pinrule/hooks/session_start.py +140 -0
- pinrule-0.16.0/pinrule/hooks/stop.py +361 -0
- pinrule-0.16.0/pinrule/hooks/subagent_start.py +116 -0
- pinrule-0.16.0/pinrule/hooks/subagent_stop.py +67 -0
- pinrule-0.16.0/pinrule/hooks/user_prompt_submit.py +233 -0
- pinrule-0.16.0/pinrule/i18n.py +98 -0
- pinrule-0.16.0/pinrule/locale_detect.py +85 -0
- pinrule-0.16.0/pinrule/model_threshold.py +151 -0
- pinrule-0.16.0/pinrule/notify.py +112 -0
- pinrule-0.16.0/pinrule/paths.py +34 -0
- pinrule-0.16.0/pinrule/rule.py +224 -0
- pinrule-0.16.0/pinrule/session_state.py +589 -0
- pinrule-0.16.0/pinrule/signals.py +210 -0
- pinrule-0.16.0/pinrule/violations.py +426 -0
- pinrule-0.16.0/pyproject.toml +80 -0
- pinrule-0.16.0/scripts/cursor-install-local.sh +65 -0
- pinrule-0.16.0/scripts/demo-fixtures/rules-en.yaml +44 -0
- pinrule-0.16.0/scripts/demo-fixtures/rules-zh.yaml +40 -0
- pinrule-0.16.0/scripts/demo-fixtures/short-term-talk-en.jsonl +1 -0
- pinrule-0.16.0/scripts/demo-fixtures/short-term-talk.jsonl +1 -0
- pinrule-0.16.0/scripts/demo-fixtures/silent-stop-en.jsonl +1 -0
- pinrule-0.16.0/scripts/demo-fixtures/silent-stop.jsonl +1 -0
- pinrule-0.16.0/scripts/demo-script.sh +124 -0
- pinrule-0.16.0/scripts/measure_perf.py +131 -0
- pinrule-0.16.0/scripts/record-demo.sh +108 -0
- pinrule-0.16.0/scripts/regenerate-demo-svg.sh +30 -0
- pinrule-0.16.0/scripts/release-finalize.sh +48 -0
- pinrule-0.16.0/scripts/release.sh +63 -0
- pinrule-0.16.0/scripts/verify-installed.sh +44 -0
- pinrule-0.16.0/skills/pinrule/SKILL.md +353 -0
- pinrule-0.16.0/tests/__init__.py +0 -0
- pinrule-0.16.0/tests/conftest.py +18 -0
- pinrule-0.16.0/tests/contract/__init__.py +0 -0
- pinrule-0.16.0/tests/contract/test_backend_contract.py +196 -0
- pinrule-0.16.0/tests/test_backends.py +492 -0
- pinrule-0.16.0/tests/test_bypass_pinrule.py +387 -0
- pinrule-0.16.0/tests/test_checks.py +1184 -0
- pinrule-0.16.0/tests/test_cli.py +1044 -0
- pinrule-0.16.0/tests/test_codex_backend.py +499 -0
- pinrule-0.16.0/tests/test_compact_hooks.py +258 -0
- pinrule-0.16.0/tests/test_config.py +79 -0
- pinrule-0.16.0/tests/test_config_defaults.py +209 -0
- pinrule-0.16.0/tests/test_cursor_native_hooks.py +45 -0
- pinrule-0.16.0/tests/test_cursor_rules_sync.py +34 -0
- pinrule-0.16.0/tests/test_cursor_user_prompt_inject.py +27 -0
- pinrule-0.16.0/tests/test_cursor_visibility.py +35 -0
- pinrule-0.16.0/tests/test_description_context.py +89 -0
- pinrule-0.16.0/tests/test_false_negative_regression.py +603 -0
- pinrule-0.16.0/tests/test_hooks.py +817 -0
- pinrule-0.16.0/tests/test_i18n.py +175 -0
- pinrule-0.16.0/tests/test_keep_pushing.py +507 -0
- pinrule-0.16.0/tests/test_locale_detect.py +172 -0
- pinrule-0.16.0/tests/test_model_threshold.py +257 -0
- pinrule-0.16.0/tests/test_no_sticky_in_user_facing.py +72 -0
- pinrule-0.16.0/tests/test_notify.py +96 -0
- pinrule-0.16.0/tests/test_paths.py +80 -0
- pinrule-0.16.0/tests/test_payload.py +91 -0
- pinrule-0.16.0/tests/test_post_tool_use_reinject.py +151 -0
- pinrule-0.16.0/tests/test_pre_tool_use.py +217 -0
- pinrule-0.16.0/tests/test_protocol_adapter.py +442 -0
- pinrule-0.16.0/tests/test_rule_format.py +263 -0
- pinrule-0.16.0/tests/test_rule_schema.py +299 -0
- pinrule-0.16.0/tests/test_run_checks.py +196 -0
- pinrule-0.16.0/tests/test_session_state.py +703 -0
- pinrule-0.16.0/tests/test_session_state_atomic.py +294 -0
- pinrule-0.16.0/tests/test_signals.py +280 -0
- pinrule-0.16.0/tests/test_sticky.py +266 -0
- pinrule-0.16.0/tests/test_subagent_isolation.py +151 -0
- pinrule-0.16.0/tests/test_transcript.py +47 -0
- pinrule-0.16.0/tests/test_violations.py +407 -0
- pinrule-0.16.0/whitelist.py +28 -0
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Bug Report (English)
|
|
3
|
+
about: Report a pinrule bug / false positive / install issue / hook malfunction
|
|
4
|
+
title: '[Bug] '
|
|
5
|
+
labels: bug
|
|
6
|
+
assignees: ''
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## What did you encounter
|
|
10
|
+
|
|
11
|
+
Brief description of the problem. For **false positives** (pinrule blocks legitimate operations), paste `pinrule audit` output with the `⚠️ possible false positive` markers.
|
|
12
|
+
|
|
13
|
+
## Reproduction steps
|
|
14
|
+
|
|
15
|
+
1. Install via `pinrule install-hooks ...`
|
|
16
|
+
2. ...
|
|
17
|
+
3. Observed error / unexpected behavior
|
|
18
|
+
|
|
19
|
+
## Real state (output of `pinrule doctor`)
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
(paste complete `pinrule doctor` output)
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Environment
|
|
26
|
+
|
|
27
|
+
- pinrule version: (`pinrule --version`)
|
|
28
|
+
- AI client: Claude Code / Codex CLI / Gemini CLI (with version)
|
|
29
|
+
- OS: macOS / Linux / WSL
|
|
30
|
+
- Python: (`python --version`)
|
|
31
|
+
- Shell: zsh / bash / fish
|
|
32
|
+
|
|
33
|
+
## Key logs (if any)
|
|
34
|
+
|
|
35
|
+
If hook output schema errors or installation failures occur, paste the stderr / Claude Code UI error section.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Bug 报告
|
|
3
|
+
about: 报告 pinrule 的 bug / 假阳 / 装机问题 / hook 失效
|
|
4
|
+
title: '[Bug] '
|
|
5
|
+
labels: bug
|
|
6
|
+
assignees: ''
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 你遇到什么
|
|
10
|
+
|
|
11
|
+
简短描述问题。如果是**假阳**(pinrule 误拦合法操作)请贴 `pinrule audit` 输出含 `⚠️ 可能假阳` 标记的 trigger。
|
|
12
|
+
|
|
13
|
+
## 复现步骤
|
|
14
|
+
|
|
15
|
+
1. 装机 `pinrule install-hooks ...`
|
|
16
|
+
2. ...
|
|
17
|
+
3. 看到的错误 / 不预期行为
|
|
18
|
+
|
|
19
|
+
## 状态(用 `pinrule doctor` 输出)
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
(贴 `pinrule doctor` 完整输出)
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## 环境
|
|
26
|
+
|
|
27
|
+
- pinrule 版本: (`pinrule --version`)
|
|
28
|
+
- AI 客户端: Claude Code / Codex CLI / Gemini CLI(含版本)
|
|
29
|
+
- OS: macOS / Linux / WSL
|
|
30
|
+
- Python: (`python --version`)
|
|
31
|
+
- Shell: zsh / bash / fish
|
|
32
|
+
|
|
33
|
+
## 关键日志(如有)
|
|
34
|
+
|
|
35
|
+
如果 hook 输出 schema 错或装机失败,贴 stderr / Claude Code UI 报错段。
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Feature / Improvement Suggestion (English)
|
|
3
|
+
about: Suggest new features / new rule scenarios / new AI client backend
|
|
4
|
+
title: '[Feature] '
|
|
5
|
+
labels: enhancement
|
|
6
|
+
assignees: ''
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Your real pain point
|
|
10
|
+
|
|
11
|
+
Describe the scenario concretely. pinrule's design principle is "user-real-pain-driven" — we don't accept "I think this might be useful" type preventive suggestions.
|
|
12
|
+
|
|
13
|
+
## Proposed solution
|
|
14
|
+
|
|
15
|
+
If you have a specific idea, write it out. Include:
|
|
16
|
+
- Is it at the rule layer (can users solve this by writing their own `rules.yaml`)?
|
|
17
|
+
- Or at the check layer (needs new engine-layer violation_check function)?
|
|
18
|
+
- Or at the hook layer (needs new hook event or changes to existing hook behavior)?
|
|
19
|
+
|
|
20
|
+
## Have you considered alternatives
|
|
21
|
+
|
|
22
|
+
pinrule explicitly **doesn't do** these things — see README's "What pinrule doesn't do" section. If your need falls outside those boundaries, explain why an exception is necessary.
|
|
23
|
+
|
|
24
|
+
## Real user scenario (not speculation)
|
|
25
|
+
|
|
26
|
+
One of pinrule v1's failure lessons was "preventive design." New features must be driven by real user scenarios; we don't accept "might be useful" type needs.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: 功能 / 改进建议
|
|
3
|
+
about: 建议新功能 / 新规则场景 / 新 AI 客户端 backend
|
|
4
|
+
title: '[Feature] '
|
|
5
|
+
labels: enhancement
|
|
6
|
+
assignees: ''
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 你的痛点
|
|
10
|
+
|
|
11
|
+
具体描述场景。pinrule 设计原则是「用户痛点驱动」— 不接受「我觉得可能有用」类预防性建议。
|
|
12
|
+
|
|
13
|
+
## 提议方案
|
|
14
|
+
|
|
15
|
+
如有具体思路写出来。包括:
|
|
16
|
+
- 是规则层(用户自己写 `rules.yaml` 能解决吗)
|
|
17
|
+
- 还是 check 层(需要新工程层 `violation_check` 函数)
|
|
18
|
+
- 还是 hook 层(需要新 hook event 或改现有 hook 行为)
|
|
19
|
+
|
|
20
|
+
## 替代方案考虑过吗
|
|
21
|
+
|
|
22
|
+
pinrule 明确**不做**这些 — 看 README「试过但放弃的」段。如果你的需求落在这些边界外,说明为什么必须破例。
|
|
23
|
+
|
|
24
|
+
## 真实用户场景(不是猜测)
|
|
25
|
+
|
|
26
|
+
pinrule v1 的教训之一是「预防性设计」— 新功能必须有真实用户场景驱动,不接受「可能有用」类需求。
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
## What this PR does
|
|
2
|
+
|
|
3
|
+
Brief description of the change. If it's a new feature, explain whether it's at the rule layer / check layer / hook layer.
|
|
4
|
+
|
|
5
|
+
## Real driving scenario
|
|
6
|
+
|
|
7
|
+
pinrule's validation criterion is "the author / user can describe 3 concrete cases" — what real scenarios does this PR solve?
|
|
8
|
+
|
|
9
|
+
## Verification evidence
|
|
10
|
+
|
|
11
|
+
- [ ] All tests pass: `pytest tests/ -q`
|
|
12
|
+
- [ ] Static checks clean: `ruff check pinrule/ tests/ && mypy pinrule/ tests/ && vulture pinrule/ --min-confidence 80`
|
|
13
|
+
- [ ] Manual run verifies hook behavior (if hooks changed)
|
|
14
|
+
- [ ] If adding new rule templates / check functions, add corresponding tests
|
|
15
|
+
|
|
16
|
+
## Boundary check
|
|
17
|
+
|
|
18
|
+
- [ ] No LLM dependency introduced
|
|
19
|
+
- [ ] No retrieval / cosine / scoring system introduced
|
|
20
|
+
- [ ] No backward-incompatible breakage of existing rule configs
|
|
21
|
+
- [ ] Small and reviewable by default; larger batches OK when the maintainer has explicitly asked for "one PR, don't fragment it"
|
|
22
|
+
|
|
23
|
+
## Related
|
|
24
|
+
|
|
25
|
+
- Related issue: #
|
|
26
|
+
- Related version: (see `pinrule --version`)
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
## 这个 PR 做什么
|
|
2
|
+
|
|
3
|
+
简短描述改动。如果是新功能,说明对应规则层 / check 层 / hook 层哪一层。
|
|
4
|
+
|
|
5
|
+
## 驱动场景
|
|
6
|
+
|
|
7
|
+
pinrule 验证标准是「作者 / 用户能讲出 3 个具体案例」— 这个 PR 解决的场景是什么?
|
|
8
|
+
|
|
9
|
+
## 验证证据
|
|
10
|
+
|
|
11
|
+
- [ ] 测试全过:`pytest tests/ -q`
|
|
12
|
+
- [ ] 静态检查清干净:`ruff check pinrule/ tests/ && mypy pinrule/ tests/ && vulture pinrule/ --min-confidence 80`
|
|
13
|
+
- [ ] manual run 验证 hook 行为(如果改了 hook)
|
|
14
|
+
- [ ] 如果加规则模板 / check 函数,加对应测试
|
|
15
|
+
|
|
16
|
+
## 边界检查
|
|
17
|
+
|
|
18
|
+
- [ ] 不引入 LLM 依赖
|
|
19
|
+
- [ ] 不引入 retrieval / cosine / 评分系统
|
|
20
|
+
- [ ] 不破现有 `rules.yaml` 配置兼容
|
|
21
|
+
- [ ] 默认保持小、可 review;维护者明确要求「一个 PR 别拆碎」时一波到位也合理
|
|
22
|
+
|
|
23
|
+
## 相关
|
|
24
|
+
|
|
25
|
+
- 关联 issue: #
|
|
26
|
+
- 相关版本: (从 `pinrule --version` 看)
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
name: ci
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
test:
|
|
11
|
+
runs-on: ${{ matrix.os }}
|
|
12
|
+
strategy:
|
|
13
|
+
fail-fast: false
|
|
14
|
+
matrix:
|
|
15
|
+
os: [ubuntu-latest, macos-latest]
|
|
16
|
+
python-version: ["3.11", "3.12"]
|
|
17
|
+
steps:
|
|
18
|
+
- uses: actions/checkout@v4
|
|
19
|
+
|
|
20
|
+
- name: Setup Python
|
|
21
|
+
uses: actions/setup-python@v5
|
|
22
|
+
with:
|
|
23
|
+
python-version: ${{ matrix.python-version }}
|
|
24
|
+
|
|
25
|
+
- name: Install
|
|
26
|
+
run: |
|
|
27
|
+
python -m pip install --upgrade pip
|
|
28
|
+
pip install -e ".[dev]"
|
|
29
|
+
|
|
30
|
+
- name: Lint (ruff)
|
|
31
|
+
run: ruff check pinrule/ tests/
|
|
32
|
+
|
|
33
|
+
- name: Dead code scan (vulture, min-confidence 60)
|
|
34
|
+
run: vulture pinrule/ whitelist.py --min-confidence 60
|
|
35
|
+
|
|
36
|
+
- name: Type check (mypy)
|
|
37
|
+
run: |
|
|
38
|
+
mypy pinrule/
|
|
39
|
+
mypy tests/
|
|
40
|
+
|
|
41
|
+
- name: Test
|
|
42
|
+
run: pytest tests/ -q
|
|
43
|
+
|
|
44
|
+
- name: Build wheel
|
|
45
|
+
run: |
|
|
46
|
+
pip install build
|
|
47
|
+
python -m build --wheel
|
|
48
|
+
|
|
49
|
+
- name: Verify wheel contains yaml templates AND signal data
|
|
50
|
+
run: |
|
|
51
|
+
python -c "
|
|
52
|
+
import glob, zipfile, sys
|
|
53
|
+
wheels = glob.glob('dist/pinrule-*-py3-none-any.whl')
|
|
54
|
+
if not wheels: sys.exit('wheel build 失败 — dist/ 无 wheel')
|
|
55
|
+
z = zipfile.ZipFile(wheels[0])
|
|
56
|
+
names = z.namelist()
|
|
57
|
+
# v0.6.0 BREAKING: sticky.* → rules.* 重命名 (v0.9.6 修)
|
|
58
|
+
# v0.9.15 critical: data/signals/ 整个目录之前漏 force-include
|
|
59
|
+
# → wheel 缺 signals 导致 compile_alternation() never-match →
|
|
60
|
+
# evidence / keep_pushing / non_blocking 等 keyword 层失效.
|
|
61
|
+
# codex GPT-5.5 cross-model audit 抓到. 影响所有 pip install 用户.
|
|
62
|
+
expected = [
|
|
63
|
+
'data/rules.dev.example.yaml',
|
|
64
|
+
'data/rules.dev.example.zh.yaml',
|
|
65
|
+
'data/locales/en.yaml',
|
|
66
|
+
'data/locales/zh.yaml',
|
|
67
|
+
'data/config.example.yaml',
|
|
68
|
+
'skills/pinrule/SKILL.md',
|
|
69
|
+
# v0.9.15: 7 个 signal type * 2 lang = 14 文件
|
|
70
|
+
# 用 sampling 而非全列:每个 signal type 至少 1 个 lang 在
|
|
71
|
+
'data/signals/weak_claims/en.txt',
|
|
72
|
+
'data/signals/completion_words/en.txt',
|
|
73
|
+
'data/signals/push_signals/en.yaml',
|
|
74
|
+
'data/signals/stop_hints/en.txt',
|
|
75
|
+
'data/signals/agent_saturation/zh.txt',
|
|
76
|
+
'data/signals/explicit_handoff/zh.txt',
|
|
77
|
+
'data/signals/user_stop_hints/zh.txt',
|
|
78
|
+
]
|
|
79
|
+
missing = [n for n in expected if n not in names]
|
|
80
|
+
if missing: sys.exit(f'wheel 缺文件: {missing}')
|
|
81
|
+
print(f'{wheels[0]} 含全部 {len(expected)} 个关键模板 + signals ✓')
|
|
82
|
+
"
|
|
83
|
+
|
|
84
|
+
- name: Wheel smoke test - signals compile_alternation truly works
|
|
85
|
+
# v0.9.15 critical: 即便 wheel 含 signal 文件,也要 functional 验证
|
|
86
|
+
# 真能编译出 non-empty regex(防 packaging path 错 / load 失败).
|
|
87
|
+
# codex GPT-5.5 推荐 smoke test pattern.
|
|
88
|
+
run: |
|
|
89
|
+
python -m venv /tmp/pinrule-wheel-test
|
|
90
|
+
/tmp/pinrule-wheel-test/bin/pip install dist/pinrule-*-py3-none-any.whl
|
|
91
|
+
/tmp/pinrule-wheel-test/bin/python -c "
|
|
92
|
+
from pinrule.signals import compile_alternation
|
|
93
|
+
# 验证 4 个关键 signal 真编译成 working regex
|
|
94
|
+
for sig in ('weak_claims', 'completion_words', 'push_signals', 'stop_hints'):
|
|
95
|
+
pat = compile_alternation(sig)
|
|
96
|
+
# never-match pattern '(?!)' 长度 4,真 pattern 应 >> 50
|
|
97
|
+
assert pat.pattern != '(?!)', f'{sig}: signals 没 load → never-match'
|
|
98
|
+
assert len(pat.pattern) > 50, f'{sig}: pattern 太短可能漏字眼 ({len(pat.pattern)} chars)'
|
|
99
|
+
print(f' ✓ {sig}: pattern {len(pat.pattern)} chars')
|
|
100
|
+
print('signals compile_alternation smoke test ✓')
|
|
101
|
+
"
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.so
|
|
6
|
+
.Python
|
|
7
|
+
.venv/
|
|
8
|
+
venv/
|
|
9
|
+
.pytest_cache/
|
|
10
|
+
.mypy_cache/
|
|
11
|
+
*.egg-info/
|
|
12
|
+
dist/
|
|
13
|
+
build/
|
|
14
|
+
|
|
15
|
+
# IDE
|
|
16
|
+
.vscode/
|
|
17
|
+
.idea/
|
|
18
|
+
|
|
19
|
+
# karma 本地状态(不进仓库)
|
|
20
|
+
violations.jsonl
|
|
21
|
+
stats.json
|
|
22
|
+
|
|
23
|
+
# Cursor IDE dogfood 资产 (含真 stdin captures 可能有 user_email 等敏感字段)
|
|
24
|
+
.cursor/
|
|
25
|
+
.dogfood/
|
|
26
|
+
|
|
27
|
+
# OS
|
|
28
|
+
.DS_Store
|