claude-dev-env 1.92.1 → 1.93.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.
- package/CLAUDE.md +6 -2
- package/_shared/CLAUDE.md +2 -1
- package/_shared/advisor/CLAUDE.md +21 -0
- package/_shared/advisor/advisor-protocol.md +142 -0
- package/_shared/advisor/scripts/config/advisor_scripts_constants/__init__.py +1 -0
- package/_shared/advisor/scripts/config/advisor_scripts_constants/model_tier_run_validator_constants.py +86 -0
- package/_shared/advisor/scripts/model_tier_run_validator.py +246 -0
- package/_shared/advisor/scripts/pyproject.toml +3 -0
- package/_shared/advisor/scripts/tests/test_model_tier_run_validator.py +302 -0
- package/_shared/advisor/scripts/tests/test_tier_model_ids.py +180 -0
- package/_shared/advisor/scripts/tier_model_ids.py +164 -0
- package/_shared/pr-loop/CLAUDE.md +1 -0
- package/_shared/pr-loop/precatch-rubric.md +65 -0
- package/_shared/pr-loop/scripts/CLAUDE.md +1 -1
- package/_shared/pr-loop/scripts/code_rules_gate.py +260 -14
- package/_shared/pr-loop/scripts/post_audit_thread.py +1 -1
- package/_shared/pr-loop/scripts/pr_loop_shared_constants/CLAUDE.md +1 -1
- package/_shared/pr-loop/scripts/pr_loop_shared_constants/code_rules_gate_constants.py +20 -0
- package/_shared/pr-loop/scripts/pr_loop_shared_constants/reviews_disabled_constants.py +2 -1
- package/_shared/pr-loop/scripts/reviewer_availability.py +42 -12
- package/_shared/pr-loop/scripts/reviews_disabled.py +65 -21
- package/_shared/pr-loop/scripts/terminology_sweep.py +69 -21
- package/_shared/pr-loop/scripts/tests/CLAUDE.md +1 -1
- package/_shared/pr-loop/scripts/tests/fixtures/{copilot_internal_user_jonecho.json → copilot_internal_user_example.json} +1 -1
- package/_shared/pr-loop/scripts/tests/test_agent_config_carveout.py +1 -1
- package/_shared/pr-loop/scripts/tests/test_code_rules_gate.py +292 -2
- package/_shared/pr-loop/scripts/tests/test_copilot_quota.py +8 -8
- package/_shared/pr-loop/scripts/tests/test_reviewer_availability.py +18 -5
- package/_shared/pr-loop/scripts/tests/test_reviews_disabled.py +56 -5
- package/_shared/pr-loop/scripts/tests/test_terminology_sweep.py +104 -17
- package/agents/CLAUDE.md +3 -2
- package/agents/clasp-deployment-orchestrator.md +2 -2
- package/agents/code-advisor.md +7 -5
- package/agents/code-verifier.md +6 -2
- package/agents/session-advisor.md +27 -0
- package/audit-rubrics/category_rubrics/category-j-code-rules-compliance.md +1 -1
- package/audit-rubrics/category_rubrics/category-k-codebase-conflicts.md +1 -1
- package/audit-rubrics/prompts/category-a-api-contracts.md +2 -2
- package/audit-rubrics/prompts/category-b-selector-engine-compat.md +2 -2
- package/audit-rubrics/prompts/category-c-resource-cleanup.md +2 -2
- package/audit-rubrics/prompts/category-d-scoping-and-ordering.md +2 -2
- package/audit-rubrics/prompts/category-e-dead-code.md +2 -2
- package/audit-rubrics/prompts/category-f-silent-failures.md +2 -2
- package/audit-rubrics/prompts/category-g-bounds-and-overflow.md +2 -2
- package/audit-rubrics/prompts/category-h-security-boundaries.md +2 -2
- package/audit-rubrics/prompts/category-i-concurrency.md +2 -2
- package/audit-rubrics/prompts/category-j-code-rules-compliance.md +2 -2
- package/audit-rubrics/prompts/category-k-codebase-conflicts.md +2 -2
- package/audit-rubrics/prompts/category-l-behavior-equivalence.md +2 -2
- package/audit-rubrics/prompts/category-m-producer-consumer-cardinality.md +2 -2
- package/audit-rubrics/prompts/category-n-test-name-scenario-verifier.md +2 -2
- package/audit-rubrics/prompts/category-o-docstring-vs-impl-drift.md +2 -2
- package/audit-rubrics/prompts/category-p-name-vs-behavior-contract.md +2 -2
- package/bin/CLAUDE.md +1 -0
- package/bin/expand_home_directory_tokens.mjs +75 -0
- package/bin/install.mjs +21 -7
- package/bin/install.test.mjs +220 -10
- package/hooks/CLAUDE.md +1 -1
- package/hooks/blocking/CLAUDE.md +4 -1
- package/hooks/blocking/_path_setup.py +13 -0
- package/hooks/blocking/bash_pre_tool_use_dispatcher.py +281 -0
- package/hooks/blocking/code_rules_dead_module_constant.py +88 -16
- package/hooks/blocking/code_rules_enforcer.py +6 -0
- package/hooks/blocking/code_rules_imports_logging.py +34 -1
- package/hooks/blocking/code_rules_paths_syspath.py +1 -1
- package/hooks/blocking/code_rules_test_layout.py +272 -0
- package/hooks/blocking/nas_ssh_binary_enforcer.py +22 -12
- package/hooks/blocking/pii_prevention_blocker.py +781 -0
- package/hooks/blocking/pii_scanner.py +365 -0
- package/hooks/blocking/pre_tool_use_dispatcher.py +3 -3
- package/hooks/blocking/stop_dispatcher.py +84 -0
- package/hooks/blocking/test__path_setup.py +39 -0
- package/hooks/blocking/test_bash_dispatcher_interpreter_starts.py +61 -0
- package/hooks/blocking/test_bash_pre_tool_use_dispatcher.py +294 -0
- package/hooks/blocking/test_code_rules_enforcer_cross_skill_duplicate.py +1 -1
- package/hooks/blocking/test_code_rules_enforcer_dead_config_field.py +2 -2
- package/hooks/blocking/test_code_rules_enforcer_dead_module_constant.py +51 -0
- package/hooks/blocking/test_code_rules_enforcer_dead_module_constant_read_cap.py +103 -0
- package/hooks/blocking/test_code_rules_enforcer_dot_test_pattern.py +1 -1
- package/hooks/blocking/test_code_rules_enforcer_file_global_constants.py +1 -1
- package/hooks/blocking/test_code_rules_enforcer_hardcoded_user_path.py +11 -11
- package/hooks/blocking/test_code_rules_enforcer_naive_datetime.py +1 -1
- package/hooks/blocking/test_code_rules_enforcer_same_file_inline_duplicate.py +1 -1
- package/hooks/blocking/test_code_rules_enforcer_test_layout.py +111 -0
- package/hooks/blocking/test_code_rules_enforcer_type_checking_scope.py +76 -0
- package/hooks/blocking/test_destructive_command_blocker.py +29 -9
- package/hooks/blocking/test_gh_body_arg_blocker.py +3 -3
- package/hooks/blocking/test_nas_ssh_binary_enforcer.py +96 -39
- package/hooks/blocking/test_pii_prevention_blocker.py +905 -0
- package/hooks/blocking/test_pii_prevention_windows_git_path.py +41 -0
- package/hooks/blocking/test_pii_scanner.py +190 -0
- package/hooks/blocking/test_pr_description_enforcer_pr_number.py +1 -1
- package/hooks/blocking/test_pre_tool_use_dispatcher.py +14 -13
- package/hooks/blocking/test_stop_dispatcher.py +187 -0
- package/hooks/blocking/test_verdict_directory_write_blocker.py +1 -1
- package/hooks/blocking/test_volatile_path_in_post_blocker.py +3 -3
- package/hooks/blocking/volatile_path_in_post_blocker.py +54 -5
- package/hooks/diagnostic/migrations/README.md +25 -26
- package/hooks/diagnostic/test_hook_log_extractor.py +10 -10
- package/hooks/hooks.json +10 -120
- package/hooks/hooks_constants/CLAUDE.md +12 -3
- package/hooks/hooks_constants/bash_pre_tool_use_dispatcher_constants.py +78 -0
- package/hooks/hooks_constants/dead_module_constant_constants.py +1 -0
- package/hooks/hooks_constants/hosted_hook_runner.py +73 -0
- package/hooks/hooks_constants/local_identity.py +182 -0
- package/hooks/hooks_constants/nas_ssh_binary_enforcer_constants.py +4 -37
- package/hooks/hooks_constants/pii_prevention_constants.py +295 -0
- package/hooks/hooks_constants/pre_tool_use_dispatcher_constants.py +4 -0
- package/hooks/hooks_constants/python_style_checks_constants.py +15 -0
- package/hooks/hooks_constants/stop_dispatcher_constants.py +26 -0
- package/hooks/hooks_constants/test_bash_pre_tool_use_dispatcher_constants.py +87 -0
- package/hooks/hooks_constants/test_hardcoded_user_path_constants.py +2 -2
- package/hooks/hooks_constants/test_hosted_hook_runner.py +101 -0
- package/hooks/hooks_constants/test_layout_constants.py +28 -0
- package/hooks/hooks_constants/test_local_identity.py +88 -0
- package/hooks/hooks_constants/test_session_env_cleanup_constants.py +1 -1
- package/hooks/hooks_constants/test_stop_dispatcher_constants.py +32 -0
- package/hooks/validators/README.md +5 -6
- package/hooks/validators/__init__.py +2 -2
- package/hooks/validators/python_style_checks.py +298 -243
- package/hooks/validators/run_all_validators.py +6 -0
- package/hooks/validators/test_python_style_checks.py +278 -163
- package/package.json +2 -2
- package/rules/CLAUDE.md +2 -1
- package/rules/bdd.md +1 -1
- package/rules/nas-ssh-invocation.md +6 -4
- package/rules/no-justification-noise.md +61 -0
- package/scripts/test_setup_project_paths.py +1 -1
- package/skills/CLAUDE.md +6 -3
- package/skills/_shared/pr-loop/scripts/_path_resolver.py +2 -2
- package/skills/_shared/pr-loop/scripts/build_audit_prompt.py +1 -1
- package/skills/_shared/pr-loop/scripts/build_fix_prompt.py +1 -1
- package/skills/_shared/pr-loop/scripts/test__path_resolver.py +42 -3
- package/skills/_shared/pr-loop/scripts/test_build_audit_prompt.py +11 -11
- package/skills/_shared/pr-loop/scripts/test_build_fix_prompt.py +26 -3
- package/skills/_shared/pr-loop/scripts/test_preflight_worktree.py +49 -25
- package/skills/autoconverge/CLAUDE.md +3 -3
- package/skills/autoconverge/SKILL.md +113 -35
- package/skills/autoconverge/reference/CLAUDE.md +2 -2
- package/skills/autoconverge/reference/convergence.md +44 -22
- package/skills/autoconverge/reference/gotchas.md +11 -0
- package/skills/autoconverge/reference/stop-conditions.md +23 -13
- package/skills/autoconverge/workflow/CLAUDE.md +2 -1
- package/skills/autoconverge/workflow/converge.clean-audit.test.mjs +15 -19
- package/skills/autoconverge/workflow/converge.contract.test.mjs +43 -42
- package/skills/autoconverge/workflow/converge.copilot-gate.test.mjs +141 -16
- package/skills/autoconverge/workflow/converge.fix-recovery.test.mjs +2 -2
- package/skills/autoconverge/workflow/converge.mjs +329 -68
- package/skills/autoconverge/workflow/converge.path-aware.test.mjs +1 -1
- package/skills/autoconverge/workflow/converge.precatch.test.mjs +152 -0
- package/skills/autoconverge/workflow/converge.run-input.test.mjs +3 -3
- package/skills/autoconverge/workflow/converge_multi.run-input.test.mjs +15 -15
- package/skills/autoconverge/workflow/test_convergence_summary.py +6 -6
- package/skills/bdd-protocol/SKILL.md +4 -5
- package/skills/bdd-protocol/references/anti-patterns.md +1 -1
- package/skills/bugteam/SKILL.md +8 -0
- package/skills/bugteam/reference/copilot-gap-analysis.md +20 -20
- package/skills/bugteam/reference/obstacles/audit-walk-categories.md +1 -1
- package/skills/bugteam/reference/team-setup.md +7 -5
- package/skills/bugteam/scripts/reflow_skill_md.py +1 -1
- package/skills/copilot-finding-triage/SKILL.md +124 -0
- package/skills/copilot-finding-triage/reference/tier-rubric.md +49 -0
- package/skills/copilot-finding-triage/scripts/conftest.py +8 -0
- package/skills/copilot-finding-triage/scripts/copilot_finding_triage_constants/__init__.py +0 -0
- package/skills/copilot-finding-triage/scripts/copilot_finding_triage_constants/config/__init__.py +0 -0
- package/skills/copilot-finding-triage/scripts/copilot_finding_triage_constants/config/notify_ntfy_constants.py +32 -0
- package/skills/copilot-finding-triage/scripts/notify_ntfy.py +192 -0
- package/skills/copilot-finding-triage/scripts/test_notify_ntfy.py +141 -0
- package/skills/copilot-finding-triage/templates/notification.md +34 -0
- package/skills/copilot-review/SKILL.md +8 -6
- package/skills/findbugs/SKILL.md +4 -0
- package/skills/fixbugs/SKILL.md +8 -7
- package/skills/gotcha/CLAUDE.md +2 -2
- package/skills/gotcha/SKILL.md +4 -4
- package/skills/log-audit/SKILL.md +4 -6
- package/skills/monitor-open-prs/CLAUDE.md +1 -1
- package/skills/monitor-open-prs/SKILL.md +6 -1
- package/skills/orchestrator/SKILL.md +74 -78
- package/skills/orchestrator-refresh/SKILL.md +24 -12
- package/skills/post-audit-findings/SKILL.md +5 -9
- package/skills/pr-consistency-audit/SKILL.md +5 -1
- package/skills/pr-converge/CLAUDE.md +1 -1
- package/skills/pr-converge/SKILL.md +86 -47
- package/skills/pr-converge/reference/CLAUDE.md +1 -1
- package/skills/pr-converge/reference/convergence-gates.md +20 -17
- package/skills/pr-converge/reference/examples.md +63 -47
- package/skills/pr-converge/reference/fix-protocol.md +15 -15
- package/skills/pr-converge/reference/ground-rules.md +11 -7
- package/skills/pr-converge/reference/multi-pr-orchestration.md +6 -5
- package/skills/pr-converge/reference/per-tick.md +129 -107
- package/skills/pr-converge/reference/state-schema.md +15 -10
- package/skills/pr-converge/scripts/check_convergence.py +5 -4
- package/skills/pr-converge/scripts/test_check_convergence.py +6 -4
- package/skills/pr-fix-protocol/SKILL.md +3 -8
- package/skills/pr-loop-cloud-transport/SKILL.md +102 -0
- package/skills/pr-loop-cloud-transport/reference/identity-and-hooks.md +40 -0
- package/skills/pr-loop-cloud-transport/reference/substitution-matrix.md +48 -0
- package/skills/pr-loop-lifecycle/SKILL.md +5 -9
- package/skills/pr-scope-resolve/SKILL.md +3 -6
- package/skills/privacy-hygiene/SKILL.md +114 -0
- package/skills/qbug/SKILL.md +8 -8
- package/skills/rebase/SKILL.md +5 -1
- package/skills/refine/SKILL.md +4 -5
- package/skills/reviewer-gates/SKILL.md +7 -11
- package/skills/session-log/SKILL.md +4 -1
- package/skills/skill-builder/SKILL.md +3 -6
- package/skills/structure-prompt/SKILL.md +4 -5
- package/skills/team-advisor/SKILL.md +56 -0
- package/skills/test_markdown_link_integrity.py +10 -6
- package/skills/update/SKILL.md +5 -1
- package/skills/usage-pause/SKILL.md +14 -5
- package/skills/usage-pause/scripts/resolve_usage_window.py +83 -5
- package/skills/usage-pause/scripts/test_resolve_usage_window.py +185 -17
- package/skills/usage-pause/scripts/usage_pause_constants/resolve_usage_window_constants.py +4 -3
- package/skills/verified-build/SKILL.md +4 -9
|
@@ -87,9 +87,9 @@ Lead: `Total: N (P0=N, P1=N, P2=N)`. For each sub-bucket D1–D8, produce Shape
|
|
|
87
87
|
|
|
88
88
|
---
|
|
89
89
|
|
|
90
|
-
# Worked example: jl-cmd/claude-
|
|
90
|
+
# Worked example: jl-cmd/claude-dev-env PR #394
|
|
91
91
|
|
|
92
|
-
Audit jl-cmd/claude-
|
|
92
|
+
Audit jl-cmd/claude-dev-env PR #394 for **Category D only** (variable scoping, ordering, and unbound references). Skip A–C, E–N. Sub-bucket forced-exhaustion mode: Category D is decomposed into 8 sub-buckets below. Each sub-bucket 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. A sub-bucket returning neither is a protocol gap.
|
|
93
93
|
|
|
94
94
|
PR: feat(scripts): add sweep-empty-dirs utility and scheduled-task installer
|
|
95
95
|
Head SHA: 62c9c169ee7a44824e5da25c4cf8b74fdca08a53
|
|
@@ -92,9 +92,9 @@ Note: most Category E findings are P2 (style / cleanup) unless the dead code mas
|
|
|
92
92
|
|
|
93
93
|
---
|
|
94
94
|
|
|
95
|
-
# Worked example: jl-cmd/claude-
|
|
95
|
+
# Worked example: jl-cmd/claude-dev-env PR #394
|
|
96
96
|
|
|
97
|
-
Audit jl-cmd/claude-
|
|
97
|
+
Audit jl-cmd/claude-dev-env PR #394 for **Category E only** (dead code and unused imports). Skip A–D, F–N. Sub-bucket forced-exhaustion mode: Category E is decomposed into 9 sub-buckets below. Each sub-bucket 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. A sub-bucket returning neither is a protocol gap.
|
|
98
98
|
|
|
99
99
|
PR: feat(scripts): add sweep-empty-dirs utility and scheduled-task installer
|
|
100
100
|
Head SHA: 62c9c169ee7a44824e5da25c4cf8b74fdca08a53
|
|
@@ -108,9 +108,9 @@ Lead: `Total: N (P0=N, P1=N, P2=N)`. For each sub-bucket F1-F10, produce Shape A
|
|
|
108
108
|
|
|
109
109
|
---
|
|
110
110
|
|
|
111
|
-
# Worked example: jl-cmd/claude-
|
|
111
|
+
# Worked example: jl-cmd/claude-dev-env PR #394
|
|
112
112
|
|
|
113
|
-
Audit jl-cmd/claude-
|
|
113
|
+
Audit jl-cmd/claude-dev-env PR #394 for **Category F only** (silent failures). Skip A–E, G–N. Sub-bucket forced-exhaustion mode: Category F is decomposed into 8 sub-buckets below. Each sub-bucket 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. A sub-bucket returning neither is a protocol gap.
|
|
114
114
|
|
|
115
115
|
PR: feat(scripts): add sweep-empty-dirs utility and scheduled-task installer
|
|
116
116
|
Head SHA: 62c9c169ee7a44824e5da25c4cf8b74fdca08a53
|
|
@@ -59,9 +59,9 @@ Lead: `Total: N (P0=N, P1=N, P2=N)`. For each sub-bucket G1-G8, produce Shape A
|
|
|
59
59
|
|
|
60
60
|
---
|
|
61
61
|
|
|
62
|
-
# Worked example: jl-cmd/claude-
|
|
62
|
+
# Worked example: jl-cmd/claude-dev-env PR #394
|
|
63
63
|
|
|
64
|
-
Audit jl-cmd/claude-
|
|
64
|
+
Audit jl-cmd/claude-dev-env PR #394 for **Category G only** (off-by-one, bounds, integer overflow). Skip A–F, H–N. Sub-bucket forced-exhaustion mode: Category G is decomposed into 8 sub-buckets below. Each sub-bucket 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. A sub-bucket returning neither is a protocol gap.
|
|
65
65
|
|
|
66
66
|
PR: feat(scripts): add sweep-empty-dirs utility and scheduled-task installer
|
|
67
67
|
Head SHA: 62c9c169ee7a44824e5da25c4cf8b74fdca08a53
|
|
@@ -81,9 +81,9 @@ Note: Category H findings tend toward P0/P1 since they're security-relevant —
|
|
|
81
81
|
|
|
82
82
|
---
|
|
83
83
|
|
|
84
|
-
# Worked example: jl-cmd/claude-
|
|
84
|
+
# Worked example: jl-cmd/claude-dev-env PR #394
|
|
85
85
|
|
|
86
|
-
Audit jl-cmd/claude-
|
|
86
|
+
Audit jl-cmd/claude-dev-env PR #394 for **Category H only** (security boundaries). Skip A–G, I–N. Sub-bucket forced-exhaustion mode: Category H is decomposed into 10 sub-buckets below. Each sub-bucket 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. A sub-bucket returning neither is a protocol gap.
|
|
87
87
|
|
|
88
88
|
PR: feat(scripts): add sweep-empty-dirs utility and scheduled-task installer
|
|
89
89
|
Head SHA: 62c9c169ee7a44824e5da25c4cf8b74fdca08a53
|
|
@@ -86,9 +86,9 @@ Lead: `Total: N (P0=N, P1=N, P2=N)`. For each sub-bucket I1–I8, produce Shape
|
|
|
86
86
|
|
|
87
87
|
---
|
|
88
88
|
|
|
89
|
-
# Worked example: jl-cmd/claude-
|
|
89
|
+
# Worked example: jl-cmd/claude-dev-env PR #394
|
|
90
90
|
|
|
91
|
-
Audit jl-cmd/claude-
|
|
91
|
+
Audit jl-cmd/claude-dev-env PR #394 for **Category I only** (concurrency hazards). Skip A–H, J–N. Sub-bucket forced-exhaustion mode: Category I is decomposed into 8 sub-buckets below. Each sub-bucket 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. A sub-bucket returning neither is a protocol gap.
|
|
92
92
|
|
|
93
93
|
PR: feat(scripts): add sweep-empty-dirs utility and scheduled-task installer
|
|
94
94
|
Head SHA: 62c9c169ee7a44824e5da25c4cf8b74fdca08a53
|
|
@@ -110,9 +110,9 @@ Note: most Category J findings are P2 (style / cleanup) since they don't affect
|
|
|
110
110
|
|
|
111
111
|
---
|
|
112
112
|
|
|
113
|
-
# Worked example: jl-cmd/claude-
|
|
113
|
+
# Worked example: jl-cmd/claude-dev-env PR #394
|
|
114
114
|
|
|
115
|
-
Audit jl-cmd/claude-
|
|
115
|
+
Audit jl-cmd/claude-dev-env PR #394 for **Category J only** (CODE_RULES.md compliance). Skip A–I, K–N. Sub-bucket forced-exhaustion mode: Category J is decomposed into 12 sub-buckets below. Each sub-bucket 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. A sub-bucket returning neither is a protocol gap.
|
|
116
116
|
|
|
117
117
|
PR: feat(scripts): add sweep-empty-dirs utility and scheduled-task installer
|
|
118
118
|
Head SHA: 62c9c169ee7a44824e5da25c4cf8b74fdca08a53
|
|
@@ -85,11 +85,11 @@ Lead: `Total: N (P0=N, P1=N, P2=N)`. For each sub-bucket K1-K11, produce Shape A
|
|
|
85
85
|
|
|
86
86
|
---
|
|
87
87
|
|
|
88
|
-
# Worked example: jl-cmd/claude-
|
|
88
|
+
# Worked example: jl-cmd/claude-dev-env PR #397 r3210166636
|
|
89
89
|
|
|
90
90
|
Note: PR #397 is the K canonical case, NOT #394.
|
|
91
91
|
|
|
92
|
-
Audit jl-cmd/claude-
|
|
92
|
+
Audit jl-cmd/claude-dev-env PR #397 for **Category K only** (codebase conflicts — incomplete propagation). Skip A–J, L–N. Sub-bucket forced-exhaustion mode: Category K is decomposed into 9 sub-buckets below. Each sub-bucket 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. A sub-bucket returning neither is a protocol gap.
|
|
93
93
|
|
|
94
94
|
PR: fix(hooks): improve hedging-language guardrail to surface user questions
|
|
95
95
|
Base SHA: 76f9c1a0048729b87c44626a3380dc840065c2fa (origin/main at PR open time)
|
|
@@ -71,9 +71,9 @@ Lead: `Total: N (P0=N, P1=N, P2=N)`. For each sub-bucket L1-L8, produce Shape A
|
|
|
71
71
|
|
|
72
72
|
---
|
|
73
73
|
|
|
74
|
-
# Worked example: jl-cmd/claude-
|
|
74
|
+
# Worked example: jl-cmd/claude-dev-env PR #479
|
|
75
75
|
|
|
76
|
-
Audit jl-cmd/claude-
|
|
76
|
+
Audit jl-cmd/claude-dev-env PR #479 for **Category L only** (behavior-equivalence for refactors). Skip A–K, M, N. Sub-bucket forced-exhaustion mode: Category L is decomposed into 8 sub-buckets below.
|
|
77
77
|
|
|
78
78
|
PR: refactor(hooks): tokenize-based exempt-marker recognition for the no-new-comments gate
|
|
79
79
|
Base SHA: (the commit before the tokenize-based rewrite landed)
|
|
@@ -72,9 +72,9 @@ Lead: `Total: N (P0=N, P1=N, P2=N)`. For each sub-bucket M1-M8, produce Shape A
|
|
|
72
72
|
|
|
73
73
|
---
|
|
74
74
|
|
|
75
|
-
# Worked example:
|
|
75
|
+
# Worked example: example-org/example-repo PR #101
|
|
76
76
|
|
|
77
|
-
Audit
|
|
77
|
+
Audit example-org/example-repo PR #101 for **Category M only** (producer/consumer cardinality vs collection-type contract). Skip A–L, N. Sub-bucket forced-exhaustion mode: Category M is decomposed into 8 sub-buckets below.
|
|
78
78
|
|
|
79
79
|
PR: feat(watchdog): use Everything CLI to enumerate watched paths
|
|
80
80
|
Head SHA: (the commit that landed `_extract_paths_from_everything_cli_stdout`)
|
|
@@ -79,9 +79,9 @@ Lead: `Total: N (P0=N, P1=N, P2=N)`. For each sub-bucket N1-N10, produce Shape A
|
|
|
79
79
|
|
|
80
80
|
---
|
|
81
81
|
|
|
82
|
-
# Worked example: jl-cmd/claude-
|
|
82
|
+
# Worked example: jl-cmd/claude-dev-env PR #476
|
|
83
83
|
|
|
84
|
-
Audit jl-cmd/claude-
|
|
84
|
+
Audit jl-cmd/claude-dev-env PR #476 for **Category N only** (test-name scenario verifier). Skip A–M. Sub-bucket forced-exhaustion mode: Category N is decomposed into 9 sub-buckets below.
|
|
85
85
|
|
|
86
86
|
PR: refactor(hooks): cross-platform path resolution for windows-rmtree-blocker
|
|
87
87
|
Head SHA: (the commit that landed the platform-conditional logic)
|
|
@@ -69,9 +69,9 @@ Lead: `Total: N (P0=N, P1=N, P2=N)`. For each sub-bucket O1-O9, produce Shape A
|
|
|
69
69
|
|
|
70
70
|
---
|
|
71
71
|
|
|
72
|
-
# Worked example: jl-cmd/claude-
|
|
72
|
+
# Worked example: jl-cmd/claude-dev-env PR #522
|
|
73
73
|
|
|
74
|
-
Audit jl-cmd/claude-
|
|
74
|
+
Audit jl-cmd/claude-dev-env PR #522 for **Category O only** (docstring / fixture-prose vs implementation drift). Skip A-N, P. Sub-bucket forced-exhaustion mode: Category O is decomposed into 9 sub-buckets below.
|
|
75
75
|
|
|
76
76
|
PR #522 split `pr_description_command_parser.py` into two modules — the original parser and a new `pr_description_pr_number.py` — but the originating module's docstring still claims the PR-number recovery responsibility. A sibling change to `pr_description_body_audit.py` introduced a module docstring whose verb (`detects vague language`) overstates the module's actual responsibility (it only exposes `_extract_vague_scan_text()`; detection runs elsewhere).
|
|
77
77
|
|
|
@@ -77,9 +77,9 @@ Lead: `Total: N (P0=N, P1=N, P2=N)`. For each sub-bucket P1-P7, produce Shape A
|
|
|
77
77
|
|
|
78
78
|
---
|
|
79
79
|
|
|
80
|
-
# Worked example: jl-cmd/claude-
|
|
80
|
+
# Worked example: jl-cmd/claude-dev-env PR #508
|
|
81
81
|
|
|
82
|
-
Audit jl-cmd/claude-
|
|
82
|
+
Audit jl-cmd/claude-dev-env PR #508 for **Category P only** (name / regex / word-list vs behavior-contract precision). Skip A-O.
|
|
83
83
|
|
|
84
84
|
PR #508 ships the plain-language blocker hook. Two fresh identifiers in `plain_language_blocker_constants.py` show the canonical P shapes:
|
|
85
85
|
|
package/bin/CLAUDE.md
CHANGED
|
@@ -7,6 +7,7 @@ The installer and its companion modules. Running `npx claude-dev-env` (or `node
|
|
|
7
7
|
| File | Purpose |
|
|
8
8
|
|---|---|
|
|
9
9
|
| `install.mjs` | Main installer: discovers install groups, copies content directories (`rules`, `docs`, `commands`, `agents`, `system-prompts`, `scripts`, `_shared`, `audit-rubrics`), merges hooks into `settings.json`, installs skills, runs `git_hooks_installer.mjs` and `install_mypy_ini.mjs` |
|
|
10
|
+
| `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 `$`) |
|
|
10
11
|
| `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 |
|
|
11
12
|
| `install_mypy_ini.mjs` | Writes `~/.mypy.ini` with settings that make mypy find the hooks package and enforce strict type checking |
|
|
12
13
|
| `install.test.mjs` | Tests for `install.mjs` — covers conflict detection, interpreter detection, settings merging |
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Install-time expansion of $HOME / ${HOME} / ~/ in settings.json commands.
|
|
3
|
+
*
|
|
4
|
+
* Hosts that require referenced env vars at hook load time (for example Grok)
|
|
5
|
+
* skip the hook when HOME is unset — common on Windows — so the installer
|
|
6
|
+
* rewrites residual tokens to absolute home paths.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Expands $HOME, ${HOME}, and ~/ in a command string to an absolute home directory
|
|
11
|
+
* using forward slashes.
|
|
12
|
+
*
|
|
13
|
+
* Replacement uses split/join and function replacers so a home path that contains
|
|
14
|
+
* `$` (for example `$&` or `$1`) is inserted literally and is never treated as a
|
|
15
|
+
* String.prototype.replace special pattern.
|
|
16
|
+
*
|
|
17
|
+
* ::
|
|
18
|
+
*
|
|
19
|
+
* expandHomeDirectoryTokens('python $HOME/a.py', 'C:\\Users\\x')
|
|
20
|
+
* # -> 'python C:/Users/x/a.py'
|
|
21
|
+
*
|
|
22
|
+
* expandHomeDirectoryTokens('python $HOME/a.py', 'C:/Users/$&evil')
|
|
23
|
+
* # -> 'python C:/Users/$&evil/a.py' (literal dollars, not regex rewrite)
|
|
24
|
+
*
|
|
25
|
+
* @param {string} commandString Hook or statusLine command text.
|
|
26
|
+
* @param {string} homeDirectory Absolute home directory (any path separators).
|
|
27
|
+
* @returns {string} Command with home tokens expanded.
|
|
28
|
+
*/
|
|
29
|
+
export function expandHomeDirectoryTokens(commandString, homeDirectory) {
|
|
30
|
+
const normalizedHome = homeDirectory.replace(/\\/g, '/').replace(/\/+$/, '');
|
|
31
|
+
let expandedCommand = commandString.split('${HOME}').join(normalizedHome);
|
|
32
|
+
expandedCommand = expandedCommand.replace(
|
|
33
|
+
/(?<![A-Za-z0-9_])\$HOME\b/g,
|
|
34
|
+
() => normalizedHome,
|
|
35
|
+
);
|
|
36
|
+
expandedCommand = expandedCommand.replace(
|
|
37
|
+
/(^|[\s"'=])~\//g,
|
|
38
|
+
(_fullMatch, boundary) => `${boundary}${normalizedHome}/`,
|
|
39
|
+
);
|
|
40
|
+
return expandedCommand;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Expands home-directory tokens in every settings.json hook command and in the
|
|
45
|
+
* optional statusLine command so residual $HOME entries from older installs
|
|
46
|
+
* become absolute paths and no longer require HOME at hook load time.
|
|
47
|
+
*
|
|
48
|
+
* @param {object} settings The parsed settings.json object (mutated in place).
|
|
49
|
+
* @param {string} homeDirectory Absolute home directory (any path separators).
|
|
50
|
+
* @returns {void}
|
|
51
|
+
*/
|
|
52
|
+
export function expandHomeDirectoryTokensInSettings(settings, homeDirectory) {
|
|
53
|
+
if (settings.hooks) {
|
|
54
|
+
for (const matcherGroups of Object.values(settings.hooks)) {
|
|
55
|
+
if (!Array.isArray(matcherGroups)) continue;
|
|
56
|
+
for (const eachGroup of matcherGroups) {
|
|
57
|
+
if (!eachGroup || !Array.isArray(eachGroup.hooks)) continue;
|
|
58
|
+
for (const eachHook of eachGroup.hooks) {
|
|
59
|
+
if (typeof eachHook.command === 'string') {
|
|
60
|
+
eachHook.command = expandHomeDirectoryTokens(
|
|
61
|
+
eachHook.command,
|
|
62
|
+
homeDirectory,
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
if (settings.statusLine && typeof settings.statusLine.command === 'string') {
|
|
70
|
+
settings.statusLine.command = expandHomeDirectoryTokens(
|
|
71
|
+
settings.statusLine.command,
|
|
72
|
+
homeDirectory,
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
}
|
package/bin/install.mjs
CHANGED
|
@@ -8,6 +8,7 @@ import { fileURLToPath } from 'node:url';
|
|
|
8
8
|
import { createRequire } from 'node:module';
|
|
9
9
|
import { installAllGitHooks } from './git_hooks_installer.mjs';
|
|
10
10
|
import { installMypyIniForClaudeHooks } from './install_mypy_ini.mjs';
|
|
11
|
+
import { expandHomeDirectoryTokensInSettings } from './expand_home_directory_tokens.mjs';
|
|
11
12
|
|
|
12
13
|
const CLAUDE_HOME = join(homedir(), '.claude');
|
|
13
14
|
const PACKAGE_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), '..');
|
|
@@ -18,6 +19,10 @@ const packageRequire = createRequire(import.meta.url);
|
|
|
18
19
|
|
|
19
20
|
export const CONTENT_DIRECTORIES = ['rules', 'docs', 'commands', 'agents', 'system-prompts', 'scripts', '_shared', 'audit-rubrics'];
|
|
20
21
|
|
|
22
|
+
export const CORE_INCLUDE_DIRECTORIES = [
|
|
23
|
+
'rules', 'docs', 'commands', 'agents', 'audit-rubrics', '_shared', 'scripts',
|
|
24
|
+
];
|
|
25
|
+
|
|
21
26
|
export function collectPackageSourceConflicts(packageDirectory) {
|
|
22
27
|
const gitConflictStatusCodes = new Set(['DD', 'AU', 'UD', 'UA', 'DU', 'AA', 'UU']);
|
|
23
28
|
const porcelainStatusLineMinLength = 4;
|
|
@@ -147,12 +152,13 @@ const INSTALL_GROUPS = {
|
|
|
147
152
|
core: {
|
|
148
153
|
description: 'Development standards, hooks, agents, commands',
|
|
149
154
|
skills: [
|
|
150
|
-
'orchestrator', 'orchestrator-refresh',
|
|
155
|
+
'orchestrator', 'orchestrator-refresh', 'team-advisor',
|
|
151
156
|
'anthropic-plan', 'everything-search',
|
|
152
157
|
'pr-review-responder',
|
|
158
|
+
'privacy-hygiene',
|
|
153
159
|
'recall', 'remember', 'task-build', 'verified-build'
|
|
154
160
|
],
|
|
155
|
-
includeDirectories:
|
|
161
|
+
includeDirectories: CORE_INCLUDE_DIRECTORIES,
|
|
156
162
|
includeAllHooks: true,
|
|
157
163
|
},
|
|
158
164
|
journal: {
|
|
@@ -507,17 +513,21 @@ function pruneManagedHooksFromEvent(settings, eventType, managedHookRelativePath
|
|
|
507
513
|
* pruning every prior managed hook (standalone script or inline validators
|
|
508
514
|
* runner) from each event's existing matcher groups before appending the freshly
|
|
509
515
|
* rewritten copies so repeated merges stay idempotent and a managed hook moved to
|
|
510
|
-
* a new matcher group does not double-run. User-authored hooks are preserved
|
|
511
|
-
*
|
|
516
|
+
* a new matcher group does not double-run. User-authored hooks are preserved as
|
|
517
|
+
* entries, but residual $HOME / ${HOME} / ~/ tokens in every hook and statusLine
|
|
518
|
+
* command are expanded to absolute home paths so hosts that require referenced
|
|
519
|
+
* env vars at load time (Grok on Windows) can execute them.
|
|
512
520
|
*
|
|
513
521
|
* @param {object} settings The parsed settings.json object (mutated in place).
|
|
514
522
|
* @param {{hooks: object}} hooksConfig Parsed hooks.json.
|
|
515
|
-
* @param {string} pluginRootDir Directory ${CLAUDE_PLUGIN_ROOT} resolves to
|
|
523
|
+
* @param {string} pluginRootDir Directory ${CLAUDE_PLUGIN_ROOT} resolves to
|
|
524
|
+
* (the installer's `~/.claude` root; home is its parent directory).
|
|
516
525
|
* @param {string} pythonCommand Interpreter command that replaces python3.
|
|
517
526
|
* @returns {number} Count of matcher groups merged.
|
|
518
527
|
*/
|
|
519
528
|
export function mergeHooksIntoSettings(settings, hooksConfig, pluginRootDir, pythonCommand) {
|
|
520
529
|
const managedHookRelativePaths = managedHookScriptRelativePaths(hooksConfig);
|
|
530
|
+
const pluginRootForward = pluginRootDir.replace(/\\/g, '/');
|
|
521
531
|
if (!settings.hooks) settings.hooks = {};
|
|
522
532
|
let groupCount = 0;
|
|
523
533
|
for (const [eventType, matcherGroups] of Object.entries(hooksConfig.hooks)) {
|
|
@@ -526,8 +536,11 @@ export function mergeHooksIntoSettings(settings, hooksConfig, pluginRootDir, pyt
|
|
|
526
536
|
for (const sourceGroup of matcherGroups) {
|
|
527
537
|
const rewrittenHooks = sourceGroup.hooks.map(hook => {
|
|
528
538
|
let command = hook.command;
|
|
529
|
-
command = command.replace(
|
|
530
|
-
|
|
539
|
+
command = command.replace(
|
|
540
|
+
/\$\{CLAUDE_PLUGIN_ROOT\}/g,
|
|
541
|
+
() => pluginRootForward,
|
|
542
|
+
);
|
|
543
|
+
command = command.replace(/^python3\b/, () => pythonCommand);
|
|
531
544
|
return { ...hook, command };
|
|
532
545
|
});
|
|
533
546
|
const existingIndex = settings.hooks[eventType].findIndex(
|
|
@@ -548,6 +561,7 @@ export function mergeHooksIntoSettings(settings, hooksConfig, pluginRootDir, pyt
|
|
|
548
561
|
groupCount++;
|
|
549
562
|
}
|
|
550
563
|
}
|
|
564
|
+
expandHomeDirectoryTokensInSettings(settings, dirname(pluginRootDir));
|
|
551
565
|
return groupCount;
|
|
552
566
|
}
|
|
553
567
|
|