claude-dev-env 8.15.0 → 8.15.1

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 (106) hide show
  1. package/.agents/agents/test_agent_frontmatter.py +0 -72
  2. package/.agents/agents-archived/code-quality-agent.md +16 -16
  3. package/.agents/skills/_shared/end-of-run-gotcha-recommendations.md +5 -21
  4. package/.agents/skills/e-code-review/SKILL.md +1 -3
  5. package/.agents/skills/e-simplify/SKILL.md +6 -6
  6. package/.agents/skills/eli5/SKILL.md +4 -14
  7. package/.agents/skills/eli5/reference/task-seeds.md +3 -4
  8. package/.agents/skills/everything-search/SKILL.md +2 -2
  9. package/.agents/skills/fresh-branch/SKILL.md +2 -3
  10. package/.agents/skills/grok-spawn/SKILL.md +3 -8
  11. package/.agents/skills/issue-tracker/SKILL.md +4 -6
  12. package/.agents/skills/orchestrator-refresh/SKILL.md +7 -7
  13. package/.agents/skills/plugin-eval-standalone-skill/SKILL.md +3 -3
  14. package/.agents/skills/privacy-hygiene/SKILL.md +6 -10
  15. package/.agents/skills/privacy-hygiene/reference/sweep-procedure.md +1 -1
  16. package/.agents/skills/pull-request/SKILL.md +11 -14
  17. package/.agents/skills/pull-request/reference/publication-tasks.md +2 -4
  18. package/.agents/skills/recovering-codex-startup/SKILL.md +3 -6
  19. package/.agents/skills/recovering-codex-startup/reference/task-seeds.md +1 -1
  20. package/.agents/skills/repairing-hook-boundaries/SKILL.md +4 -7
  21. package/.agents/skills/repairing-hook-boundaries/reference/task-seeds.md +1 -2
  22. package/.agents/skills/syncing-submodules/SKILL.md +7 -17
  23. package/.agents/skills/syncing-submodules/reference/run-tasks.md +1 -1
  24. package/.agents/skills/task-build/SKILL.md +1 -1
  25. package/.agents/skills/task-build/reference/tool-routing.md +1 -1
  26. package/.agents/skills/team-advisor/SKILL.md +2 -4
  27. package/.agents/skills/usage-pause/SKILL.md +1 -1
  28. package/.agents/skills/windows-scheduled-task/SKILL.md +1 -1
  29. package/AGENTS.md +1 -1
  30. package/_shared/advisor/advisor-protocol.md +4 -4
  31. package/_shared/advisor/reference/consult-format.md +1 -1
  32. package/_shared/advisor/reference/identity.md +2 -2
  33. package/_shared/advisor/reference/warm-up.md +1 -1
  34. package/audit-rubrics/category_rubrics/category-o-docstring-vs-impl-drift.md +1 -1
  35. package/audit-rubrics/prompts/category-o-docstring-vs-impl-drift.md +2 -16
  36. package/bin/install.mjs +1 -0
  37. package/bin/install.prompt-context.test.mjs +7 -3
  38. package/bin/install.test.mjs +3 -2
  39. package/commands/sr-loop.md +2 -2
  40. package/docs/CODE_RULES.md +2 -2
  41. package/docs/DJANGO_PATTERNS.md +3 -3
  42. package/docs/REACT_PATTERNS.md +6 -6
  43. package/docs/TEST_QUALITY.md +10 -16
  44. package/docs/agent-spawn-protocol.md +4 -4
  45. package/docs/codex-compatibility.md +4 -33
  46. package/docs/references/team-advisor-skill.md +0 -1
  47. package/docs/worker-completion-gate.md +0 -1
  48. package/hooks/advisory/migration_safety_advisor.py +3 -2
  49. package/hooks/advisory/refactor_guard.py +3 -3
  50. package/hooks/hooks.json +1 -1
  51. package/hooks/hooks_constants/issue_tracker_session_starter_constants.py +1 -2
  52. package/hooks/hooks_constants/orchestrator_auto_starter_constants.py +1 -2
  53. package/package.json +1 -1
  54. package/rules/explore-thoroughly.md +0 -1
  55. package/rules/filesystem-search.md +1 -1
  56. package/rules/git-workflow.md +5 -5
  57. package/rules/long-horizon-autonomy.md +1 -5
  58. package/rules/re-stage-before-commit.md +0 -2
  59. package/rules/shell-invocation.md +1 -1
  60. package/scripts/dev_env_scripts_constants/grok_worker_constants.py +8 -2
  61. package/scripts/policy_lint/config/constants.py +1 -0
  62. package/scripts/policy_lint/engine.py +5 -2
  63. package/scripts/repository_checks/config/constants.py +1 -1
  64. package/scripts/spawn_grok_batch.py +12 -1
  65. package/scripts/test_spawn_grok_batch.py +22 -0
  66. package/scripts/tests/test_banned_prose_words.py +1 -1
  67. package/scripts/tests/test_policy_lint_rules_archive.py +16 -0
  68. package/scripts/tests/test_policy_lint_rules_engine.py +2 -2
  69. package/scripts/tests/test_rules.py +9 -9
  70. package/system-prompts/software-engineer.xml +15 -30
  71. package/audit-rubrics/audit-categories.json +0 -700
  72. package/audit-rubrics/category_rubrics/category-a-api-contracts.md +0 -90
  73. package/audit-rubrics/category_rubrics/category-b-selector-engine-compat.md +0 -36
  74. package/audit-rubrics/category_rubrics/category-c-resource-cleanup.md +0 -35
  75. package/audit-rubrics/category_rubrics/category-d-scoping-and-ordering.md +0 -35
  76. package/audit-rubrics/category_rubrics/category-e-dead-code.md +0 -40
  77. package/audit-rubrics/category_rubrics/category-f-silent-failures.md +0 -41
  78. package/audit-rubrics/category_rubrics/category-g-bounds-and-overflow.md +0 -38
  79. package/audit-rubrics/category_rubrics/category-h-security-boundaries.md +0 -40
  80. package/audit-rubrics/category_rubrics/category-i-concurrency.md +0 -38
  81. package/audit-rubrics/category_rubrics/category-j-code-rules-compliance.md +0 -59
  82. package/audit-rubrics/category_rubrics/category-k-codebase-conflicts.md +0 -66
  83. package/audit-rubrics/category_rubrics/category-l-behavior-equivalence.md +0 -48
  84. package/audit-rubrics/category_rubrics/category-m-producer-consumer-cardinality.md +0 -44
  85. package/audit-rubrics/category_rubrics/category-n-test-name-scenario-verifier.md +0 -54
  86. package/audit-rubrics/category_rubrics/category-p-name-vs-behavior-contract.md +0 -59
  87. package/audit-rubrics/category_rubrics/category-q-cross-surface-claims.md +0 -46
  88. package/audit-rubrics/prompts/category-a-api-contracts.md +0 -407
  89. package/audit-rubrics/prompts/category-b-selector-engine-compat.md +0 -401
  90. package/audit-rubrics/prompts/category-c-resource-cleanup.md +0 -420
  91. package/audit-rubrics/prompts/category-d-scoping-and-ordering.md +0 -414
  92. package/audit-rubrics/prompts/category-e-dead-code.md +0 -434
  93. package/audit-rubrics/prompts/category-f-silent-failures.md +0 -432
  94. package/audit-rubrics/prompts/category-g-bounds-and-overflow.md +0 -383
  95. package/audit-rubrics/prompts/category-h-security-boundaries.md +0 -423
  96. package/audit-rubrics/prompts/category-i-concurrency.md +0 -429
  97. package/audit-rubrics/prompts/category-j-code-rules-compliance.md +0 -458
  98. package/audit-rubrics/prompts/category-k-codebase-conflicts.md +0 -338
  99. package/audit-rubrics/prompts/category-l-behavior-equivalence.md +0 -131
  100. package/audit-rubrics/prompts/category-m-producer-consumer-cardinality.md +0 -129
  101. package/audit-rubrics/prompts/category-n-test-name-scenario-verifier.md +0 -139
  102. package/audit-rubrics/prompts/category-p-name-vs-behavior-contract.md +0 -89
  103. package/audit-rubrics/prompts/category-q-cross-surface-claims.md +0 -51
  104. package/hooks/hooks_constants/style_reminder_prompt_constants.py +0 -9
  105. package/hooks/session/style_reminder_prompt.py +0 -55
  106. package/hooks/session/test_style_reminder_prompt.py +0 -86
@@ -1,90 +0,0 @@
1
- # Category A — API contract verification
2
-
3
- **What this category audits:** function signatures, return types, async/await correctness, callback shape compatibility, positional-vs-keyword arg mismatches at call sites, declared-vs-actual return types, and cross-module/cross-language argument shape contracts.
4
-
5
- **Examples of Category A findings:**
6
- - A call site passes positional arguments that the callee expects as keyword arguments.
7
- - `await` is missing on a function that returns a coroutine.
8
- - Return type annotated as `bool` while a code path returns `None`.
9
- - A callback handed to `os.walk(onerror=…)` has the wrong arity.
10
- - A PowerShell cmdlet is invoked with a parameter that belongs to a different parameter set.
11
- - A new gate-time validator omits the `all_changed_lines` parameter that peer span-based validators accept, so the dispatcher cannot plumb diff scope through and the check silently over- or under-blocks.
12
- - A new span-based check applies its result cap before honoring `defer_scope_to_caller=True`, while peer checks return all violations in that mode and let the caller cap; this leaves the new sibling stale against the established pattern.
13
- - A call passes `PollingIntervals.resume_check` (a poll interval — how often to re-check) into a `progress_check_timeout` parameter (a timeout — how long to wait). The value's role does not match the parameter's role, so the call type-checks while the behavior is wrong.
14
-
15
- **Companion reference:** see `../source-material-section-types.md` for guidance on how to chunk the artifact under audit.
16
-
17
- ---
18
-
19
- ## Sub-bucket decomposition (Category A)
20
-
21
- Use 5–10 sub-buckets. Each bucket must be **disjoint** from the others and **collectively exhaustive** of the dimension. Numbered with stable IDs (A1, A2, …) so findings can reference the bucket they belong to.
22
-
23
- The decomposition that worked best for PR #394 (a Python+PowerShell scheduled-task installer):
24
-
25
- | ID | Axis name | Concrete checks |
26
- |---|---|---|
27
- | A1 | Python function signatures vs internal call sites | Parameter count, names, defaults, kw-only barriers; every internal call binds correctly. Is the symbol `async def`? Confirm the exact access path a caller uses: free function vs instance method reached through an object attribute vs import path. A keyword-only parameter with no default is required; omitting it raises `TypeError`. When a call passes a config value as an argument, confirm the value's documented role matches the parameter's role — a poll interval is not a timeout, and a timeout is not a budget. |
28
- | A2 | Python return-type annotation vs every code path | Each function's return annotation is satisfied by every path: explicit `return X`, fall-through, exception-handler exit. The full failure contract is the return value AND every exception raised — trace the body and the docstring `Raises:` for each `raise`, including custom errors. A `-> bool` function that also raises is not fully described by "returns bool". |
29
- | A3 | argparse parser → Namespace contract | Every `add_argument(...)` produces the exact dest name accessed downstream; `type=` matches downstream usage; switches produce bools. |
30
- | A4 | Stdlib callback contracts | `os.walk(onerror=...)` callback shape; `os.path.getctime` / `os.rmdir` argument and exception contracts; `time.sleep` argument types. Catch-site precision: for any claim that code "catches X", confirm the exact catch site and scope — an `except` around only a rollback inside `finally` does not catch the same error raised in the `with` body. |
31
- | A5 | subprocess invocation contract | `subprocess.run` kwargs valid for the targeted Python; `args=[list]` shape; exception propagation under `check=True`. |
32
- | A6 | PowerShell cmdlet parameter sets and binding | `param(...)` with `ParameterSetName=`; `[CmdletBinding(DefaultParameterSetName=…)]` presence; cmdlet parameter combinations valid per Microsoft docs. |
33
- | A7 | Cross-language argv boundary | The `-Argument` string composition → Windows process loader → C-runtime argv parser → Python `sys.argv` → argparse. Trailing-backslash and embedded-space hazards. |
34
- | A8 | Documented API/tool calls vs official API documentation | Every API, MCP tool, SDK method, or CLI command documented in the diff. Look up the official documentation for that API. Verify parameter names, types, and required-ness match the documented call. Make a safe, read-only API call to confirm the documented invocation succeeds. Address any mismatch. |
35
- | A9 | Intra-module sibling-helper API parity | When the diff adds a new check / validator / parser / handler alongside existing sibling checks in the same module, the new one matches the sibling cohort's signature (every parameter peer checks accept), scoping semantics (whole-file vs fragment, diff-line filtering via `all_changed_lines`), and result-shape contract (caps pre-scope vs post-scope, `defer_scope_to_caller` honored, return type). When the new helper omits a sibling-established parameter, runs on a different content surface, or applies the result cap at a different point in the pipeline than its siblings, the audit teammate names this as an A9 finding. |
36
-
37
- Adapt these axes for your artifact. For a pure Python codebase, drop A6 and A7 and add (e.g.) "type-stub vs runtime divergence" or "C-extension boundary." For a pure PowerShell codebase, drop A1–A5 and split A6 into "param-set declaration" / "cmdlet invocation" / "type coercion at param boundary."
38
-
39
- ---
40
-
41
- ### Documentation as contract: verifying a doc claim about code
42
-
43
- When the audited artifact is documentation — a CLAUDE.md, a rule file, a README, a table mapping symbols to behavior — that asserts facts about the codebase, API-contract verification means checking every assertion against the current code, not just confirming the symbol exists and its return type matches. A doc that passes the happy-path contract can still be wrong on any of the seven checks below. Run all seven up front. Checks 1, 2, and 6 are the full-contract sharpening of sub-buckets A1, A2, and A4 applied to a doc claim; checks 3, 4, 5, and 7 are specific to documentation artifacts.
44
-
45
- 1. **Full failure contract** — the failure signals of a function are its return value AND every exception it raises; trace the body and the docstring `Raises:` for every `raise`. _Example:_ a docs PR says a UI helper "returns `bool`", but it also raises a custom not-found error, and a database writer documented by its return type also raises `ValueError` / `RuntimeError` / a driver error, so "returns bool" understates the contract.
46
- 2. **Call shape** — required versus optional parameters (a keyword-only parameter with NO default is required; omitting it raises `TypeError`), sync versus async, and the exact access path (free function versus instance method reached through an object attribute versus import path). _Example:_ a doc presents a helper as a free function, but it is an `async` instance method reached through an object attribute and one keyword-only parameter has no default, so the call example in the doc would raise `TypeError`.
47
- 3. **Reuse-first** — before a doc endorses a hand-written snippet, search for a dedicated helper that already does it. _Example:_ a doc endorses hand-composing `normalize(name).lower()` inline while a dedicated `normalize_for_matching()` helper already does exactly that, contradicting the reuse-before-building rule the doc itself states.
48
- 4. **Path resolution** — every file or directory path a doc cites resolves from the repository root. _Example:_ a doc cites a bare `snapshots/` directory as if it sat at the repo root, but the tree lives under `subsystem/snapshots/`.
49
- 5. **Cross-entry consistency** — scan parallel rows, sections, and table entries for claims that contradict each other. _Example:_ two adjacent table rows map the same subsystem to two different exception base classes.
50
- 6. **Catch-site precision** — when a doc claims code "catches X", confirm the exact site and scope of the catch. _Example:_ a doc says a context manager catches a driver error, but the `except` wraps only the rollback inside `finally`, so an error raised in the `with` body propagates uncaught.
51
- 7. **Citation freshness** — re-derive every `file:line` claim against the current code; never trust a prior "verified" assertion or wording borrowed from a comment. _Example:_ an attribute name carried over from a review comment names a member the class does not define; the current code exposes it under a different name.
52
-
53
- ---
54
-
55
- ## Sample prompt
56
-
57
- The literal text used in the May 2026 audit experiment is in [`../prompts/category-a-api-contracts.md`](../prompts/category-a-api-contracts.md). It produced 8–10 findings (P0=1–2, P1=2–6, P2=2–5) across two runs. Inline the full diff verbatim — do not ask the agent to fetch it.
58
-
59
- ---
60
-
61
- ## What stays verbatim across topics (do not change)
62
-
63
- - The opening "Sub-bucket forced-exhaustion mode" sentence
64
- - "REQUIRES at least one Shape A finding OR exactly one Shape B proof-of-absence with **at least 3 adversarial probes** specific to that sub-bucket"
65
- - "A sub-bucket returning neither is a protocol gap"
66
- - The verbatim adversarial-pass phrasing: `"assume your first pass missed at least 3 P1 [findings] across these [N] sub-buckets — find them"`
67
- - The preamble line format: `Total: N (P0=N, P1=N, P2=N)`
68
- - Source material inlined verbatim, not fetched
69
-
70
- ## What you fill in
71
-
72
- - Dimension and exclusion list (e.g. "Skip B–J")
73
- - 5–10 sub-bucket axes specific to your dimension
74
- - 3–6 concrete checks per sub-bucket
75
- - Cross-bucket Q1–Q3 phrased to your domain
76
- - Verbatim source material inlined
77
-
78
- ## Calibration parameters
79
-
80
- | Knob | Lower | Higher | Effect (from limited experiment data) |
81
- |---|---|---|---|
82
- | Sub-bucket count | 5 | 10 | More buckets = deeper coverage; returns appeared to flatten past ~8 |
83
- | Probes per Shape B | 3 | 5 | More probes = more proof; quality dropped past 5 |
84
- | Adversarial quota | "at least 1" | "at least 5" | A quota of 3 produced the best signal-to-noise; 5+ produced noise findings |
85
- | Cross-bucket questions | 2 | 5 | 3 was sufficient; 5 produced redundant answers |
86
- | Severity tiers | P0/P1/P2 | P0–P4 | Three tiers concentrate reasoning; more tiers fragment it |
87
-
88
- ## Reproducibility caveat
89
-
90
- Run-to-run variance was significant in the experiment. Across two runs, ~5 of ~9 findings were stable; the rest of the long tail varied. To capture the union of findings, run multiple times and merge. A single-run output is a snapshot, not a complete audit. The sample size (n=2 per variant on one PR) is too small to draw firm conclusions; the format is the best of three tested but not proven optimal.
@@ -1,36 +0,0 @@
1
- # Category B — Selector / query / engine compatibility
2
-
3
- **What this category audits:** CSS selectors, SQL queries, regex patterns, JSON-path / XPath, search-DSL queries, CLI / cmdlet syntax — looking for incompatibility with the specific engine, runtime version, or dialect in use.
4
-
5
- **Examples of Category B findings:**
6
- - A CSS selector uses a pseudo-class the target browser engine lacks (e.g. `:has()` on Firefox before 121).
7
- - A SQL `WITH ... AS (... )` CTE on a MySQL version older than 8.0.
8
- - A regex lookbehind in POSIX ERE (which has no lookbehind support).
9
- - A PowerShell cmdlet parameter that exists in PS 7+ but not in Windows PowerShell 5.1.
10
- - A Lucene query syntax fragment fed to an Elasticsearch endpoint that disabled query_string.
11
-
12
- **Companion reference:** see `../source-material-section-types.md`.
13
-
14
- ---
15
-
16
- ## Sub-bucket decomposition (Category B)
17
-
18
- | ID | Axis name | Concrete checks |
19
- |---|---|---|
20
- | B1 | CSS / DOM selector vs target browser engine | Pseudo-class support; attribute selectors; `:has()`, `:is()`, `:where()` availability across the supported engine matrix. |
21
- | B2 | SQL syntax vs database version | Window functions, CTEs, JSON operators, dialect-specific functions vs the declared minimum DB version. |
22
- | B3 | Regex syntax vs engine flavor | Lookbehind / lookahead support; named groups (`(?P<…>)` vs `(?<…>)`); backreferences; Unicode character classes. |
23
- | B4 | Shell / CLI / cmdlet syntax vs runtime version | PowerShell 5.1 vs 7+; bash 3 vs 5; cmdlet parameters added in later versions; CLI flag deprecations. |
24
- | B5 | JSON path / XPath / structural query vs library | jq vs Python jsonpath-ng vs JavaScript jsonpath syntax; XPath 1.0 vs 2.0/3.0 functions. |
25
- | B6 | Search query DSL vs engine | Lucene / Elasticsearch / OpenSearch syntax; differences in escaping, fuzzy matching, multi-field queries. |
26
- | B7 | ORM vs raw SQL semantic differences | SQLAlchemy `.filter()` vs `.filter_by()`; Django Q expressions vs raw SQL; lazy vs eager evaluation. |
27
-
28
- Use 5–10 sub-buckets for any single audit. For an audit that doesn't touch SQL or web frontends, drop B1 / B2 entirely and split B4 across the relevant runtimes.
29
-
30
- ---
31
-
32
- ## Sample prompt
33
-
34
- The reusable Variant C template for Category B is in [`../prompts/category-b-selector-engine-compat.md`](../prompts/category-b-selector-engine-compat.md). Inline your artifact under `## Source material` and adapt the sub-bucket bullets to your project's compat targets.
35
-
36
- For a literal worked example using PR #394 inlined verbatim (Python + PowerShell scheduled-task installer), see [`category-a-api-contracts.md`](category-a-api-contracts.md) — the diff there is the canonical sample artifact. To audit the same PR for Category B specifically, copy the diff section from [`../prompts/category-a-api-contracts.md`](../prompts/category-a-api-contracts.md) and paste it under `## Source material` in the Category B prompt; the relevant Category B sub-buckets for PR #394 are B4 (PowerShell cmdlet version compat — `Get-ScheduledTask`, `New-ScheduledTaskTrigger`, `New-ScheduledTaskAction` are Windows-only and require PS 5.1+) and B3 (the `(Get-Item '{path}')` pattern in the test helper).
@@ -1,35 +0,0 @@
1
- # Category C — Resource cleanup and lifecycle
2
-
3
- **What this category audits:** file handles, network connections, subprocess processes, locks, semaphores, temporary files, subscriptions, event listeners, background tasks — anything acquired that must be released, and anything that must be released on every code path including error and exception paths.
4
-
5
- **Examples of Category C findings:**
6
- - A file is opened in a function that returns before reaching `close()` or a `with` block.
7
- - A database connection is acquired without a release path on every error branch.
8
- - A background asyncio task is started without a cancellation hook on shutdown.
9
- - A `subprocess.Popen` is spawned without `wait()` / `communicate()` and the process becomes a zombie.
10
- - A `tempfile.TemporaryDirectory` is constructed manually (without `with`) and leaks on exception.
11
-
12
- **Companion reference:** see `../source-material-section-types.md`.
13
-
14
- ---
15
-
16
- ## Sub-bucket decomposition (Category C)
17
-
18
- | ID | Axis name | Concrete checks |
19
- |---|---|---|
20
- | C1 | File handles / file objects | `open()` without `with`; explicit `close()` reachable on every path; `os.fdopen` lifetime. |
21
- | C2 | Subprocess / child processes | `Popen` without `wait` / `communicate`; `subprocess.run` is fine; signal handling on parent exit. |
22
- | C3 | Temporary files and directories | `tempfile.NamedTemporaryFile` without `delete=` semantics understood; `TemporaryDirectory` cleanup on exception. |
23
- | C4 | Network connections | Sockets, HTTP clients, DB connections — closed on every path; connection pooling lifecycle. |
24
- | C5 | Locks, semaphores, mutexes | Acquired in one place, released on every exit path; `threading.Lock` vs `asyncio.Lock` mixing. |
25
- | C6 | Subscriptions / event listeners / signal handlers | Registered → unregistered pairs; teardown on object destruction. |
26
- | C7 | Background threads / async tasks | Cancellation propagated; `asyncio.gather` exception handling; thread `join` on shutdown. |
27
- | C8 | OS-level resources | File descriptors / handles; named pipes; shared memory; mmap regions. |
28
-
29
- ---
30
-
31
- ## Sample prompt
32
-
33
- The reusable Variant C template for Category C is in [`../prompts/category-c-resource-cleanup.md`](../prompts/category-c-resource-cleanup.md). Inline your artifact under `## Source material` and adapt the sub-bucket bullets to your project's resource lifecycle.
34
-
35
- For a literal worked example using PR #394 inlined verbatim, see [`category-a-api-contracts.md`](category-a-api-contracts.md). The Category C–relevant pieces of that diff are C2 (the `subprocess.run` in the test helper — naturally bounded), C3 (the `tempfile.TemporaryDirectory()` calls — all use `with`, verified clean), and C7 (the `while True: sleep` watch loop in `main()` — has no shutdown hook beyond `KeyboardInterrupt`).
@@ -1,35 +0,0 @@
1
- # Category D — Variable scoping, ordering, and unbound references
2
-
3
- **What this category audits:** closures, variable hoisting, declaration order, late binding in loops, name shadowing, conditional definition, mutable defaults — anything that can cause a name to bind to the wrong value (or to be unbound entirely) at the point of use.
4
-
5
- **Examples of Category D findings:**
6
- - A variable is referenced before assignment on one branch of an `if`/`else`.
7
- - A loop closure captures the loop variable by reference where by-value capture is required.
8
- - A name shadows an outer-scope variable the function still relies on.
9
- - A mutable default argument (`def f(x=[])`) accumulates state across calls.
10
- - A module-level import is conditionally executed and the symbol is unbound on some import paths.
11
-
12
- **Companion reference:** see `../source-material-section-types.md`.
13
-
14
- ---
15
-
16
- ## Sub-bucket decomposition (Category D)
17
-
18
- | ID | Axis name | Concrete checks |
19
- |---|---|---|
20
- | D1 | Variable referenced before assignment on a branch | `UnboundLocalError` candidates; partial `try/except` where the target is set only in `try`. |
21
- | D2 | Loop closure capture (by-ref vs by-value) | Lambdas / nested functions in a loop body that close over the loop variable. |
22
- | D3 | Name shadowing of outer-scope symbols | A local name that shadows a builtin, module-level, or class-level symbol still in use. |
23
- | D4 | Conditional definition leaving symbol undefined | `try/except ImportError` blocks; platform-conditional defs without fallbacks. |
24
- | D5 | Mutable default arguments | `def f(x=[])`, `def f(x={})` — bound at definition, shared across calls. |
25
- | D6 | Module-level circular imports / load order | Import-time side effects depending on partial-module state. |
26
- | D7 | Async/sync ordering of side effects | `await` placed where a side effect should have already happened; out-of-order coroutine resolution. |
27
- | D8 | Class-attribute vs instance-attribute confusion | `cls.x` vs `self.x`; attribute defined in `__init__` vs class body. |
28
-
29
- ---
30
-
31
- ## Sample prompt
32
-
33
- The reusable Variant C template for Category D is in [`../prompts/category-d-scoping-and-ordering.md`](../prompts/category-d-scoping-and-ordering.md). Inline your artifact under `## Source material` and adapt the sub-bucket bullets to your project's scoping conventions.
34
-
35
- For a literal worked example using PR #394, see [`category-a-api-contracts.md`](category-a-api-contracts.md). The Category D–relevant pieces of that diff: D1 (the `try: created = os.path.getctime(…) / except OSError: continue` block — `created` only bound inside `try`, but the `if now - created` is *inside* the try so no UnboundLocalError) and D2 (the `for each_directory_path, _, _ in os.walk(…)` — no closures inside, verified clean).
@@ -1,40 +0,0 @@
1
- # Category E — Dead code and unused imports
2
-
3
- **What this category audits:** imports the diff adds but leaves unreferenced (dead imports), functions defined but never called, code made unreachable by a prior return or raise (dead returns), conditions that are always true or always false (dead branches), parameters that are accepted but never used (dead parameters), local variables assigned but never read (dead locals), removed-but-not-deleted symbols.
4
-
5
- **Examples of Category E findings:**
6
- - A new `import` line with zero corresponding references in the file.
7
- - A defined helper function whose call sites the diff also removed.
8
- - Code after an unconditional `return` or `raise`.
9
- - A condition like `if False:` or `while True: ... return` where the loop body always returns immediately.
10
- - An accepted parameter that the function body never uses.
11
- - A local variable assigned and never read afterward in the same function.
12
-
13
- **Companion reference:** see `../source-material-section-types.md`.
14
-
15
- ---
16
-
17
- ## Sub-bucket decomposition (Category E)
18
-
19
- | ID | Axis name | Concrete checks |
20
- |---|---|---|
21
- | E1 | New imports without references | Every `import X` and `from X import Y` introduced by the diff has at least one usage in the same file. |
22
- | E2 | Functions / methods defined but never called | Internal helpers defined in this PR with no call sites in this PR or elsewhere. |
23
- | E3 | Code after unconditional return / raise / exit | Statements following a top-level `return`, `raise`, `sys.exit`, `os._exit` that cannot execute. |
24
- | E4 | Always-true / always-false conditions | `if True:` / `if False:` / conditions provably constant given context. |
25
- | E5 | Unused parameters and locals | Parameters declared but never read inside the function body; local variables assigned but never read afterward in the same scope. |
26
- | E6 | Removed-but-not-deleted symbol references | Symbols renamed/removed elsewhere with stale import or call sites left behind. |
27
- | E7 | Test fixtures / helpers defined but never used | Pytest fixtures, test data builders, mock factories with no callers. |
28
- | E8 | Stub / placeholder code without tracking | Judge `pass`, `...`, and `raise NotImplementedError` directly; track follow-up work outside source code. |
29
- | E9 | Constants-module exports with no importer | A module-level `UPPER_SNAKE` constant added to a `*_constants.py` / `config/` module that no module in the repo imports and that the constants file itself never references. No write-time check reads a constants module, and every name such a module exports carries zero in-file references by design, so a dead export reaches the audit untouched. Distinguish dead from live by grepping the whole repo for each constant name: a sibling such as `MEDIUM_TERMINAL` imported by a consumer module is live; a `MEDIUM_TEXT` that no `from ... import` line and no in-file reference names is dead (CODE_RULES 9.8). Remove the dead export. |
30
-
31
- ---
32
-
33
- ## Sample prompt
34
-
35
- The reusable Variant C template for Category E is in [`../prompts/category-e-dead-code.md`](../prompts/category-e-dead-code.md). Inline your artifact under `## Source material` and adapt the sub-bucket bullets to your project.
36
-
37
- For a literal worked example using PR #394, see [`category-a-api-contracts.md`](category-a-api-contracts.md). Category E walks for that diff:
38
- - E1: every import (`argparse`, `os`, `sys`, `time`, `DEFAULT_AGE_SECONDS`, `DEFAULT_POLL_INTERVAL` in main script; `datetime`, `os`, `subprocess`, `sys`, `tempfile`, `time`, `Path`, `sweep` in test file) has at least one reference — verified clean.
39
- - E5: `for each_directory_path, _, _ in os.walk(...)` discards two of three tuple elements — intentional, not dead.
40
- - E2: `_log_walk_error` is referenced once (passed to `os.walk`); `_build_parser` and `sweep` and `main` all have call sites.
@@ -1,41 +0,0 @@
1
- # Category F — Silent failures
2
-
3
- **What this category audits:** catch-all except clauses, unconditional success returns, errors logged then swallowed, default fallback values masking failure, async task error swallowing, boolean returns that produce the same value on success and failure, ignored return values from fallible calls, PowerShell `-ErrorAction SilentlyContinue` patterns that hide errors.
4
-
5
- **Examples of Category F findings:**
6
- - `except Exception: pass` swallows every error including programming bugs.
7
- - A function returns `True` on the success path and `True` on every error path too.
8
- - An async task error is logged while the caller continues as if it succeeded.
9
- - `subprocess.run(...)` without `check=True` and the return code is never inspected.
10
- - `Get-Command X -ErrorAction SilentlyContinue` followed by `.Source` access — the null is silently absorbed.
11
- - A new write-time gate parses `tool_input` content with `ast.parse`; the dispatcher passes the Edit tool's `new_string` fragment; the partial fragment never parses; `except SyntaxError: return []` silently fires zero findings. The gate appears to ship working tests against full-file fixtures but is dead on every Edit in production.
12
-
13
- **Companion reference:** see `../source-material-section-types.md`.
14
-
15
- ---
16
-
17
- ## Sub-bucket decomposition (Category F)
18
-
19
- | ID | Axis name | Concrete checks |
20
- |---|---|---|
21
- | F1 | Catch-all except clauses | `except:` (bare), `except Exception:`, `except BaseException:` followed by `pass` / `continue` / log-only. |
22
- | F2 | Errors logged then swallowed | `logger.error(...)` followed by `return None` / `return default` without re-raise. |
23
- | F3 | Default fallback values masking failure | `dict.get(key, default)` where the absence of the key is itself a bug; `or default` short-circuits hiding `None`. Includes the stale-payload-key shape: a `payload.get("KEY", "")` (or `payload["KEY"]` wrapped in a fallback) read against an external-input dict whose contract the diff migrated — the rest of the module reads the payload through a different key set named in the docstring and bound to same-named variables, while this lone read targets a dropped key, so it resolves to the default on every payload and silently records an empty value into the field it feeds. The audit teammate lists every string-literal key read from each `*_payload` / event / request dict, checks each key against the payload contract the module's docstring and other reads set up, and flags a key read at one site that no docstring, second read, or same-named binding anchors. A key consumed inline with a meaningful default (`resolve(payload.get("cwd", "."))`) is legitimate, not stale — the flag is the dropped key whose value the field needs but never receives. |
24
- | F4 | Async task error swallowing | `asyncio.create_task(...)` without exception observation; `gather(..., return_exceptions=True)` consumed loosely. |
25
- | F5 | Boolean / status returns identical on success and failure | A function returns `True` on the happy path and `True` on the catch-all error path. |
26
- | F6 | Ignored return values from fallible calls | `subprocess.run` without `check=True` and unchecked `returncode`; `os.write` return value discarded. |
27
- | F7 | PowerShell error-suppression patterns | `-ErrorAction SilentlyContinue` followed by `.Property` access; `2>$null` or `*>$null`; `$?` not consulted. |
28
- | F8 | Test-level swallowing | Tests that catch and log instead of asserting; `pytest.warns` used instead of `pytest.raises`. |
29
- | F9 | Gate-validator self-defeat via parse-failure swallow | A new gate / validator / hook check parses input as code (`ast.parse`) and catches the parse error with `return []` / `return None` / `return True` (clean signal). When the dispatcher feeds the check a partial fragment (e.g., the Edit tool's `new_string` rather than the full file content), the parse always fails and the check silently fires zero findings. The audit teammate lists every new `ast.parse` / `tokenize` / `json.loads` / `yaml.safe_load` call in gate code and asks: does the catch branch produce a clean signal that would mask the gate being broken? |
30
- | F10 | Guard helper returns success-default on unverifiable input | A guard helper / predicate / classifier short-circuits to `True` / `Ok` / the success sentinel when it cannot validate the input shape (missing positional args, wrong arity, unexpected None). Guards must default-deny when they cannot verify; default-allow on unverifiable input masks violations downstream. |
31
-
32
- ---
33
-
34
- ## Sample prompt
35
-
36
- The reusable Variant C template for Category F is in [`../prompts/category-f-silent-failures.md`](../prompts/category-f-silent-failures.md). Inline your artifact under `## Source material` and adapt the sub-bucket bullets to your project's error-handling conventions.
37
-
38
- For a literal worked example using PR #394, see [`category-a-api-contracts.md`](category-a-api-contracts.md). Category F walks for that diff:
39
- - F1: two `except OSError: pass` blocks at lines 26 and 32 in `sweep_empty_dirs.py` — first absorbs `getctime` failures (probably fine — file gone), second absorbs `rmdir` failures (silently skips non-empty dirs, no log).
40
- - F7: `Get-Command py -ErrorAction SilentlyContinue` plus `.Source` access — the `if ($_py)` guard catches the null. But `Get-Command python` (fallback) lacks `-ErrorAction` — opposite F7 hazard (loud where silent was intended).
41
- - F6: `Unregister-ScheduledTask -ErrorAction SilentlyContinue` — verify the script's intent on missing task.
@@ -1,38 +0,0 @@
1
- # Category G — Off-by-one, bounds, integer overflow
2
-
3
- **What this category audits:** loop bounds, slice indices, signed/unsigned overflow, floating-point comparison, time arithmetic, byte-vs-codepoint length confusion — anything where the boundary or the numeric type is wrong by one or by a factor.
4
-
5
- **Examples of Category G findings:**
6
- - `range(len(items) + 1)` walks one element past the end of the array.
7
- - A slice `s[:n+1]` where the intent was `s[:n]`.
8
- - Timestamp arithmetic uses 32-bit integer math on a 64-bit value.
9
- - `==` between floats where epsilon comparison is required.
10
- - `len(string)` used for byte length when the consumer expects codepoints (or vice versa).
11
-
12
- **Companion reference:** see `../source-material-section-types.md`.
13
-
14
- ---
15
-
16
- ## Sub-bucket decomposition (Category G)
17
-
18
- | ID | Axis name | Concrete checks |
19
- |---|---|---|
20
- | G1 | Loop bounds | `range(...)`, `while i < n`, `for i in range(len(x)+1)`; off-by-one inclusive vs exclusive. |
21
- | G2 | Slice / substring indices | `s[i:j]` where `j` can be `len(s)+1`; negative indices clamping unexpectedly. |
22
- | G3 | Array / list indexing with computed offsets | `arr[i + offset]` where `offset` can push past the boundary. |
23
- | G4 | Integer arithmetic overflow | 32-bit vs 64-bit assumptions; PowerShell `[int]` overflow at 2^31; `time.time() * 1000` precision. |
24
- | G5 | Floating-point comparison | `a == b` for floats; `0.1 + 0.2 != 0.3`; epsilon-free comparisons in iterative loops. |
25
- | G6 | Date / time arithmetic | Timezone math; DST transitions; leap seconds; `now - then >= threshold` precision. |
26
- | G7 | Unicode codepoint vs byte length | `len()` returning codepoints in Python; bytes in Go; UTF-16 code units in JS. |
27
- | G8 | Threshold and age comparisons | `>=` vs `>`; inclusive vs exclusive boundary on age / size / count thresholds. |
28
-
29
- ---
30
-
31
- ## Sample prompt
32
-
33
- The reusable Variant C template for Category G is in [`../prompts/category-g-bounds-and-overflow.md`](../prompts/category-g-bounds-and-overflow.md). Inline your artifact under `## Source material` and adapt the sub-bucket bullets to your project's numeric domain.
34
-
35
- For a literal worked example using PR #394, see [`category-a-api-contracts.md`](category-a-api-contracts.md). Category G walks for that diff:
36
- - G6: `now = time.time()` then `now - created >= min_age_seconds` — float minus float, comparison against int. No DST/timezone concerns since `time.time()` is UTC-based monotonic-ish.
37
- - G8: `>=` boundary at exactly `min_age_seconds` — a directory exactly 120s old is deleted. Likely intended.
38
- - G4: `[int]$AgeSeconds = 120` in PowerShell — well within 32-bit int range, no overflow risk for realistic age values.
@@ -1,40 +0,0 @@
1
- # Category H — Security boundaries
2
-
3
- **What this category audits:** injection (SQL / command / template), path traversal, authentication and authorization bypass, secret and credential leakage, SSRF, CSRF, deserialization gadgets, file-upload validation — anything where untrusted input crosses a privilege boundary without proper sanitization.
4
-
5
- **Examples of Category H findings:**
6
- - User input concatenated into SQL rather than parameterized.
7
- - File path joined from untrusted input without normalization or root containment.
8
- - Token, password, or API key written to a log line.
9
- - A `pickle.loads` call against attacker-controllable bytes.
10
- - An HTTP redirect to a URL derived from a query parameter without an allowlist.
11
-
12
- **Companion reference:** see `../source-material-section-types.md`.
13
-
14
- ---
15
-
16
- ## Sub-bucket decomposition (Category H)
17
-
18
- | ID | Axis name | Concrete checks |
19
- |---|---|---|
20
- | H1 | SQL injection | Parameterization vs string concatenation; ORM `raw()` usage; dynamic table/column names. |
21
- | H2 | Command injection | `shell=True`, `os.system`, f-string into shell, PowerShell `-Command` with interpolated input. |
22
- | H3 | Path traversal | User input joined to a base path without `realpath` + root containment check. |
23
- | H4 | Authentication bypass | Missing auth checks; role checks bypassed via direct API; cookie / token validation gaps. |
24
- | H5 | Authorization checks | Vertical (admin vs user) and horizontal (user A vs user B) access controls; IDOR vulnerabilities. |
25
- | H6 | Secret / credential leakage | API keys / tokens / passwords in logs, errors, traces, env-dump endpoints, telemetry. |
26
- | H7 | SSRF / external request validation | URL parameters not validated against allowlist; cloud metadata endpoint blocked? |
27
- | H8 | CSRF / state-changing without token | POST/PUT/DELETE handlers without CSRF protection; same-origin assumptions. |
28
- | H9 | Deserialization | `pickle.loads`, `yaml.load` (without SafeLoader), `eval` / `exec` against external input. |
29
- | H10 | File upload / MIME validation | Trusted Content-Type from client; no extension allowlist; no magic-byte verification. |
30
-
31
- ---
32
-
33
- ## Sample prompt
34
-
35
- The reusable Variant C template for Category H is in [`../prompts/category-h-security-boundaries.md`](../prompts/category-h-security-boundaries.md). Inline your artifact under `## Source material` and adapt the sub-bucket bullets to your project's threat model.
36
-
37
- For a literal worked example using PR #394, see [`category-a-api-contracts.md`](category-a-api-contracts.md). Category H walks for that diff:
38
- - H2: the test helper builds `f"(Get-Item '{path}').CreationTimeUtc = [DateTime]'{date_str}'"` and passes to `subprocess.run(["powershell", "-Command", ...])`. The `path` is from `tempfile.TemporaryDirectory` (locally trusted) but the f-string into a single-quoted PowerShell literal is fragile; if an attacker controlled the path they could break out of the literal with a single quote. Severity P2 in this context (test code, locally bounded).
39
- - H3: `arguments.root` from CLI is passed to `os.walk` and `os.rmdir`. Path traversal isn't applicable since the script *is* the privileged process — it walks whatever is given. The trust assumption is "operator provides correct root."
40
- - H6: no secrets / credentials handled.
@@ -1,38 +0,0 @@
1
- # Category I — Concurrency hazards
2
-
3
- **What this category audits:** race conditions, missing awaits, shared mutable state, lock ordering, atomicity of compound operations, cancellation handling, thread-local / async-local context bleed, signal handling in multi-threaded code.
4
-
5
- **Examples of Category I findings:**
6
- - Two coroutines append to the same list without synchronization.
7
- - An `await` is missing on a critical-section operation, allowing other tasks to interleave.
8
- - A lock is acquired in different orders on two code paths (deadlock potential).
9
- - TOCTOU between `os.path.exists` and `os.open` in a directory another process can modify.
10
- - A `threading.local` value leaking across thread-pool reuse.
11
-
12
- **Companion reference:** see `../source-material-section-types.md`.
13
-
14
- ---
15
-
16
- ## Sub-bucket decomposition (Category I)
17
-
18
- | ID | Axis name | Concrete checks |
19
- |---|---|---|
20
- | I1 | Shared mutable state without synchronization | Module-level lists/dicts/sets mutated from multiple threads or coroutines. |
21
- | I2 | Missing await on async operations | `coro()` discarded without `await`; functions returning coroutines never awaited. |
22
- | I3 | Lock ordering / deadlock potential | Multiple locks acquired in different orders on different code paths. |
23
- | I4 | Race conditions / TOCTOU | Check-then-use patterns with a window where state can change. |
24
- | I5 | Atomicity of compound operations | Read-modify-write sequences without atomic primitives. |
25
- | I6 | Thread-local / async-local context bleed | `threading.local` in pools; `contextvars` propagation across `asyncio.create_task`. |
26
- | I7 | Cancellation handling | `asyncio.CancelledError` propagation; cleanup on cancel. |
27
- | I8 | Signal handling in multi-threaded code | Signals always go to main thread in Python; assumptions about handler thread. |
28
-
29
- ---
30
-
31
- ## Sample prompt
32
-
33
- The reusable Variant C template for Category I is in [`../prompts/category-i-concurrency.md`](../prompts/category-i-concurrency.md). Inline your artifact under `## Source material` and adapt the sub-bucket bullets to your project's concurrency model.
34
-
35
- For a literal worked example using PR #394, see [`category-a-api-contracts.md`](category-a-api-contracts.md). Category I walks for that diff:
36
- - I4: TOCTOU between `os.walk` enumerating a directory and `os.path.getctime` / `os.rmdir` on the same path — another process could delete or repopulate the dir in the window. The `try/except OSError` handles the race correctly (Category F notes the same blocks for silent-failure concerns; here they're protective).
37
- - I4 (PowerShell): `Test-Path $Target` followed by `Register-ScheduledTask` — directory could be deleted between the check and the registration. Low-impact since the schedule still registers.
38
- - I1, I2, I3, I5–I8: not applicable — script is single-threaded synchronous Python with no asyncio, no shared mutable state across processes.
@@ -1,59 +0,0 @@
1
- # Category J — CODE_RULES.md compliance
2
-
3
- **What this category audits:** the hook-enforced and rubric-enforced rules from `~/.claude/docs/CODE_RULES.md`. Every PR passes through `code_rules_enforcer.py` at write time; flagging Category J findings during audit prevents fix-loops that the gate would otherwise trigger after the fact.
4
-
5
- **Examples of Category J findings:**
6
- - A literal `60` appears in a production function body (magic value rule).
7
- - A new `MAX_RETRIES = 3` declared at module scope outside `config/`.
8
- - A parameter named `ctx` where the name `context` belongs (abbreviation rule).
9
- - A function that returns a value with no return-type annotation.
10
- - A new `# explains the loop logic` comment added to production code.
11
-
12
- **Companion reference:** see `../source-material-section-types.md`.
13
-
14
- ---
15
-
16
- ## Sub-bucket decomposition (Category J)
17
-
18
- | ID | Axis name | Concrete checks |
19
- |---|---|---|
20
- | J1 | Magic values in production function bodies | Literals other than `0`, `1`, `-1` inside production function bodies. Test files exempt. |
21
- | J2 | String-template magic | f-strings whose structural literal text (paths, URLs, patterns) belongs in `config/`. |
22
- | J3 | Constants location | Module-level `UPPER_SNAKE = ...` outside `config/` in production code. Exempt path families: `config/*`, `/migrations/`, `/workflow/`, `_tab.py`, `/states.py`, `/modules.py`, test files. |
23
- | J5 | Abbreviations | `ctx`, `cfg`, `msg`, `btn`, `idx`, `cnt`, `elem`, `val`, `tmp`, `str`, `num`, `arr`, `obj`, `fn`, `cb`, `req`, `res`. (Loop counters `i`/`j`/`k` and `e` for exceptions are exempt.) |
24
- | J6 | Vague names | `result`, `data`, `output`, `response`, `value`, `item`, `temp`, `info`, `stuff`, `thing`. Vague prefixes: `handle`, `process`, `manage`, `do`. |
25
- | J7 | Type hints | Missing type annotation on a parameter or return; presence of `Any` or `# type: ignore`. |
26
- | J8 | New inline comments | New `#` or `//` comments in production or test code added by this diff; changed directive, TODO, FIXME, HACK, XXX, and type-ignore comments are also findings. |
27
- | J9 | Logging format | `log_*(f"...")` rather than `log_*("...", arg)`. |
28
- | J10 | Imports inside functions | `import` statements placed inside function bodies. |
29
- | J11 | sys.path.insert dedup | `sys.path.insert(0, X)` must be guarded by `if X not in sys.path:` (test files exempt). |
30
- | J12 | Hardcoded user paths | String literals naming a specific user's home directory (`C:/Users/example/...`, `/Users/alice/...`, `/home/bob/...`). Use `pathlib.Path.home()`. |
31
-
32
- The write-time hook (`code_rules_enforcer.py`) exempts test files (`test_*.py`, `*_test.py`, `*.test.*`, `*.spec.*`, `conftest.py`, paths under `/tests/`) from most Category J sub-buckets, while comment changes use one rule for production and tests. It skips the naming, logging, annotation, and unused-import rules on `.mjs` / `.js` files. J11 (`sys.path.insert`) always applies. Read the next section for the sub-buckets this audit applies more widely than the hook.
33
-
34
- When a change touches code that an existing comment describes or is attached to, remove that comment in the same change and carry its meaning through clear names and structure. Leave comments tied to untouched code unchanged. Keep comment cleanup inside the requested task. Production and tests follow one rule. Changed directive, TODO, FIXME, HACK, XXX, and type-ignore comments are removed rather than added or justified.
35
-
36
- ## Write-time exemptions do not scope this audit
37
-
38
- The write-time hook skips several rules on test files and on `.mjs` / `.js` files. This audit does not. Apply these rules to every changed line — production files, test files, and JavaScript files alike:
39
-
40
- - **Naming (J5, J6)** — banned identifiers (`ctx`, `cfg`, `msg`, `result`, `data`, `output`, `value`, `item`, `temp`, `elem`, `val`, …) and banned function prefixes (`handle_`, `process_`, `manage_`, `do_`); boolean names prefixed `is_` / `has_` / `should_` / `can_` / `was_` / `did_`.
41
- - **Logging format (J9)** — the format string and its arguments pass as separate parameters (`log_*("...", arg)`), never an f-string.
42
- - **Type annotations (J7)** — every changed function parameter and return is typed; no `Any`, no `# type: ignore` directives.
43
- - **Unused imports** — a module-level import a changed file does not read is a finding.
44
- - **Function length** — a changed function that runs past the length threshold splits into named helpers.
45
-
46
- A `test_*.py` name or a `.mjs` extension takes the line out of the write-time gate, not out of this audit. When the diff touches a test or a JavaScript file, walk these five rules against the changed lines there too. J1 (magic values) and J3 (constants location) keep their test-file exemption.
47
-
48
- ---
49
-
50
- ## Sample prompt
51
-
52
- The reusable Variant C template for Category J is in [`../prompts/category-j-code-rules-compliance.md`](../prompts/category-j-code-rules-compliance.md). Inline your artifact under `## Source material` and walk every sub-bucket — many J findings are caught by the write-time hook, but the audit catches the residue.
53
-
54
- For a literal worked example using PR #394, see [`category-a-api-contracts.md`](category-a-api-contracts.md). Category J walks for that diff:
55
- - J1: literal `120` in `[int]$AgeSeconds = 120` — already centralized in `config/sweep_config.py:DEFAULT_AGE_SECONDS`. PowerShell side duplicates the value (cross-language drift, see Category K for the conflict-with-existing-code framing).
56
- - J2: f-strings like `f"deleted: {each_directory_path}"` and `f"watching {arguments.root} every {arguments.interval}s"` — the surrounding literal text is descriptive output, not structural; not flagged.
57
- - J3: `_SCRIPTS_DIR` in test file is exempt (test files).
58
- - J7: every parameter and return is annotated; no `Any`, no `# type: ignore`.
59
- - J8: only module-level docstrings; no inline comments added.
@@ -1,66 +0,0 @@
1
- # Category K — Codebase conflicts (incomplete propagation)
2
-
3
- **What this category audits:** changes that update one site of a pattern but leave parallel sites stale, producing contradictory behavior between the new and old code paths. Common when a name is renamed in one file, a default is changed in one constant but duplicated as a literal elsewhere, a fallback path is updated but the primary path isn't (or vice versa), or a feature flag is flipped in one branch of conditional code but missed in others.
4
-
5
- **Why this category is narrow but recurrent:** the change *itself* is internally consistent — the diff looks correct in isolation. The bug only surfaces when you compare the diff against the *unchanged* parts of the codebase that share a contract with what was changed. Linters and unit tests rarely catch these; reviewers only catch them by mentally cross-referencing the change against every parallel site.
6
-
7
- **Canonical example:** [jl-cmd/claude-dev-env PR #397, comment r3210166636](https://github.com/jl-cmd/claude-dev-env/pull/397#discussion_r3210166636). The PR updated an instruction at line 137 to direct the model to use `AskUserQuestion` instead of bailing out with "I don't know." But the fallback `skill_reference` string at lines 123–127 in the same file *still* told the model to "reply 'I don't know'." Both strings interpolate into the same `reason` field, giving the model contradictory guidance — the exact escape hatch the PR was meant to close remained available through the unchanged path.
8
-
9
- ## Other typical patterns
10
-
11
- - A function signature renamed in the definition; one of three call sites still uses the old kwarg name.
12
- - A CSS class renamed in the stylesheet; templates still reference the old name.
13
- - A config key renamed in `defaults.yml`; a fallback in the loader still reads the old key.
14
- - A feature flag deprecated; one conditional branch still checks the old flag.
15
- - An enum variant renamed; documentation, error messages, or test fixtures still reference the old name.
16
- - A constant updated in one constants file; a duplicated literal remains in a sibling file.
17
- - A type signature widened in the producer; a consumer's type annotation still claims the narrower type.
18
- - A migration that adds a column; ORM model file gets the column but a raw-SQL migration query elsewhere doesn't.
19
- - An API endpoint version bumped; the SDK in the same repo still hits the old version.
20
- - A README section and the implementation it describes disagree after a behavior change — one surface carries the new contract, the other still describes the old one.
21
-
22
- - A module's existing `_resolve_base_ref` guards a missing remote with `getattr(remote, "name", "") or DEFAULT_REMOTE`; the diff adds `_resolve_head_ref` beside it that dereferences `remote.name` bare, crashing on the detached-HEAD case its sibling survives.
23
- - A rules reference whose enforcement table marks letter J with ⚡ (blocking hook) while its audit-surface section three paragraphs later lists J under "non-blocking, multi-file reasoning" — one letter, two contradictory enforcement claims in one document.
24
- - A hooks.json with the same hook registered in two parallel matcher blocks (Write|Edit + MultiEdit) when an existing Write|Edit|MultiEdit block already handles the same surface.
25
- - A new function re-implements an in-place atomic file rewrite — stream to a temp sibling, `os.replace` over the original, best-effort temp cleanup on failure — that a shared helper already centralizes (`rewrite_stp_member_atomically` and the like); the two copies drift the moment one gets a temp-naming or concurrency fix the other misses (CODE_RULES §3, reuse before create). The audit catches it by matching the diff's temp-sibling-plus-`os.replace` orchestration against the shared module the same file already imports from.
26
-
27
- **Companion reference:** see `../source-material-section-types.md`.
28
-
29
- ---
30
-
31
- ## Sub-bucket decomposition (Category K)
32
-
33
- Decomposition is by the **kind of parallel site** that needs to stay in sync with what the diff changed.
34
-
35
- | ID | Axis name | Concrete checks |
36
- |---|---|---|
37
- | K1 | Multi-site name renames | A renamed symbol — every reference (call sites, imports, type annotations, error messages, docs, tests) updated? |
38
- | K2 | Duplicated constants / defaults | A value changed in one source-of-truth — every duplicated literal in sibling files / cross-language partners updated? |
39
- | K3 | Primary path vs fallback path | A behavior changed on the happy path — does the fallback / error path produce consistent behavior? |
40
- | K4 | Feature flag / version gate consistency | A flag flipped or version bumped — every guard, conditional branch, and consumer checked? |
41
- | K5 | Producer-vs-consumer type contracts | A producer's output shape changed — every consumer's expected shape still matches? |
42
- | K6 | Code vs documentation sync (cross-surface) | An implementation behavior changed — README, ADRs, skill docs, comments still describe the new behavior? Docstring-prose drift belongs to Category O (docstring / fixture-prose vs implementation drift); K6 owns documentation surfaces outside docstrings. |
43
- | K7 | Code vs test sync | An implementation behavior changed — every test (positive, negative, edge) still expresses the right contract? |
44
- | K8 | Cross-file / cross-language contract sync | A value or shape that lives in multiple languages or files (e.g., PowerShell + Python) — both sides reflect the change? |
45
- | K9 | Schema / data-shape propagation | A schema field added/removed/renamed — migrations, ORM, serializers, fixtures, API docs all updated? |
46
- | K10 | Intra-file sibling-helper pattern propagation | When the diff adds a new helper alongside an existing helper in the same module, the new helper inherits the established defensive idioms (None-guards, `getattr(..., default) or fallback`, scope-exit semantics, span construction). When sibling helper A uses pattern P and newly-added helper B in the same file omits P, that omission is a K10 finding regardless of whether B is internally correct. |
47
- | K11 | Intra-document internal contradiction | When two sections of the same document make contradictory claims about the same subject (one paragraph says X is hook-enforced, another lists X as non-blocking; one table row says label is `Foo`, another row labels the same subject `Bar`; one example shows shape A, another shows shape B for the same input), the contradiction is a K11 finding even when each statement is locally coherent. |
48
-
49
- Customize per-artifact: for a single-file change with no parallel sites, Category K reduces to "verify there are no parallel sites we missed." For a cross-cutting change (e.g., renaming a public API), Category K may need 8+ sub-buckets to enumerate every consumer surface.
50
-
51
- ---
52
-
53
- ## Sample prompt
54
-
55
- The reusable Variant C template for Category K is in [`../prompts/category-k-codebase-conflicts.md`](../prompts/category-k-codebase-conflicts.md). Unlike other categories, the Category K source-material block needs to include both the diff AND the unchanged parallel files the agent must cross-reference.
56
-
57
- ## Why Category K matters as its own bucket
58
-
59
- Categories A–J describe failure modes within a single change. Category K describes the failure mode that emerges *between* the change and what didn't change. A reviewer walking only A–J reads the diff and judges it on its own merits — they can miss K entirely because the diff is internally consistent. K forces the reviewer to read the unchanged code with the diff in hand and look for sites that *should* have been touched.
60
-
61
- The PR #397 case demonstrates the cost of not running K: a security-related instruction (close the "I don't know" escape hatch) was correctly updated in the primary path but left wide open in the fallback, defeating the purpose of the change. The diff looked clean. Only by reading lines 123–127 *with* the new line 137 in mind could the contradiction surface.
62
-
63
- For a literal worked example using PR #394, see [`category-a-api-contracts.md`](category-a-api-contracts.md). Category K walks for that diff:
64
- - K2: `[int]$AgeSeconds = 120` (PowerShell installer) duplicates `DEFAULT_AGE_SECONDS = 120` (`config/sweep_config.py`). Both files are new in the same PR, so there's no "stale parallel site" yet — but a future change to one without the other would land squarely in K2.
65
- - K8: same as K2, framed as cross-language contract.
66
- - K1, K3–K7, K9: not applicable to this PR (no renames, no schema changes, no feature flags). Verified clean.
@@ -1,48 +0,0 @@
1
- # Category L — Behavior-equivalence for refactors
2
-
3
- When a change touches code that an existing comment describes or is attached to, remove that comment in the same change and carry its meaning through clear names and structure. Leave comments tied to untouched code unchanged. Keep comment cleanup inside the requested task.
4
- Production and tests follow one rule. Changed directive, TODO, FIXME, HACK, XXX, and type-ignore comments are removed rather than added or justified.
5
-
6
- **What this category audits:** rewrites of an existing function (especially an enforcement check, parser, classifier, or normalizer) where the new implementation must accept every input the old implementation accepted and reject every input the old implementation rejected. Common when a regex-based check is rewritten as a tokenize-based check, when a `str.startswith` chain is consolidated into a single regex, when a hand-rolled split is replaced with a library call, or when a multi-step pipeline is collapsed into one pass.
7
-
8
- **Why this category is its own bucket:** Categories A–K catch failure modes inside the rewrite itself (wrong signature, dead code, missed branch). Category L catches the failure mode that emerges between the rewrite and the *historically valid inputs* the original code accepted. The diff looks internally consistent and the new unit tests pass — but inputs the prior code accepted fall through under the new implementation, or inputs the prior code rejected slip past. The bug only surfaces against the corpus of canonical inputs the original implementation was tuned for.
9
-
10
- **Examples of Category L findings:**
11
- - A refactored comment check changes acceptance for marker-shaped input when code changes.
12
- - A new comment classifier misreads a bare `#` lookalike that the original regex correctly rejected. (ccc#479 F4)
13
- - A refactored shebang detector drops the inline `#!` variant the original handled. (ccc#479 F5)
14
- - An invariant the original loop enforced at the first match (early-exit) is dropped in the rewrite. (ccc#479 F6)
15
- - A `startswith('## Problem')` shape is too loose compared to the sibling regex shape, accepting `## Problems and Pitfalls`. (ccc#472 F44)
16
-
17
- **Companion reference:** see `../source-material-section-types.md`.
18
-
19
- ---
20
-
21
- ## Sub-bucket decomposition (Category L)
22
-
23
- Decomposition is by the **kind of historically valid input** the rewrite must continue to accept (or reject) without behavior drift.
24
-
25
- | ID | Axis name | Concrete checks |
26
- |---|---|---|
27
- | L1 | KNOWN_GOOD_INPUTS table presence | The rewrite ships a fixture (parametric test, table-driven inputs, or sibling-implementation comparison) enumerating the canonical historically-valid inputs the original accepted. |
28
- | L2 | Whitespace / separator variants | Inputs with no space, leading whitespace, trailing whitespace, multiple internal spaces, tabs, or CRLF line endings retain their original accept/reject classification. |
29
- | L3 | Adjacent-form regressions | A looser pattern in the rewrite (`startswith` where the original used a regex) accepts inputs the original rejected; OR a tighter pattern rejects inputs the original accepted. |
30
- | L4 | Empty / boundary inputs | Empty string, single character, single-line vs multi-line, EOF without newline retain their original classification. |
31
- | L5 | Invariant preservation | Early-exit guarantees, idempotence, ordering, stable iteration, "first match wins" semantics carry over. |
32
- | L6 | Implementation-tag parity | Token-based vs regex-based vs str-method-based: the new tag accepts every input shape the old tag accepted (no shape silently dropped). |
33
- | L7 | Changed-comment handling | Shebangs on line 1 and docstrings retain their handling. Changed directive, TODO, FIXME, HACK, XXX, and type-ignore comments are findings. |
34
- | L8 | Sibling-implementation comparison | When two parallel implementations exist (e.g., Python + PowerShell, regex + tokenize), the rewrite of one must still produce the same accept/reject decisions as the sibling for shared inputs. |
35
-
36
- Customize per-artifact: a parser refactor without an explicit sibling implementation reduces L8 to "verified clean — no parallel implementation"; a single-axis rewrite (whitespace handling only) may exhaust the per-sub-bucket checks against just L2 and L7.
37
-
38
- ---
39
-
40
- ## Sample prompt
41
-
42
- The reusable Variant C template for Category L is in [`../prompts/category-l-behavior-equivalence.md`](../prompts/category-l-behavior-equivalence.md). Inline the BEFORE state of the rewritten function, the AFTER state, and the KNOWN_GOOD_INPUTS the original accepted under `## Source material`.
43
-
44
- ## Why Category L matters as its own bucket
45
-
46
- Categories A–K describe failure modes that show up in the rewrite's own surface. Category L describes the failure mode that shows up only when the rewrite is compared against the inputs the original was tuned for. A reviewer walking only A–K reads the rewrite, finds it clean, and approves it — without re-running the original test inputs through the new code path. L forces the reviewer to pin the original's known-good inputs in a table and assert each still passes against the rewrite.
47
-
48
- The ccc#479 F1 case illustrates the cost of not comparing changed-code marker handling with the original input corpus. Category L requires the reviewer to pin the original inputs and verify that shebangs and docstrings remain preserved while changed marker comments are rejected.