claude-dev-env 2.4.0 → 2.5.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/CLAUDE.md +53 -49
- package/_shared/pr-loop/scripts/_claude_permissions_common.py +84 -0
- package/_shared/pr-loop/scripts/code_rules_gate.py +4 -2
- package/_shared/pr-loop/scripts/grant_project_claude_permissions.py +306 -306
- package/_shared/pr-loop/scripts/pr_loop_shared_constants/claude_permissions_constants.py +44 -0
- package/_shared/pr-loop/scripts/pr_loop_shared_constants/copilot_quota_constants.py +24 -24
- package/_shared/pr-loop/scripts/pr_loop_shared_constants/stale_worktree_rule_sweep_constants.py +107 -107
- package/_shared/pr-loop/scripts/revoke_project_claude_permissions.py +290 -48
- package/_shared/pr-loop/scripts/tests/test_claude_permissions_common.py +42 -2
- package/_shared/pr-loop/scripts/tests/test_claude_permissions_constants.py +36 -0
- package/_shared/pr-loop/scripts/tests/test_code_rules_gate.py +100 -1
- package/_shared/pr-loop/scripts/tests/test_fix_hookspath.py +497 -497
- package/_shared/pr-loop/scripts/tests/test_revoke_project_claude_permissions.py +311 -2
- package/_shared/pr-loop/scripts/tests/test_stale_worktree_rule_sweep.py +301 -301
- package/_shared/pr-loop/scripts/tests/test_stale_worktree_rule_sweep_constants.py +85 -85
- package/_shared/pr-loop/worker-spawn.md +1 -1
- package/agents/CLAUDE.md +2 -1
- package/agents/caveman.md +0 -1
- package/agents/clasp-deployment-orchestrator.md +0 -1
- package/agents/clean-coder.md +0 -1
- package/agents/code-advisor.md +0 -1
- package/agents/code-quality-agent.md +1 -2
- package/agents/code-verifier.md +0 -1
- package/agents/deep-research.md +0 -1
- package/agents/docs-agent.md +0 -1
- package/agents/git-commit-crafter.md +0 -1
- package/agents/issue-tracker.md +42 -0
- package/agents/plan-packet-validator.md +0 -1
- package/agents/pr-description-writer.md +0 -1
- package/agents/test_agent_frontmatter.py +67 -18
- package/audit-rubrics/category_rubrics/category-o-docstring-vs-impl-drift.md +143 -141
- package/bin/CLAUDE.md +68 -5
- package/bin/ever-shipped-skills.mjs +1 -0
- package/bin/install-constants.mjs +88 -0
- package/bin/install.mjs +1138 -114
- package/bin/install.prune.test.mjs +869 -19
- package/bin/install.test.mjs +906 -2
- package/commands/implement.md +1 -1
- package/commands/right-size.md +1 -1
- package/docs/CLAUDE.md +1 -0
- package/docs/host-pool-health-monitor.md +102 -0
- package/docs/references/CLAUDE.md +4 -2
- package/docs/references/advisor-tool.md +13 -0
- package/docs/references/code-review-enforcement.md +10 -0
- package/docs/references/team-advisor-skill.md +14 -0
- package/hooks/blocking/CLAUDE.md +1 -0
- package/hooks/blocking/code_review_pr_create_gate.py +7 -3
- package/hooks/blocking/code_review_push_gate.py +9 -4
- package/hooks/blocking/code_review_stamp_directory_write_blocker.py +8 -0
- package/hooks/blocking/config/__init__.py +5 -5
- package/hooks/blocking/config/code_review_enforcement_constants.py +4 -1
- package/hooks/blocking/config/test_code_review_enforcement_constants.py +5 -0
- package/hooks/blocking/config/verified_commit_constants.py +160 -159
- package/hooks/blocking/orchestrator_refresh_reschedule_gate.py +256 -0
- package/hooks/blocking/pre_tool_use_dispatcher.py +24 -24
- package/hooks/blocking/test_code_review_pr_create_gate.py +14 -0
- package/hooks/blocking/test_code_review_push_gate.py +16 -0
- package/hooks/blocking/test_code_review_stamp_directory_write_blocker.py +19 -0
- package/hooks/blocking/test_orchestrator_refresh_reschedule_gate.py +231 -0
- package/hooks/blocking/test_pre_tool_use_dispatcher.py +10 -1
- package/hooks/blocking/test_verdict_directory_write_blocker.py +808 -808
- package/hooks/blocking/test_verification_verdict_store.py +54 -0
- package/hooks/blocking/test_verified_commit_gate.py +581 -581
- package/hooks/blocking/test_verified_commit_message_accuracy_blocker.py +131 -131
- package/hooks/blocking/verdict_directory_write_blocker.py +687 -687
- package/hooks/blocking/verification_verdict_store.py +1039 -1036
- package/hooks/blocking/verified_commit_message_accuracy_blocker.py +167 -167
- package/hooks/blocking/verifier_verdict_minter.py +280 -280
- package/hooks/git-hooks/test_pre_push.py +25 -0
- package/hooks/hooks.json +10 -0
- package/hooks/hooks_constants/CLAUDE.md +2 -1
- package/hooks/hooks_constants/enter_worktree_prefetch_constants.py +18 -18
- package/hooks/hooks_constants/orchestrator_refresh_reschedule_gate_constants.py +48 -0
- package/hooks/hooks_constants/ruff_integration_constants.py +16 -0
- package/hooks/lifecycle/enter_worktree_origin_prefetch.py +163 -146
- package/hooks/lifecycle/test_enter_worktree_origin_prefetch.py +185 -178
- package/hooks/pyproject.toml +1 -0
- package/hooks/validators/CLAUDE.md +1 -0
- package/hooks/validators/config/__init__.py +0 -0
- package/hooks/validators/config/directory_exemption_constants.py +183 -0
- package/hooks/validators/config/test_directory_exemption_constants.py +21 -0
- package/hooks/validators/conftest.py +4 -0
- package/hooks/validators/ruff_integration.py +49 -5
- package/hooks/validators/run_all_validators.py +206 -9
- package/hooks/validators/test_directory_exemption_constants.py +185 -0
- package/hooks/validators/test_python_antipattern_checks.py +110 -5
- package/hooks/validators/test_ruff_integration.py +92 -1
- package/hooks/validators/test_run_all_validators.py +115 -68
- package/hooks/validators/test_run_all_validators_pretooluse.py +159 -1
- package/package.json +10 -2
- package/rules/CLAUDE.md +1 -0
- package/rules/docstring-prose-matches-implementation.md +45 -44
- package/rules/state-what-is.md +25 -0
- package/rules/verified-commit-gate-skip.md +1 -1
- package/scripts/CLAUDE.md +1 -0
- package/scripts/Capture-PoolHealth.ps1 +410 -0
- package/scripts/_code_review_test_support.py +404 -0
- package/scripts/claude_chain_runner.py +141 -1
- package/scripts/conftest.py +16 -1
- package/scripts/dev_env_scripts_constants/CLAUDE.md +1 -1
- package/scripts/dev_env_scripts_constants/claude_chain_constants.py +9 -0
- package/scripts/resolve_worker_spawn.py +626 -626
- package/scripts/spawn_grok_batch.py +672 -672
- package/scripts/test_claude_chain_runner.py +131 -0
- package/scripts/test_invoke_code_review_chain.py +70 -0
- package/scripts/test_invoke_code_review_cli.py +192 -0
- package/scripts/test_invoke_code_review_contract.py +256 -0
- package/scripts/test_invoke_code_review_git.py +123 -0
- package/scripts/test_invoke_code_review_mode.py +99 -0
- package/scripts/test_resolve_worker_spawn.py +1014 -1014
- package/skills/CLAUDE.md +2 -0
- package/skills/auditing-claude-config/SKILL.md +114 -114
- package/skills/autoconverge/SKILL.md +427 -427
- package/skills/autoconverge/reference/convergence.md +24 -3
- package/skills/autoconverge/workflow/CLAUDE.md +1 -0
- package/skills/autoconverge/workflow/converge.clean-audit.test.mjs +3 -3
- package/skills/autoconverge/workflow/converge.contract.test.mjs +1263 -1263
- package/skills/autoconverge/workflow/converge.mjs +167 -0
- package/skills/autoconverge/workflow/converge.p2-advance.test.mjs +202 -0
- package/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a11d903476b803493.jsonl +2 -2
- package/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a26213978adeef6fb.jsonl +2 -2
- package/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a3def0d15ed9d9110.jsonl +2 -2
- package/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a41f41b1b708ee3b7.jsonl +2 -2
- package/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a758b880abecc3ff7.jsonl +2 -2
- package/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a8897b89656b1bd16.jsonl +2 -2
- package/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-abd463d744a1437bc.jsonl +2 -2
- package/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-ad19d027ae8ee1816.jsonl +2 -2
- package/skills/autoconverge/workflow/fixtures/wf_run/workflows/wf_881252e6-700.json +265 -265
- package/skills/closeout/SKILL.md +33 -50
- package/skills/codex-review/scripts/codex_review_scripts_constants/run_constants.py +8 -0
- package/skills/codex-review/scripts/run_codex_review.py +233 -1
- package/skills/codex-review/scripts/test_run_codex_review.py +189 -0
- package/skills/condensing-instructions/SKILL.md +81 -0
- package/skills/copilot-review/SKILL.md +119 -119
- package/skills/e-code-review/SKILL.md +52 -0
- package/skills/e-code-review/reference/fix.md +54 -0
- package/skills/e-code-review/reference/loop.md +43 -0
- package/skills/e-code-review/reference/low.md +57 -0
- package/skills/e-code-review/reference/medium.md +153 -0
- package/skills/e-code-review/reference/xhigh.md +182 -0
- package/skills/e-simplify/SKILL.md +97 -0
- package/skills/issue-tracker/SKILL.md +92 -0
- package/skills/issue-tracker/reference/epic-and-sub-issue-model.md +55 -0
- package/skills/issue-tracker/reference/handoff-schema.md +64 -0
- package/skills/issue-tracker/reference/operation-matrix.md +41 -0
- package/skills/orchestrator/SKILL.md +162 -21
- package/skills/orchestrator/scripts/status_gate.py +625 -0
- package/skills/orchestrator/scripts/status_gate_constants/__init__.py +1 -0
- package/skills/orchestrator/scripts/status_gate_constants/config/__init__.py +1 -0
- package/skills/orchestrator/scripts/status_gate_constants/config/constants.py +47 -0
- package/skills/orchestrator/scripts/test_status_gate.py +439 -0
- package/skills/orchestrator-refresh/SKILL.md +110 -35
- package/skills/plan-to-pr/SKILL.md +155 -0
- package/skills/plan-to-pr/reference/final-validation-tasks.md +15 -0
- package/skills/plan-to-pr/reference/model-routing.md +36 -0
- package/skills/plan-to-pr/reference/packet-contract.md +43 -0
- package/skills/plan-to-pr/reference/packet-schema.json +57 -0
- package/skills/plan-to-pr/reference/process-inventory.md +22 -0
- package/skills/plan-to-pr/reference/review-loop.md +33 -0
- package/skills/plan-to-pr/reference/run-record.schema.json +27 -0
- package/skills/plan-to-pr/reference/self-audit-tasks.md +15 -0
- package/skills/plan-to-pr/reference/task-seeds.md +14 -0
- package/skills/plan-to-pr/reference/task-ticket.md +38 -0
- package/skills/plan-to-pr/scripts/config/__init__.py +1 -0
- package/skills/plan-to-pr/scripts/config/constants.py +193 -0
- package/skills/plan-to-pr/scripts/create_packet.py +173 -0
- package/skills/plan-to-pr/scripts/test_create_packet.py +102 -0
- package/skills/plan-to-pr/scripts/test_validate_packet.py +256 -0
- package/skills/plan-to-pr/scripts/test_validate_protocol.py +135 -0
- package/skills/plan-to-pr/scripts/test_validate_run.py +158 -0
- package/skills/plan-to-pr/scripts/validate_packet.py +655 -0
- package/skills/plan-to-pr/scripts/validate_protocol.py +622 -0
- package/skills/plan-to-pr/scripts/validate_run.py +173 -0
- package/skills/plan-to-pr/test_skill_contract.py +207 -0
- package/skills/plan-to-pr/test_task_ticket_contract.py +151 -0
- package/skills/pr-converge/SKILL.md +472 -469
- package/skills/pr-converge/reference/examples.md +3 -3
- package/skills/pr-converge/reference/fix-protocol.md +1 -1
- package/skills/pr-converge/reference/ground-rules.md +7 -4
- package/skills/pr-converge/reference/multi-pr-orchestration.md +4 -1
- package/skills/pr-converge/reference/per-tick.md +5 -5
- package/skills/pr-converge/reference/progress-checklist.md +1 -1
- package/skills/pr-converge/scripts/check_convergence_gates.py +279 -279
- package/skills/pr-converge/scripts/test_check_convergence_codex.py +507 -507
- package/skills/pr-converge/scripts/test_check_convergence_gates.py +84 -84
- package/skills/pr-converge/test_step5_host_branch.py +1 -1
- package/skills/pr-fix-protocol/SKILL.md +1 -1
- package/skills/privacy-hygiene/SKILL.md +68 -68
- package/skills/prototype/workflows/promotion.md +1 -1
- package/skills/release-notes-html/SKILL.md +164 -0
- package/skills/task-build/CLAUDE.md +8 -7
- package/skills/task-build/SKILL.md +16 -8
- package/skills/task-build/reference/tool-routing.md +19 -0
- package/scripts/test_invoke_code_review.py +0 -966
- package/skills/closeout/reference/issue-body-templates.md +0 -108
|
@@ -1,85 +1,85 @@
|
|
|
1
|
-
"""Behavioral tests for stale_worktree_rule_sweep_constants.
|
|
2
|
-
|
|
3
|
-
Confirms get_claude_worktrees_root resolves the worktrees directory under
|
|
4
|
-
the user's ~/.claude home, and that the rule-parsing constants carry the
|
|
5
|
-
literal shapes the sweep relies on.
|
|
6
|
-
"""
|
|
7
|
-
|
|
8
|
-
from __future__ import annotations
|
|
9
|
-
|
|
10
|
-
import importlib.util
|
|
11
|
-
import sys
|
|
12
|
-
from pathlib import Path
|
|
13
|
-
from types import ModuleType
|
|
14
|
-
|
|
15
|
-
import pytest
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
def _load_constants_module() -> ModuleType:
|
|
19
|
-
scripts_directory = Path(__file__).parent.parent
|
|
20
|
-
parent_directory = str(scripts_directory.resolve())
|
|
21
|
-
if parent_directory not in sys.path:
|
|
22
|
-
sys.path.insert(0, parent_directory)
|
|
23
|
-
module_path = (
|
|
24
|
-
scripts_directory
|
|
25
|
-
/ "pr_loop_shared_constants"
|
|
26
|
-
/ "stale_worktree_rule_sweep_constants.py"
|
|
27
|
-
)
|
|
28
|
-
specification = importlib.util.spec_from_file_location(
|
|
29
|
-
"pr_loop_shared_constants.stale_worktree_rule_sweep_constants", module_path
|
|
30
|
-
)
|
|
31
|
-
assert specification is not None
|
|
32
|
-
assert specification.loader is not None
|
|
33
|
-
module = importlib.util.module_from_spec(specification)
|
|
34
|
-
specification.loader.exec_module(module)
|
|
35
|
-
return module
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
def test_worktrees_root_resolves_under_the_user_claude_home(
|
|
39
|
-
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
|
|
40
|
-
) -> None:
|
|
41
|
-
constants_module = _load_constants_module()
|
|
42
|
-
monkeypatch.setenv("HOME", str(tmp_path))
|
|
43
|
-
monkeypatch.setenv("USERPROFILE", str(tmp_path))
|
|
44
|
-
resolved_worktrees_root = constants_module.get_claude_worktrees_root()
|
|
45
|
-
assert resolved_worktrees_root == tmp_path / ".claude" / "worktrees"
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
def test_extract_rule_target_path_reads_the_delimited_path() -> None:
|
|
49
|
-
constants_module = _load_constants_module()
|
|
50
|
-
extracted_path = constants_module.extract_rule_target_path(
|
|
51
|
-
"Edit(/repo/wt/.claude/**)"
|
|
52
|
-
)
|
|
53
|
-
assert extracted_path == "/repo/wt/.claude/**"
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
def test_extract_rule_target_path_returns_none_for_a_non_rule() -> None:
|
|
57
|
-
constants_module = _load_constants_module()
|
|
58
|
-
assert constants_module.extract_rule_target_path("not a rule") is None
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
def test_worktree_directory_for_rule_keeps_nested_segments_below_the_root() -> None:
|
|
62
|
-
constants_module = _load_constants_module()
|
|
63
|
-
worktrees_root = Path("/home/dev/.claude/worktrees")
|
|
64
|
-
resolved_directory = constants_module.worktree_directory_for_rule(
|
|
65
|
-
"Edit(/home/dev/.claude/worktrees/repo/feature/.claude/**)", worktrees_root
|
|
66
|
-
)
|
|
67
|
-
assert resolved_directory == worktrees_root / "repo" / "feature"
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
def test_worktree_directory_for_rule_keeps_one_segment_flat_layout() -> None:
|
|
71
|
-
constants_module = _load_constants_module()
|
|
72
|
-
worktrees_root = Path("/home/dev/.claude/worktrees")
|
|
73
|
-
resolved_directory = constants_module.worktree_directory_for_rule(
|
|
74
|
-
"Edit(/home/dev/.claude/worktrees/flat-worktree/.claude/**)", worktrees_root
|
|
75
|
-
)
|
|
76
|
-
assert resolved_directory == worktrees_root / "flat-worktree"
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
def test_worktree_directory_for_rule_returns_none_outside_the_root() -> None:
|
|
80
|
-
constants_module = _load_constants_module()
|
|
81
|
-
worktrees_root = Path("/home/dev/.claude/worktrees")
|
|
82
|
-
resolved_directory = constants_module.worktree_directory_for_rule(
|
|
83
|
-
"Edit(/home/dev/project/.claude/**)", worktrees_root
|
|
84
|
-
)
|
|
85
|
-
assert resolved_directory is None
|
|
1
|
+
"""Behavioral tests for stale_worktree_rule_sweep_constants.
|
|
2
|
+
|
|
3
|
+
Confirms get_claude_worktrees_root resolves the worktrees directory under
|
|
4
|
+
the user's ~/.claude home, and that the rule-parsing constants carry the
|
|
5
|
+
literal shapes the sweep relies on.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import importlib.util
|
|
11
|
+
import sys
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
from types import ModuleType
|
|
14
|
+
|
|
15
|
+
import pytest
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def _load_constants_module() -> ModuleType:
|
|
19
|
+
scripts_directory = Path(__file__).parent.parent
|
|
20
|
+
parent_directory = str(scripts_directory.resolve())
|
|
21
|
+
if parent_directory not in sys.path:
|
|
22
|
+
sys.path.insert(0, parent_directory)
|
|
23
|
+
module_path = (
|
|
24
|
+
scripts_directory
|
|
25
|
+
/ "pr_loop_shared_constants"
|
|
26
|
+
/ "stale_worktree_rule_sweep_constants.py"
|
|
27
|
+
)
|
|
28
|
+
specification = importlib.util.spec_from_file_location(
|
|
29
|
+
"pr_loop_shared_constants.stale_worktree_rule_sweep_constants", module_path
|
|
30
|
+
)
|
|
31
|
+
assert specification is not None
|
|
32
|
+
assert specification.loader is not None
|
|
33
|
+
module = importlib.util.module_from_spec(specification)
|
|
34
|
+
specification.loader.exec_module(module)
|
|
35
|
+
return module
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def test_worktrees_root_resolves_under_the_user_claude_home(
|
|
39
|
+
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
|
|
40
|
+
) -> None:
|
|
41
|
+
constants_module = _load_constants_module()
|
|
42
|
+
monkeypatch.setenv("HOME", str(tmp_path))
|
|
43
|
+
monkeypatch.setenv("USERPROFILE", str(tmp_path))
|
|
44
|
+
resolved_worktrees_root = constants_module.get_claude_worktrees_root()
|
|
45
|
+
assert resolved_worktrees_root == tmp_path / ".claude" / "worktrees"
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def test_extract_rule_target_path_reads_the_delimited_path() -> None:
|
|
49
|
+
constants_module = _load_constants_module()
|
|
50
|
+
extracted_path = constants_module.extract_rule_target_path(
|
|
51
|
+
"Edit(/repo/wt/.claude/**)"
|
|
52
|
+
)
|
|
53
|
+
assert extracted_path == "/repo/wt/.claude/**"
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def test_extract_rule_target_path_returns_none_for_a_non_rule() -> None:
|
|
57
|
+
constants_module = _load_constants_module()
|
|
58
|
+
assert constants_module.extract_rule_target_path("not a rule") is None
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def test_worktree_directory_for_rule_keeps_nested_segments_below_the_root() -> None:
|
|
62
|
+
constants_module = _load_constants_module()
|
|
63
|
+
worktrees_root = Path("/home/dev/.claude/worktrees")
|
|
64
|
+
resolved_directory = constants_module.worktree_directory_for_rule(
|
|
65
|
+
"Edit(/home/dev/.claude/worktrees/repo/feature/.claude/**)", worktrees_root
|
|
66
|
+
)
|
|
67
|
+
assert resolved_directory == worktrees_root / "repo" / "feature"
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def test_worktree_directory_for_rule_keeps_one_segment_flat_layout() -> None:
|
|
71
|
+
constants_module = _load_constants_module()
|
|
72
|
+
worktrees_root = Path("/home/dev/.claude/worktrees")
|
|
73
|
+
resolved_directory = constants_module.worktree_directory_for_rule(
|
|
74
|
+
"Edit(/home/dev/.claude/worktrees/flat-worktree/.claude/**)", worktrees_root
|
|
75
|
+
)
|
|
76
|
+
assert resolved_directory == worktrees_root / "flat-worktree"
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def test_worktree_directory_for_rule_returns_none_outside_the_root() -> None:
|
|
80
|
+
constants_module = _load_constants_module()
|
|
81
|
+
worktrees_root = Path("/home/dev/.claude/worktrees")
|
|
82
|
+
resolved_directory = constants_module.worktree_directory_for_rule(
|
|
83
|
+
"Edit(/home/dev/project/.claude/**)", worktrees_root
|
|
84
|
+
)
|
|
85
|
+
assert resolved_directory is None
|
|
@@ -146,7 +146,7 @@ Mode decision:
|
|
|
146
146
|
| `ThirdParty` | any | `chain` | Headless spawn through `claude_chain_runner` |
|
|
147
147
|
|
|
148
148
|
The review always runs at effort **high** on model **opus**. Chain mode builds
|
|
149
|
-
a single-turn prompt `/code-review
|
|
149
|
+
a single-turn prompt `/code-review ultra --fix`, pins `--model opus`, sets
|
|
150
150
|
subprocess `cwd` to the PR working tree, and reads stdin from the empty stream
|
|
151
151
|
so the spawn does not wait for input.
|
|
152
152
|
|
package/agents/CLAUDE.md
CHANGED
|
@@ -15,6 +15,7 @@ Agent definition files installed into `~/.claude/agents/` by `bin/install.mjs`.
|
|
|
15
15
|
| `deep-research.md` | Deep Research | Citation-grounded research with web search |
|
|
16
16
|
| `docs-agent.md` | Docs Agent | Documentation authoring and maintenance |
|
|
17
17
|
| `git-commit-crafter.md` | Git Commit Crafter | Stages changes, writes conventional commit messages, creates commits |
|
|
18
|
+
| `issue-tracker.md` | Issue Tracker | Primary handler for one GitHub issue action per spawn; loads the issue-tracker skill (plain-brief); returns issue numbers and URLs |
|
|
18
19
|
| `plan-packet-validator.md` | Plan Packet Validator | Fresh-context validator for workflow-generated plan packets under `docs/plans/` |
|
|
19
20
|
| `pr-description-writer.md` | PR Description Writer | Authors PR descriptions in Anthropic-style shapes that pass the `pr_description_enforcer` hook's body audit |
|
|
20
21
|
| `session-advisor.md` | Session Advisor | Standing multi-consumer reviewer; SendMessage only; returns endorse/correction/plan/stop |
|
|
@@ -22,7 +23,7 @@ Agent definition files installed into `~/.claude/agents/` by `bin/install.mjs`.
|
|
|
22
23
|
|
|
23
24
|
## Format
|
|
24
25
|
|
|
25
|
-
Each file uses YAML frontmatter (`name`, `description`, `tools`, optional `color`) followed by a Markdown body with the agent's behavioral instructions. The `description` field appears in the Claude Code agent picker.
|
|
26
|
+
Each file uses YAML frontmatter (`name`, `description`, `tools`, optional `color`) followed by a Markdown body with the agent's behavioral instructions. The `description` field appears in the Claude Code agent picker. An agent definition carries no `model` key — the caller supplies the model on each spawn.
|
|
26
27
|
|
|
27
28
|
## Adding an agent
|
|
28
29
|
|
package/agents/caveman.md
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: caveman
|
|
3
3
|
description: Trims noise from an artifact the main caller has already authored. Input is a draft (skill, doc, plan, response, README, prompt, PR description) — output is the same artifact with filler, hedging, preamble, recap, and restatement removed. Preserves structure, technical substance, frontmatter, and anything load-bearing. Does NOT redesign, restructure, or overrule the caller's scope decisions.
|
|
4
|
-
model: inherit
|
|
5
4
|
color: red
|
|
6
5
|
---
|
|
7
6
|
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: clasp-deployment-orchestrator
|
|
3
3
|
description: Use PROACTIVELY when creating or deploying Google Apps Script projects with multiple files, complex configuration, or batch operations. Invokes the clasp-deployment skill for command execution.
|
|
4
|
-
model: inherit
|
|
5
4
|
tools: Task, Read, Write, Glob, Grep
|
|
6
5
|
color: green
|
|
7
6
|
---
|
package/agents/clean-coder.md
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: clean-coder
|
|
3
3
|
description: "Use PROACTIVELY for ALL code generation — feature development, bug fixes, refactoring, hook creation, automation scripts, and any task that produces code. Internalizes CODE_RULES.md and the 8-dimension readability standard so thoroughly that /check finds zero issues. The definitive code-writing agent."
|
|
4
|
-
model: opus
|
|
5
4
|
tools: Read, Write, Edit, Bash, Grep, Glob, Task, Skill, SendMessage
|
|
6
5
|
color: green
|
|
7
6
|
---
|
package/agents/code-advisor.md
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
name: code-advisor
|
|
3
3
|
description: Single-executor mid-run advisor. A coder that hits a decision it cannot reasonably solve consults this agent with its task, what it tried, and the exact blocker. Returns PLAN, CORRECTION, or STOP as final reply text (not SendMessage). Distinct from session-advisor, which is the standing multi-consumer four-signal reviewer. Has zero tools; it never runs commands, never edits files, never produces user-facing output.
|
|
4
4
|
tools: []
|
|
5
|
-
model: inherit
|
|
6
5
|
color: purple
|
|
7
6
|
---
|
|
8
7
|
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: code-quality-agent
|
|
3
3
|
description: Use this agent for comprehensive code quality reviews across multiple files.
|
|
4
|
-
model: opus
|
|
5
4
|
color: red
|
|
6
5
|
---
|
|
7
6
|
|
|
@@ -175,7 +174,7 @@ Followed by the Shape A finding list, the Shape B proof-of-absence list, and the
|
|
|
175
174
|
|
|
176
175
|
## Caller Context
|
|
177
176
|
|
|
178
|
-
Callers /bugteam, /qbug, and /findbugs invoke this agent at different models per call (opus for /bugteam, sonnet primary for /findbugs, haiku secondary for both /qbug and /findbugs). The frontmatter `model
|
|
177
|
+
Callers /bugteam, /qbug, and /findbugs invoke this agent at different models per call (opus for /bugteam, sonnet primary for /findbugs, haiku secondary for both /qbug and /findbugs). The frontmatter carries no `model:` key, so each caller's `Agent()` model applies. Persistence files such as `loop-N-audit.json` and `loop-N-diagnostics.json` are the calling skill's responsibility — your output is the structured finding list defined above.
|
|
179
178
|
|
|
180
179
|
## Examples
|
|
181
180
|
|
package/agents/code-verifier.md
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
name: code-verifier
|
|
3
3
|
description: Post-hoc verification agent for the three-phase code workflow. Spawned by the main session after coder agents finish. Runs every check itself in a fresh context — named gates, tests against recorded baselines, two-way diff-vs-task reading — puts the draft verdict through one strongest-tier validation subagent that tries to refute it, then ends with a fenced verdict block the verifier_verdict_minter hook turns into the commit-gate verdict. Read and execute only; it never edits files.
|
|
4
4
|
tools: Read, Grep, Glob, Bash, Task
|
|
5
|
-
model: sonnet
|
|
6
5
|
color: orange
|
|
7
6
|
---
|
|
8
7
|
|
package/agents/deep-research.md
CHANGED
package/agents/docs-agent.md
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: git-commit-crafter
|
|
3
3
|
description: Use this agent when you need to create git commits, stage changes, or organize multiple file changes into atomic commits. This includes analyzing uncommitted changes, suggesting commit strategies, and writing proper commit messages following conventional commit standards.
|
|
4
|
-
model: inherit
|
|
5
4
|
color: yellow
|
|
6
5
|
---
|
|
7
6
|
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: issue-tracker
|
|
3
|
+
description: >-
|
|
4
|
+
Primary handler for one GitHub issue action per spawn on a work-stream:
|
|
5
|
+
open an epic, file a sub-issue, update status in place, refresh the epic
|
|
6
|
+
checklist, or close a sub-issue. Spawn with one action plus the issue-candidate
|
|
7
|
+
or issue number it needs; loads the issue-tracker skill; returns affected
|
|
8
|
+
issue numbers and URLs. Prefer the same warm agent for follow-ups on the same
|
|
9
|
+
issue or the same epic work-stream.
|
|
10
|
+
tools: Read, Bash, Skill, mcp__github__search_issues, mcp__github__issue_read, mcp__github__issue_write, mcp__github__sub_issue_write, mcp__github__add_issue_comment
|
|
11
|
+
color: green
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
# Issue tracker agent
|
|
15
|
+
|
|
16
|
+
**Caller wants one issue action. You run that action and hand back numbers + URLs.**
|
|
17
|
+
|
|
18
|
+
**dedup -> one action -> markers only -> numbers + URLs**
|
|
19
|
+
|
|
20
|
+
You are the primary handler for one action per turn. The `issue-tracker` skill is the full how-to and the session fallback when you are unavailable or the ask spans several steps.
|
|
21
|
+
|
|
22
|
+
## Warm reuse (callers)
|
|
23
|
+
|
|
24
|
+
Keep the same warm `issue-tracker` agent for follow-up actions on the **same issue** or a **related issue on the same epic**. Message that agent again with the next action. Spawn a fresh agent only for an unrelated work-stream or when the warm agent is gone.
|
|
25
|
+
|
|
26
|
+
## Voice
|
|
27
|
+
|
|
28
|
+
Use the `plain-brief` output style (`output-styles/plain-brief.md`). Final message is issue number(s) and URL(s) only.
|
|
29
|
+
|
|
30
|
+
## On each turn
|
|
31
|
+
|
|
32
|
+
1. **Load the skill** if this is the first turn of this agent. Use the Skill tool to load `issue-tracker`. Follow it for markers, dedup, tools, handoff schema, PR auto-close, and gotchas. Do not invent a second path.
|
|
33
|
+
2. **Run the named action.** The ticket names one action: file a sub-issue from an issue-candidate, open an epic, update status in place, refresh the epic checklist, or close a sub-issue. Run that action end to end (every step *that* action needs: labels, attach, checklist refresh when the action creates or closes a child). Do not start a second, unrelated action in this turn.
|
|
34
|
+
3. **Return numbers and URLs.** Affected issue number(s) and URL(s) only, no narration after that payload, so the caller can send the next action to this same agent or spawn another when the work-stream changes.
|
|
35
|
+
|
|
36
|
+
## Hold these lines
|
|
37
|
+
|
|
38
|
+
- Dedup open **and** closed before create.
|
|
39
|
+
- Edit only between marker pairs; comments are cross-links only.
|
|
40
|
+
- Attach with REST `.id` and `gh -F`, never display `#N` or `-f`.
|
|
41
|
+
- Prefer GitHub MCP; fall back to `gh` per the skill matrix.
|
|
42
|
+
- When a fix ships: **PR body first** for auto-close. On the PR that merges into the **default branch**, put `Closes #N` for each finished sub-issue (`Closes #12` and `Closes #13`, not `Closes #12, #13`). Prefer the same line on the first commit. Stacked PRs that are not default-branch merges use plain `#N` only. A related UI link without a closing keyword does not close the issue. You own picking the correct `#N`.
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
name: plan-packet-validator
|
|
3
3
|
description: Fresh-context validator for workflow-generated plan packets. Use after a plan packet is written under docs/plans/<slug>/ to verify source accuracy, completeness, TDD readiness, scope control, handoff quality, and no invented repo behavior. Read-only; never edits files.
|
|
4
4
|
tools: Read, Grep, Glob, Bash
|
|
5
|
-
model: inherit
|
|
6
5
|
color: purple
|
|
7
6
|
---
|
|
8
7
|
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
name: pr-description-writer
|
|
3
3
|
description: "Optional agent for PR descriptions and PR comments. Authors bodies in one of three Anthropic-derived shapes (Trivial / Standard / Heavy) so PRs match merged-PR style in `anthropics/claude-code`, `anthropics/claude-code-action`, and `anthropics/claude-code-sdk-python`, and pass the `pr_description_enforcer` PreToolUse hook's body audit on `gh pr create`, `gh pr edit`, and `gh pr comment`."
|
|
4
4
|
tools: Read,Grep,Glob,Bash
|
|
5
|
-
model: haiku
|
|
6
5
|
---
|
|
7
6
|
|
|
8
7
|
# PR Description Writer
|
|
@@ -5,47 +5,79 @@ Code subagent loader reads. The loader accepts a fixed key set; an unrecognized
|
|
|
5
5
|
top-level key breaks the spawn — the subagent starts with a broken definition,
|
|
6
6
|
idles, and dies without a report::
|
|
7
7
|
|
|
8
|
-
ok: name / description / tools /
|
|
8
|
+
ok: name / description / tools / color
|
|
9
9
|
flag: effort <- unrecognized, subagent dies delivering nothing
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
11
|
+
An agent definition carries no `model` key at all — the caller supplies the
|
|
12
|
+
model on every spawn, so no agent definition names one, concrete or
|
|
13
|
+
`inherit`::
|
|
14
|
+
|
|
15
|
+
ok: <no model key at all>
|
|
16
|
+
flag: model: inherit <- caller can no longer choose the model
|
|
17
|
+
flag: model: opus <- pinned concrete model, caller can't override
|
|
18
|
+
|
|
19
|
+
Frontmatter parsing is self-contained here (stdlib only): the block is the
|
|
20
|
+
text between the file's opening and closing `---` fence lines, and top-level
|
|
21
|
+
keys are read with a line scan so an agent whose `description` embeds
|
|
22
|
+
informal `<example>` prose is not mistaken for one carrying extra keys.
|
|
16
23
|
"""
|
|
17
24
|
|
|
18
25
|
from __future__ import annotations
|
|
19
26
|
|
|
20
27
|
import re
|
|
28
|
+
from functools import cache
|
|
21
29
|
from pathlib import Path
|
|
22
30
|
|
|
23
31
|
import pytest
|
|
24
32
|
import yaml
|
|
25
33
|
|
|
26
|
-
ACCEPTED_FRONTMATTER_KEYS = frozenset(
|
|
27
|
-
{"name", "description", "tools", "model", "color"}
|
|
28
|
-
)
|
|
29
|
-
FRONTMATTER_FENCE = "---"
|
|
30
|
-
FRONTMATTER_SEGMENT_COUNT = 3
|
|
34
|
+
ACCEPTED_FRONTMATTER_KEYS = frozenset({"name", "description", "tools", "color"})
|
|
31
35
|
CODE_VERIFIER_AGENT_NAME = "code-verifier"
|
|
36
|
+
EXEMPT_MARKDOWN_FILENAME = "CLAUDE.md"
|
|
37
|
+
FRONTMATTER_FENCE_LINE = "---"
|
|
38
|
+
MODEL_KEY_NAME = "model"
|
|
32
39
|
TOP_LEVEL_KEY_PATTERN = re.compile(r"^([a-z][a-z0-9_]*):", re.MULTILINE)
|
|
33
40
|
|
|
34
41
|
|
|
35
|
-
def
|
|
42
|
+
def _extract_frontmatter_block(markdown_text: str) -> str | None:
|
|
43
|
+
"""Return the YAML text between the file's opening and closing --- fences.
|
|
44
|
+
|
|
45
|
+
Args:
|
|
46
|
+
markdown_text: The full text of an agent definition markdown file.
|
|
47
|
+
|
|
48
|
+
Returns:
|
|
49
|
+
The frontmatter text (the lines strictly between the two fence
|
|
50
|
+
lines), or None when the file does not open with a --- fence line or
|
|
51
|
+
never closes one.
|
|
52
|
+
"""
|
|
53
|
+
all_lines = markdown_text.splitlines()
|
|
54
|
+
if not all_lines or all_lines[0].strip() != FRONTMATTER_FENCE_LINE:
|
|
55
|
+
return None
|
|
56
|
+
for each_line_index in range(1, len(all_lines)):
|
|
57
|
+
if all_lines[each_line_index].strip() == FRONTMATTER_FENCE_LINE:
|
|
58
|
+
return "\n".join(all_lines[1:each_line_index])
|
|
59
|
+
return None
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
@cache
|
|
63
|
+
def _agent_definition_paths() -> tuple[Path, ...]:
|
|
36
64
|
agents_directory = Path(__file__).parent
|
|
37
65
|
all_markdown_files = sorted(agents_directory.glob("*.md"))
|
|
38
|
-
return
|
|
66
|
+
return tuple(
|
|
39
67
|
each_markdown_file
|
|
40
68
|
for each_markdown_file in all_markdown_files
|
|
41
|
-
if each_markdown_file.
|
|
42
|
-
|
|
69
|
+
if each_markdown_file.name != EXEMPT_MARKDOWN_FILENAME
|
|
70
|
+
and _extract_frontmatter_block(each_markdown_file.read_text(encoding="utf-8"))
|
|
71
|
+
is not None
|
|
72
|
+
)
|
|
43
73
|
|
|
44
74
|
|
|
45
75
|
def _frontmatter_block(agent_definition_path: Path) -> str:
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
76
|
+
frontmatter_block = _extract_frontmatter_block(
|
|
77
|
+
agent_definition_path.read_text(encoding="utf-8")
|
|
78
|
+
)
|
|
79
|
+
assert frontmatter_block is not None
|
|
80
|
+
return frontmatter_block
|
|
49
81
|
|
|
50
82
|
|
|
51
83
|
def _top_level_keys(frontmatter_block: str) -> set[str]:
|
|
@@ -76,3 +108,20 @@ def test_code_verifier_frontmatter_parses_and_names_the_agent() -> None:
|
|
|
76
108
|
parsed_frontmatter = yaml.safe_load(code_verifier_block)
|
|
77
109
|
assert parsed_frontmatter["name"] == CODE_VERIFIER_AGENT_NAME
|
|
78
110
|
assert set(parsed_frontmatter) <= ACCEPTED_FRONTMATTER_KEYS
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
@pytest.mark.parametrize(
|
|
114
|
+
"agent_definition_path",
|
|
115
|
+
_agent_definition_paths(),
|
|
116
|
+
ids=lambda each_path: each_path.name,
|
|
117
|
+
)
|
|
118
|
+
def test_agent_frontmatter_carries_no_model_key(
|
|
119
|
+
agent_definition_path: Path,
|
|
120
|
+
) -> None:
|
|
121
|
+
frontmatter_block = _frontmatter_block(agent_definition_path)
|
|
122
|
+
declared_keys = _top_level_keys(frontmatter_block)
|
|
123
|
+
assert MODEL_KEY_NAME not in declared_keys, (
|
|
124
|
+
f"{agent_definition_path.name} carries a model: key in frontmatter; "
|
|
125
|
+
"the caller supplies the model on every spawn, so agent definitions "
|
|
126
|
+
"carry no model key at all, not even model: inherit"
|
|
127
|
+
)
|