claude-dev-env 1.19.1 → 1.19.3
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/docs/CODE_RULES.md +24 -2
- package/hooks/blocking/code-rules-enforcer.py +33 -13
- package/package.json +1 -1
- package/skills/skill-builder/SKILL.md +3 -3
- package/skills/skill-builder/workflows/improve-skill.md +1 -1
- package/skills/skill-builder/workflows/new-skill.md +1 -1
- package/skills/skill-builder/workflows/polish-skill.md +1 -1
- package/skills/skill-writer/SKILL.md +2 -2
package/docs/CODE_RULES.md
CHANGED
|
@@ -44,7 +44,7 @@ These rules are automatically enforced by `code-rules-enforcer.py`. Violations b
|
|
|
44
44
|
| No NEW comments | `#` / `//` in new code only (existing comments NEVER removed; shebangs, type:, noqa, eslint, docstrings exempt) |
|
|
45
45
|
| Imports at top | No `import` inside function bodies |
|
|
46
46
|
| Logging format args | No `log_*(f"...")` - use `log_*("...", arg)` |
|
|
47
|
-
| File line count |
|
|
47
|
+
| File line count | Advisory only — see [File length guidance](#65-file-length-guidance) |
|
|
48
48
|
| Magic values | No literals in function bodies (0, 1, -1 exempt). Includes string templates — if you strip the interpolations from an f-string and the remaining literal text is structural (paths, URLs, patterns), those fragments are magic values that belong in config |
|
|
49
49
|
| Constants location | No `UPPER_SNAKE =` outside `config/` |
|
|
50
50
|
|
|
@@ -121,6 +121,28 @@ def function_name(
|
|
|
121
121
|
|
|
122
122
|
---
|
|
123
123
|
|
|
124
|
+
## 6.5 FILE LENGTH GUIDANCE
|
|
125
|
+
|
|
126
|
+
File length is a **smell signal, not a hard threshold**. Long files often hide multiple responsibilities, but legitimately long files exist (migrations, generated code, registries, fixtures). The hook surfaces advisories instead of blocking.
|
|
127
|
+
|
|
128
|
+
**Two advisory thresholds (non-blocking, stderr only):**
|
|
129
|
+
|
|
130
|
+
| Threshold | Source basis | Hook behavior |
|
|
131
|
+
|-----------|--------------|---------------|
|
|
132
|
+
| `>= 400` lines | Robert C. Martin, *Clean Code* (2008), Ch. 5 "Formatting" — small files preferred; Martin Fowler, *Refactoring* — "Large Class" code smell | Soft advisory: "consider splitting" |
|
|
133
|
+
| `>= 1000` lines | pylint default `max-module-lines=1000`; SonarQube rule S104 default `1000` | Strong nudge: "exceeds widely-used static-analysis defaults" |
|
|
134
|
+
|
|
135
|
+
**What we deliberately reject:**
|
|
136
|
+
|
|
137
|
+
- **Hard numeric blocks** — Google's Python Style Guide imposes no file-length cap (only a ~40-line function review hint at https://google.github.io/styleguide/pyguide.html). A blocking rule produces false positives on legitimate cases.
|
|
138
|
+
- **A single magic number** — Different sources land at 200 (*Clean Code* preference), 750 (some SonarQube language profiles), or 1000 (pylint, Sonar Java). No source justifies a single universal cap.
|
|
139
|
+
|
|
140
|
+
**When to actually split:**
|
|
141
|
+
|
|
142
|
+
The size signal matters *because* of what it usually indicates: multiple responsibilities (Single Responsibility Principle — Robert C. Martin, *Agile Software Development*, 2002), poor cohesion (Steve McConnell, *Code Complete 2e*, 2004, Ch. 5–6), or the "Large Class" / "Long Function" smells (Fowler). Use the readability rubric (`~/.claude/skills/readability-review/SKILL.md`) when an advisory fires — split based on cohesion, not line count.
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
124
146
|
## 7. RIGHT-SIZED ENGINEERING
|
|
125
147
|
|
|
126
148
|
**Simple > Clever. Functions > Classes. Concrete > Abstract.**
|
|
@@ -175,7 +197,7 @@ Hook will enforce:
|
|
|
175
197
|
[⚡] No magic values
|
|
176
198
|
[⚡] Imports at top
|
|
177
199
|
[⚡] Logging format args
|
|
178
|
-
[
|
|
200
|
+
[ ] File length reasonable (advisory at 400, strong nudge at 1000 — see §6.5)
|
|
179
201
|
[⚡] Constants in config/
|
|
180
202
|
|
|
181
203
|
Manual check:
|
|
@@ -2,15 +2,17 @@
|
|
|
2
2
|
"""
|
|
3
3
|
CODE_RULES.md enforcer - blocks code that violates mandatory rules.
|
|
4
4
|
|
|
5
|
-
Checks (
|
|
5
|
+
Checks (blocking):
|
|
6
6
|
1. No comments (# or // in code, excluding shebangs/type: ignore)
|
|
7
7
|
2. Imports at top (no imports inside functions)
|
|
8
8
|
3. Logging f-strings (log_* calls must use format args)
|
|
9
|
-
4.
|
|
10
|
-
5.
|
|
11
|
-
6.
|
|
12
|
-
7.
|
|
13
|
-
|
|
9
|
+
4. Windows API None (win32gui calls with None parameter)
|
|
10
|
+
5. Magic values (literals in function bodies)
|
|
11
|
+
6. E2E test naming (no online/offline in test names)
|
|
12
|
+
7. Constants outside config (UPPER_SNAKE = in non-config files)
|
|
13
|
+
|
|
14
|
+
Advisory only (non-blocking):
|
|
15
|
+
- File line count: stderr warning at 400 lines (soft) and 1000 lines (hard)
|
|
14
16
|
"""
|
|
15
17
|
import json
|
|
16
18
|
import re
|
|
@@ -27,6 +29,9 @@ HOOK_INFRASTRUCTURE_PATTERNS = {"/.claude/hooks/", "\\.claude\\hooks\\", "\\.cla
|
|
|
27
29
|
WORKFLOW_REGISTRY_PATTERNS = {"/workflow/", "\\workflow\\", "_tab.py", "/states.py", "\\states.py", "/modules.py", "\\modules.py"}
|
|
28
30
|
MIGRATION_PATH_PATTERNS = {"/migrations/", "\\migrations\\"}
|
|
29
31
|
|
|
32
|
+
ADVISORY_LINE_THRESHOLD_SOFT = 400
|
|
33
|
+
ADVISORY_LINE_THRESHOLD_HARD = 1000
|
|
34
|
+
|
|
30
35
|
|
|
31
36
|
def get_file_extension(file_path: str) -> str:
|
|
32
37
|
"""Extract lowercase file extension."""
|
|
@@ -308,12 +313,27 @@ def check_logging_fstrings(content: str) -> list[str]:
|
|
|
308
313
|
return issues
|
|
309
314
|
|
|
310
315
|
|
|
311
|
-
def
|
|
312
|
-
"""
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
316
|
+
def advise_file_line_count(content: str, file_path: str) -> None:
|
|
317
|
+
"""Emit non-blocking stderr advisories when a file crosses size smell thresholds.
|
|
318
|
+
|
|
319
|
+
Thresholds are smell signals, not hard caps. See CODE_RULES.md "File length guidance"
|
|
320
|
+
for rationale. Soft threshold aligns with Clean Code Ch. 5 / Fowler "Large Class".
|
|
321
|
+
Hard threshold matches pylint default max-module-lines and SonarQube S104 default.
|
|
322
|
+
"""
|
|
323
|
+
line_count = len(content.splitlines())
|
|
324
|
+
if line_count >= ADVISORY_LINE_THRESHOLD_HARD:
|
|
325
|
+
print(
|
|
326
|
+
f"[CODE_RULES advisory] {file_path}: {line_count} lines - "
|
|
327
|
+
f"exceeds pylint/SonarQube default ({ADVISORY_LINE_THRESHOLD_HARD}); "
|
|
328
|
+
f"strongly consider splitting by responsibility (SRP / cohesion)",
|
|
329
|
+
file=sys.stderr,
|
|
330
|
+
)
|
|
331
|
+
elif line_count >= ADVISORY_LINE_THRESHOLD_SOFT:
|
|
332
|
+
print(
|
|
333
|
+
f"[CODE_RULES advisory] {file_path}: {line_count} lines - "
|
|
334
|
+
f"consider splitting (Clean Code Ch. 5; Fowler 'Large Class' smell)",
|
|
335
|
+
file=sys.stderr,
|
|
336
|
+
)
|
|
317
337
|
|
|
318
338
|
|
|
319
339
|
def check_windows_api_none(content: str) -> list[str]:
|
|
@@ -485,7 +505,7 @@ def validate_content(content: str, file_path: str, old_content: str = "") -> lis
|
|
|
485
505
|
all_issues.extend(check_e2e_test_naming(content, file_path))
|
|
486
506
|
|
|
487
507
|
if extension in ALL_CODE_EXTENSIONS:
|
|
488
|
-
|
|
508
|
+
advise_file_line_count(content, file_path)
|
|
489
509
|
|
|
490
510
|
return all_issues
|
|
491
511
|
|
package/package.json
CHANGED
|
@@ -62,8 +62,8 @@ The feedback loop: observe Claude B's behavior, bring insights back, refine the
|
|
|
62
62
|
|
|
63
63
|
When building a **new** skill as a **full package** (architecture inventory, progressive disclosure files, `evals/`, **human checkpoint after each file**), treat the following as **mandatory** before implementation:
|
|
64
64
|
|
|
65
|
-
- **Read:** `prompt-generator/templates/skill-from-ground-up.md`
|
|
66
|
-
- **Do:** Run `/prompt-generator`
|
|
65
|
+
- **Read:** the installed `@jl-cmd/prompt-generator` template `prompt-generator/templates/skill-from-ground-up.md` (upstream repository path: `skills/prompt-generator/templates/skill-from-ground-up.md` in [jl-cmd/prompt-generator](https://github.com/jl-cmd/prompt-generator)).
|
|
66
|
+
- **Do:** Run `/prompt-generator` using that installed template with the file’s token table filled so the downstream session follows architecture-first sequencing, per-file review gates, and eval rows tied only to user-pasted or explicitly approved evidence.
|
|
67
67
|
|
|
68
68
|
Use this **together with** gap-analysis and eval-scenario templates in this package; the ground-up template supplies the **orchestration contract** for the multi-file layout Anthropic recommends.
|
|
69
69
|
|
|
@@ -71,7 +71,7 @@ Use this **together with** gap-analysis and eval-scenario templates in this pack
|
|
|
71
71
|
|
|
72
72
|
When **improving** an existing skill as a **multi-file** or **checkpointed** package (baseline directory plus planned deltas, observation-grounded evals), treat the following as **mandatory** before Phase 2–6 file work in `improve-skill.md` or package-aware steps in `polish-skill.md`:
|
|
73
73
|
|
|
74
|
-
- **Read:** `prompt-generator/templates/skill-refinement-package.md` (repository path: `
|
|
74
|
+
- **Read:** `prompt-generator/templates/skill-refinement-package.md` (repository path: `skills/prompt-generator/templates/skill-refinement-package.md` in [jl-cmd/prompt-generator](https://github.com/jl-cmd/prompt-generator)).
|
|
75
75
|
- **Do:** Run `/prompt-generator` with that file’s token table filled (`[[BASELINE_SKILL_ROOT]]`, `[[WORKSPACE_ROOT]]`, observation gap path, evidence rule) so rollout stays architecture-first, delta-focused, and tied to real observation or approved excerpts.
|
|
76
76
|
|
|
77
77
|
Net-new packages without a baseline skill directory use `skill-from-ground-up.md` instead.
|
|
@@ -55,7 +55,7 @@ From here, follow the same phases as `${CLAUDE_SKILL_DIR}/workflows/new-skill.md
|
|
|
55
55
|
|
|
56
56
|
Whenever Phases 2–6 will touch **multiple files**, **progressive disclosure layout**, or use **checkpointed file-by-file rollout**, treat this as **required** before expanding or rewriting the tree:
|
|
57
57
|
|
|
58
|
-
1. Read `
|
|
58
|
+
1. Read `skill-refinement-package.md` from the installed prompt-generator skill, typically at `~/.claude/skills/prompt-generator/templates/skill-refinement-package.md` (source dependency: [jl-cmd/prompt-generator](https://github.com/jl-cmd/prompt-generator)).
|
|
59
59
|
2. Run `/prompt-generator` with that template’s token table filled: set `[[BASELINE_SKILL_ROOT]]` to the existing skill directory, `[[WORKSPACE_ROOT]]` to your iteration workspace (in-place or snapshot per user preference), and `[[DESIGN_INPUT_GLOB]]` to this workflow’s observation-based `gap-analysis.md` when it exists.
|
|
60
60
|
|
|
61
61
|
Use `skill-from-ground-up.md` **only** for **greenfield** packages where no baseline skill directory exists yet; use `skill-refinement-package.md` for every refinement anchored to an existing skill.
|
|
@@ -11,7 +11,7 @@ Full evaluation-driven lifecycle for building a new skill from scratch.
|
|
|
11
11
|
|
|
12
12
|
When the outcome includes **ARCHITECTURE.md**, **REFERENCE / EXAMPLES / WORKFLOWS**, and **`evals/*.json`** under a workspace (Anthropic-style progressive disclosure plus checkpointed rollout):
|
|
13
13
|
|
|
14
|
-
1. Read `prompt-generator/templates/skill-from-ground-up.md` from the claude
|
|
14
|
+
1. Read `prompt-generator/templates/skill-from-ground-up.md` from the installed `~/.claude/skills/` tree (provided by [@jl-cmd/prompt-generator](https://github.com/jl-cmd/prompt-generator)).
|
|
15
15
|
2. Run `/prompt-generator` using that template (substitute tokens per its table) **before** Phase 3 expands the repo; align the XML scope block with this workflow’s workspace and evidence rules.
|
|
16
16
|
3. Keep Phase 1–2 artifacts honest: eval prompts and expectations stay grounded in **real** user scenarios; the template reinforces eval rows that reference pasted or explicitly approved evidence only.
|
|
17
17
|
|
|
@@ -12,7 +12,7 @@ Final optimization pass for a skill that is functionally complete.
|
|
|
12
12
|
|
|
13
13
|
When the polish pass will touch **more than frontmatter alone** (for example `REFERENCE.md`, `EXAMPLES.md`, `WORKFLOWS.md`, link structure, or eval JSON), or the user wants **checkpointed** multi-file updates alongside description work:
|
|
14
14
|
|
|
15
|
-
1. Read `prompt-generator/templates/skill-refinement-package.md` (repository path: `
|
|
15
|
+
1. Read `prompt-generator/templates/skill-refinement-package.md` (repository path: `skills/prompt-generator/templates/skill-refinement-package.md` in [jl-cmd/prompt-generator](https://github.com/jl-cmd/prompt-generator)).
|
|
16
16
|
2. Run `/prompt-generator` with tokens filled so `ARCHITECTURE.md` records baseline inventory, planned deltas for polish, and evidence rules for any new trigger or behavior evals.
|
|
17
17
|
|
|
18
18
|
Purely **single-field** `description` edits with no structural package changes can skip this block.
|
|
@@ -36,7 +36,7 @@ When invoked with arguments (e.g. `/skill-writer improve this: [paste]`), treat
|
|
|
36
36
|
|
|
37
37
|
When the user is creating a **new** skill as a **package** (workspace with `ARCHITECTURE.md`, `REFERENCE.md`, `EXAMPLES.md`, `WORKFLOWS.md`, `evals/*.json`, per-file human review), **before** drafting `SKILL.md`:
|
|
38
38
|
|
|
39
|
-
1. Read `
|
|
39
|
+
1. Read `prompt-generator/templates/skill-from-ground-up.md` (installed layout: sibling folder under the same `skills/` parent; repository path: `skills/prompt-generator/templates/skill-from-ground-up.md` in [jl-cmd/prompt-generator](https://github.com/jl-cmd/prompt-generator)).
|
|
40
40
|
2. Ensure `/prompt-generator` has run with that template filled so architecture-first steps, checkpoint gates, and eval evidence rules are already agreed.
|
|
41
41
|
|
|
42
42
|
If the task is **only** editing an existing `SKILL.md` or a small single-file tweak, this subsection does not apply.
|
|
@@ -45,7 +45,7 @@ If the task is **only** editing an existing `SKILL.md` or a small single-file tw
|
|
|
45
45
|
|
|
46
46
|
When the user is **refining** an existing skill as a **package** (baseline skill directory, `ARCHITECTURE.md` with planned deltas, checkpointed updates to REFERENCE / EXAMPLES / WORKFLOWS / `evals/`), **before** rewriting multiple files:
|
|
47
47
|
|
|
48
|
-
1. Read `
|
|
48
|
+
1. Read `prompt-generator/templates/skill-refinement-package.md` (installed layout: under the same `skills/` parent; repository path: `skills/prompt-generator/templates/skill-refinement-package.md` in [jl-cmd/prompt-generator](https://github.com/jl-cmd/prompt-generator)).
|
|
49
49
|
2. Ensure `/prompt-generator` has run with that template filled so baseline root, workspace root, observation inputs, and evidence rules are fixed before edits proceed.
|
|
50
50
|
|
|
51
51
|
If the change set is a **small single-file** tweak, this subsection does not apply.
|