claude-dev-env 2.28.0 → 2.29.0
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.
- package/.agents/agents/AGENTS.md +0 -31
- package/.agents/agents/clean-coder.md +1 -1
- package/.agents/agents/test_agent_frontmatter.py +3 -1
- package/.agents/skills/AGENTS.md +0 -70
- package/.agents/skills/_shared/AGENTS.md +0 -44
- package/.agents/skills/_shared/advisor/AGENTS.md +0 -8
- package/.agents/skills/_shared/pr-loop/AGENTS.md +0 -57
- package/.agents/skills/_shared/pr-loop/prompts/AGENTS.md +0 -8
- package/.agents/skills/_shared/pr-loop/scripts/AGENTS.md +0 -34
- package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/AGENTS.md +0 -23
- package/.agents/skills/autoconverge/AGENTS.md +0 -35
- package/.agents/skills/autoconverge/reference/AGENTS.md +0 -15
- package/.agents/skills/autoconverge/workflow/AGENTS.md +0 -25
- package/.agents/skills/autoconverge/workflow/autoconverge_report_constants/AGENTS.md +0 -15
- package/.agents/skills/everything-search/AGENTS.md +0 -16
- package/.agents/skills/fresh-branch/AGENTS.md +0 -13
- package/.agents/skills/grok-spawn/AGENTS.md +0 -27
- package/.agents/skills/orchestrator/.claude/CLAUDE.md +1 -0
- package/.agents/skills/orchestrator/AGENTS.md +1 -0
- package/.agents/skills/orchestrator/SKILL.md +44 -53
- package/.agents/skills/orchestrator/reference/.claude/CLAUDE.md +1 -0
- package/.agents/skills/orchestrator/reference/AGENTS.md +1 -0
- package/.agents/skills/orchestrator/reference/consult-the-orchestrator.md +70 -0
- package/.agents/skills/orchestrator/reference/executor-consult-block.md +62 -0
- package/.agents/skills/orchestrator/reference/host-detect.md +15 -0
- package/.agents/skills/orchestrator/test_orchestrator_skill_contract.py +62 -0
- package/.agents/skills/orchestrator-refresh/SKILL.md +16 -34
- package/.agents/skills/rebase/AGENTS.md +0 -31
- package/.agents/skills/session-log/AGENTS.md +0 -31
- package/.agents/skills/session-tidy/AGENTS.md +0 -35
- package/.agents/skills/skill-builder/AGENTS.md +0 -48
- package/.agents/skills/skill-builder/references/AGENTS.md +0 -24
- package/.agents/skills/skill-builder/templates/AGENTS.md +0 -13
- package/.agents/skills/skill-builder/workflows/AGENTS.md +0 -18
- package/.agents/skills/task-build/AGENTS.md +0 -28
- package/.agents/skills/update/AGENTS.md +0 -37
- package/.agents/skills-archived/AGENTS.md +0 -44
- package/.agents/skills-archived/anthropic-plan/AGENTS.md +0 -33
- package/.agents/skills-archived/anthropic-plan/scripts/AGENTS.md +0 -10
- package/.agents/skills-archived/anthropic-plan/scripts/anthropic_plan_scripts_constants/AGENTS.md +0 -15
- package/.agents/skills-archived/anthropic-plan/templates/AGENTS.md +0 -12
- package/.agents/skills-archived/anthropic-plan/workflow/AGENTS.md +0 -13
- package/.agents/skills-archived/auditing-claude-config/AGENTS.md +0 -20
- package/.agents/skills-archived/bugteam/AGENTS.md +0 -29
- package/.agents/skills-archived/bugteam/reference/AGENTS.md +0 -19
- package/.agents/skills-archived/bugteam/reference/obstacles/AGENTS.md +0 -23
- package/.agents/skills-archived/bugteam/scripts/AGENTS.md +0 -29
- package/.agents/skills-archived/bugteam/scripts/bugteam_scripts_constants/AGENTS.md +0 -17
- package/.agents/skills-archived/codex-review/AGENTS.md +0 -45
- package/.agents/skills-archived/codex-review/reference/AGENTS.md +0 -14
- package/.agents/skills-archived/codex-review/scripts/codex_review_scripts_constants/AGENTS.md +0 -17
- package/.agents/skills-archived/codex-review/test_skill_scaffold.py +13 -3
- package/.agents/skills-archived/copilot-review/AGENTS.md +0 -17
- package/.agents/skills-archived/pr-converge/AGENTS.md +0 -31
- package/.agents/skills-archived/pr-converge/pr_converge_skill_constants/AGENTS.md +0 -25
- package/.agents/skills-archived/pr-converge/reference/AGENTS.md +0 -27
- package/.agents/skills-archived/pr-converge/reference/obstacles/AGENTS.md +0 -22
- package/.agents/skills-archived/pr-converge/scripts/AGENTS.md +0 -45
- package/.agents/skills-archived/pr-converge/scripts/pr_converge_scripts_constants/AGENTS.md +0 -17
- package/.agents/skills-archived/pr-converge/workflows/AGENTS.md +0 -15
- package/.agents/skills-archived/pr-loop-cloud-transport/reference/identity-and-hooks.md +1 -1
- package/.agents/skills-archived/recall/AGENTS.md +0 -29
- package/.agents/skills-archived/remember/AGENTS.md +0 -30
- package/AGENTS.md +0 -112
- package/_shared/AGENTS.md +0 -16
- package/_shared/advisor/AGENTS.md +0 -21
- package/_shared/advisor/advisor-protocol.md +4 -1
- package/_shared/advisor/reference/consult-format.md +4 -2
- package/_shared/pr-loop/AGENTS.md +0 -27
- package/_shared/pr-loop/scripts/AGENTS.md +0 -49
- package/_shared/pr-loop/scripts/code_rules_gate_parts/AGENTS.md +0 -41
- package/_shared/pr-loop/scripts/codex_review_scripts_constants/AGENTS.md +0 -17
- package/_shared/pr-loop/scripts/pr_converge_scripts_constants/AGENTS.md +0 -17
- package/_shared/pr-loop/scripts/pr_converge_skill_constants/AGENTS.md +0 -25
- package/_shared/pr-loop/scripts/pr_loop_shared_constants/AGENTS.md +0 -25
- package/_shared/pr-loop/scripts/tests/AGENTS.md +0 -43
- package/_shared/process-tree/AGENTS.md +0 -40
- package/audit-rubrics/AGENTS.md +0 -42
- package/audit-rubrics/category_rubrics/AGENTS.md +0 -36
- package/audit-rubrics/category_rubrics/category-o-docstring-vs-impl-drift.md +16 -29
- package/audit-rubrics/prompts/AGENTS.md +0 -36
- package/audit-rubrics/prompts/category-o-docstring-vs-impl-drift.md +2 -2
- package/bin/AGENTS.md +0 -118
- package/bin/install.test.mjs +1 -1
- package/commands/AGENTS.md +0 -14
- package/docs/AGENTS.md +0 -31
- package/docs/CODE_RULES.md +3 -3
- package/docs/agent-spawn-protocol.md +1 -1
- package/docs/references/AGENTS.md +0 -16
- package/docs/references/prose-style-enforcement.md +5 -9
- package/hooks/AGENTS.md +0 -27
- package/hooks/advisory/AGENTS.md +0 -15
- package/hooks/blocking/AGENTS.md +0 -122
- package/hooks/blocking/claude_md_orphan_file_blocker_parts/AGENTS.md +0 -27
- package/hooks/blocking/code_rules_docstrings.py +10 -2138
- package/hooks/blocking/code_rules_enforcer.py +0 -121
- package/hooks/blocking/code_rules_imports_logging.py +1 -236
- package/hooks/blocking/code_rules_shared.py +23 -0
- package/hooks/blocking/code_rules_test_layout.py +8 -8
- package/hooks/blocking/config/AGENTS.md +0 -9
- package/hooks/blocking/config/prose_style_enforcement_constants.py +4 -2
- package/hooks/blocking/config/test_prose_style_enforcement_constants.py +5 -1
- package/hooks/blocking/inventory_intent_records/AGENTS.md +0 -25
- package/hooks/blocking/package_inventory_stale_blocker_parts/AGENTS.md +0 -25
- package/hooks/blocking/pii_prevention_blocker_parts/AGENTS.md +0 -23
- package/hooks/blocking/precommit_code_rules_gate.py +8 -43
- package/hooks/blocking/state_description_blocker.py +1 -7
- package/hooks/blocking/tdd_enforcer_parts/AGENTS.md +0 -29
- package/hooks/blocking/test_code_rules_enforcer_cap_meta.py +0 -1
- package/hooks/blocking/test_code_rules_enforcer_dispatch_wiring.py +0 -8
- package/hooks/blocking/test_code_rules_enforcer_module_docstring_roster.py +11 -112
- package/hooks/blocking/test_code_rules_enforcer_narrow_edit.py +0 -1
- package/hooks/blocking/test_code_rules_enforcer_split_entry_1.py +1 -18
- package/hooks/blocking/test_code_rules_shared.py +12 -0
- package/hooks/blocking/test_precommit_code_rules_gate.py +32 -179
- package/hooks/blocking/test_precommit_code_rules_gate_native_owner.py +0 -1
- package/hooks/blocking/test_state_description_blocker.py +6 -4
- package/hooks/blocking/test_stop_dispatcher.py +5 -29
- package/hooks/git-hooks/AGENTS.md +0 -31
- package/hooks/git-hooks/git_hooks_constants/AGENTS.md +0 -20
- package/hooks/hooks_constants/AGENTS.md +0 -104
- package/hooks/hooks_constants/bash_pre_tool_use_dispatcher_constants.py +0 -1
- package/hooks/hooks_constants/code_rules_enforcer_constants.py +3 -0
- package/hooks/hooks_constants/messages.py +0 -2
- package/hooks/hooks_constants/precommit_code_rules_gate_constants.py +3 -17
- package/hooks/hooks_constants/stop_dispatcher_constants.py +0 -2
- package/hooks/hooks_constants/test_bash_pre_tool_use_dispatcher_constants.py +0 -1
- package/hooks/hooks_constants/test_code_rules_enforcer_constants.py +7 -0
- package/hooks/hooks_constants/test_messages.py +5 -3
- package/hooks/hooks_constants/test_stop_dispatcher_constants.py +0 -2
- package/hooks/lifecycle/AGENTS.md +0 -17
- package/hooks/observability/AGENTS.md +0 -19
- package/hooks/session/AGENTS.md +0 -37
- package/hooks/validation/AGENTS.md +0 -19
- package/hooks/validators/AGENTS.md +0 -51
- package/hooks/workflow/AGENTS.md +0 -15
- package/output-styles/AGENTS.md +0 -14
- package/package.json +1 -1
- package/rules/AGENTS.md +0 -58
- package/rules/claims-as-quotes.md +0 -10
- package/rules/code-standards.md +6 -6
- package/rules/explore-thoroughly.md +0 -1
- package/rules/failure-blast-radius.md +0 -8
- package/rules/falsify-before-green.md +0 -8
- package/rules/file-global-constants.md +2 -2
- package/rules/filesystem-search.md +1 -1
- package/rules/git-workflow.md +1 -9
- package/rules/hedging-claims.md +2 -6
- package/rules/long-horizon-autonomy.md +1 -1
- package/rules/measurement-denominators.md +0 -9
- package/rules/research-mode.md +0 -6
- package/rules/verify-before-asking.md +0 -5
- package/rules/verify-runtime-state.md +0 -5
- package/scripts/AGENTS.md +0 -55
- package/scripts/codex_compat_materializer.py +0 -12
- package/scripts/dev_env_scripts_constants/AGENTS.md +0 -20
- package/scripts/sync_to_cursor/AGENTS.md +0 -22
- package/scripts/sync_to_cursor/rules.py +0 -10
- package/scripts/tests/AGENTS.md +0 -34
- package/scripts/tests/test_engine.py +0 -1
- package/scripts/tests/test_rules.py +0 -1
- package/scripts/tests/test_sync_to_cursor.py +0 -1
- package/system-prompts/AGENTS.md +0 -24
- package/system-prompts/software-engineer.xml +3 -3
- package/hooks/blocking/code_rules_dead_argparse_argument.py +0 -554
- package/hooks/blocking/code_rules_dead_config_field.py +0 -568
- package/hooks/blocking/code_rules_dead_dataclass_field.py +0 -348
- package/hooks/blocking/code_rules_dead_module_constant.py +0 -757
- package/hooks/blocking/code_rules_dead_split_branch.py +0 -225
- package/hooks/blocking/code_rules_mock_completeness.py +0 -295
- package/hooks/blocking/code_rules_scope_binding.py +0 -151
- package/hooks/blocking/code_rules_unused_imports.py +0 -197
- package/hooks/blocking/hedging_language_blocker.py +0 -221
- package/hooks/blocking/intent_only_ending_blocker.py +0 -148
- package/hooks/blocking/test_code_rules_enforcer_dead_argparse_argument.py +0 -534
- package/hooks/blocking/test_code_rules_enforcer_dead_config_field.py +0 -846
- package/hooks/blocking/test_code_rules_enforcer_dead_dataclass_field.py +0 -507
- package/hooks/blocking/test_code_rules_enforcer_dead_module_constant.py +0 -679
- package/hooks/blocking/test_code_rules_enforcer_dead_module_constant_alias.py +0 -133
- package/hooks/blocking/test_code_rules_enforcer_dead_module_constant_read_cap.py +0 -103
- package/hooks/blocking/test_code_rules_enforcer_dead_split_branch.py +0 -105
- package/hooks/blocking/test_code_rules_enforcer_docstring_args_span_scope.py +0 -425
- package/hooks/blocking/test_code_rules_enforcer_docstring_cardinal_family.py +0 -176
- package/hooks/blocking/test_code_rules_enforcer_docstring_delegation_summary.py +0 -385
- package/hooks/blocking/test_code_rules_enforcer_docstring_fallback_branch.py +0 -398
- package/hooks/blocking/test_code_rules_enforcer_docstring_field_runmode_outcome.py +0 -129
- package/hooks/blocking/test_code_rules_enforcer_docstring_inline_literal_claim.py +0 -93
- package/hooks/blocking/test_code_rules_enforcer_docstring_length_constant_superlative.py +0 -198
- package/hooks/blocking/test_code_rules_enforcer_docstring_mark_glyph_enumeration.py +0 -262
- package/hooks/blocking/test_code_rules_enforcer_docstring_no_consumer.py +0 -93
- package/hooks/blocking/test_code_rules_enforcer_docstring_no_network.py +0 -115
- package/hooks/blocking/test_code_rules_enforcer_docstring_raises_largezipfile.py +0 -226
- package/hooks/blocking/test_code_rules_enforcer_docstring_returns_plural_cardinality.py +0 -207
- package/hooks/blocking/test_code_rules_enforcer_docstring_step_dispatch.py +0 -262
- package/hooks/blocking/test_code_rules_enforcer_docstring_type_checking_gate.py +0 -164
- package/hooks/blocking/test_code_rules_enforcer_docstring_unguarded_payload.py +0 -188
- package/hooks/blocking/test_code_rules_enforcer_import_block_sort.py +0 -157
- package/hooks/blocking/test_code_rules_enforcer_split_mocks_1.py +0 -303
- package/hooks/blocking/test_code_rules_enforcer_split_mocks_2.py +0 -111
- package/hooks/blocking/test_code_rules_enforcer_unused_imports.py +0 -656
- package/hooks/blocking/test_hedging_language_blocker.py +0 -261
- package/hooks/blocking/test_intent_only_ending_blocker.py +0 -209
- package/hooks/hooks_constants/dead_argparse_argument_constants.py +0 -28
- package/hooks/hooks_constants/dead_config_field_constants.py +0 -39
- package/hooks/hooks_constants/dead_dataclass_field_constants.py +0 -25
- package/hooks/hooks_constants/dead_module_constant_constants.py +0 -30
- package/hooks/hooks_constants/hedging_uncertainty_constants.py +0 -42
- package/hooks/hooks_constants/test_dispatcher_constants_docstrings.py +0 -44
- package/rules/conservative-action.md +0 -17
- package/rules/context7.md +0 -8
- package/rules/few-words.md +0 -3
- package/rules/parallel-tools.md +0 -23
|
@@ -1,44 +1 @@
|
|
|
1
|
-
# _shared/pr-loop/scripts/tests
|
|
2
1
|
|
|
3
|
-
pytest suite for the scripts and constants in `_shared/pr-loop/scripts/`. Each test file covers one script or one constants module.
|
|
4
|
-
|
|
5
|
-
## Test files
|
|
6
|
-
|
|
7
|
-
| File | Covers |
|
|
8
|
-
|---|---|
|
|
9
|
-
| `test__claude_permissions_common.py` | Internal helpers in `_claude_permissions_common.py` (legacy underscore prefix) |
|
|
10
|
-
| `test_claude_permissions_common.py` | Public API of `_claude_permissions_common.py` |
|
|
11
|
-
| `test_claude_permissions_constants.py` | `pr_loop_shared_constants/claude_permissions_constants.py` |
|
|
12
|
-
| `test_claude_settings_keys_constants.py` | `pr_loop_shared_constants/claude_settings_keys_constants.py` |
|
|
13
|
-
| `test_code_rules_gate.py` | `code_rules_gate.py` gate logic |
|
|
14
|
-
| `test_terminology_sweep.py` | `terminology_sweep.py` near-miss detection and exit codes |
|
|
15
|
-
| `test_code_rules_gate_constants.py` | `pr_loop_shared_constants/code_rules_gate_constants.py` |
|
|
16
|
-
| `test_fix_hookspath.py` | `fix_hookspath.py` repair logic |
|
|
17
|
-
| `test_fix_hookspath_constants.py` | `pr_loop_shared_constants/fix_hookspath_constants.py` |
|
|
18
|
-
| `test_grant_project_claude_permissions.py` | `grant_project_claude_permissions.py` end-to-end |
|
|
19
|
-
| `test_post_audit_thread.py` | `post_audit_thread.py` review-posting flow |
|
|
20
|
-
| `test_post_audit_thread_constants.py` | `pr_loop_shared_constants/post_audit_thread_constants.py` |
|
|
21
|
-
| `test_preflight.py` | `preflight.py` pre-flight checks |
|
|
22
|
-
| `test_preflight_constants.py` | `pr_loop_shared_constants/preflight_constants.py` |
|
|
23
|
-
| `test_preflight_self_heal.py` | `preflight_self_heal.py` hooks-path repair |
|
|
24
|
-
| `test_reviews_disabled.py` | `reviews_disabled.py` opt-out gate parsing |
|
|
25
|
-
| `test_copilot_quota.py` | `copilot_quota.py` end-to-end: account resolution, premium-quota classification, exit codes, and skip logging |
|
|
26
|
-
| `test_copilot_quota_constants.py` | `pr_loop_shared_constants/copilot_quota_constants.py` |
|
|
27
|
-
| `test_reviewer_availability.py` | `reviewer_availability.py` end-to-end: Copilot and Bugbot availability, opt-out via `CLAUDE_REVIEWS_DISABLED`, and every Copilot quota outcome |
|
|
28
|
-
| `test_reviewer_availability_constants.py` | `pr_loop_shared_constants/reviewer_availability_constants.py` |
|
|
29
|
-
| `test_revoke_project_claude_permissions.py` | `revoke_project_claude_permissions.py` end-to-end |
|
|
30
|
-
| `test_stale_worktree_rule_sweep.py` | `stale_worktree_rule_sweep.py` sweep and deduplication end-to-end |
|
|
31
|
-
| `test_stale_worktree_rule_sweep_constants.py` | `pr_loop_shared_constants/stale_worktree_rule_sweep_constants.py` worktrees-root resolution and rule-format readers |
|
|
32
|
-
| `test_agent_config_carveout.py` | Agent-config deny-rule carve-out logic |
|
|
33
|
-
| `conftest.py` | Shared pytest fixtures |
|
|
34
|
-
|
|
35
|
-
## Fixtures
|
|
36
|
-
|
|
37
|
-
`fixtures/copilot_internal_user_example.json` — a captured `gh api
|
|
38
|
-
copilot_internal/user` response driving `test_copilot_quota.py`.
|
|
39
|
-
|
|
40
|
-
## Running
|
|
41
|
-
|
|
42
|
-
```bash
|
|
43
|
-
python -m pytest packages/claude-dev-env/_shared/pr-loop/scripts/tests/
|
|
44
|
-
```
|
|
@@ -1,41 +1 @@
|
|
|
1
|
-
# _shared/process-tree
|
|
2
1
|
|
|
3
|
-
One home for ending a spawned process together with every descendant it
|
|
4
|
-
started. Callers that capture a CLI's output import it so a grandchild can
|
|
5
|
-
never outlive the run and hold the capture pipe open.
|
|
6
|
-
|
|
7
|
-
## Consumers
|
|
8
|
-
|
|
9
|
-
| Caller | Use |
|
|
10
|
-
|---|---|
|
|
11
|
-
| `scripts/grok_headless_runner.py` | Kills a timed-out worker's tree between drain attempts |
|
|
12
|
-
| `_shared/pr-loop/scripts/run_codex_review.py` | Kills the review tree on timeout, then drains |
|
|
13
|
-
| `_shared/pr-loop/scripts/codex_usage_probe.py` | Tears the app-server tree down after the rate-limits exchange |
|
|
14
|
-
|
|
15
|
-
A PR-loop script reaches this home the way convergence scripts reach
|
|
16
|
-
`_shared/pr-loop/scripts`: it puts the directory on `sys.path` and imports by
|
|
17
|
-
module name. `bin/install.mjs` copies `_shared` and `scripts` together, and
|
|
18
|
-
every install group that carries a consumer carries `_shared`, so the import
|
|
19
|
-
resolves in the repository and under `~/.claude` alike.
|
|
20
|
-
|
|
21
|
-
## Key files
|
|
22
|
-
|
|
23
|
-
| File | Purpose |
|
|
24
|
-
|---|---|
|
|
25
|
-
| `scripts/process_tree_kill.py` | `terminate_process_tree` (poll, platform tree kill, re-poll, `Popen.kill()` fallback), `kill_process_tree_by_identifier`, and `should_start_new_session` for the matching `Popen` flag |
|
|
26
|
-
| `scripts/test_process_tree_kill.py` | Behavioral tests for every public entry point here, each platform branch, each failure the helper swallows, and the `Popen.kill()` fallback |
|
|
27
|
-
| `scripts/config/process_tree_scripts_constants/process_tree_kill_constants.py` | The taskkill command, its `/T`, `/F`, and `/PID` flags, and the bound on the kill command |
|
|
28
|
-
| `scripts/pyproject.toml` | mypy configuration; `check.ps1` runs it under the `mypy-process-tree` label |
|
|
29
|
-
|
|
30
|
-
## Platform guard
|
|
31
|
-
|
|
32
|
-
Both the branch selector and the POSIX helper compare `sys.platform` against
|
|
33
|
-
the literal `"win32"`. That literal is what mypy narrows on: behind a named
|
|
34
|
-
constant, `os.getpgid`, `os.killpg`, and `signal.SIGKILL` fail type checking on
|
|
35
|
-
Windows.
|
|
36
|
-
|
|
37
|
-
## Pairing rule
|
|
38
|
-
|
|
39
|
-
`os.killpg` signals a whole process group, so a child sharing the caller's
|
|
40
|
-
group takes the caller down with it. Every `Popen` whose tree this module ends
|
|
41
|
-
passes `start_new_session=should_start_new_session()`.
|
package/audit-rubrics/AGENTS.md
CHANGED
|
@@ -1,43 +1 @@
|
|
|
1
|
-
# audit-rubrics
|
|
2
1
|
|
|
3
|
-
Audit rubrics for the PR-loop code-review suite. The rubrics define the 17 bug categories (A–Q), their sub-bucket decompositions, and the prompt templates agents use during an audit pass. Installed into `~/.claude/audit-rubrics/` by `bin/install.mjs`.
|
|
4
|
-
|
|
5
|
-
## Key file
|
|
6
|
-
|
|
7
|
-
| File | Purpose |
|
|
8
|
-
|---|---|
|
|
9
|
-
| `audit-categories.json` | Machine-readable A-Q schema: id, title, slug, and sub-bucket id/axis pairs; single source for rubric and prompt skeleton parity |
|
|
10
|
-
| `source-material-section-types.md` | Lookup table for how to chunk an artifact into sections for an audit prompt; covers code PRs, docs, SQL schemas, config files, and more |
|
|
11
|
-
|
|
12
|
-
## Subdirectories
|
|
13
|
-
|
|
14
|
-
| Entry | Description |
|
|
15
|
-
|---|---|
|
|
16
|
-
| `category_rubrics/` | One `.md` per category (A–Q): defines what the category audits, example findings, and a sub-bucket decomposition table |
|
|
17
|
-
| `prompts/` | One `.md` per category: the ready-to-use audit prompt template an agent inlines the artifact into |
|
|
18
|
-
|
|
19
|
-
## Categories
|
|
20
|
-
|
|
21
|
-
| ID | Name |
|
|
22
|
-
|---|---|
|
|
23
|
-
| A | API contract verification |
|
|
24
|
-
| B | Selector engine compatibility |
|
|
25
|
-
| C | Resource cleanup |
|
|
26
|
-
| D | Scoping and ordering |
|
|
27
|
-
| E | Dead code |
|
|
28
|
-
| F | Silent failures |
|
|
29
|
-
| G | Bounds and overflow |
|
|
30
|
-
| H | Security boundaries |
|
|
31
|
-
| I | Concurrency |
|
|
32
|
-
| J | Code-rules compliance |
|
|
33
|
-
| K | Codebase conflicts |
|
|
34
|
-
| L | Behavior equivalence |
|
|
35
|
-
| M | Producer-consumer cardinality |
|
|
36
|
-
| N | Test name / scenario verifier |
|
|
37
|
-
| O | Docstring vs implementation drift |
|
|
38
|
-
| P | Name vs behavior contract |
|
|
39
|
-
| Q | Cross-surface claim consistency |
|
|
40
|
-
|
|
41
|
-
## Breaking-change rule
|
|
42
|
-
|
|
43
|
-
Adding a sub-bucket to a category rubric requires updating `audit-categories.json` and the matching prompt template in `prompts/` in the same commit, then running `audit_category_schema.py --validate`. Skills that reference category IDs (`bugteam`, `findbugs`) rely on stable sub-bucket IDs (A1, A2, … Q-n). Worked examples stay in the rubric markdown only; they are outside the schema.
|
|
@@ -1,37 +1 @@
|
|
|
1
|
-
# audit-rubrics/category_rubrics
|
|
2
1
|
|
|
3
|
-
One rubric file per audit category (A–Q). Each file defines what the category covers, gives concrete examples of findings, and provides the sub-bucket decomposition an audit agent uses to structure its pass.
|
|
4
|
-
|
|
5
|
-
## Files
|
|
6
|
-
|
|
7
|
-
| File | Category |
|
|
8
|
-
|---|---|
|
|
9
|
-
| `category-a-api-contracts.md` | A — API contract verification |
|
|
10
|
-
| `category-b-selector-engine-compat.md` | B — Selector engine compatibility |
|
|
11
|
-
| `category-c-resource-cleanup.md` | C — Resource cleanup |
|
|
12
|
-
| `category-d-scoping-and-ordering.md` | D — Scoping and ordering |
|
|
13
|
-
| `category-e-dead-code.md` | E — Dead code |
|
|
14
|
-
| `category-f-silent-failures.md` | F — Silent failures |
|
|
15
|
-
| `category-g-bounds-and-overflow.md` | G — Bounds and overflow |
|
|
16
|
-
| `category-h-security-boundaries.md` | H — Security boundaries |
|
|
17
|
-
| `category-i-concurrency.md` | I — Concurrency |
|
|
18
|
-
| `category-j-code-rules-compliance.md` | J — Code-rules compliance |
|
|
19
|
-
| `category-k-codebase-conflicts.md` | K — Codebase conflicts |
|
|
20
|
-
| `category-l-behavior-equivalence.md` | L — Behavior equivalence |
|
|
21
|
-
| `category-m-producer-consumer-cardinality.md` | M — Producer-consumer cardinality |
|
|
22
|
-
| `category-n-test-name-scenario-verifier.md` | N — Test name / scenario verifier |
|
|
23
|
-
| `category-o-docstring-vs-impl-drift.md` | O — Docstring vs implementation drift |
|
|
24
|
-
| `category-p-name-vs-behavior-contract.md` | P — Name vs behavior contract |
|
|
25
|
-
| `category-q-cross-surface-claims.md` | Q — Cross-surface claim consistency |
|
|
26
|
-
|
|
27
|
-
## Rubric structure
|
|
28
|
-
|
|
29
|
-
Each file has:
|
|
30
|
-
- A plain-language description of what the category audits
|
|
31
|
-
- Concrete finding examples
|
|
32
|
-
- A companion-reference pointer to `../source-material-section-types.md`
|
|
33
|
-
- A sub-bucket decomposition table with stable IDs (A1, A2, …) and the concrete checks each bucket requires
|
|
34
|
-
|
|
35
|
-
## Relationship to prompts/
|
|
36
|
-
|
|
37
|
-
`category_rubrics/` is the human-readable reference. `prompts/` holds the agent-ready prompt templates that inline the same sub-bucket list in a structured prompt format. Keep both in sync when sub-buckets change.
|
|
@@ -36,11 +36,11 @@ Decomposition is by the **kind of docstring claim** that needs to be cross-check
|
|
|
36
36
|
| O1 | Module-level responsibility verbs | A module docstring uses verbs (`detects`, `validates`, `enforces`, `recovers`, `parses`, `routes`) — every claimed responsibility is implemented by an exported symbol in the same module. Symbols absent from the module body should not appear as this module's responsibilities. A module whose one-line docstring scopes its contents to user-facing text (`User-facing strings: CLI flag names, help text, and log messages`) also names every category of constant the body holds. When the body also defines serialization field keys (`JSONL_FIELD_*`), run-metadata schema keys (`RUN_METADATA_CLI_ARG_KEY_*`), or runtime config (`STDOUT_ENCODING`, `MAIN_LOGGING_FORMAT_STRING`), the strings-only summary under-describes the module. Broaden the summary to name the data-schema keys and runtime config. The `check_module_docstring_scope_omits_data_schema_constants` gate blocks this drift at Write/Edit time when the summary claims a user-facing-text scope and names no data-schema or runtime-config category. |
|
|
37
37
|
| O2 | Fixture docstring vs sibling-test behavior | An autouse / module-scope fixture docstring asserts an invariant (`readability is disabled`, `network is mocked`, `tmp_path is empty`). No sibling test in the same module explicitly opts out of the invariant. |
|
|
38
38
|
| O3 | Predicate-name and -docstring vs body breadth | A boolean helper's name and docstring promise a narrow predicate. Walk the body's branches: every branch's `return True` path is consistent with the promised name. Bodies that accept inputs broader than the name (`_dir_value_resolves_to_shared_temp` also accepting HOME/TMP env-derived paths) are O3 findings. |
|
|
39
|
-
| O4 | Step-ordering narrative | A docstring describes processing as `A then B then C`. Walk the body and confirm the call order matches. Mismatched order is an O4 finding regardless of whether the final output is the same. A docstring step enumeration that names the body's linear steps but omits a corrective workflow step the body guards inside an `if`/`elif` branch (`if not await cancel_and_reinitiate_update(...): return`) is also an O4 finding: the reader trusts the step list to be complete and misses the conditional path. The branch-guarded-dispatch shape of this drift — a docstring that names two or more linear-step callees while the body guards a two-or-more-token dispatch callee inside a branch whose name the prose never spells out —
|
|
39
|
+
| O4 | Step-ordering narrative | A docstring describes processing as `A then B then C`. Walk the body and confirm the call order matches. Mismatched order is an O4 finding regardless of whether the final output is the same. A docstring step enumeration that names the body's linear steps but omits a corrective workflow step the body guards inside an `if`/`elif` branch (`if not await cancel_and_reinitiate_update(...): return`) is also an O4 finding: the reader trusts the step list to be complete and misses the conditional path. The branch-guarded-dispatch shape of this drift — a docstring that names two or more linear-step callees while the body guards a two-or-more-token dispatch callee inside a branch whose name the prose never spells out — stays judgment for this lane, alongside re-ordered steps and plain unguarded steps the prose omits. |
|
|
40
40
|
| O5 | Named-sentinel / filename references | A docstring names a sentinel marker, environment variable, filename, or magic string. Confirm the named token actually exists in the module body or in the repo's naming convention. |
|
|
41
|
-
| O6 | Free-form `Args:`-adjacent claims | A docstring's `Returns:` / `Raises:` / `Note:` / `Example:` sections make claims (`returns shared-temp only`, `raises ValueError on missing key`). Verify each claim against the body. When a docstring enumerates the inputs a body counts (a "field counts as read when ..." list, a list of conditions treated as a match, a list of cases the body skips), list every union member and every suppressor the body applies (`read_names = a \| b \| c`, each early-return guard) and confirm each appears in the prose enumeration. A union member or suppressor the body applies but the prose omits is an O6 finding. When a docstring sentence excludes a named category of input from what the function flags (`X are not dispatch steps`, `Y is not a match`), confirm the axis the prose excludes on is the axis the body's branch condition actually keys on. A body that flags a call when it sits inside an `If.test` guard, paired with prose that excludes by the call's receiver shape (`method-on-local calls inside a branch are not dispatch steps`), is an O6 finding: a guarded method-on-local call is flagged even though the prose lists it as excluded — the exclusion is keyed to the wrong axis. A thin delegating method whose docstring names its actions and points at the home of the real body lists the same actions the delegated function's own summary lists; when an edit moves one action out of the delegated body, the same edit rewords both summaries
|
|
41
|
+
| O6 | Free-form `Args:`-adjacent claims | A docstring's `Returns:` / `Raises:` / `Note:` / `Example:` sections make claims (`returns shared-temp only`, `raises ValueError on missing key`). Verify each claim against the body. When a docstring enumerates the inputs a body counts (a "field counts as read when ..." list, a list of conditions treated as a match, a list of cases the body skips), list every union member and every suppressor the body applies (`read_names = a \| b \| c`, each early-return guard) and confirm each appears in the prose enumeration. A union member or suppressor the body applies but the prose omits is an O6 finding. When a docstring sentence excludes a named category of input from what the function flags (`X are not dispatch steps`, `Y is not a match`), confirm the axis the prose excludes on is the axis the body's branch condition actually keys on. A body that flags a call when it sits inside an `If.test` guard, paired with prose that excludes by the call's receiver shape (`method-on-local calls inside a branch are not dispatch steps`), is an O6 finding: a guarded method-on-local call is flagged even though the prose lists it as excluded — the exclusion is keyed to the wrong axis. A thin delegating method whose docstring names its actions and points at the home of the real body lists the same actions the delegated function's own summary lists; when an edit moves one action out of the delegated body, the same edit rewords both summaries — judgment for this lane. A conditional bullet in the delegated prose also names every exception the body honors — that conditional-completeness slice stays a judgment call for this lane. A `Returns:` that names the mechanism, tool, or output format the function produces (`instructing a StructuredOutput summary`, `returns a YAML document`, `emits a JSON object`) matches the artifact the body actually builds. A dataclass or `TypedDict` field documented in the class `Attributes:` block states what the field means for one record; when the code sets that field the same way for every record (a run-mode flag such as `is_dry_run = not is_execute`), the description states the run-mode meaning, not a per-record outcome — judgment for this lane. A workflow gate-outcome status flag whose in-code prose (a schema property `description`, an architecture `detail`/overview string) describes the outcome as bypassing or skipping matches the branch that handles it: when the code routes that outcome to a blocker (`blocker = ...; break`) that holds the PR in draft, prose that reads "skips without blocking" or "the gate is bypassed" for that outcome is an O6 finding. The remaining deterministic O6 shape is gated at Write/Edit time — see **Write-time gate inventory** below — so the audit lane focuses on the free-form shapes the gate cannot match. |
|
|
42
42
|
| O7 | Module-doc-vs-split-module after refactor | When a refactor moves a responsibility to a sibling module, the originating module's docstring and the receiving module's docstring both describe the home of that responsibility. A module docstring should describe only the responsibilities it owns. |
|
|
43
|
-
| O8 | Companion-doc ordering/content vs producer | When a PR changes a producer function's ordering or union, read that skill's companion `SKILL.md` and sibling `.md` docs for any sentence naming the same produced artifact (a file path, a JSON key, a named list). A doc sentence that claims the artifact is `sorted` / `alphabetical` / `in sorted order`, or holds `just the at-risk names` / `only the current set`, while the producer merges stored names with new names and appends — preserving file order, not re-sorting the union — is an O8 finding on both counts (wrong order claim, hidden merged-in entries). The finding stands even when the PR diff never touched the `.md` file, because the behavior change orphaned the doc claim. A producer docstring asserting that no consumer reads its output yet (`producer-only artifact`, `no submission-run consumer reads it yet`) is the
|
|
43
|
+
| O8 | Companion-doc ordering/content vs producer | When a PR changes a producer function's ordering or union, read that skill's companion `SKILL.md` and sibling `.md` docs for any sentence naming the same produced artifact (a file path, a JSON key, a named list). A doc sentence that claims the artifact is `sorted` / `alphabetical` / `in sorted order`, or holds `just the at-risk names` / `only the current set`, while the producer merges stored names with new names and appends — preserving file order, not re-sorting the union — is an O8 finding on both counts (wrong order claim, hidden merged-in entries). The finding stands even when the PR diff never touched the `.md` file, because the behavior change orphaned the doc claim. A producer docstring asserting that no consumer reads its output yet (`producer-only artifact`, `no submission-run consumer reads it yet`) is the same companion-doc producer/consumer drift — judgment for this lane. The O6 pattern recurs at the companion-doc layer: when a PR routes a gate outcome to a blocker, read every skill's `SKILL.md` and reference `.md` docs that name that gate for a line still calling the outcome a bypass — an O8 finding. |
|
|
44
44
|
| O9 | Python docstring plainness for a general developer | A changed module / class / public-function docstring's narrative prose — the summary and description before the first `Args:` / `Returns:` / `Raises:` / `Yields:` section — reads plainly and paints a concrete scene a general developer follows on first read. Flag a narrative that stacks abstract machinery nouns into a wall (`the SIGINT install/restore/installability check, the atexit terminal-record registration, and the interrupted-run finalizer`), that defines a thing by what it is not (`the non-promoter-specific machinery`), or that runs one sentence long while joining clauses with an em-dash or a semicolon. The diagram-first shape carries this best: a summary line, then a `::` example block or a doctest that shows a concrete input and its marked outcome, then a couple of short prose lines. The deterministic run-on mark is gated at Write/Edit time by `check_docstring_runon_sentence` in `code_rules_docstrings.py`, and a narrative that runs more than six prose lines with no such block is gated by `check_docstring_prose_wall_without_illustration` in the same module, so this lane carries the judgment the gates cannot: whether a stranger to the code pictures the moment, the input, and the outcome after one read, and whether the diagram truly illustrates — a real input, a marked outcome, an `ok:` / `flag:` contrast a reader learns from. See `../../rules/plain-illustrative-docstrings.md`. |
|
|
45
45
|
|
|
46
46
|
---
|
|
@@ -54,29 +54,16 @@ Deterministic slices of Category O that fire at Write/Edit. The free-form rest s
|
|
|
54
54
|
| Gate | Drift it blocks |
|
|
55
55
|
|---|---|
|
|
56
56
|
| `check_docstring_args_match_signature` | `Args:` section parameter names vs the signature. |
|
|
57
|
-
| `
|
|
58
|
-
| `check_docstring_names_absent_type_checking_gate` | Docstring names a `TYPE_CHECKING` gate or `type-checking-gate` helper family while no identifier in the module carries the `type_checking` marker. |
|
|
59
|
-
| `check_docstring_length_constant_superlative_vs_exact_gate` | Module docstring describes an integer `*_LENGTH` constant with a superlative or range word while every consumer compares `len(...)` with `==`/`!=` (exact-length gate). Scans the constant module's package tree. |
|
|
60
|
-
| `check_docstring_fallback_branch_coverage` | Summary scopes a fallback to one condition while the body routes to that fallback from two or more early-return guards. |
|
|
57
|
+
| `check_docstring_documents_unreferenced_parameter` | A documented `Args:` parameter the function body never references. |
|
|
61
58
|
| `check_class_docstring_names_public_methods` | Class docstring is a single summary line while the class exposes two or more public methods the summary never names. |
|
|
62
|
-
| `check_docstring_no_consumer_claim` | Producer docstring asserts no consumer reads its output yet. |
|
|
63
|
-
| `check_docstring_returns_plural_cardinality` | `Returns:` names a dict-key prefix family with a plural noun while the returned dict holds exactly one key in that family. |
|
|
64
|
-
| `check_docstring_args_single_line_scope_vs_span` | `Args:` scopes a finding to one named line while the body scopes through a `range(...)` span-intersection. |
|
|
65
|
-
| `check_docstring_cardinal_count_matches_constant_family` | Docstring states a cardinal count of an outcome family and lists members, while the module references more members of the same `UPPER_SNAKE` family than the count names. Runs on test modules as well as production. |
|
|
66
|
-
| `check_docstring_raises_unraisable_largezipfile` | `Raises:` names `zipfile.LargeZipFile` while the writer opens with `allowZip64` at its default of True. |
|
|
67
|
-
| `check_docstring_no_network_claim_with_metadata_access` | Docstring promises a path returns without touching the network while the body calls path-metadata methods (`is_file`, `is_dir`, `exists`, `stat`, `lstat`). |
|
|
68
|
-
| `check_docstring_step_enumeration_dispatch_coverage` | Step-enumeration docstring omits a two-or-more-token dispatch step the body guards inside a branch. |
|
|
69
|
-
| `check_docstring_unguarded_malformed_payload_claim` | Docstring promises a malformed payload resolves to None while a payload subscript sits outside the try/except whose handler returns None. |
|
|
70
|
-
| `check_docstring_field_runmode_outcome` | `Attributes:` entry for a run-mode flag field (name carrying `dry_run`) whose description carries a per-record write-outcome phrase and no run-mode phrase. |
|
|
71
59
|
| `check_module_docstring_scope_omits_data_schema_constants` | Module summary claims user-facing-text scope while the body also defines data-schema or runtime-config constants. |
|
|
72
60
|
| `check_module_docstring_names_public_checks` | One-line check-registry module docstring omits a public `check_*` function the module dispatches. |
|
|
73
|
-
| `check_docstring_tuple_enumeration_match` | Docstring enumerates inline-code tokens that drift from the literal string tuple the body reads (a listed token the tuple lacks, or a tuple member the prose omits). |
|
|
74
|
-
| `check_docstring_punctuation_mark_enumeration_coverage` | Docstring names some marks of a punctuation-glyph tuple by their English names but omits one the tuple holds. |
|
|
75
|
-
| `check_docstring_no_inline_literal_claim` | Constants-module docstring asserts no literals appear inline in a companion file. |
|
|
76
61
|
| `check_docstring_names_undefined_constant` | Docstring names an `UPPER_SNAKE` constant identifier nothing in the module backs. |
|
|
77
62
|
| `check_docstring_runon_sentence` | Narrative run-on mark (O9 backstop). |
|
|
78
63
|
| `check_docstring_prose_wall_without_illustration` | Narrative longer than six prose lines with no `::` / doctest illustration (O9 backstop). |
|
|
79
64
|
|
|
65
|
+
The bespoke single-shape detectors this table listed before (delegation-summary drift, TYPE_CHECKING-gate naming, length-constant superlative-vs-exact, fallback-branch coverage, no-consumer claims, returns-plural cardinality, Args single-line-vs-span, cardinal-count families, `LargeZipFile` reachability, no-network claims, step-enumeration dispatch, unguarded-malformed-payload claims, run-mode-outcome field meaning, tuple-enumeration match, punctuation-mark enumeration, no-inline-literal claims) were retired from `code_rules_docstrings.py` — each named one exact stdlib API, field name, phrase, or enumeration shape rather than a general docstring-vs-body class. Their drift classes stay judgment for this lane; the free-form checklist below still names each shape.
|
|
66
|
+
|
|
80
67
|
### JavaScript / `.mjs` — `packages/claude-dev-env/hooks/blocking/code_rules_imports_logging.py`
|
|
81
68
|
|
|
82
69
|
These are the `.mjs` slice of the same Category O standard. The Python AST docstring gates never inspect JavaScript source.
|
|
@@ -96,22 +83,22 @@ Read the body and the docstring side by side. Apply each check that matches the
|
|
|
96
83
|
|
|
97
84
|
- **Read-source / match-source unions.** A body that computes `read_names = a | b | c` (or any union of "what counts") names each union member in the prose enumeration.
|
|
98
85
|
- **Suppressor / skip lists.** A body with several early returns that suppress the check names each suppressor in the prose.
|
|
99
|
-
- **Shared fallback routes.** A summary that scopes a fallback call to one condition names every condition that reaches that call
|
|
100
|
-
- **Step order.** A docstring that says `A then B then C` matches the call order in the body. A step enumeration that names the body's linear steps also names every corrective step the body guards inside an `if`/`elif` branch
|
|
101
|
-
- **Delegation pointer summaries.** A thin delegating method whose docstring names its actions and points at the home of the real body lists the same actions the delegated function's own summary lists
|
|
86
|
+
- **Shared fallback routes.** A summary that scopes a fallback call to one condition names every condition that reaches that call — judgment for this lane.
|
|
87
|
+
- **Step order.** A docstring that says `A then B then C` matches the call order in the body. A step enumeration that names the body's linear steps also names every corrective step the body guards inside an `if`/`elif` branch — judgment for this lane.
|
|
88
|
+
- **Delegation pointer summaries.** A thin delegating method whose docstring names its actions and points at the home of the real body lists the same actions the delegated function's own summary lists — judgment for this lane, including a conditional bullet in the delegated prose that names every exception the body honors.
|
|
102
89
|
- **JS/`.mjs` resume-task, `@returns` object, sibling return keys, bare-flag directives.** See the JavaScript gate inventory above.
|
|
103
|
-
- **Returns-clause cardinality.** A `Returns:` clause that names a dict-key prefix family with a plural noun matches the count of keys in that family in the returned dict literal
|
|
104
|
-
- **Length-constant superlative vs exact gate.** A module docstring that describes an integer `*_LENGTH` constant with a superlative or range word matches how the code consumes the constant
|
|
105
|
-
- **Args single-line scope vs span body.** An `Args:` entry that scopes a finding to one named line matches the line breadth the body scopes by
|
|
106
|
-
- **Cardinal-count enumerations.** A docstring that states a count of an outcome family and lists those members names every member of that family the module references
|
|
107
|
-
- **Raises-clause reachability for `LargeZipFile`.** A `Raises:` clause that names `zipfile.LargeZipFile` matches a writer the body opens with ZIP64 forbidden
|
|
90
|
+
- **Returns-clause cardinality.** A `Returns:` clause that names a dict-key prefix family with a plural noun matches the count of keys in that family in the returned dict literal — judgment for this lane.
|
|
91
|
+
- **Length-constant superlative vs exact gate.** A module docstring that describes an integer `*_LENGTH` constant with a superlative or range word matches how the code consumes the constant — judgment for this lane.
|
|
92
|
+
- **Args single-line scope vs span body.** An `Args:` entry that scopes a finding to one named line matches the line breadth the body scopes by — judgment for this lane.
|
|
93
|
+
- **Cardinal-count enumerations.** A docstring that states a count of an outcome family and lists those members names every member of that family the module references — judgment for this lane.
|
|
94
|
+
- **Raises-clause reachability for `LargeZipFile`.** A `Raises:` clause that names `zipfile.LargeZipFile` matches a writer the body opens with ZIP64 forbidden — judgment for this lane.
|
|
108
95
|
- **Module summary scope versus data-schema constants.** A module whose one-line docstring scopes its contents to user-facing text names every category of constant the body holds. Gated form: `check_module_docstring_scope_omits_data_schema_constants`.
|
|
109
|
-
- **Field meaning: run mode versus per record.** A dataclass or `TypedDict` field documented in the class `Attributes:` block states what the field means for one record. When the code sets that field the same way for every record, the description states the run-mode meaning
|
|
96
|
+
- **Field meaning: run mode versus per record.** A dataclass or `TypedDict` field documented in the class `Attributes:` block states what the field means for one record. When the code sets that field the same way for every record, the description states the run-mode meaning — judgment for this lane.
|
|
110
97
|
- **Predicate breadth.** A boolean helper whose prose promises a narrow check accepts only the inputs the prose names — no broader input class the name and prose do not mention.
|
|
111
98
|
- **Exclusion-clause distinguisher.** A docstring sentence that says a named category of input "are not" / "is not" the thing the function flags keys the exclusion to the same axis the body's classification keys on. Read the body's actual branch condition, then state the exclusion on that same axis.
|
|
112
99
|
- **Companion-doc ordering and content claims.** A `SKILL.md` (or sibling `.md`) sentence that names a produced artifact and claims its order or its content matches the producer function's docstring and body for that same artifact. The two move together in one commit, even when the producer edit does not touch the `.md` file.
|
|
113
100
|
- **Gate-outcome status flags.** A workflow gate outcome the body routes to a blocker (`blocker = ...; break`) reads as blocked in every in-code prose string (a schema `description`, an architecture `detail`/overview string) and companion doc, never as a bypass — judgment for this lane.
|
|
114
|
-
- **TYPE_CHECKING gate claim vs code.** A docstring that names a `TYPE_CHECKING` gate-detection step matches a module whose code handles TYPE_CHECKING
|
|
101
|
+
- **TYPE_CHECKING gate claim vs code.** A docstring that names a `TYPE_CHECKING` gate-detection step matches a module whose code handles TYPE_CHECKING — judgment for this lane.
|
|
115
102
|
|
|
116
103
|
---
|
|
117
104
|
|
|
@@ -1,37 +1 @@
|
|
|
1
|
-
# audit-rubrics/prompts
|
|
2
1
|
|
|
3
|
-
Agent-ready audit prompt templates, one per category (A–Q). An agent inlines the artifact under review into the `[INLINE THE FULL ARTIFACT HERE]` placeholder and runs the prompt as-is.
|
|
4
|
-
|
|
5
|
-
## Files
|
|
6
|
-
|
|
7
|
-
| File | Category |
|
|
8
|
-
|---|---|
|
|
9
|
-
| `category-a-api-contracts.md` | A — API contract verification |
|
|
10
|
-
| `category-b-selector-engine-compat.md` | B — Selector engine compatibility |
|
|
11
|
-
| `category-c-resource-cleanup.md` | C — Resource cleanup |
|
|
12
|
-
| `category-d-scoping-and-ordering.md` | D — Scoping and ordering |
|
|
13
|
-
| `category-e-dead-code.md` | E — Dead code |
|
|
14
|
-
| `category-f-silent-failures.md` | F — Silent failures |
|
|
15
|
-
| `category-g-bounds-and-overflow.md` | G — Bounds and overflow |
|
|
16
|
-
| `category-h-security-boundaries.md` | H — Security boundaries |
|
|
17
|
-
| `category-i-concurrency.md` | I — Concurrency |
|
|
18
|
-
| `category-j-code-rules-compliance.md` | J — Code-rules compliance |
|
|
19
|
-
| `category-k-codebase-conflicts.md` | K — Codebase conflicts |
|
|
20
|
-
| `category-l-behavior-equivalence.md` | L — Behavior equivalence |
|
|
21
|
-
| `category-m-producer-consumer-cardinality.md` | M — Producer-consumer cardinality |
|
|
22
|
-
| `category-n-test-name-scenario-verifier.md` | N — Test name / scenario verifier |
|
|
23
|
-
| `category-o-docstring-vs-impl-drift.md` | O — Docstring vs implementation drift |
|
|
24
|
-
| `category-p-name-vs-behavior-contract.md` | P — Name vs behavior contract |
|
|
25
|
-
| `category-q-cross-surface-claims.md` | Q — Cross-surface claim consistency |
|
|
26
|
-
|
|
27
|
-
## Prompt structure
|
|
28
|
-
|
|
29
|
-
Each template:
|
|
30
|
-
- Scopes the audit to one category only (skip the others)
|
|
31
|
-
- Lists all sub-buckets from the matching `category_rubrics/` file
|
|
32
|
-
- Requires each sub-bucket to produce at least one Shape A finding OR one Shape B proof-of-absence with three or more adversarial probes
|
|
33
|
-
- Uses `find` as the finding ID prefix (single-pass audits) rather than `loop<N>-<K>`
|
|
34
|
-
|
|
35
|
-
## Relationship to category_rubrics/
|
|
36
|
-
|
|
37
|
-
`prompts/` is the executable form; `category_rubrics/` is the reference form. When a sub-bucket decomposition changes in a rubric, update the matching prompt in the same commit.
|
|
@@ -48,7 +48,7 @@ ID prefix: `find`.
|
|
|
48
48
|
- Adversarial probes: (a) walk each `return True` branch and ask whether the input that reached it satisfies the name's promise; (b) construct an input class outside the named promise that still returns True — that is an O3 finding; (c) check the name against neighboring helpers — is one of them the better home for the broader case.
|
|
49
49
|
|
|
50
50
|
**O4. Step-ordering narrative**
|
|
51
|
-
- Judgment: thick rubric O4 (includes branch-guarded dispatch
|
|
51
|
+
- Judgment: thick rubric O4 (includes branch-guarded dispatch).
|
|
52
52
|
- Adversarial probes: (a) read the body strictly top-to-bottom and label each call A/B/C against the docstring's named steps; (b) check for early returns that reorder visible steps; (c) check for `try/finally` blocks where the finally clause is itself one of the named steps and runs out of declared order.
|
|
53
53
|
|
|
54
54
|
**O5. Named-sentinel / filename references**
|
|
@@ -64,7 +64,7 @@ ID prefix: `find`.
|
|
|
64
64
|
- Adversarial probes: (a) for each module in the split, list its exported symbols and compare to the docstring's claimed responsibilities; (b) grep the responsibility's verb against the originating module — does the originating docstring still claim what left; (c) check for cross-module imports that reveal which file hosts each responsibility.
|
|
65
65
|
|
|
66
66
|
**O8. Companion-doc ordering/content vs producer**
|
|
67
|
-
- Judgment: thick rubric O8 (order/content claims vs producer
|
|
67
|
+
- Judgment: thick rubric O8 (order/content claims vs producer, including the producer-only assertion slice).
|
|
68
68
|
- Adversarial probes: (a) for each changed producer, name the artifact it builds and grep the skill's `SKILL.md` and sibling `.md` files for any sentence naming that artifact; (b) walk the producer body's build step — does it sort, or does it merge stored names and append in file order — and compare against the doc's order word (`sorted`, `alphabetical`); (c) check whether the doc's content claim (`just the at-risk names`, `only the current set`) hides merged-in prior entries the producer carries over from the stored file.
|
|
69
69
|
|
|
70
70
|
**O9. Python docstring plainness for a general developer**
|
package/bin/AGENTS.md
CHANGED
|
@@ -1,119 +1 @@
|
|
|
1
|
-
# bin
|
|
2
1
|
|
|
3
|
-
The installer and its companion modules. Running `npx claude-dev-env` (or `node bin/install.mjs`) copies package files into the managed root (`~/.claude/` by default; `CLAUDE_CONFIG_DIR` or `--target` selects another), copies skills and agents into the agents home (`~/.agents/` for the default root) and publishes directory pointers at `skills/` and `agents/` under the managed root, merges hook entries into that root's `settings.json`, installs Git hooks, writes `~/.mypy.ini` under the process home, and copies Codex exec-policy files into `~/.codex/rules` (`CODEX_HOME/rules` when that variable is set), and generates Cursor `.mdc` files into `~/.cursor/rules` from the installed Claude rules.
|
|
4
|
-
|
|
5
|
-
## Files
|
|
6
|
-
|
|
7
|
-
| File | Purpose |
|
|
8
|
-
|---|---|
|
|
9
|
-
| `install.mjs` | Main installer: builds a read-only plan via `install-plan.mjs`, then runs mutations inside `install-transaction.mjs` recovery (publish skill/agent lookup pointers, copy content directories, merge hooks, install skills, prune, git hooks, mypy.ini); routes `CLAUDE_HOME`, the agents home, the manifest path, and `~/.mypy.ini` through `resolve-install-root.mjs`; resolves single or multi-profile targets before mutation and writes one ownership manifest per target |
|
|
10
|
-
| `resolve-install-root.mjs` | Pure install-root resolver: precedence `--target` > `CLAUDE_CONFIG_DIR` > `~/.claude`, sibling `.agents` home (or `<root>.agents` for a named profile), separator-boundary containment, and the declared external allowlist for `~/.mypy.ini` plus files under the Codex rules directory, the Cursor home, and the agents home |
|
|
11
|
-
| `resolve-package-managed-directory.mjs` | Package-source resolver: skills and agents under `.agents/<name>/`, with a package-root `<name>/` fallback for dependency packages |
|
|
12
|
-
| `resolve-package-managed-directory.test.mjs` | Real-filesystem tests for the source resolver plus the live package `.agents` trees and `.claude` pointers |
|
|
13
|
-
| `publish-directory-pointer.mjs` | Directory-pointer helper: POSIX symlink or Windows junction from a Claude lookup path to the agents home; relocates a real directory at the lookup path into the target |
|
|
14
|
-
| `publish-directory-pointer.test.mjs` | Real-filesystem tests for pointer create, refresh, relocate, and unlink |
|
|
15
|
-
| `select-install-targets.mjs` | Pure target selection for main-default, explicit `--target`, and `--profile`/`--profiles`; rejects ambiguous or duplicate targets; builds per-target manifest records with `targetIdentity` and `managedRoot` |
|
|
16
|
-
| `install-plan.mjs` | Read-only install and uninstall plans: install preflight (managed root, source conflicts, Python, settings when hooks install) and uninstall preflight (settings JSON before removal, removable vs skipped manifest records), freezes plans E2/F execute |
|
|
17
|
-
| `install-transaction.mjs` | Install, update, and uninstall transaction journal: captures prior settings, manifest, managed files, and `core.hooksPath`, restores them on failure, and supports fault injection phases for recovery tests |
|
|
18
|
-
| `install.transaction.test.mjs` | Unit and sandbox installer tests for snapshot/restore and fault phases (`after_file_staging`, `after_settings_write`, `after_git_config`, `after_manifest_write`) |
|
|
19
|
-
| `install.uninstall-transaction.test.mjs` | Uninstall plan preflight and recovery: malformed/non-object settings fail before removal, each fault phase restores files/settings/manifest/`core.hooksPath`, retry succeeds, selected-root containment |
|
|
20
|
-
| `install.profile-root.test.mjs` | Contract tests for the install-root resolver: precedence, containment boundary, external allowlist, agents-home pairing, and the install.mjs import smoke check |
|
|
21
|
-
| `install.agents-home.test.mjs` | End-to-end tests that a sandbox install writes skills and agents under `.agents` and publishes `.claude/skills` and `.claude/agents` as directory pointers |
|
|
22
|
-
| `install.codex-rules.test.mjs` | Tests that Codex exec-policy files copy to `~/.codex/rules`, honor `CODEX_HOME`, skip `--only journal`, and uninstall without touching `default.rules` |
|
|
23
|
-
| `install.cursor-rules.test.mjs` | Tests that Cursor `.mdc` files generate into `~/.cursor/rules` from Claude rules, skip `--only journal`, and leave a local extra `.mdc` in place |
|
|
24
|
-
| `install-constants.mjs` | The named values `install.mjs` reads: `SKIPPED_SOURCE_ENTRY_NAMES` and `SKIPPED_SOURCE_FILE_EXTENSIONS` for the build artifacts the source walk leaves behind, `RUN_BACKUP_DIRECTORY_NAME_PATTERN` for the timestamp shape a run backup directory carries, `PACKAGE_AGENTS_HOME_DIRECTORY_NAME` for the `.agents` source home, `MANAGED_SKILLS_DIRECTORY_NAME` and `MANAGED_AGENTS_DIRECTORY_NAME` for the directory name each of those trees carries in a package source and under the agents home — read by the copy loops, the pointer publisher, and the prunes alike — `MANAGED_HOOKS_DIRECTORY_NAME` for the hooks tree under `~/.claude`, `SETTINGS_FILE_NAME` for the settings file the merge, the retired-hook prune, and the uninstall purge share, and `MYPY_INI_FILE_NAME` for the home-directory file `install_mypy_ini.mjs` writes, plus the Codex home and rules directory names `resolve-install-root.mjs` uses |
|
|
25
|
-
| `ever-shipped-skills.mjs` | Static `EVER_SHIPPED_SKILL_NAMES` set of every top-level skill directory name the package has shipped; the installer subtracts the current skill set from it to prune retired skills left under `~/.agents/skills` |
|
|
26
|
-
| `expand_home_directory_tokens.mjs` | Expands residual `$HOME` / `${HOME}` / `~/` tokens in settings.json hook and statusLine commands to absolute home paths at install time (literal-safe for homes that contain `$`) |
|
|
27
|
-
| `git_hooks_installer.mjs` | Installs or updates the `pre-commit`, `pre-push`, and `post-commit` Git hooks in the user's git config; writes hook scripts that delegate to the installed Python hooks |
|
|
28
|
-
| `install_mypy_ini.mjs` | Writes `~/.mypy.ini` with settings that make mypy find the hooks package and enforce strict type checking |
|
|
29
|
-
| `install.test.mjs` | Unit tests for `install.mjs` — covers conflict detection, interpreter detection, settings merging, the settings shapes the installer never wrote — those every hook walk hands back untouched, and the shipped-event value the merge replaces with a warning — the source-artifact skip in `collectFiles`, the case-only rename decision and the `copyTree` copy that acts on it, the retired-hook diff and settings prune, the stale-file prune: the manifest diff, path-key case folding, emptied-parent cleanup, and the warn-and-keep paths, and backup retention: the sweep a moved-content run drives, the empty root a run whose moves failed gives up, and the populated root retention keeps |
|
|
30
|
-
| `install.profiles.test.mjs` | Profile target-selection and per-target ownership manifest contract tests (main-default, multi-profile, ambiguity/duplicate rejection, help text) |
|
|
31
|
-
| `install.plan.test.mjs` | Read-only plan and preflight tests: zero-write plan construction, source-conflict and missing-Python fail-closed, settings check only when hooks install, tolerant broken-manifest, invalid managed root, mutation-kind list for E2 |
|
|
32
|
-
| `install.prune.test.mjs` | End-to-end prune tests that run the real installer against a sandbox `HOME` — retired-skill, retired-hook, and stale-file moves into one timestamped backup, the settings entry a retired hook loses, the top-level paths every root's diff leaves alone, the manifest record a failed move keeps, the full-install and resolved-dependency gates, backup retention, and the uninstall: the `~/.mypy.ini` removal, the containment guard, and nested-directory cleanup |
|
|
33
|
-
| `git_hooks_installer.test.mjs` | Tests for `git_hooks_installer.mjs` |
|
|
34
|
-
| `install_mypy_ini.test.mjs` | Tests for `install_mypy_ini.mjs` |
|
|
35
|
-
|
|
36
|
-
## Source build artifacts
|
|
37
|
-
|
|
38
|
-
`collectFiles` walks the package source and skips the artifacts a contributor's tooling writes beside it: the entry names `__pycache__`, `.ruff_cache`, `.pytest_cache`, `.mypy_cache`, `node_modules`, `.DS_Store`, and any file ending `.pyc` or `.pyo`. A skipped directory takes everything under it out of the walk. The `files` negations in `package.json` (`!**/__pycache__/**`, `!**/*.py[cod]`, the cache directories, `!**/*.log`, `!**/*.egg-info/**`) keep the same artifacts out of the published tarball, and `.npmignore` carries those patterns for tooling that reads it — keep the two in step. An `npx` install reads a clean tree; the walk covers a local `node bin/install.mjs` run against a working tree that holds the artifacts.
|
|
39
|
-
|
|
40
|
-
The skip and the cleanup of artifacts an earlier install copied are one code path. A `.pyc` a prior manifest records under any managed root sits outside the set the walk returns, so the next full install reads it as stale, moves it into that run's backup root, and drops it from the manifest the run writes.
|
|
41
|
-
|
|
42
|
-
## Copying a file whose name changed letter case
|
|
43
|
-
|
|
44
|
-
`copyTree` renames a destination entry that differs from the shipped file name only in letter case to the shipped name, then copies. On a case-insensitive volume `copyFileSync` writes its bytes through whichever entry the filesystem resolves the path to, so a package shipping `README.md` over an installed `Readme.md` would fill the installed entry and leave the earlier spelling standing. The rename runs first because `renameSync` inside one directory is atomic: a run interrupted between the rename and the copy leaves the file present under the shipped name holding the earlier content, which the next install overwrites.
|
|
45
|
-
|
|
46
|
-
The decision reads the destination directory's entry names, cached one listing per directory for the whole copy run. On a case-sensitive volume the two names are two files, so the rename is skipped and each name keeps its own content. `caseOnlyRenameSourceName(shippedName, existingNames, options)` holds the decision, and `options.isCaseInsensitive` carries the platform answer as a value so a test drives either branch on a host of either kind.
|
|
47
|
-
|
|
48
|
-
## Retired-skill prune
|
|
49
|
-
|
|
50
|
-
The full-install prune renames a retired skill directory into a timestamped backup rather than deleting it. Each pruned directory is renamed to `~/.claude/.claude-dev-env-pruned/<timestamp>/skills/<skill-name>/`, a backup root outside `~/.agents/skills` so a backed-up directory is never re-discovered as a skill. The `skills/` segment matches the layout the stale-file prune writes, so one recovery point reads as a copy of the tree it came from. One run shares one timestamped root, so a run leaves one recovery point. A rename that fails leaves the directory in place with a logged warning and never falls back to deletion, so a prune failure costs at most a cosmetic leftover.
|
|
51
|
-
|
|
52
|
-
Matching is by directory name alone, so a user-authored directory whose name collides with a retired skill is backed up as if it were that skill. A directory is pruned when the prior install's manifest recorded it or the ever-shipped set names it, and the current install did not just write it. A name absent from all three of those sets, together with `~/.agents/skills/_shared`, is left in place. Recovery of a wrongly-matched directory runs until the next pruning install, which keeps its own backup and retires the rest.
|
|
53
|
-
|
|
54
|
-
## Stale-file prune
|
|
55
|
-
|
|
56
|
-
A full install also moves aside a file under a managed root that the run leaves unwritten. `copyTree` adds and overwrites but never removes, so every root the installer writes carries the same drift, and the prune covers all of them: `rules`, `docs`, `commands`, `agents`, `system-prompts`, `scripts`, `_shared`, `audit-rubrics`, `skills`, and `hooks` — the names in `MANAGED_TOP_LEVEL_DIRECTORY_NAMES`.
|
|
57
|
-
|
|
58
|
-
Nothing moves unless a prior install recorded it. That single rule is what makes covering ten roots as safe as covering one: the installer reads the file list from `~/.claude/.claude-dev-env-manifest.json`, subtracts every file the run copied across all source roots, and moves what remains.
|
|
59
|
-
|
|
60
|
-
The prune runs once per root, each call confined to its own root. Per-root iteration gives the containment guard and the emptied-parent walk the root that owns each file, and it settles `_shared`: `~/.claude/_shared` and `~/.agents/skills/_shared` are distinct absolute paths, so the `_shared` call and the `skills` call each see their own files and no path enters two diffs. Each root's content lands under `~/.claude/.claude-dev-env-pruned/<timestamp>/<root-name>/<relative>`. Every prune in a run shares that one timestamped root. A recorded path under no managed root — `~/.claude/CLAUDE.md`, `settings.json`, the manifest itself, and the `~/.mypy.ini` that sits in the home directory beside `~/.claude` — reaches no root's diff and stays where it is. The install summary reports the skills root's own count on the `skills:` line and the sum across roots on its own line.
|
|
61
|
-
|
|
62
|
-
The manifest diff limits the move to files the installer itself wrote. Runtime-generated content — a Python `__pycache__` entry, a ruff cache, a log — and any file a user authored under a managed root stay in place, because no install recorded them. Path comparison ignores letter case on Windows and macOS, so a package shipping `README.md` over an installed `Readme.md` keeps the bytes the run just wrote. A directory or a link standing where the manifest records a file is skipped with a warning, so the mover never renames a whole tree and never follows a link out of `~/.claude`. A directory emptied by a move is removed, walking up to the root the file sat under. A move that fails logs a warning and leaves the file in place, so a prune failure costs at most a stale file. The installer records each such path in the fresh manifest when the file is still on disk, so the file stays inside the next full install's diff and gets another attempt.
|
|
63
|
-
|
|
64
|
-
A missing or unreadable manifest, or one carrying no file list, holds the stale-file prune for that run: with no record of what an install wrote, the run has nothing to diff against.
|
|
65
|
-
|
|
66
|
-
A run writes both manifest keys — the file list and the skill-name list — wholesale from what it just installed only when the prunes ran that run and read the prior record all the way through, so the next diff reads as "the package stopped shipping this". Every other run unions what it wrote onto the prior lists: a scoped `--only` install, a full install holding its prunes behind an unresolved dependency group, and a run whose prune step ends early with a logged warning. The union keeps every entry a later prune needs to spot a stale file or a retired skill, and keeps `--uninstall` able to name the whole tree. The prune itself bounds the lists: a stale path leaves the record on the first full install that moves it aside.
|
|
67
|
-
|
|
68
|
-
## Retired-hook entries in settings.json
|
|
69
|
-
|
|
70
|
-
A hook script under `~/.claude/hooks` carries a second reference: the `settings.json` entry that runs it. A full install removes that entry in the same run that moves the script aside, and removes it first — a `settings.json` naming a script that has left the hooks directory makes every session start invoke a missing file.
|
|
71
|
-
|
|
72
|
-
The retired set comes from the manifest diff alone: the hook files a prior install recorded that this run leaves unwritten, each taken relative to `~/.claude/hooks`. A script the run still writes stays out of the set, and a path no install of ours recorded never enters it, so a user-authored hook is out of reach of the prune. Each command is matched on the anchored `/.claude/hooks/<relative>` tail the merge uses to tell this installer's entries from a user's, so a command whose path is a retired tail plus a suffix (`retired_gate.py.bak`) names another file and stays.
|
|
73
|
-
|
|
74
|
-
The walk covers every event type the settings file holds rather than the ones the current `hooks.json` names, so an entry under an event type the package stopped shipping is reached too. A matcher group left empty is dropped, and an event type left empty goes with it. The file is written once, and only when an entry left it, so a run that retires no hook leaves `settings.json` byte-identical.
|
|
75
|
-
|
|
76
|
-
Every settings walk recognizes the shapes the installer writes and steps around the rest, so a hand-edited or third-party `settings.json` carries an install through rather than ending it. A matcher group carrying no `hooks` array and a hook entry whose `command` is not a string survive every walk untouched. An event type whose value is not an array of groups survives this prune and the uninstall purge; the merge replaces that value with the group list it ships for that event type, warning with the event type named so the user can recover the value from their own history. An event type the package ships no groups for keeps whatever value the file holds.
|
|
77
|
-
|
|
78
|
-
## Backup retention
|
|
79
|
-
|
|
80
|
-
A run that moves content into `~/.claude/.claude-dev-env-pruned/<timestamp>/` then retires the other run backups, so the directory holds the one recovery point closest to what sits on disk. The retired-skill prune and the stale-file prune each report how many moves succeeded, and their sum is the signal the sweep answers to. The sweep removes a direct child whose name matches the installer's timestamp shape (`2026-07-25T18-04-11-923Z`), which leaves anything else under the pruned-backup directory in place, along with the directory itself. A removal that fails logs a warning and the sweep carries on, so retention never ends an install. The install output names the count when the sweep removes anything.
|
|
81
|
-
|
|
82
|
-
A run that moves nothing sweeps nothing, so every recovery point the user holds stays where it is. `moveIntoRunBackup` creates the directories leading to a backup path before it renames, so a run whose every move fails — the antivirus scanner or open editor case — leaves that timestamped root standing empty. Retention clears it with `rmdirSync` alone, depth first, so a directory holding anything survives every step.
|
|
83
|
-
|
|
84
|
-
## Uninstall
|
|
85
|
-
|
|
86
|
-
`--uninstall` builds a read-only uninstall plan, captures a recovery snapshot, then removes each file the plan lists.
|
|
87
|
-
|
|
88
|
-
Settings JSON is validated before any removal. A malformed or non-object `settings.json` fails closed with the managed files still on disk. Each manifest record passes a containment guard: the path resolves under `~/.claude`, or it names the `~/.mypy.ini` the install writes in the home directory, or it sits under the Codex rules directory, or it sits under the Cursor home, or it sits under the agents home. Every other record is skipped with a warning and counted. Skipping keeps one malformed record — hand-edited, or written by an installer that ran against a different home — from stranding the user with a half-removed install. The purge removes every legitimate record, clears the manifest, and reports the skipped count.
|
|
89
|
-
|
|
90
|
-
The uninstall runs inside the same snapshot/restore journal as install: prior settings, manifest, managed files, and `core.hooksPath` restore when a later phase fails, so a retry starts from a complete ownership record. The journal is discarded only after a successful commit.
|
|
91
|
-
|
|
92
|
-
Removing a file leaves its directory a candidate for cleanup. Once the file loop ends, the purge walks up from each such directory to the managed top-level directory the file sits under (`MANAGED_TOP_LEVEL_DIRECTORY_NAMES`), removing each directory it finds empty. That reaches a nested tree such as `skills/<name>/scripts/`. A record under no managed root gets no walk, so `~/.claude` itself is never a stop root and a directory the installer never wrote stays. A separate pass drops each managed top-level directory the purge empties.
|
|
93
|
-
|
|
94
|
-
## Prune gates
|
|
95
|
-
|
|
96
|
-
Every prune runs behind the same two gates: a full install, and every declared dependency group resolved. When any dependency group fails to resolve, all of them are skipped for the whole run with a logged notice naming the unresolved group. An unresolved dependency contributes no skills to the installed set, so a live skill that a dependency package supplies would look retired and its files would look stale; holding every prune until each dependency resolves keeps that skill's files in place and keeps their manifest records, so a run with every dependency resolved can still prune them.
|
|
97
|
-
|
|
98
|
-
## Key exports from install.mjs
|
|
99
|
-
|
|
100
|
-
| Export | Description |
|
|
101
|
-
|---|---|
|
|
102
|
-
| `CONTENT_DIRECTORIES` | Array of package subdirectory names copied verbatim to `~/.claude/` (skills and agents are outside this list; they copy into the agents home) |
|
|
103
|
-
| `MANAGED_TOP_LEVEL_DIRECTORY_NAMES` | The content directories plus `skills`, `agents`, and `hooks`; the stale-file prune walks it to give each root its own diff, and the uninstall purge reads it to find the root a recorded file belongs to |
|
|
104
|
-
| `collectFiles(directory)` | Lists every file under a source directory, skipping the build-artifact names and extensions in `install-constants.mjs` |
|
|
105
|
-
| `pythonCandidatesForPlatform(platform)` | Returns ordered Python interpreter candidates to probe; `py -3` first on Windows to avoid Microsoft Store alias issues |
|
|
106
|
-
| `isWindowsStorePythonStub(path)` | Returns true when the path resolves to the non-spawnable WindowsApps stub |
|
|
107
|
-
| `interpreterCommandFromPath(path)` | Formats an absolute interpreter path as a settings.json hook command prefix |
|
|
108
|
-
| `collectPackageSourceConflicts(dir)` | Returns any unmerged git conflicts in the package source; installer aborts when any exist |
|
|
109
|
-
| `pruneStaleInstalledFiles(priorFiles, currentFiles, destinationRoot, backupRoot, options)` | Moves each manifest-recorded file under the destination root that the run leaves unwritten into the run's backup root; returns `{ prunedCount, failedPaths }`. `options.isCaseInsensitive` drives path-key case folding, defaulting to this host's filesystem; `options.managedHomeDirectory` sets the home the containment guard tests against, defaulting to `~/.claude` |
|
|
110
|
-
| `copyTree(sourceBase, destBase, options)` | Copies every file under a source directory, renaming a destination entry that differs from the shipped name only in letter case to the shipped name first; returns `{ created, updated, paths }`. `options.isCaseInsensitive` drives that rename, defaulting to this host's filesystem |
|
|
111
|
-
| `caseOnlyRenameSourceName(shippedName, existingNames, options)` | Returns the existing directory entry a shipped file name would overwrite through a case-only spelling difference, or null; `options.isCaseInsensitive` defaults to this host's filesystem |
|
|
112
|
-
| `retiredManagedHookRelativePaths(priorFiles, currentFiles, hooksRoot)` | Returns the hook script paths a prior install recorded under the hooks root that this run leaves unwritten, each relative to that root |
|
|
113
|
-
| `pruneRetiredHookEntriesFromSettings(settingsPath, retiredPaths)` | Removes each settings.json entry running a retired managed hook script, writing the file only when an entry left it; returns the removed count |
|
|
114
|
-
| `retainNewestRunBackupOnly(runBackupRoot, didRunMoveContent)` | Retires every run backup sitting beside the run's own when `didRunMoveContent` holds; clears the run's empty root with `rmdirSync` when it does not |
|
|
115
|
-
| `comparisonKeyForPath(path, options)` | Builds the key two paths are compared through: resolved, forward-slashed, and lowercased when `options.isCaseInsensitive` holds — which defaults to true on Windows and macOS |
|
|
116
|
-
|
|
117
|
-
## Install groups
|
|
118
|
-
|
|
119
|
-
`install.mjs` defines install groups (`core`, `journal`) plus any dependency groups discovered from `package.json` `dependencies`. The `core` group installs skills, all hooks, and the content directories. `journal` installs only its skill set.
|
package/bin/install.test.mjs
CHANGED
|
@@ -190,7 +190,7 @@ test('CONTENT_DIRECTORIES omits agents because that tree installs to the agents
|
|
|
190
190
|
test('core includeDirectories ships _shared and scripts for advisor protocol and CLI fallback', () => {
|
|
191
191
|
assert.ok(
|
|
192
192
|
CORE_INCLUDE_DIRECTORIES.includes('_shared'),
|
|
193
|
-
'_shared must ship with --only core so advisor-protocol.md lands for team-advisor
|
|
193
|
+
'_shared must ship with --only core so advisor-protocol.md lands for team-advisor',
|
|
194
194
|
);
|
|
195
195
|
assert.ok(
|
|
196
196
|
CORE_INCLUDE_DIRECTORIES.includes('scripts'),
|
package/commands/AGENTS.md
CHANGED
|
@@ -1,15 +1 @@
|
|
|
1
|
-
# commands
|
|
2
1
|
|
|
3
|
-
Slash-command definitions installed into `~/.claude/commands/` by `bin/install.mjs`. Each `.md` file registers a `/command-name` the user can type in Claude Code. The file name (without `.md`) becomes the command name.
|
|
4
|
-
|
|
5
|
-
Command bodies use `rules/asd-ste100-language.md` for user-facing word choice, sentence style, tone, punctuation, and prose form. Each command keeps its workflow contract.
|
|
6
|
-
|
|
7
|
-
## Command files
|
|
8
|
-
|
|
9
|
-
| File | Command | What it does |
|
|
10
|
-
|---|---|---|
|
|
11
|
-
| `sr-loop.md` | `/sr-loop` | Runs the converging cleanup loop: /simplify passes until clean, then a code-review fix pass |
|
|
12
|
-
|
|
13
|
-
## Format
|
|
14
|
-
|
|
15
|
-
Each file is plain Markdown. The first paragraph is the command's help text shown in the Claude Code UI. The body is the full instruction set Claude follows when the command runs.
|
package/docs/AGENTS.md
CHANGED
|
@@ -1,32 +1 @@
|
|
|
1
|
-
# docs
|
|
2
1
|
|
|
3
|
-
Reference documentation installed into `~/.claude/docs/` by `bin/install.mjs`. These files are loaded on demand by rules, skills, and agents — they are not always-on context.
|
|
4
|
-
|
|
5
|
-
## Files
|
|
6
|
-
|
|
7
|
-
| File | Purpose |
|
|
8
|
-
|---|---|
|
|
9
|
-
| `CODE_RULES.md` | Compact agent reference for all code rules; ⚡ marks hook-enforced rules; canonical source agents load before writing code |
|
|
10
|
-
| `TEST_QUALITY.md` | Test writing standards: what to test, what to remove, React testing patterns, anti-patterns |
|
|
11
|
-
| `BDD_DISCOVERY_PROTOCOL.md` | Example Mapping algorithm for discovery before implementation; based on Smart & Molak *BDD in Action* §6.4 |
|
|
12
|
-
| `BDD_SCENARIO_QUALITY.md` | Seven scenario quality patterns (§7.6-style catalog) |
|
|
13
|
-
| `BDD_TEST_LAYOUT.md` | `describe/when/should` test layout and soap-opera personas |
|
|
14
|
-
| `DJANGO_PATTERNS.md` | Django-specific coding patterns |
|
|
15
|
-
| `REACT_PATTERNS.md` | React-specific coding patterns |
|
|
16
|
-
| `agent-spawn-protocol.md` | Full agent-spawn protocol behind the `rules/agent-spawn-protocol.md` kernel: context-sufficiency check, `/prompt-generator` prompt crafting, and the spawn step |
|
|
17
|
-
| `nas-ssh-invocation.md` | Full NAS ssh policy behind the `rules/nas-ssh-invocation.md` kernel: the OpenSSH binary form, config sources, and hook enforcement |
|
|
18
|
-
| `worker-completion-gate.md` | Full worker-completion gate behind the `rules/workers-done-before-complete.md` kernel: the checklist, examples, and run-state records |
|
|
19
|
-
| `wsl-docker-cowork-starter-matrix.md` | Host matrix: WSL/Docker/cowork component → starter → required? → shutdown; policy options with costs; no unmeasured `.wslconfig` memory cap |
|
|
20
|
-
| `host-pool-health-monitor.md` | Operator recipe for Windows pool/handle health: thresholds, clean-shell re-run of `Capture-PoolHealth.ps1`, RC2/RC3/RC4 remediation map |
|
|
21
|
-
|
|
22
|
-
## Subdirectory
|
|
23
|
-
|
|
24
|
-
| Entry | Description |
|
|
25
|
-
|---|---|
|
|
26
|
-
| `references/` | Pointer documents to external sources and standard terminology; loaded on demand |
|
|
27
|
-
|
|
28
|
-
## Load pattern
|
|
29
|
-
|
|
30
|
-
A rule points to a doc with the path wrapped in backticks, such as `@~/.claude/docs/<file>.md`. The backticks make it a plain pointer: Claude Code reads the doc only when a rule, skill, or agent opens it, so the doc stays out of session-start context. The same path without backticks expands into context at launch when it sits in a file that loads at session start.
|
|
31
|
-
|
|
32
|
-
The `InstructionsLoaded` hook confirms this: a bare `@`-import fires an `include` load event; a backtick-wrapped path fires none.
|
package/docs/CODE_RULES.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Code Rules Reference
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The canonical review-criteria instruction set for every AI agent that audits pull requests in this repository, loaded on demand. [`.cursor/BUGBOT.md`](../../../.cursor/BUGBOT.md) is the checked-in pointer file Cursor BugBot reads; it points here.
|
|
4
4
|
|
|
5
5
|
⚡ marks rules enforced by hand-maintained `code_rules_enforcer.py` — the hook blocks the Write/Edit and returns the corrective detail at violation time, so this document lists those rules by name only. Session policy (question routing, task tracking) lives in `rules/*.md`; see [`code-standards.md`](../rules/code-standards.md).
|
|
6
6
|
|
|
@@ -28,7 +28,7 @@ Scaffolding and placeholder code carry a `TODO:` comment naming the permanent im
|
|
|
28
28
|
|
|
29
29
|
`code_rules_enforcer.py` blocks each of these at Write/Edit and explains the specific violation when it fires; exact patterns and exemption lists live in the hook:
|
|
30
30
|
|
|
31
|
-
no new comments · imports at top · logging format args (`log_*("...", arg)`) · no `%s`/`%d` printf tokens in a `str.format`-logger message (`log_*` imported from `automation_logging`; `str.format` drops the args — use `{}`) · no magic values in production bodies (0, 1, -1 exempt) · UPPER_SNAKE constants only in `config/` (exempt: `config
|
|
31
|
+
no new comments · imports at top · logging format args (`log_*("...", arg)`) · no `%s`/`%d` printf tokens in a `str.format`-logger message (`log_*` imported from `automation_logging`; `str.format` drops the args — use `{}`) · no magic values in production bodies (0, 1, -1 exempt) · UPPER_SNAKE constants only in `config/` (exempt: `config/*`; `/migrations/`; Workflow registries: path contains any of these substrings — `/workflow/`, `_tab.py`, `/states.py`, or `/modules.py`, each matching independently as a substring, so `pkg/states.py` qualifies while a top-level `states.py` follows the standard `config/` rule; test files — path or filename matches `test_`, `_test.`, `.spec.`, `conftest`, or `/tests/`) · no hardcoded user home paths · guarded `sys.path.insert` · banned identifiers (`ctx`, `cfg`, `msg`, `btn`, `idx`, `cnt`, `tmp`, `elem`, `val`) · banned function prefixes (`handle_`, `process_`, `manage_`, `do_`) · no type escape hatches (`Any` import, `cast()`, inline `Any`, a parameter typed bare `object` whose body reads `param.attribute`) outside boundary files · no bare/broad `except` · no `Any` in signatures or class attributes · no stub bodies (`pass`/`...`/`raise NotImplementedError`) outside abstract/Protocol · TypedDict `_encode_*`/`_decode_*` companions in the same module · no test-mode branching in production (use dependency injection) · no thin wrapper modules · Google-style docstrings on public functions with `Args:` matching the signature · boolean names prefixed `is_`/`has_`/`should_`/`can_`/`was_`/`did_` (assignments AND bool-typed parameters) · must-check returns (`find_and_click`, `write_outcome`) assigned and checked · known pytest fixture parameters in test files annotated with their single documented type (`tmp_path: Path`, `monkeypatch: pytest.MonkeyPatch`, `capsys`, `caplog`, `request`, …) · known pytest fixture parameters a test function declares but never references (drop the unused parameter — pytest still pays its setup cost) · JavaScript/TypeScript boolean declarations (`const`/`let`/`var` bound to a boolean literal or negation) and `@param {boolean}` JSDoc names prefixed `is`/`has`/`should`/`can`/`was`/`did` (camelCase forms) · banned identifiers as `.mjs`/`.js` declaration names (`result`, `data`, `ctx`, `msg`, …), scoped to changed lines · in test files, banned identifiers fire on changed lines, and pytest-collectable `test_*` functions need a return annotation · unused module-level imports and unsorted import blocks are ruff's job (F401, isort I001), not this hook's · a `hooks/blocking/` command classifier anchors its multi-word command regex to the command start (`^`/`\A`) or tokenizes the first word (`shlex.split`), never matching a command as a bare substring
|
|
32
32
|
|
|
33
33
|
Test files are exempt from most checks. The one annotation the test-file exemption does NOT cover is a known pytest builtin fixture parameter: `tmp_path`, `monkeypatch`, `capsys`, `capfd`, `caplog`, `request`, and `tmp_path_factory` each have a single documented injected type, so the gate requires that annotation (`tmp_path: Path`) even inside a test file. The same set of fixtures is also subject to a use check: a pytest-collected test function that declares one of these parameters and never references it in its body fails the gate, because pytest materializes the fixture's setup (the temp directory, the monkeypatch context, the output capture) on every run whether or not the body reads the value — drop the unused parameter. A parameter counts as referenced when its name is read, augmented-assigned, or deleted anywhere in the body, including inside a nested function or comprehension. Only pytest-collectable functions are inspected — those at module top level or defined directly in a class body; a function nested inside another function's body is a local helper pytest never collects, so its fixture-named parameter is exempt. A `@pytest.fixture`-decorated function is exempt from the use check, since injecting one fixture into another purely to order its setup is intentional. Ordinary test parameters stay exempt from both checks. See also the file-global constants use-count rule: [`rules/file-global-constants.md`](../rules/file-global-constants.md).
|
|
34
34
|
|
|
@@ -108,4 +108,4 @@ If you already have the data, don't fetch it again.
|
|
|
108
108
|
|
|
109
109
|
## 11. ENFORCEMENT SURFACES
|
|
110
110
|
|
|
111
|
-
⚡ **Hooks** block pattern-matchable violations at Write/Edit time. 🤖 **Prompt context** carries judgment principles (SRP, Right-Sized Engineering,
|
|
111
|
+
⚡ **Hooks** block pattern-matchable violations at Write/Edit time. 🤖 **Prompt context** carries judgment principles (SRP, Right-Sized Engineering, research-first action on ambiguous intent, BDD discovery, docstring-prose-matches-implementation). 👥 **Audit rubrics** (`/check`, `packages/claude-dev-env/audit-rubrics/` categories A–Q) cover cross-file architectural concerns. Rules with documented-but-pending hook coverage live in `~/.claude/rules/*.md`; each names its own promotion path. The docstring-prose standard (free-form enumerations match the body) lives in `packages/claude-dev-env/rules/docstring-prose-matches-implementation.md`, enforced via Category O6 audit. The diagram-first docstring standard (a summary line, then a `::` example or doctest, then a couple of short prose lines) lives in `packages/claude-dev-env/rules/plain-illustrative-docstrings.md`, enforced by the `check_docstring_runon_sentence` and `check_docstring_prose_wall_without_illustration` backstop hooks and Category O9 audit.
|
|
@@ -35,5 +35,5 @@ An agent that receives a vague prompt wastes tokens exploring in circles, produc
|
|
|
35
35
|
|
|
36
36
|
## Relationship to other rules
|
|
37
37
|
|
|
38
|
-
-
|
|
38
|
+
- Acting when intent is ambiguous goes to investigation or a user question first, never straight to a subagent; this protocol extends that guard to the spawn decision itself.
|
|
39
39
|
- Project-specific rules or `~/.claude/CLAUDE.md` may decide whether to use subagents at all; this protocol governs how to craft the prompt once you delegate.
|