claude-dev-env 1.19.2 → 1.20.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 +16 -0
- package/bin/install.mjs +34 -1
- package/docs/BDD_DISCOVERY_PROTOCOL.md +53 -0
- package/docs/BDD_SCENARIO_QUALITY.md +89 -0
- package/docs/BDD_TEST_LAYOUT.md +71 -0
- package/docs/CODE_RULES.md +1 -208
- package/hooks/blocking/tdd-enforcer.py +3 -3
- package/package.json +5 -2
- package/rules/agent-spawn-protocol.md +1 -47
- package/rules/bdd.md +28 -0
- package/rules/cleanup-temp-files.md +1 -27
- package/rules/code-reviews.md +1 -11
- package/rules/code-standards.md +1 -43
- package/rules/conservative-action.md +1 -20
- package/rules/context7.md +1 -12
- package/rules/explore-thoroughly.md +1 -27
- package/rules/git-workflow.md +1 -42
- package/rules/parallel-tools.md +1 -23
- package/rules/research-mode.md +1 -23
- package/rules/right-sized-engineering.md +1 -28
- package/rules/self-contained-docs.md +1 -0
- package/rules/vault-context.md +1 -0
- package/rules/verify-before-asking.md +1 -0
- package/scripts/sync-to-cursor.py +22 -0
- package/scripts/sync_to_cursor/__init__.py +13 -0
- package/scripts/sync_to_cursor/canonical_docs.py +66 -0
- package/scripts/sync_to_cursor/config.py +5 -0
- package/scripts/sync_to_cursor/engine.py +194 -0
- package/scripts/sync_to_cursor/hashing.py +7 -0
- package/scripts/sync_to_cursor/paths.py +18 -0
- package/scripts/sync_to_cursor/rules.py +321 -0
- package/scripts/tests/test_sync_to_cursor.py +255 -0
- package/skills/bdd-protocol/SKILL.md +31 -0
- package/skills/bdd-protocol/references/anti-patterns.md +26 -0
- package/skills/bdd-protocol/references/example-mapping.md +23 -0
- package/skills/npm-creator/SKILL.md +3 -3
- package/skills/rule-audit/SKILL.md +2 -2
- 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/system-prompts/software-engineer.xml +387 -0
- package/rules/tdd.md +0 -7
package/CLAUDE.md
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Claude Development Assistant
|
|
2
|
+
|
|
3
|
+
Canonical behavior policy lives in `~/.claude/system-prompts/software-engineer.xml`.
|
|
4
|
+
|
|
5
|
+
## Canonical Pointers
|
|
6
|
+
|
|
7
|
+
- Code quality rules: `~/.claude/docs/CODE_RULES.md` (pointer to `<code_quality>`)
|
|
8
|
+
- Git workflow: `~/.claude/rules/git-workflow.md` (pointer to `<git_workflow>`)
|
|
9
|
+
- Development protocol: `<behavior_protocol>` in the system prompt; lean rule `~/.claude/rules/bdd.md`; on-demand `bdd-protocol` skill
|
|
10
|
+
- Tool usage and workflow: `<tool_usage>` and `<agent_workflow>` in the system prompt
|
|
11
|
+
|
|
12
|
+
## Additional Non-overlapping Rules
|
|
13
|
+
|
|
14
|
+
- Prompt workflow controls: `@~/.claude/rules/prompt-workflow-context-controls.md`
|
|
15
|
+
- Testing quality specifics: `@~/.claude/rules/testing.md`
|
|
16
|
+
- Path-scoped Tasklings preferences load automatically via `~/.claude/rules/tasklings-preferences.md`
|
package/bin/install.mjs
CHANGED
|
@@ -13,7 +13,7 @@ const MANIFEST_FILE = join(CLAUDE_HOME, '.claude-dev-env-manifest.json');
|
|
|
13
13
|
const PACKAGE_NAME = 'claude-dev-env';
|
|
14
14
|
const packageRequire = createRequire(import.meta.url);
|
|
15
15
|
|
|
16
|
-
const CONTENT_DIRECTORIES = ['rules', 'docs', 'commands', 'agents'];
|
|
16
|
+
const CONTENT_DIRECTORIES = ['rules', 'docs', 'commands', 'agents', 'system-prompts', 'scripts'];
|
|
17
17
|
|
|
18
18
|
function resolveDependencyPackageRoot(dependencyPackageName) {
|
|
19
19
|
const dependencyPackageJsonPath = packageRequire.resolve(
|
|
@@ -152,6 +152,23 @@ function copyTree(sourceBase, destBase) {
|
|
|
152
152
|
return stats;
|
|
153
153
|
}
|
|
154
154
|
|
|
155
|
+
/**
|
|
156
|
+
* If destPath exists and differs from incomingPath, copy the existing file to
|
|
157
|
+
* ~/.claude/backups/CLAUDE.md.<timestamp>.bak before the installer overwrites it.
|
|
158
|
+
*/
|
|
159
|
+
function backupClaudeHubBeforeOverwrite(destPath, incomingPath) {
|
|
160
|
+
if (!existsSync(destPath)) return null;
|
|
161
|
+
const existingBytes = readFileSync(destPath);
|
|
162
|
+
const incomingBytes = readFileSync(incomingPath);
|
|
163
|
+
if (existingBytes.equals(incomingBytes)) return null;
|
|
164
|
+
const backupsDir = join(CLAUDE_HOME, 'backups');
|
|
165
|
+
mkdirSync(backupsDir, { recursive: true });
|
|
166
|
+
const stamp = new Date().toISOString().replace(/[:.]/g, '-');
|
|
167
|
+
const backupPath = join(backupsDir, `CLAUDE.md.${stamp}.bak`);
|
|
168
|
+
copyFileSync(destPath, backupPath);
|
|
169
|
+
return backupPath;
|
|
170
|
+
}
|
|
171
|
+
|
|
155
172
|
function mergeHooks(hooksSourceRoot, pythonCommand) {
|
|
156
173
|
const hooksJsonPath = join(hooksSourceRoot, 'hooks', 'hooks.json');
|
|
157
174
|
if (!existsSync(hooksJsonPath)) return 0;
|
|
@@ -338,6 +355,19 @@ function install(selectedGroups) {
|
|
|
338
355
|
summary.hookGroups = totalHookGroups;
|
|
339
356
|
console.log(` Hook groups: ${totalHookGroups} merged into settings.json`);
|
|
340
357
|
}
|
|
358
|
+
const claudeHubSource = join(PACKAGE_ROOT, 'CLAUDE.md');
|
|
359
|
+
if (existsSync(claudeHubSource)) {
|
|
360
|
+
const claudeHubDest = join(CLAUDE_HOME, 'CLAUDE.md');
|
|
361
|
+
const backupPath = backupClaudeHubBeforeOverwrite(claudeHubDest, claudeHubSource);
|
|
362
|
+
if (backupPath) {
|
|
363
|
+
console.log(
|
|
364
|
+
` \u21bb ${relative(CLAUDE_HOME, backupPath)} (previous CLAUDE.md hub preserved)`
|
|
365
|
+
);
|
|
366
|
+
}
|
|
367
|
+
copyFileSync(claudeHubSource, claudeHubDest);
|
|
368
|
+
allInstalledFiles.push(claudeHubDest);
|
|
369
|
+
console.log(` \u2713 ${relative(CLAUDE_HOME, claudeHubDest)} (hub)`);
|
|
370
|
+
}
|
|
341
371
|
writeManifest(allInstalledFiles);
|
|
342
372
|
console.log(`\nInstalled ${PACKAGE_NAME}:`);
|
|
343
373
|
for (const directory of CONTENT_DIRECTORIES) {
|
|
@@ -423,6 +453,9 @@ Examples:
|
|
|
423
453
|
npx ${PACKAGE_NAME} --only prompt-generator,research
|
|
424
454
|
|
|
425
455
|
Install location: ~/.claude/
|
|
456
|
+
|
|
457
|
+
If ~/.claude/CLAUDE.md already exists and differs from the package copy, the installer
|
|
458
|
+
writes the previous contents to ~/.claude/backups/CLAUDE.md.<timestamp>.bak first.
|
|
426
459
|
`);
|
|
427
460
|
}
|
|
428
461
|
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# BDD Discovery Protocol
|
|
2
|
+
|
|
3
|
+
This protocol guides Claude through **Example Mapping** to discover test ideas from user requests before writing code. Work **breadth-first**: map rules, examples, and unknowns first; park unresolved questions instead of guessing. Based on Smart & Molak *BDD in Action* §6.4 and Dan North, "Introducing BDD" (2006).
|
|
4
|
+
|
|
5
|
+
> §6.4.2: "The team discuss the rules and asks for an example of each. Examples are often described using a short phrase that starts with the words 'The one where ...' This notation, originally described by Daniel Terhorst-North, is known as the 'Friends episode notation', from the 90s TV series of the same name."
|
|
6
|
+
|
|
7
|
+
> §6.4.4: "Questions that can't be answered immediately are noted as pink cards."
|
|
8
|
+
|
|
9
|
+
> §6.4.5: "Example Mapping sessions should be quite short; 25–30 minutes is usually enough to get through a story."
|
|
10
|
+
|
|
11
|
+
## Core algorithm
|
|
12
|
+
|
|
13
|
+
1. **State the rule or feature** — Restate until the rule is clearly defined. *Exit:* shared understanding of what we are exploring.
|
|
14
|
+
|
|
15
|
+
2. **Generate examples** — Produce 3–5 phrases using **"The one where …"** notation, simple to complex. *Exit:* examples cover the rule’s scope without duplicating the same case.
|
|
16
|
+
|
|
17
|
+
3. **Probe the first unchecked example** — Ask: *What if …?* *Is this always the case?* *Are there examples where this rule behaves differently?* *Exit:* all three probes asked for this example.
|
|
18
|
+
|
|
19
|
+
4. **Evaluate answers** — When a new rule emerges, return to Step 3 for that rule. New edge cases may become **new rules** (add 2–3 examples each). Questions you cannot answer become **parked items**. *Exit:* probes for this example are processed.
|
|
20
|
+
|
|
21
|
+
5. **Next example** — Repeat steps 3–4. *Exit:* all examples probed.
|
|
22
|
+
|
|
23
|
+
6. **Compile and confirm** — In steady state, present a full compile of rules, examples, and parking lot. Ask: "Does this Example Map cover the behavior you need? Any rules or examples to add, remove, or refine?" *Exit:* user confirms; exit when user confirms.
|
|
24
|
+
|
|
25
|
+
7. **Time-box and exit** — Keep discovery within ~25–30 minutes when possible; also **exit** when tests are under way or the session ends.
|
|
26
|
+
|
|
27
|
+
> "What to call your test is easy: it's a sentence describing the next behaviour in which you are interested." — Dan North (2006)
|
|
28
|
+
|
|
29
|
+
## Worked Example: Theme Asset Release Date Validation
|
|
30
|
+
|
|
31
|
+
- **Rule:** A theme asset must not go live before its configured release date.
|
|
32
|
+
- **Examples (the one where …):**
|
|
33
|
+
- … the release date is tomorrow and today’s import runs — should block or warn
|
|
34
|
+
- … the release date was last week — should allow publish
|
|
35
|
+
- … the release date field is empty — should use policy default
|
|
36
|
+
- … the release date is updated after a draft was already scheduled — should re-validate against policy
|
|
37
|
+
- **Probe:** *What if the server timezone is UTC but the editor is local?* → Surfaces a **new rule** about timezone for "release day."
|
|
38
|
+
- **New rule examples:** same calendar date in UTC vs local; DST boundary.
|
|
39
|
+
- **Parked:** certification API does not return a timezone — follow up with vendor.
|
|
40
|
+
|
|
41
|
+
## Using This Protocol
|
|
42
|
+
|
|
43
|
+
- State the business rule clearly
|
|
44
|
+
- Generate concrete examples (the one where ...)
|
|
45
|
+
- Probe each example with three question forms
|
|
46
|
+
- Capture open questions as a parked list for later resolution
|
|
47
|
+
- Compile and confirm the Example Map with the user
|
|
48
|
+
- Proceed to test writing only after user approval
|
|
49
|
+
|
|
50
|
+
## References
|
|
51
|
+
|
|
52
|
+
- Smart & Molak, *BDD in Action* 2e, Chapter 6, §6.4 (Example Mapping)
|
|
53
|
+
- Dan North, "Introducing BDD" (2006), https://dannorth.net/blog/introducing-bdd/
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# BDD Scenario Quality Guide
|
|
2
|
+
|
|
3
|
+
This guide defines the seven patterns that make scenarios clear, focused, and testable, enabling teams to align on business behavior, merge ideas from shared examples, and verify outcomes with automation and review.
|
|
4
|
+
|
|
5
|
+
Source: Smart & Molak, *BDD in Action* 2e, Chapter 7.6 — scenario quality patterns.
|
|
6
|
+
|
|
7
|
+
## Declarative Focus
|
|
8
|
+
|
|
9
|
+
Scenarios work best when they name what users want to achieve in the language of the business. Lead with goals and recognizable domain tasks so readers grasp intent at a glance. Reserve step-level or UI detail for places where it truly clarifies behavior.
|
|
10
|
+
|
|
11
|
+
> "Good scenarios model business behavior, not system interactions." — Smart & Molak §7.6.3
|
|
12
|
+
|
|
13
|
+
Good scenarios name user goals and tasks in domain language before any implementation detail.
|
|
14
|
+
|
|
15
|
+
## Single-Rule Focus
|
|
16
|
+
|
|
17
|
+
Each scenario tests one business rule. When a rule is complex or a scenario grows hard to read, split it into smaller scenarios that each test one aspect of the rule. That keeps failures pointing to a single behavior.
|
|
18
|
+
|
|
19
|
+
> "Good scenarios focus on testing a single business rule. If a business rule is complex, or if a scenario gets too big and hard to read, a good trick is to break the scenario into smaller, more focused ones that test a specific aspect of the rule." — Smart & Molak §7.6.4
|
|
20
|
+
|
|
21
|
+
Good scenarios isolate one rule so failures point to a single behavior.
|
|
22
|
+
|
|
23
|
+
### Example: hotel search (illustrates single-rule focus and declarative data)
|
|
24
|
+
|
|
25
|
+
This scenario shows one rule: search returns hotels within a distance threshold.
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
Scenario: Search for available hotels by distance
|
|
29
|
+
Given the following hotels:
|
|
30
|
+
| Hotel Name | Location | Distance from center |
|
|
31
|
+
| Ritz | Paris | 3.2 |
|
|
32
|
+
| Savoy | Paris | 6.9 |
|
|
33
|
+
| Hilton | Paris | 12.5 |
|
|
34
|
+
When I search for a hotel within 10 km of Paris
|
|
35
|
+
Then I should be presented with the following hotels:
|
|
36
|
+
| Hotel Name | Location | Distance from center |
|
|
37
|
+
| Ritz | Paris | 3.2 |
|
|
38
|
+
| Savoy | Paris | 6.9 |
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Meaningful Actors
|
|
42
|
+
|
|
43
|
+
Personas ground scenarios in realistic goals and context. Use light soap-opera personas when you need depth before full UX research: introduce names and roles as needed and deepen them across scenarios.
|
|
44
|
+
|
|
45
|
+
> Smart & Molak §7.6.5 describe personas as rich, realistic descriptions: each persona captures goals, abilities, and background information that ground the test scenario in a real user context.
|
|
46
|
+
|
|
47
|
+
Good scenarios name who acts and what they need in plain language.
|
|
48
|
+
|
|
49
|
+
## Essential Detail
|
|
50
|
+
|
|
51
|
+
Include columns and fields that affect the outcome; verify each column contributes, and simplify tables where values repeat or stay neutral to the result. Every visible value should earn its place in the example.
|
|
52
|
+
|
|
53
|
+
> Smart & Molak §7.6.6 — essential detail is information directly relevant to the business rule.
|
|
54
|
+
|
|
55
|
+
Good scenarios tie every field to a value that changes the outcome.
|
|
56
|
+
|
|
57
|
+
## State Clarity
|
|
58
|
+
|
|
59
|
+
When examples use data to illustrate behavior, spell out the starting situation and the expected end state in the same breath. Set up or reference test data so the system begins in the expected initial state before the action. Readers should always see both the before and after picture when data carries the story.
|
|
60
|
+
|
|
61
|
+
> "Well-written scenarios describe both behavior and data. When a scenario uses data to illustrate behavior, it should describe the initial state and the final state and manage or set up the test data to ensure that the system is in the expected initial state." — Smart & Molak §7.6.6
|
|
62
|
+
|
|
63
|
+
Good scenarios state initial and final state when data illustrates behavior.
|
|
64
|
+
|
|
65
|
+
## Outcome Description
|
|
66
|
+
|
|
67
|
+
Well-written scenarios state target outcomes in clear, measurable terms any reader can verify—business results observers can confirm directly in the Then steps.
|
|
68
|
+
|
|
69
|
+
> Smart & Molak §7.6.7 — scenarios state outcomes observers can confirm.
|
|
70
|
+
|
|
71
|
+
Good scenarios describe observable outcomes in domain terms.
|
|
72
|
+
|
|
73
|
+
## Independence
|
|
74
|
+
|
|
75
|
+
Each scenario sets up its own data and system state so it can run alone; give every scenario a self-contained setup so the suite passes in any run order. Every scenario carries its own setup and makes preconditions explicit.
|
|
76
|
+
|
|
77
|
+
> Smart & Molak §7.6.8 — independent scenarios work in isolation.
|
|
78
|
+
|
|
79
|
+
Good scenarios carry their own setup and expose every precondition needed to run in any order.
|
|
80
|
+
|
|
81
|
+
## Quick Reference
|
|
82
|
+
|
|
83
|
+
- ✓ Scenarios describe user goals and business tasks in domain terms
|
|
84
|
+
- ✓ Each scenario tests one business rule
|
|
85
|
+
- ✓ Actors have recognizable goals and context
|
|
86
|
+
- ✓ Tables and fields carry the information that affects the outcome
|
|
87
|
+
- ✓ Initial and final state are clear when data matters
|
|
88
|
+
- ✓ Outcomes are unambiguous and measurable
|
|
89
|
+
- ✓ Scenarios run independently with their own data
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# BDD Test Layout and Personas
|
|
2
|
+
|
|
3
|
+
Tests are **technical documentation**: they should read clearly when you return to the codebase after time away. Organize by **behavior and functional slice**, not necessarily by mirroring production file paths, when that aids navigation.
|
|
4
|
+
|
|
5
|
+
For future readers, tests read as documentation: names, grouping, and **should** sentences should make behavior discoverable without opening production code first.
|
|
6
|
+
|
|
7
|
+
> "Many organizations apply a looser association between test classes and production classes. … Test packages or directories organized in terms of functional slices are often easier to navigate." — Smart & Molak §16.5.5
|
|
8
|
+
|
|
9
|
+
> "Writing unit tests that make good technical documentation relies more on an attitude than on using a particular tool." — Smart & Molak §16.5.5
|
|
10
|
+
|
|
11
|
+
## Describe / when / should
|
|
12
|
+
|
|
13
|
+
- Outermost **describe** names the unit under test (component, module, or feature slice).
|
|
14
|
+
- Inner **describe** uses **When [context]** (or equivalent grouping) for the situation.
|
|
15
|
+
- **it** (or **test**) names start with **should** and state one observable outcome.
|
|
16
|
+
|
|
17
|
+
Dan North (2006): naming tests as sentences keeps focus on the **next behaviour** you care about.
|
|
18
|
+
|
|
19
|
+
## Soap-opera personas
|
|
20
|
+
|
|
21
|
+
When you lack full personas, introduce **short-lived characters** with a name and role and deepen them as scenarios grow—like a serial drama adding cast over episodes (Smart & Molak §7.6.5). Embed **\[Name], the \[role]** in scenario titles or setup where the actor changes behavior.
|
|
22
|
+
|
|
23
|
+
## Example (JavaScript-style)
|
|
24
|
+
|
|
25
|
+
```javascript
|
|
26
|
+
describe("PaymentProcessor", () => {
|
|
27
|
+
describe("When Carrie the compliance officer requests a refund for a disputed charge", () => {
|
|
28
|
+
it("should deduct the refund amount from the account balance", async () => {
|
|
29
|
+
const disputedChargeAmount = 150.0;
|
|
30
|
+
const refundResult = await processor.refund(carrieAccountId, disputedChargeAmount);
|
|
31
|
+
expect(refundResult.status).toBe("completed");
|
|
32
|
+
expect(refundResult.amount).toBe(disputedChargeAmount);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it("should create an audit record with a timestamp and initiator", async () => {
|
|
36
|
+
const disputedChargeAmount = 150.0;
|
|
37
|
+
const auditRecord = await processor.refund(carrieAccountId, disputedChargeAmount);
|
|
38
|
+
expect(auditRecord.timestamp).toBeDefined();
|
|
39
|
+
expect(auditRecord.initiator).toBe("carrie_compliance");
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
describe("When Barry the small business owner requests a refund", () => {
|
|
44
|
+
it("should send a confirmation notification within business hours", async () => {
|
|
45
|
+
const refundAmount = 500.0;
|
|
46
|
+
const confirmation = await processor.refund(barryAccountId, refundAmount);
|
|
47
|
+
expect(confirmation.notificationSent).toBe(true);
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Adapt naming to your test runner (pytest: functions; Jest/Vitest: `it`; JUnit: `@Test` methods with `should_` names).
|
|
54
|
+
|
|
55
|
+
## File organization
|
|
56
|
+
|
|
57
|
+
- Prefer **one file per feature slice** or user journey when it keeps related behaviours together.
|
|
58
|
+
- Split when files grow hard to scan; keep **should** names readable in lists and IDEs.
|
|
59
|
+
|
|
60
|
+
## Checklist
|
|
61
|
+
|
|
62
|
+
- [ ] Every test name reads as a **should** sentence for one outcome
|
|
63
|
+
- [ ] Groups use **When**-style context where it helps navigation
|
|
64
|
+
- [ ] Personas appear only when they change behaviour or clarity
|
|
65
|
+
- [ ] Tests do not mirror production folders if that obscures behaviour
|
|
66
|
+
- [ ] A new reader can understand intent without opening production code first
|
|
67
|
+
|
|
68
|
+
## References
|
|
69
|
+
|
|
70
|
+
- Smart & Molak, *BDD in Action* 2e, §16.5.5 (test layout), §7.6.5 (personas)
|
|
71
|
+
- Dan North, "Introducing BDD" (2006)
|
package/docs/CODE_RULES.md
CHANGED
|
@@ -1,208 +1 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
Compact reference for agents. Hook-enforced rules marked with ⚡.
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## COMMENT PRESERVATION (ABSOLUTE RULE)
|
|
8
|
-
|
|
9
|
-
**NEVER remove existing comments.** If you are not adding or removing code on a line, do not touch its comments.
|
|
10
|
-
|
|
11
|
-
- Existing comments are SACRED — never delete, rewrite, or "clean up" existing comments
|
|
12
|
-
- New inline comments are not needed — write self-documenting code instead
|
|
13
|
-
- Docstrings for new files/methods/classes are allowed
|
|
14
|
-
- The hook enforces BOTH directions: blocks new inline comments AND blocks deletion of existing comments
|
|
15
|
-
|
|
16
|
-
**Scope:** Only evaluate comments on lines YOU are actively changing. If code is untouched, its comments are untouched.
|
|
17
|
-
|
|
18
|
-
---
|
|
19
|
-
|
|
20
|
-
## CORE PRINCIPLES
|
|
21
|
-
|
|
22
|
-
### Self-Documenting Code
|
|
23
|
-
New code explains itself through naming. Do not add new inline comments — use descriptive names instead. Docstrings on functions/methods/classes are allowed.
|
|
24
|
-
|
|
25
|
-
> **Full readability standard:** `~/.claude/skills/readability-review/SKILL.md` — 8-dimension rubric (naming, SRP, abstraction, control flow, domain language, call sites, state clarity, visual rhythm). Run `/check` for parallel team review or `/readability-review` standalone.
|
|
26
|
-
|
|
27
|
-
### Centralized Configuration
|
|
28
|
-
One source of truth. Every constant lives in ONE place (`config/`).
|
|
29
|
-
|
|
30
|
-
### Reuse Before Create
|
|
31
|
-
Search first. Import second. Create last.
|
|
32
|
-
|
|
33
|
-
### Encapsulation Enables Cleaner Naming
|
|
34
|
-
Expose constants via helper functions: `isMaxLevel(level)` > `level >= MAXIMUM_LEVEL`
|
|
35
|
-
|
|
36
|
-
---
|
|
37
|
-
|
|
38
|
-
## ⚡ HOOK-ENFORCED RULES
|
|
39
|
-
|
|
40
|
-
These rules are automatically enforced by `code-rules-enforcer.py`. Violations block Write/Edit.
|
|
41
|
-
|
|
42
|
-
| Rule | What's Checked |
|
|
43
|
-
|------|----------------|
|
|
44
|
-
| No NEW comments | `#` / `//` in new code only (existing comments NEVER removed; shebangs, type:, noqa, eslint, docstrings exempt) |
|
|
45
|
-
| Imports at top | No `import` inside function bodies |
|
|
46
|
-
| Logging format args | No `log_*(f"...")` - use `log_*("...", arg)` |
|
|
47
|
-
| File line count | Advisory only — see [File length guidance](#65-file-length-guidance) |
|
|
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
|
-
| Constants location | No `UPPER_SNAKE =` outside `config/` |
|
|
50
|
-
|
|
51
|
-
---
|
|
52
|
-
|
|
53
|
-
## 3. REUSE CONSTANTS (DRY CONFIG)
|
|
54
|
-
|
|
55
|
-
**Before writing ANY constant:**
|
|
56
|
-
|
|
57
|
-
```bash
|
|
58
|
-
# Find config files
|
|
59
|
-
# Search your project for existing config files before creating new ones
|
|
60
|
-
|
|
61
|
-
# Search for value
|
|
62
|
-
grep -r "VALUE" config/
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
**Decision tree:**
|
|
66
|
-
1. Search exact value → Found? → IMPORT IT
|
|
67
|
-
2. Search semantic match → Found? → USE EXISTING NAME
|
|
68
|
-
3. Config file exists? → ADD TO EXISTING
|
|
69
|
-
4. Create new (rare)
|
|
70
|
-
|
|
71
|
-
---
|
|
72
|
-
|
|
73
|
-
## 4. CONFIG LOCATIONS
|
|
74
|
-
|
|
75
|
-
| Constant Type | Location |
|
|
76
|
-
|---------------|----------|
|
|
77
|
-
| Timeouts, delays, retries | `config/timing.py` |
|
|
78
|
-
| Ports, URLs, thresholds | `config/constants.py` |
|
|
79
|
-
| CSS selectors | `config/selectors.py` |
|
|
80
|
-
|
|
81
|
-
---
|
|
82
|
-
|
|
83
|
-
## 5. NO ABBREVIATIONS
|
|
84
|
-
|
|
85
|
-
Full words only. No mental translation.
|
|
86
|
-
|
|
87
|
-
| Bad | Good |
|
|
88
|
-
|-----|------|
|
|
89
|
-
| `ctx`, `cfg`, `msg` | `context`, `configuration`, `message` |
|
|
90
|
-
| `btn`, `idx`, `cnt` | `button`, `index`, `count` |
|
|
91
|
-
| `tmp`, `elem`, `val` | `temporary_value`, `element`, `value` |
|
|
92
|
-
|
|
93
|
-
**Exception:** `i`, `j`, `k` in loops; `e` for exception.
|
|
94
|
-
|
|
95
|
-
**Extended naming rules** (from readability-review rubric):
|
|
96
|
-
- Loop vars: `each_order`, `each_user` (prefix `each_`)
|
|
97
|
-
- Booleans: `is_valid`, `has_permission`, `should_retry` (prefix `is_`/`has_`/`should_`/`can_`)
|
|
98
|
-
- Collections: `all_orders`, `all_users` (prefix `all_`)
|
|
99
|
-
- Maps: `price_by_product`, `user_by_id` (pattern `X_by_Y`)
|
|
100
|
-
- Preposition params: `from_path=`, `to=`, `into=`
|
|
101
|
-
- **Banned names:** `result`, `data`, `output`, `response`, `value`, `item`, `temp`
|
|
102
|
-
- **Banned prefixes:** `handle`, `process`, `manage`, `do`
|
|
103
|
-
|
|
104
|
-
---
|
|
105
|
-
|
|
106
|
-
## 6. COMPLETE TYPE HINTS
|
|
107
|
-
|
|
108
|
-
```python
|
|
109
|
-
def function_name(
|
|
110
|
-
parameter: str,
|
|
111
|
-
optional: Optional[str] = None,
|
|
112
|
-
) -> ReturnType:
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
- ALL parameters typed
|
|
116
|
-
- ALL returns typed
|
|
117
|
-
- No `Any` type
|
|
118
|
-
- No `# type: ignore`
|
|
119
|
-
|
|
120
|
-
*(Also enforced by mypy_validator.py hook)*
|
|
121
|
-
|
|
122
|
-
---
|
|
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
|
-
|
|
146
|
-
## 7. RIGHT-SIZED ENGINEERING
|
|
147
|
-
|
|
148
|
-
**Simple > Clever. Functions > Classes. Concrete > Abstract.**
|
|
149
|
-
|
|
150
|
-
Never: ABC for single impl, DI frameworks, factory for single type
|
|
151
|
-
Always: Functions when no state, concrete classes, simple imports
|
|
152
|
-
|
|
153
|
-
---
|
|
154
|
-
|
|
155
|
-
## 8. TDD PROCESS
|
|
156
|
-
|
|
157
|
-
1. **RED** - Failing test first
|
|
158
|
-
2. **GREEN** - Minimum code to pass
|
|
159
|
-
3. **REFACTOR** - Only if valuable
|
|
160
|
-
|
|
161
|
-
---
|
|
162
|
-
|
|
163
|
-
## 9. SELF-CONTAINED COMPONENTS
|
|
164
|
-
|
|
165
|
-
Components own their complete feature. Parents just render `<Child />`.
|
|
166
|
-
|
|
167
|
-
Child handles: state, modals, overlays, toasts
|
|
168
|
-
Parent knows: nothing about child's internals
|
|
169
|
-
|
|
170
|
-
---
|
|
171
|
-
|
|
172
|
-
## 10. NO REDUNDANT DATA FETCHES
|
|
173
|
-
|
|
174
|
-
If you already have data, don't fetch again.
|
|
175
|
-
|
|
176
|
-
```typescript
|
|
177
|
-
// BAD
|
|
178
|
-
const profile = await getProfile();
|
|
179
|
-
const localProfile = await db.profile.first(); // same data!
|
|
180
|
-
|
|
181
|
-
// GOOD
|
|
182
|
-
const profile = await db.profile.first();
|
|
183
|
-
// ... use profile throughout ...
|
|
184
|
-
```
|
|
185
|
-
|
|
186
|
-
---
|
|
187
|
-
|
|
188
|
-
## QUICK CHECKLIST
|
|
189
|
-
|
|
190
|
-
```
|
|
191
|
-
Before ANY code:
|
|
192
|
-
[ ] Searched existing configs?
|
|
193
|
-
[ ] Importing from centralized config?
|
|
194
|
-
|
|
195
|
-
Hook will enforce:
|
|
196
|
-
[⚡] No NEW comments (existing comments NEVER removed)
|
|
197
|
-
[⚡] No magic values
|
|
198
|
-
[⚡] Imports at top
|
|
199
|
-
[⚡] Logging format args
|
|
200
|
-
[ ] File length reasonable (advisory at 400, strong nudge at 1000 — see §6.5)
|
|
201
|
-
[⚡] Constants in config/
|
|
202
|
-
|
|
203
|
-
Manual check:
|
|
204
|
-
[ ] No abbreviations?
|
|
205
|
-
[ ] Complete type hints?
|
|
206
|
-
[ ] Self-contained components?
|
|
207
|
-
[ ] Readability: /check or /readability-review
|
|
208
|
-
```
|
|
1
|
+
# CODE_RULES pointer: canonical code-quality policy lives in `~/.claude/system-prompts/software-engineer.xml` under `<code_quality>`.
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
2
|
"""
|
|
3
|
-
|
|
3
|
+
BDD Automate-phase reminder (production code touch).
|
|
4
4
|
|
|
5
|
-
Prompts confirmation when writing
|
|
5
|
+
Prompts confirmation when writing or editing production code files.
|
|
6
6
|
Skips: Test files, config files, documentation.
|
|
7
7
|
"""
|
|
8
8
|
import json
|
|
@@ -51,7 +51,7 @@ def main() -> None:
|
|
|
51
51
|
"hookSpecificOutput": {
|
|
52
52
|
"hookEventName": "PreToolUse",
|
|
53
53
|
"permissionDecision": "allow",
|
|
54
|
-
"additionalContext": "[
|
|
54
|
+
"additionalContext": "[BDD] Writing production code. Confirm you have a failing specification (test) first."
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
57
|
print(json.dumps(result))
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-dev-env",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.20.1",
|
|
4
4
|
"description": "Claude Code development standards — rules, hooks, agents, commands, and skills",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -13,7 +13,10 @@
|
|
|
13
13
|
"commands/",
|
|
14
14
|
"agents/",
|
|
15
15
|
"skills/",
|
|
16
|
-
"hooks/"
|
|
16
|
+
"hooks/",
|
|
17
|
+
"system-prompts/",
|
|
18
|
+
"scripts/",
|
|
19
|
+
"CLAUDE.md"
|
|
17
20
|
],
|
|
18
21
|
"keywords": [
|
|
19
22
|
"claude-code",
|
|
@@ -1,47 +1 @@
|
|
|
1
|
-
# Agent
|
|
2
|
-
|
|
3
|
-
**When this applies:** Before any Agent or Task tool invocation (Explore, implementation, research, or team subagents).
|
|
4
|
-
|
|
5
|
-
<agent_spawn_protocol>
|
|
6
|
-
|
|
7
|
-
## Before spawning ANY agent — no exceptions
|
|
8
|
-
|
|
9
|
-
Every Agent and Task tool call must follow this protocol. This includes Explore agents, research agents, execution agents, and team members.
|
|
10
|
-
|
|
11
|
-
### Step 1: Context sufficiency check
|
|
12
|
-
|
|
13
|
-
Before writing any agent prompt, verify you can answer all of these:
|
|
14
|
-
- [ ] What specific files, directories, or areas of the codebase are involved?
|
|
15
|
-
- [ ] What constraints apply? (patterns to follow, things NOT to change, boundaries)
|
|
16
|
-
- [ ] What does success look like? (expected output, acceptance criteria)
|
|
17
|
-
- [ ] Is the task unambiguous enough to delegate?
|
|
18
|
-
|
|
19
|
-
If ANY answer is "I don't know" -- investigate first (read files, search code) or ask the user. Do NOT spawn with incomplete context.
|
|
20
|
-
|
|
21
|
-
### Step 2: Craft the prompt with /prompt-generator
|
|
22
|
-
|
|
23
|
-
Run the `/prompt-generator` skill to produce a structured prompt. Feed it:
|
|
24
|
-
- The task description and goal
|
|
25
|
-
- Target files/directories discovered in Step 1
|
|
26
|
-
- Constraints and boundaries
|
|
27
|
-
- Expected output format
|
|
28
|
-
- Acceptance criteria
|
|
29
|
-
|
|
30
|
-
The skill will ask 1-3 clarifying questions if information is missing -- this is the built-in context verification.
|
|
31
|
-
|
|
32
|
-
Use the skill's output as the agent's `prompt` parameter.
|
|
33
|
-
|
|
34
|
-
### Step 3: Spawn the agent
|
|
35
|
-
|
|
36
|
-
Pass the structured prompt from Step 2 to the Agent/Task tool.
|
|
37
|
-
|
|
38
|
-
</agent_spawn_protocol>
|
|
39
|
-
|
|
40
|
-
## Why
|
|
41
|
-
|
|
42
|
-
Agents receiving vague prompts waste tokens exploring in circles, produce code that misses constraints, and require expensive rework. A 30-second investment in prompt quality via /prompt-generator saves 5-minute agent failures. This applies equally to Explore agents (which waste context on unfocused searches) and execution agents (which write wrong code).
|
|
43
|
-
|
|
44
|
-
## Relationship to other rules
|
|
45
|
-
|
|
46
|
-
- **conservative-action.md** gates acting when ambiguous. This extends that: do not delegate when the task is ambiguous—investigate or ask the user first.
|
|
47
|
-
- Project-specific rules or `~/.claude/CLAUDE.md` may define *whether* to use subagents or teams; this rule governs *how* to craft prompts when you do delegate.
|
|
1
|
+
# Agent-spawn-protocol pointer: canonical policy lives in `~/.claude/system-prompts/software-engineer.xml` under `<agent_workflow>`.
|
package/rules/bdd.md
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# BDD (discovery-driven development)
|
|
2
|
+
|
|
3
|
+
**Canonical detail:** `~/.claude/system-prompts/software-engineer.xml` → `<behavior_protocol>`.
|
|
4
|
+
|
|
5
|
+
**On-demand depth:** `@~/.claude/skills/bdd-protocol/SKILL.md` (Example Mapping §6.4, §7.6 catalog, solo patterns). Tracking design: [jl-cmd/claude-code-config#82](https://github.com/jl-cmd/claude-code-config/issues/82).
|
|
6
|
+
|
|
7
|
+
**Optional long-form references (load when needed):**
|
|
8
|
+
|
|
9
|
+
- `@~/.claude/docs/BDD_SCENARIO_QUALITY.md` — seven scenario quality patterns (§7.6-style)
|
|
10
|
+
- `@~/.claude/docs/BDD_DISCOVERY_PROTOCOL.md` — Example Mapping algorithm for chat
|
|
11
|
+
- `@~/.claude/docs/BDD_TEST_LAYOUT.md` — describe/when/should layout and soap-opera personas
|
|
12
|
+
|
|
13
|
+
## What you do for every non-trivial feature
|
|
14
|
+
|
|
15
|
+
1. **Deliberate Discovery** — Reduce uncertainty before code; surface what you do not know (Smart & Molak §5.4).
|
|
16
|
+
2. **Illustrate** — Explore goals, constraints, and concrete examples in chat; "given … when … then …" style outcomes.
|
|
17
|
+
3. **Formulate** — Express behavior as narrow **"should …"** specifications the user can approve.
|
|
18
|
+
4. **Automate** — Failing specification first, then minimum code to pass; refactor only for a concrete smell.
|
|
19
|
+
|
|
20
|
+
Conversation is the essential practice: if discovery is skipped, structured formats do not rescue the workflow (Minimal BDD).
|
|
21
|
+
|
|
22
|
+
## Solo developer
|
|
23
|
+
|
|
24
|
+
You are often the stakeholder. Use **Example Mapping** in chat ("the one where …", probes, parking lot). Load **`bdd-protocol`** when you need the full algorithm and anti-pattern list.
|
|
25
|
+
|
|
26
|
+
## Naming
|
|
27
|
+
|
|
28
|
+
Developer-facing specs and tests use **should** sentences so intent stays visible (Dan North, "Introducing BDD", 2006).
|
|
@@ -1,27 +1 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
**When this applies:** After tasks that created scratch files, debug dumps, or one-off scripts the user did not ask to keep.
|
|
4
|
-
|
|
5
|
-
Source: [Anthropic — Reduce file creation in agentic coding](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/claude-prompting-best-practices#reduce-file-creation-in-agentic-coding)
|
|
6
|
-
|
|
7
|
-
## During a task
|
|
8
|
-
|
|
9
|
-
- Prefer working in memory over creating scratchpad files. Use variables and tool results instead of writing intermediate data to disk.
|
|
10
|
-
- When a temporary file is genuinely needed (e.g., a helper script, a test fixture, a debug output), track it mentally for cleanup.
|
|
11
|
-
|
|
12
|
-
## When a task is complete
|
|
13
|
-
|
|
14
|
-
- Remove every temporary file, script, or helper file you created during the task.
|
|
15
|
-
- Leave the working directory cleaner than you found it.
|
|
16
|
-
- If a file was created at the user's explicit request (not as a byproduct of your process), leave it in place.
|
|
17
|
-
|
|
18
|
-
## What counts as temporary
|
|
19
|
-
|
|
20
|
-
- Scripts written to test a hypothesis or run a one-off check
|
|
21
|
-
- Debug output files, log dumps, or intermediate data exports
|
|
22
|
-
- Helper files created to work around tool limitations
|
|
23
|
-
- Any file the user did not ask for and would not expect to find after the task
|
|
24
|
-
|
|
25
|
-
## Why
|
|
26
|
-
|
|
27
|
-
Temporary files accumulate across sessions and clutter the project root. Latest models sometimes use files as scratchpads during iteration, and these leftovers confuse both the user and future sessions if not cleaned up.
|
|
1
|
+
# Cleanup-temp-files pointer: canonical policy lives in `~/.claude/system-prompts/software-engineer.xml` under `<cleanup>`.
|
package/rules/code-reviews.md
CHANGED
|
@@ -1,11 +1 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
**When this applies:** GitHub PR review feedback on a branch you are fixing.
|
|
4
|
-
|
|
5
|
-
**MANDATORY PROTOCOL (use pr-review-responder skill):**
|
|
6
|
-
|
|
7
|
-
1. Fetch ALL reviewer comments BEFORE any fixes
|
|
8
|
-
2. Create TodoWrite checklist - One item per comment
|
|
9
|
-
3. Fix systematically - Mark each todo complete
|
|
10
|
-
4. Reply to EACH comment inline
|
|
11
|
-
5. Create ONE review fix commit - DO NOT squash with original
|
|
1
|
+
# Code-reviews pointer: canonical policy lives in `~/.claude/system-prompts/software-engineer.xml` under `<code_review_response>`.
|