Skip to content

Commit afcf795

Browse files
Trecekclaude
andcommitted
fix(tests): add tracking comments to _KNOWN_NON_CONFORMING_RULES and enforce
- Add # tracking: #4069 comments to agent-eval and skill-eval entries in _KNOWN_NON_CONFORMING_RULES - Reduce _ALLOWLIST_CAP from 5 to 4 (research entry already removed) - Add test_known_non_conforming_entries_have_tracking_comments to enforce that every allowlist entry carries a tracking issue reference - Update tests/arch/AGENTS.md and resolve-review/SKILL.md registries Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 888d3f1 commit afcf795

4 files changed

Lines changed: 39 additions & 5 deletions

File tree

src/autoskillit/skills_extended/resolve-review/SKILL.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -504,7 +504,7 @@ classified `REJECT` with `category: "arch_violation"`.
504504
| Subagent filter guard | `test_subagent_filter_guard.py` | NDJSON assistant-record consumers missing `_is_parent_assistant_record` or `_is_parent_assistant` predicate — subagent records contaminate parent metrics |
505505
| Env-var-set constant consumption | `test_canonical_constant_consumption.py` | `*_ENV_FORWARD_VARS` or `*_REQUIRED_ENV` constant with zero production importers — every canonical env-var-set must be consumed |
506506
| MCP env forward coverage | `test_mcp_env_forward_coverage.py` | `mcp_env_forward_vars` values missing from `CmdSpec.env` in any cmd-builder (skill, food-truck, headless, resume, interactive) |
507-
| Rule severity consistency | `test_rule_severity_consistency.py` | Direct `RuleFinding()` construction in `@semantic_rule`/`@block_rule` bodies — must use `make_finding()`/`make_block_finding()` |
507+
| Rule severity consistency | `test_rule_severity_consistency.py` | Direct `RuleFinding()` construction in `@semantic_rule`/`@block_rule` bodies — must use `make_finding()`/`make_block_finding()`; `_KNOWN_NON_CONFORMING_RULES` entries without `# tracking: #NNNN` comments |
508508
| No direct swap_labels in fleet | `test_swap_labels_guard.py` | Direct `swap_labels` calls in `fleet/` outside `_label_cleanup.py` — must route through `cleanup_orphaned_labels` |
509509
| Pipeline ordering | `test_pipeline_ordering.py` | Moving `run_semantic_rules` before `_prune_skipped_steps` in `load_and_validate` — semantic rules must run on post-prune recipe |
510510

tests/arch/AGENTS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ AST enforcement, sub-package layer contracts, and architectural invariant tests.
7676
| `test_python_no_hardcoded_temp.py` | Architectural invariant: no literal `.autoskillit/temp` outside the whitelist |
7777
| `test_quota_capability_isolation.py` | AST guard: quota modules must not reference BackendCapabilities fields |
7878
| `test_recipe_rule_registration.py` | REQ-RECIPE-001: every recipe/rules_*.py file must be imported by recipe/__init__.py |
79-
| `test_rule_severity_consistency.py` | AST guards: rule functions must use make_finding()/make_block_finding() and RuleFinding severity must match @semantic_rule decorator severity |
79+
| `test_rule_severity_consistency.py` | AST guards: rule functions must use make_finding()/make_block_finding(); RuleFinding severity must match @semantic_rule decorator severity; _KNOWN_NON_CONFORMING_RULES entries must carry tracking comments |
8080
| `test_regex_guards.py` | Arch guard: keyword regexes in cmd-scanning rules must use path-safe lookbehind guards |
8181
| `test_regex_import.py` | Structural guard: src/ must use `import regex as re`, not bare `import re` (hooks/ exempt) |
8282
| `test_registry.py` | Symbolic rule registry tests (RuleDescriptor, RULES, Violation) |

tests/arch/test_rule_severity_consistency.py

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
from __future__ import annotations
1616

1717
import ast
18+
import re as _re
1819
from pathlib import Path
1920

2021
import pytest
@@ -156,7 +157,7 @@ def test_rule_findings_match_rule_def_severity() -> None:
156157
Path(__file__).resolve().parents[1] / "recipe" / "test_bundled_recipes_dispatch_ready.py"
157158
)
158159

159-
_ALLOWLIST_CAP = 5
160+
_ALLOWLIST_CAP = 4
160161

161162

162163
def _collect_allowlist_rule_names() -> set[str]:
@@ -205,6 +206,39 @@ def test_dispatch_readiness_allowlist_size_cap() -> None:
205206
)
206207

207208

209+
def test_known_non_conforming_entries_have_tracking_comments() -> None:
210+
"""Every _KNOWN_NON_CONFORMING_RULES entry must reference a tracking issue."""
211+
source = _DISPATCH_READY_TEST.read_text()
212+
lines = source.splitlines()
213+
tree = ast.parse(source)
214+
215+
missing: list[str] = []
216+
for node in ast.walk(tree):
217+
if isinstance(node, ast.AnnAssign):
218+
target = node.target
219+
value = node.value
220+
elif isinstance(node, ast.Assign):
221+
target = node.targets[0] if node.targets else None
222+
value = node.value
223+
else:
224+
continue
225+
if not isinstance(target, ast.Name) or target.id != "_KNOWN_NON_CONFORMING_RULES":
226+
continue
227+
if not isinstance(value, ast.Dict):
228+
continue
229+
for key in value.keys:
230+
if isinstance(key, ast.Constant) and isinstance(key.value, str):
231+
line = lines[key.lineno - 1]
232+
if not _re.search(r"#\s*tracking:\s*#\d+", line):
233+
missing.append(f"{key.value!r} (line {key.lineno})")
234+
235+
assert not missing, (
236+
"Entries in _KNOWN_NON_CONFORMING_RULES missing tracking comments: "
237+
+ ", ".join(missing)
238+
+ ". Add '# tracking: #NNNN' with the relevant GitHub issue number."
239+
)
240+
241+
208242
def _decorator_rule_name(dec: ast.Call) -> str | None:
209243
"""Extract the ``name=`` keyword string value from a decorator call."""
210244
for kw in dec.keywords:

tests/recipe/test_bundled_recipes_dispatch_ready.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,11 @@
2929

3030

3131
_KNOWN_NON_CONFORMING_RULES: dict[str, set[str]] = {
32-
"agent-eval": {
32+
"agent-eval": { # tracking: #4069
3333
"all-dispatchable-stops-have-sentinel",
3434
"dead-output",
3535
},
36-
"skill-eval": {
36+
"skill-eval": { # tracking: #4069
3737
"all-dispatchable-stops-have-sentinel",
3838
"dead-output",
3939
},

0 commit comments

Comments
 (0)