@neikyun/ciel 6.11.2 → 6.13.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/assets/.claude/agents/ciel-critic.md +71 -12
- package/assets/.claude/agents/ciel-explorer.md +59 -18
- package/assets/.claude/agents/ciel-improver.md +6 -3
- package/assets/.claude/agents/ciel-researcher.md +85 -25
- package/assets/.claude/hooks/block-destructive.sh +2 -2
- package/assets/.claude/hooks/check-test-first.sh +2 -2
- package/assets/.claude/hooks/memory-bootstrap.sh +0 -0
- package/assets/.claude/hooks/memory-engine.py +82 -15
- package/assets/.claude/hooks/post-tool-write.sh +32 -0
- package/assets/.claude/hooks/pre-agent-gate.sh +11 -6
- package/assets/.claude/hooks/pre-compact.sh +18 -0
- package/assets/.claude/hooks/pre-tool-write.sh +56 -31
- package/assets/.claude/hooks/session-start.sh +22 -1
- package/assets/.claude/hooks/session-version-check.sh +1 -1
- package/assets/.claude/hooks/stop.sh +104 -0
- package/assets/.claude/hooks/subagent-stop.sh +54 -0
- package/assets/.claude/hooks/track-file.sh +2 -2
- package/assets/.claude/hooks/user-prompt-submit.sh +11 -15
- package/assets/.claude/settings.json +18 -4
- package/assets/AGENTS.md +1 -1
- package/assets/CLAUDE.md +103 -175
- package/assets/commands/ciel-audit.md +58 -399
- package/assets/commands/ciel-create-skill.md +24 -38
- package/assets/commands/ciel-eval.md +25 -37
- package/assets/commands/ciel-init.md +36 -126
- package/assets/commands/ciel-status.md +22 -19
- package/assets/commands/ciel-update.md +20 -39
- package/assets/platforms/opencode/.opencode/agents/ciel-researcher.md +71 -895
- package/assets/platforms/opencode/.opencode/commands/ciel-audit.md +58 -296
- package/assets/platforms/opencode/.opencode/commands/ciel-create-skill.md +24 -46
- package/assets/platforms/opencode/.opencode/commands/ciel-eval.md +25 -45
- package/assets/platforms/opencode/.opencode/commands/ciel-init.md +36 -131
- package/assets/platforms/opencode/.opencode/commands/ciel-status.md +22 -24
- package/assets/platforms/opencode/.opencode/commands/ciel-update.md +20 -40
- package/assets/platforms/opencode/AGENTS.md +4 -4
- package/assets/rules/security.md +30 -0
- package/assets/rules/testing.md +23 -0
- package/assets/skills/agile/SKILL.md +42 -0
- package/assets/skills/alerting/SKILL.md +55 -0
- package/assets/skills/api-design/SKILL.md +46 -0
- package/assets/skills/appsec/SKILL.md +43 -0
- package/assets/skills/architecture/SKILL.md +74 -0
- package/assets/skills/backend/SKILL.md +41 -0
- package/assets/skills/backup-recovery/SKILL.md +42 -0
- package/assets/skills/caching/SKILL.md +44 -0
- package/assets/skills/cdn/SKILL.md +42 -0
- package/assets/skills/chaos/SKILL.md +41 -0
- package/assets/skills/cicd-pipeline/SKILL.md +56 -0
- package/assets/skills/cloud/SKILL.md +42 -0
- package/assets/skills/code-quality/SKILL.md +42 -0
- package/assets/skills/code-review/SKILL.md +41 -0
- package/assets/skills/communication/SKILL.md +42 -0
- package/assets/skills/containers/SKILL.md +42 -0
- package/assets/skills/cqrs/SKILL.md +41 -0
- package/assets/skills/crypto/SKILL.md +46 -0
- package/assets/skills/data-engineering/SKILL.md +42 -0
- package/assets/skills/database-design/SKILL.md +46 -0
- package/assets/skills/ddd/SKILL.md +45 -0
- package/assets/skills/deployment-strategies/SKILL.md +51 -0
- package/assets/skills/desktop/SKILL.md +42 -0
- package/assets/skills/devsecops/SKILL.md +43 -0
- package/assets/skills/event-driven/SKILL.md +46 -0
- package/assets/skills/frontend/SKILL.md +41 -0
- package/assets/skills/functional/SKILL.md +42 -0
- package/assets/skills/high-availability/SKILL.md +42 -0
- package/assets/skills/iac/SKILL.md +46 -0
- package/assets/skills/logging/SKILL.md +46 -0
- package/assets/skills/meta/ciel-improve/SKILL.md +127 -0
- package/assets/skills/meta/learnings-capture/SKILL.md +105 -0
- package/assets/skills/meta/patch-spec/patch-spec.md +50 -0
- package/assets/skills/meta/skill-creator/SKILL.md +115 -0
- package/assets/skills/meta/skill-freshness-auditor/SKILL.md +164 -0
- package/assets/skills/meta/skill-variant-evaluator/SKILL.md +100 -0
- package/assets/skills/meta/skills-first-design-auditor/SKILL.md +192 -0
- package/assets/skills/ml-engineering/SKILL.md +42 -0
- package/assets/skills/mobile/SKILL.md +42 -0
- package/assets/skills/monitoring/SKILL.md +54 -0
- package/assets/skills/networking/SKILL.md +42 -0
- package/assets/skills/nosql/SKILL.md +41 -0
- package/assets/skills/oop-solid/SKILL.md +42 -0
- package/assets/skills/performance/SKILL.md +41 -0
- package/assets/skills/reactive/SKILL.md +42 -0
- package/assets/skills/release-management/SKILL.md +51 -0
- package/assets/skills/research/fact-check-claims/SKILL.md +98 -0
- package/assets/skills/research/research-forums/SKILL.md +103 -0
- package/assets/skills/research/research-github-issues/SKILL.md +103 -0
- package/assets/skills/research/research-web-sources/SKILL.md +108 -0
- package/assets/skills/research/synthesize-findings/SKILL.md +112 -0
- package/assets/skills/research/validate-source-credibility/SKILL.md +103 -0
- package/assets/skills/resilience/SKILL.md +41 -0
- package/assets/skills/serverless/SKILL.md +42 -0
- package/assets/skills/servers/SKILL.md +41 -0
- package/assets/skills/sql/SKILL.md +45 -0
- package/assets/skills/supply-chain/SKILL.md +41 -0
- package/assets/skills/system-design/SKILL.md +91 -0
- package/assets/skills/tech-leadership/SKILL.md +46 -0
- package/assets/skills/testing/SKILL.md +41 -0
- package/assets/skills/tracing/SKILL.md +36 -0
- package/assets/skills/utility/branch-cleaner/SKILL.md +195 -0
- package/assets/skills/utility/branch-setup/SKILL.md +144 -0
- package/assets/skills/utility/changelog-updater/SKILL.md +125 -0
- package/assets/skills/utility/commit-writer/SKILL.md +154 -0
- package/assets/skills/utility/issue-closer/SKILL.md +106 -0
- package/assets/skills/utility/issue-creator/SKILL.md +200 -0
- package/assets/skills/utility/pr-merger/SKILL.md +189 -0
- package/assets/skills/utility/pr-opener/SKILL.md +180 -0
- package/assets/skills/utility/release-publisher/SKILL.md +224 -0
- package/assets/skills/workflow/ciel-dev-process/SKILL.md +94 -0
- package/assets/skills/workflow/faire-gatekeeper/SKILL.md +3 -1
- package/assets/skills/workflow/prouver-verifier/SKILL.md +11 -2
- package/dist/cli/check.d.ts.map +1 -1
- package/dist/cli/check.js +11 -2
- package/dist/cli/check.js.map +1 -1
- package/dist/cli/claude.d.ts.map +1 -1
- package/dist/cli/claude.js +0 -2
- package/dist/cli/claude.js.map +1 -1
- package/dist/cli/init.d.ts.map +1 -1
- package/dist/cli/init.js +11 -2
- package/dist/cli/init.js.map +1 -1
- package/dist/cli/opencode.d.ts.map +1 -1
- package/dist/cli/opencode.js +2 -1
- package/dist/cli/opencode.js.map +1 -1
- package/package.json +1 -1
- package/assets/commands/ciel-migrate.md +0 -35
- package/assets/commands/ciel-refresh.md +0 -91
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: skill-variant-evaluator
|
|
3
|
+
description: AutoResearch eval runner that generates 2-3 variants of a skill, executes them headlessly against binary eval datasets, compares aggregate scores, and proposes the winner with tiebreak on token usage. Use when /ciel-eval is invoked or when ciel-improve needs to pick between candidate rewrites.
|
|
4
|
+
allowed-tools: Read, Bash, Glob
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# skill-variant-evaluator — AutoResearch eval harness
|
|
8
|
+
|
|
9
|
+
## What this covers
|
|
10
|
+
Implements Karpathy-style AutoResearch for Ciel skills: define binary evals, run variants, compare scores, keep the winner.
|
|
11
|
+
|
|
12
|
+
## Core principle
|
|
13
|
+
**Binary evals, not vibes.** Every skill improvement is measured against concrete pass/fail criteria. The variant with the highest score wins.
|
|
14
|
+
|
|
15
|
+
## Inputs
|
|
16
|
+
|
|
17
|
+
- **skill-path**: path to `SKILL.md`
|
|
18
|
+
- **variants** (optional): 2-3 candidate SKILL.md contents
|
|
19
|
+
- **dataset**: eval dataset in `evals/datasets/<name>.jsonl`
|
|
20
|
+
- **baseline-only**: boolean — only score current skill, no variants
|
|
21
|
+
|
|
22
|
+
## Process
|
|
23
|
+
|
|
24
|
+
### 1. Locate eval dataset
|
|
25
|
+
|
|
26
|
+
Look for `evals/datasets/<skill-name>.jsonl`. If missing, warn and exit.
|
|
27
|
+
|
|
28
|
+
### 2. Load variants
|
|
29
|
+
|
|
30
|
+
- Variant A: current SKILL.md (baseline)
|
|
31
|
+
- Variants B, C: alternatives provided or from `variants/`
|
|
32
|
+
|
|
33
|
+
### 3. Execute each variant headlessly
|
|
34
|
+
|
|
35
|
+
For each variant:
|
|
36
|
+
1. Write to `SKILL.md.eval.<letter>`
|
|
37
|
+
2. For each eval entry, run `claude --print` with the eval prompt
|
|
38
|
+
3. Capture output + token usage + duration
|
|
39
|
+
4. Score against `expected_behavior` criteria (binary per criterion)
|
|
40
|
+
|
|
41
|
+
### 4. Aggregate scores
|
|
42
|
+
|
|
43
|
+
`aggregate = sum(criteria_passed) / total_criteria`
|
|
44
|
+
|
|
45
|
+
Winner = highest aggregate. Tiebreak: lowest total token usage.
|
|
46
|
+
|
|
47
|
+
### 5. Persist results
|
|
48
|
+
|
|
49
|
+
Write to `evals/results/<skill-name>-<timestamp>.json`.
|
|
50
|
+
|
|
51
|
+
## Common patterns
|
|
52
|
+
|
|
53
|
+
### Good eval result
|
|
54
|
+
|
|
55
|
+
```
|
|
56
|
+
# Skill variant evaluation — flux-narrator
|
|
57
|
+
|
|
58
|
+
Dataset: evals/datasets/flux-narration.jsonl (8 entries)
|
|
59
|
+
|
|
60
|
+
| Variant | Score | Tokens | Duration |
|
|
61
|
+
|---------|-------|--------|----------|
|
|
62
|
+
| A (baseline) | 0.72 | 14.5k | 12.5s |
|
|
63
|
+
| B (tightened) | 0.89 | 15.1k | 13.2s ← WINNER |
|
|
64
|
+
| C (reduced) | 0.81 | 12.8k | 11.7s |
|
|
65
|
+
|
|
66
|
+
Winner: **Variant B** (+0.17 over baseline)
|
|
67
|
+
Recommendation: adopt Variant B.
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Bad eval result
|
|
71
|
+
|
|
72
|
+
```
|
|
73
|
+
Variant B seems better. Use it.
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Problems: no scores, no comparison table, no dataset reference.
|
|
77
|
+
|
|
78
|
+
## Anti-patterns
|
|
79
|
+
|
|
80
|
+
- **Dataset > 20 entries** — cap to prevent runaway costs
|
|
81
|
+
- **> 3 variants** — no clear winner possible
|
|
82
|
+
- **Token cost > 500k without confirmation** — estimate first
|
|
83
|
+
- **Overwriting SKILL.md** — variants go to `.eval.<letter>` files
|
|
84
|
+
- **Not cleaning up** — delete `.eval.<letter>` temp files after results persisted
|
|
85
|
+
|
|
86
|
+
## How to verify
|
|
87
|
+
|
|
88
|
+
- [ ] Dataset exists and loaded?
|
|
89
|
+
- [ ] All variants executed?
|
|
90
|
+
- [ ] Scores aggregated correctly?
|
|
91
|
+
- [ ] Winner identified with tiebreak if needed?
|
|
92
|
+
- [ ] Results persisted to `evals/results/`?
|
|
93
|
+
- [ ] Temp files cleaned up?
|
|
94
|
+
- [ ] Token cost within budget?
|
|
95
|
+
|
|
96
|
+
## When triggered
|
|
97
|
+
|
|
98
|
+
- User runs `/ciel-eval [skill-name]`
|
|
99
|
+
- `ciel-improve` calls this for each proposed patch
|
|
100
|
+
- `improver` agent invokes this as part of its loop
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: skills-first-design-auditor
|
|
3
|
+
description: Lints and audits Agent Skills (Anthropic format) for design quality — frontmatter completeness, body length ≤500 lines, presence of 2-3 concrete examples, verification scripts for critical checks, clear WHEN-triggered section, and alignment with the 6 principles from Anthropic's April 2026 skills guide. Used by @ciel-improver when creating or reviewing a skill.
|
|
4
|
+
allowed-tools: Read, Grep, Glob, Bash
|
|
5
|
+
context: fork
|
|
6
|
+
agent: improver
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# skills-first-design-auditor — Good skills discover themselves
|
|
10
|
+
|
|
11
|
+
A skill that doesn't auto-activate is just a document. Anthropic's April 2026 guide ("Equipping Agents for the Real World with Agent Skills") codifies what makes a skill actually useful to an agent. This skill audits against those principles.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Inputs
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
SKILL_PATH: [absolute path to a SKILL.md file OR a directory containing SKILL.md + companions]
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## The 6 principles (Anthropic April 2026)
|
|
24
|
+
|
|
25
|
+
### 1. Evaluation-driven design
|
|
26
|
+
|
|
27
|
+
The skill must encode a capability the agent ACTUALLY lacks. Don't add skills that duplicate what the base model does well.
|
|
28
|
+
|
|
29
|
+
**Audit**: is there evidence (a failing eval, a user complaint, a prior incident) that motivated this skill? → Check git history / CHANGELOG entry.
|
|
30
|
+
|
|
31
|
+
### 2. Searchable frontmatter
|
|
32
|
+
|
|
33
|
+
`description` must be specific enough that agents invoke it via semantic search. "Helps with code" is USELESS; "Validates that each proposed external API call exists in the pinned version's official documentation" is GOOD.
|
|
34
|
+
|
|
35
|
+
**Audit**:
|
|
36
|
+
- `name`: kebab-case, < 40 chars
|
|
37
|
+
- `description`: 1-3 sentences, names the trigger condition AND the output
|
|
38
|
+
- `allowed-tools`: present, minimal (`Read, Grep` not `*`)
|
|
39
|
+
- Agent field if applicable (`agent: critic` / `agent: researcher` / ...)
|
|
40
|
+
|
|
41
|
+
### 3. Body ≤ 500 lines
|
|
42
|
+
|
|
43
|
+
Skills are loaded into agent context. A 2000-line skill burns 5k tokens just to be available. If the body exceeds 500 lines:
|
|
44
|
+
|
|
45
|
+
- Split into a core SKILL.md + reference docs in the same folder
|
|
46
|
+
- Link from SKILL.md to the references; agent fetches them on demand
|
|
47
|
+
|
|
48
|
+
**Audit**: `wc -l SKILL.md`. Frontmatter doesn't count. 500-700 lines = WARN. >700 = BLOCK.
|
|
49
|
+
|
|
50
|
+
### 4. Concrete examples, not abstract prose
|
|
51
|
+
|
|
52
|
+
Each skill body must contain 2-3 examples showing input → reasoning → output. Not "the skill handles X" — an actual trace.
|
|
53
|
+
|
|
54
|
+
**Audit**: grep for `### Example` or `#### Example` or ```` ```<lang> `` code blocks with realistic values. 0 examples = BLOCK. 1 example = WARN. 2+ = PASS.
|
|
55
|
+
|
|
56
|
+
### 5. Verification scripts for critical checks
|
|
57
|
+
|
|
58
|
+
If the skill includes a "is this condition met?" check, that check should be executable (bash, python, grep), not a prose instruction telling the agent to "verify visually". Executable checks are reliable; prose checks degrade.
|
|
59
|
+
|
|
60
|
+
**Audit**: does the PROCESS section contain at least one runnable command per check? If all checks are prose ("verify the input is valid") → WARN.
|
|
61
|
+
|
|
62
|
+
### 6. Clear WHEN-triggered section
|
|
63
|
+
|
|
64
|
+
The skill must state explicitly when it activates: which step of the pipeline, which agent dispatches it, which user command. Without this, auto-activation via description-matching misfires.
|
|
65
|
+
|
|
66
|
+
**Audit**: presence of a `## When triggered` section (or equivalent) with at least 2 concrete triggers.
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## Ciel-specific additions
|
|
71
|
+
|
|
72
|
+
### A. Consistency with existing skills
|
|
73
|
+
|
|
74
|
+
- Same section order as peer skills in the same category (workflow/ research/ domain/ utility/ meta)
|
|
75
|
+
- Same frontmatter field ordering (`name`, `description`, `allowed-tools`, `context`, `agent`)
|
|
76
|
+
- Output format uses `##` + `###` hierarchy consistent with `relire-critic` style
|
|
77
|
+
|
|
78
|
+
### B. No duplication
|
|
79
|
+
|
|
80
|
+
Before approving a new skill, grep the existing 36 skills for overlap. If the new skill covers ≥70% of an existing skill's scope → reject or merge.
|
|
81
|
+
|
|
82
|
+
### C. Dispatch target aligned
|
|
83
|
+
|
|
84
|
+
`agent: <role>` must match where the skill logically fits:
|
|
85
|
+
- **researcher** — external investigation, doc fetching, source validation
|
|
86
|
+
- **explorer** — codebase reading, pattern detection, domain knowledge
|
|
87
|
+
- **critic** — post-write review, hostile analysis, correctness checking
|
|
88
|
+
- **improver** — meta-level, auditing other skills or the system itself
|
|
89
|
+
|
|
90
|
+
Wrong `agent:` = skill won't be dispatched via the right fork context.
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## Audit output format
|
|
95
|
+
|
|
96
|
+
```
|
|
97
|
+
## SKILL AUDIT: <name>
|
|
98
|
+
|
|
99
|
+
### Frontmatter
|
|
100
|
+
[✓] name: kebab-case, 22 chars
|
|
101
|
+
[✓] description: specific, names trigger + output
|
|
102
|
+
[✓] allowed-tools: minimal (Read, Grep, Glob, Bash)
|
|
103
|
+
[✓] agent: explorer (aligned with body content)
|
|
104
|
+
|
|
105
|
+
### Body
|
|
106
|
+
[✓] Length: 342 lines (under 500)
|
|
107
|
+
[✓] Examples: 3 (passes minimum 2)
|
|
108
|
+
[✓] Executable checks: 4 (grep commands, wc -l, etc.)
|
|
109
|
+
[✓] "When triggered" section: present, 4 triggers listed
|
|
110
|
+
|
|
111
|
+
### Principles
|
|
112
|
+
[✓] 1. Evaluation-driven — CHANGELOG v2.1.0 references ISSTA 2025 gap
|
|
113
|
+
[✓] 2. Searchable frontmatter
|
|
114
|
+
[✓] 3. Body ≤500 lines
|
|
115
|
+
[✓] 4. Concrete examples
|
|
116
|
+
[✓] 5. Verification scripts
|
|
117
|
+
[✓] 6. WHEN-triggered clarity
|
|
118
|
+
|
|
119
|
+
### Ciel-specific
|
|
120
|
+
[✓] Consistent section order with peer skills in workflow/
|
|
121
|
+
[✓] No overlap with existing skills (checked: pattern-fitness-check, flux-narrator)
|
|
122
|
+
[✓] agent field matches skill content (explorer for codebase-reading)
|
|
123
|
+
|
|
124
|
+
### Findings
|
|
125
|
+
(none — skill passes audit)
|
|
126
|
+
|
|
127
|
+
### Verdict
|
|
128
|
+
PASS — ready to ship
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## Typical issues found (with fixes)
|
|
134
|
+
|
|
135
|
+
### Issue: vague description
|
|
136
|
+
```yaml
|
|
137
|
+
# BAD
|
|
138
|
+
description: Helps with code review.
|
|
139
|
+
# GOOD
|
|
140
|
+
description: Generates 3 hostile critiques per changed file (1 functional, 1 import, 1 data-assumption) and resolves each with FIX/ACCEPT/DEFER. Invoked by the PostToolUse hook on Write/Edit for Standard/Critical tasks with 3+ changed files.
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### Issue: no examples
|
|
144
|
+
Add at least 2 concrete `### Example` blocks showing input → skill output. Prose-only skills don't transfer knowledge well; examples anchor behavior.
|
|
145
|
+
|
|
146
|
+
### Issue: missing WHEN section
|
|
147
|
+
Add section listing: (a) pipeline step, (b) dispatching agent, (c) user command triggers. 4-6 bullets is plenty.
|
|
148
|
+
|
|
149
|
+
### Issue: overbroad allowed-tools
|
|
150
|
+
```yaml
|
|
151
|
+
# BAD
|
|
152
|
+
allowed-tools: "*"
|
|
153
|
+
# GOOD
|
|
154
|
+
allowed-tools: Read, Grep, Glob, Bash
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
## How to verify
|
|
160
|
+
|
|
161
|
+
- [ ] All 6 Anthropic principles checked?
|
|
162
|
+
- [ ] Frontmatter audit complete (name, description, allowed-tools, agent)?
|
|
163
|
+
- [ ] Body length measured (wc -l)?
|
|
164
|
+
- [ ] Examples counted (grep for Example blocks)?
|
|
165
|
+
- [ ] Verification scripts checked (executable vs prose)?
|
|
166
|
+
- [ ] WHEN-triggered section present?
|
|
167
|
+
- [ ] Ciel-specific checks (consistency, no duplication, dispatch target)?
|
|
168
|
+
|
|
169
|
+
## Guardrails
|
|
170
|
+
|
|
171
|
+
- **Don't auto-fix, just audit** — propose changes in the report; let the human/improver decide.
|
|
172
|
+
- **Don't re-audit on every commit** — this is a "when a skill is added or significantly edited" task.
|
|
173
|
+
- **Prior-session skills** count under principle 1 — if the skill came from a past Ciel iteration and was never re-validated, flag for re-evaluation.
|
|
174
|
+
- **Skills in `skills/meta/`** should be extra strict — they shape how the system grows.
|
|
175
|
+
- **Exceptions allowed** — a meta skill legitimately exceeds 500 lines if it encodes a taxonomy; document the rationale in a comment at the top of the file.
|
|
176
|
+
|
|
177
|
+
---
|
|
178
|
+
|
|
179
|
+
## When triggered
|
|
180
|
+
|
|
181
|
+
- `@ciel-improver` on `/ciel-create-skill`
|
|
182
|
+
- PR touching `skills/**/SKILL.md`
|
|
183
|
+
- Before merging a skill from a research branch
|
|
184
|
+
- Quarterly sweep across all skills (release gate)
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
## References
|
|
189
|
+
|
|
190
|
+
- Anthropic April 2026 — "Equipping Agents for the Real World with Agent Skills" — anthropic.com/engineering
|
|
191
|
+
- Anthropic Skills intro — anthropic.skilljar.com/introduction-to-agent-skills
|
|
192
|
+
- Claude API docs — platform.claude.com/docs/en/agents-and-tools/agent-skills/overview
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ml-engineering
|
|
3
|
+
description: "ML Engineering — pipelines ML, feature stores, model serving, drift detection, MLOps, experiment tracking. A charger quand on met en production des modeles ML."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# ML Engineering
|
|
7
|
+
|
|
8
|
+
**Principe premier :** Le ML engineering n'est pas "entrainer un modele avec le meilleur score" — c'est mettre un modele en production et garantir qu'il reste performant dans le temps. La metrique qui compte n'est pas l'accuracy sur le dataset de test (qui est un instantane du passe) — c'est la performance en production sur les donnees de demain. Un modele est un programme qui se degrade passivement : le monde change, les distributions derivent, et un modele a 98% de precision aujourd'hui peut tomber a 72% dans 6 mois sans que personne ne le sache. La difference entre un notebook Jupyter et un systeme ML de production, c'est le monitoring, le versioning, et la capacite a re-entrainer.
|
|
9
|
+
|
|
10
|
+
## Checklist
|
|
11
|
+
- [ ] Les donnees sont versionnees (DVC, LakeFS, Delta Lake) — pas de `dataset_v3_final_FINAL.csv`
|
|
12
|
+
- [ ] Les experiences sont trackees (MLflow, W&B, ClearML) avec hyperparametres, code version, dataset version
|
|
13
|
+
- [ ] Le feature store est la source unique de verite pour les features — pas de features calculees differemment en train et en inference
|
|
14
|
+
- [ ] Le serving est monitorise : latence P95, taux d'erreur, distribution des predictions
|
|
15
|
+
- [ ] Le data drift ET le concept drift sont monitorises — alerter quand la distribution change
|
|
16
|
+
- [ ] Le pipeline d'entrainement est reproductible (DAG, conteneurise, versionne)
|
|
17
|
+
- [ ] Le rollback de modele est aussi simple que le rollback de code (model registry avec versioning)
|
|
18
|
+
|
|
19
|
+
## Anti-patterns
|
|
20
|
+
### Notebook → production
|
|
21
|
+
**Ce qu'on voit :** le data scientist donne son notebook "il marche sur mon laptop". L'ingenieur le copie-colle dans un endpoint. 2000 lignes de code non structure.
|
|
22
|
+
**Pourquoi c'est dangereux :** un notebook n'est pas un programme — c'est un journal d'exploration. Pas de gestion d'erreur, pas de typage, pas de tests, pas de reproductibilite (execution ordonnee non garantie). Les imports sont eparpilles, les variables persistent entre cellules, le code est impossible a maintenir.
|
|
23
|
+
**Faire plutot :** le notebook est un outil d'exploration. Le code de production est dans des modules Python standards, versionnes, testes. Le data scientist et le ML engineer travaillent ensemble sur la transition notebook → module. Le notebook documente l'intention, le module implemente la production.
|
|
24
|
+
|
|
25
|
+
### Features train/serve inconsistantes
|
|
26
|
+
**Ce qu'on voit :** les features sont calculees en Python (pandas) pour l'entrainement, et en Go/Java dans le serving. Implementation differente → comportement different → modele qui performe mal en production sans raison apparente.
|
|
27
|
+
**Pourquoi c'est dangereux :** c'est le bug le plus pernicieux en ML. Les metriques d'entrainement sont bonnes, les tests passent, mais le modele est mauvais en production. La cause est quasi impossible a debugger sans comparer les implementations feature par feature.
|
|
28
|
+
**Faire plutot :** feature store central. Les memes features, calculees par le meme code, servent l'entrainement ET l'inference. Si le calcul change, le feature store versionne. Zero implementation divergente.
|
|
29
|
+
|
|
30
|
+
### Drift = surprise
|
|
31
|
+
**Ce qu'on voit :** pas de monitoring du drift. Le modele se degrade lentement. 6 mois plus tard, un utilisateur remarque que les predictions sont mauvaises.
|
|
32
|
+
**Pourquoi c'est dangereux :** la degradation est silencieuse et graduelle. Le modele ne crash pas — il devient juste de plus en plus mauvais. Les decisions basees sur ces predictions deviennent de plus en plus mauvaises. Le MTTD (mean time to detect) est de 6 mois.
|
|
33
|
+
**Faire plutot :** monitoring continu de la distribution des features en production vs distribution d'entrainement (data drift). Monitoring des predictions (concept drift : relation feature → cible qui change). Alerter quand la divergence depasse un seuil. Re-entrainement automatise ou manuel selon la criticite.
|
|
34
|
+
|
|
35
|
+
## Patterns
|
|
36
|
+
### Model registry
|
|
37
|
+
**Quand :** plusieurs modeles en production ou re-entrainements frequents.
|
|
38
|
+
**Comment :** MLflow Model Registry, Seldon, ou Sagemaker Model Registry. Chaque modele a : version, metriques, dataset d'origine, artefact, statut (staging/production/archived). Promotion staging → production via CI/CD. Rollback = pointer vers la version precedente en un clic.
|
|
39
|
+
|
|
40
|
+
### Feature store
|
|
41
|
+
**Quand :** features reutilisees entre plusieurs modeles ou entre train/serving.
|
|
42
|
+
**Comment :** Feast, Tecton, ou solution interne. Les features sont definies une fois, calculees offline (batch) et servies online (low latency). Le feature store garantit la consistance entre train et serve. Chaque feature est versionnee et documentee.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: mobile
|
|
3
|
+
description: "Mobile — iOS/Android/React Native/Flutter, offline-first, batterie, store review, push notifications. A charger quand on developpe une application mobile."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Mobile
|
|
7
|
+
|
|
8
|
+
**Principe premier :** Le mobile n'est pas "un petit ecran" — c'est un environnement hostile. Reseau instable (tunnel → metro → edge → 3G), batterie limitee, stockage restreint, OS qui peut killer l'app a tout moment. Si ton app ne fonctionne pas dans un tunnel avec 1 barre de 3G et 10% de batterie, elle ne fonctionne pas. Le store (App Store, Play Store) est ton canal de distribution mais aussi ton gatekeeper — chaque release est une revue humaine qui peut etre rejetee. Le mobile recompense l'optimisme offline et le pessimisme reseau : suppose toujours que le reseau est lent, cher, et hostile.
|
|
9
|
+
|
|
10
|
+
## Checklist
|
|
11
|
+
- [ ] Offline-first : l'app fonctionne sans reseau — donnees en cache local, actions en file d'attente
|
|
12
|
+
- [ ] Les images sont lazy-loadees et resizees (pas de 4K telecharge sur un ecran 400px de large)
|
|
13
|
+
- [ ] La batterie est respectee : pas de polling every 5s, pas de wake lock permanent, pas de GPS continu
|
|
14
|
+
- [ ] Le state est preserve a travers les kills d'OS (serialisation automatique du state critique)
|
|
15
|
+
- [ ] Les crashs sont reportes (Crashlytics, Sentry) — pas de "ca crash sur le telephone de Julie"
|
|
16
|
+
- [ ] Les updates sont gerees : forced update si API incompatible, optional update sinon
|
|
17
|
+
- [ ] Le stockage local a un TTL et une limite de taille — pas de cache infini qui remplit le telephone
|
|
18
|
+
|
|
19
|
+
## Anti-patterns
|
|
20
|
+
### Mobile = site web en webview
|
|
21
|
+
**Ce qu'on voit :** une webview qui charge le site responsive. Publie sur les stores. "Ca marche sur mobile."
|
|
22
|
+
**Pourquoi c'est dangereux :** zero integration native. Pas de push notifications, pas de stockage offline, pas de gestures natives, pas de transition fluide. Les utilisateurs le sentent immediatement et desinstallent. Les stores peuvent rejeter si l'app n'apporte rien par rapport au site.
|
|
23
|
+
**Faire plutot :** si le contenu est statique → PWA (plus leger, pas besoin de store). Si besoin natif (push, camera, offline) → app native ou React Native/Flutter avec vrais composants natifs.
|
|
24
|
+
|
|
25
|
+
### Optimiste sur le reseau
|
|
26
|
+
**Ce qu'on voit :** l'app suppose que le reseau est disponible et rapide. Pas de cache, pas de queue offline, pas de gestion d'erreur reseau. L'app affiche un spinner blanc des que le reseau est lent.
|
|
27
|
+
**Pourquoi c'est dangereux :** le reseau mobile est le pire reseau de tous les clients. L'utilisateur est dans un ascenseur, un metro, une cave, une campagne. Si l'app ne fonctionne pas offline, elle est inutilisable 30% du temps. L'utilisateur ouvre l'app concurrente.
|
|
28
|
+
**Faire plutot :** cache local (SQLite, Realm, WatermelonDB). Sync en arriere-plan quand le reseau est disponible. UI qui montre les donnees en cache immediatement, puis rafraichit. Indicateur "donnees de X minutes" plutot qu'un spinner.
|
|
29
|
+
|
|
30
|
+
### Release = pari
|
|
31
|
+
**Ce qu'on voit :** soumission sur le store sans test de recette. Rejet pour violation de guideline. 3 jours de delai. Corrections en catastrophe.
|
|
32
|
+
**Pourquoi c'est dangereux :** le store review est un processus humain, lent, et imprevisible. Un rejet decale la release de 3-7 jours. Les utilisateurs attendent, les bugs critiques restent en production.
|
|
33
|
+
**Faire plutot :** pre-release checklist (guidelines store, screenshots, permissions documentees). TestFlight/Internal Testing pour valider le binaire avant soumission. Soumission en debut de semaine pour maximiser les chances de review rapide.
|
|
34
|
+
|
|
35
|
+
## Patterns
|
|
36
|
+
### Offline-first avec sync queue
|
|
37
|
+
**Quand :** app qui modifie des donnees (notes, taches, commandes).
|
|
38
|
+
**Comment :** ecriture locale immediate → queue de synchronisation → synchro background quand online. Resolution de conflits : last-write-wins pour donnees simples, merge pour donnees complexes. UI qui montre l'etat de synchro (sync, synced, error).
|
|
39
|
+
|
|
40
|
+
### Gradual rollout sur stores
|
|
41
|
+
**Quand :** release avec risque (refonte, nouvelle fonctionnalite).
|
|
42
|
+
**Comment :** Play Store : staged rollout (10% → 50% → 100% avec possibilite de halt). App Store : phased release sur 7 jours. Monitoring des crashs et des ratings par version. Rollback en arretant le rollout (pas besoin de nouvelle soumission).
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: monitoring
|
|
3
|
+
description: "Monitoring — RED/USE metrics, SLI/SLO/SLA comme contrats, dashboards comme outils de debugging, alerting fatigue. À charger quand on met en place du monitoring."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Monitoring
|
|
7
|
+
|
|
8
|
+
**Principe premier :** Le monitoring n'est pas "avoir des dashboards" — c'est pouvoir répondre à deux questions en < 30 secondes : "est-ce que le système fonctionne ?" et "si non, qu'est-ce qui a changé ?". Si tes dashboards ne répondent pas à ça, ils sont du bruit visuel. La métrique fondamentale n'est pas le nombre de graphiques — c'est le Mean Time To Detect (MTTD). Combien de temps entre le début de l'incident et la première alerte ? Si la réponse est "quand un client ouvre un ticket", ton monitoring a échoué.
|
|
9
|
+
|
|
10
|
+
## Checklist
|
|
11
|
+
- [ ] RED metrics par service : Rate, Errors, Duration (P50/P95/P99) — collectées via Prometheus, exposées sur `/metrics`
|
|
12
|
+
- [ ] USE metrics par ressource : Utilization, Saturation, Errors — node_exporter/cAdvisor → Prometheus → Grafana
|
|
13
|
+
- [ ] Dashboards, règles Prometheus, et config AlertManager sont dans le repo (monitoring as code) — pas créés à la main dans l'UI Grafana
|
|
14
|
+
- [ ] Dashboards Grafana avec seuils visuels (vert/jaune/rouge) — pas juste des lignes sur un graphique
|
|
15
|
+
- [ ] SLI définis (ce qu'on mesure), SLO documentés (l'objectif), SLA communiqués (la promesse)
|
|
16
|
+
- [ ] Alertes sur les signaux critiques uniquement — pas d'alerte sur "CPU > 70% pendant 30s à 3h du matin"
|
|
17
|
+
- [ ] Runbook associé à chaque alerte — "si cette alerte sonne, voici quoi faire"
|
|
18
|
+
|
|
19
|
+
## Anti-patterns
|
|
20
|
+
### Dashboard = décoration
|
|
21
|
+
**Ce qu'on voit :** un écran mural avec 50 graphiques, pas de titre, pas d'échelle, pas de seuil. Personne ne le regarde. Les incidents sont découverts par les utilisateurs.
|
|
22
|
+
**Pourquoi c'est dangereux :** un dashboard sans contexte n'est pas un outil — c'est du bruit. Les anomalies sont noyées dans la masse de données non interprétables. Le MTTD est infini.
|
|
23
|
+
**Faire plutôt :** un dashboard par service. Titre explicite. Description : "Ce dashboard montre la santé du service X. Si ce graphique est rouge, regarder Y." Seuils visuels. Maximum 10 métriques par dashboard. Le dashboard doit permettre de répondre "est-ce que c'est normal ?" en un coup d'œil.
|
|
24
|
+
|
|
25
|
+
### Alerte sur tout
|
|
26
|
+
**Ce qu'on voit :** 200 alertes configurées. "CPU > 50%", "mémoire > 60%", "disque > 70%". 15 alertes par nuit. L'équipe a muté le canal. Les vraies urgences sont ignorées.
|
|
27
|
+
**Pourquoi c'est dangereux :** l'alert fatigue est réelle. Chaque fausse alerte entraîne la suivante vers l'ignorance. Quand une vraie alerte critique arrive, personne ne la voit parce que tout le monde a appris que "les alertes = du bruit".
|
|
28
|
+
**Faire plutôt :** alerter sur les SYMPTÔMES, pas sur les causes potentielles. "P95 latency > 1s pendant 5 min" (symptôme utilisateur), pas "CPU > 70%" (cause possible). Chaque alerte doit être actionable — si tu ne peux pas écrire le runbook en 3 étapes, ne crée pas l'alerte.
|
|
29
|
+
|
|
30
|
+
### Monitoring = dashboards Grafana
|
|
31
|
+
**Ce qu'on voit :** tout est dans Grafana. Pas de logs structurés, pas de tracing, pas d'alerting. "On regardera le dashboard si quelqu'un se plaint."
|
|
32
|
+
**Pourquoi c'est dangereux :** le monitoring sans observabilité, c'est regarder le tableau de bord de ta voiture. Tu vois que la vitesse est à 0, mais tu ne sais pas POURQUOI. Les dashboards montrent les symptômes, les logs et traces montrent les causes. L'un sans l'autre = tu sais que c'est cassé, pas pourquoi.
|
|
33
|
+
**Faire plutôt :** monitoring (métriques + dashboards + alertes) + logging (logs structurés JSON + correlation ID) + tracing (OpenTelemetry, traces distribuées). Les trois piliers de l'observabilité.
|
|
34
|
+
|
|
35
|
+
## Patterns
|
|
36
|
+
### Prometheus + Grafana (stack standard)
|
|
37
|
+
**Quand :** toute application en production.
|
|
38
|
+
**Comment :** Prometheus scrape les métriques exposées par l'app (`/metrics`). Grafana interroge Prometheus (PromQL) et affiche les dashboards. Pas de solution propriétaire — cette stack est le standard ouvert, toutes les bibliothèques l'implémentent. Chaque service expose ses propres métriques RED, l'infrastructure expose les USE via node_exporter / cAdvisor.
|
|
39
|
+
|
|
40
|
+
### RED method (services)
|
|
41
|
+
**Quand :** monitoring de tout service (API, worker, etc.).
|
|
42
|
+
**Comment :** Rate (requêtes/s), Errors (taux d'erreur), Duration (P50/P95/P99) via histogram Prometheus. 3 métriques par endpoint. Couvre l'expérience utilisateur. PromQL : `rate(http_requests_total[5m])`, `rate(http_errors_total[5m])`, `histogram_quantile(0.95, rate(http_duration_bucket[5m]))`.
|
|
43
|
+
|
|
44
|
+
### USE method (ressources)
|
|
45
|
+
**Quand :** monitoring de toute ressource (CPU, RAM, disque, réseau, DB pool).
|
|
46
|
+
**Comment :** Utilization (% utilisé), Saturation (file d'attente), Errors (compteur d'erreurs) via node_exporter. 3 métriques par ressource. Dashboard Grafana avec seuils vert/jaune/rouge. Si Utilization > 80%, si Saturation > 0, si Errors > 0 — investiguer.
|
|
47
|
+
|
|
48
|
+
### SLO-based alerting
|
|
49
|
+
**Quand :** définir les alertes sans tomber dans l'alert fatigue.
|
|
50
|
+
**Comment :** définir un SLO (ex: "99.9% des requêtes < 500ms sur 30 jours"). L'alerte se déclenche quand le error budget est consommé trop vite (ex: 5% du budget mensuel en 1h). Configurer dans AlertManager via Prometheus rules : `alert: HighErrorBurnRate`, `expr: rate(http_errors_total[1h]) / rate(http_requests_total[1h]) > 0.05`.
|
|
51
|
+
|
|
52
|
+
### Monitoring as Code (dashboards + rules dans le repo)
|
|
53
|
+
**Quand :** toute équipe de plus d'une personne.
|
|
54
|
+
**Comment :** dashboards Grafana en JSON (Grafonnet pour les générer), règles Prometheus en YAML, config AlertManager en YAML — tout dans `monitoring/` du repo. Déploiement via CI/CD (Terraform, Grafana provisioning API). PR pour chaque changement de dashboard ou alerte. Le monitoring est de l'infrastructure — le même niveau de rigueur que le Terraform de prod.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: networking
|
|
3
|
+
description: "Networking — le reseau comme fondation invisible. DNS, TLS, HTTP/2/3, VPC, firewall, load balancing. A charger quand on configure des connexions ou debug la connectivite."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Networking
|
|
7
|
+
|
|
8
|
+
**Principe premier :** Le reseau n'est pas "ce qui connecte les machines" — c'est la couche de securite zero. Avant que ton application ne recoive un octet, le reseau a deja pris 100 decisions : routage, filtrage, terminaison TLS, rate limiting. Un reseau bien configure rend 80% des attaques impossibles avant meme qu'elles n'atteignent l'application. Le probleme inverse : un reseau mal configure est invisible jusqu'a l'incident — "pourquoi le service B ne peut pas parler au service C en prod ?" La connectivite n'est jamais acquise — elle est configuree, testee, monitorisee.
|
|
9
|
+
|
|
10
|
+
## Checklist
|
|
11
|
+
- [ ] DNS est configure avec TTL raisonnable (300s pour APEX, 60s pour failover) — pas de TTL de 86400s
|
|
12
|
+
- [ ] TLS >= 1.2 partout, TLS 1.3 pour les services internes — pas de TLS 1.0/1.1, pas de SSL
|
|
13
|
+
- [ ] Les certificats sont auto-renouveles (LetsEncrypt, cert-manager, ACM) — pas d'expiration surprise
|
|
14
|
+
- [ ] Firewall : seuls les ports necessaires sont ouverts. SSH (22) restreint par IP source
|
|
15
|
+
- [ ] Les VPC/VNET sont isoles par environnement (dev/staging/prod) avec peering explicite
|
|
16
|
+
- [ ] HTTP/2 ou HTTP/3 active — multiplexing, header compression, 0-RTT
|
|
17
|
+
- [ ] Le load balancer a un health check actif (pas juste TCP connect — verifier le endpoint)
|
|
18
|
+
|
|
19
|
+
## Anti-patterns
|
|
20
|
+
### "C'est un probleme reseau"
|
|
21
|
+
**Ce qu'on voit :** chaque bug de connexion est blame sur "le reseau". Personne ne debug. Le probleme persiste 3 semaines.
|
|
22
|
+
**Pourquoi c'est dangereux :** le reseau est un bouc emissaire facile parce qu'il est invisible. En realite, la plupart des problemes "reseau" sont des problemes d'application : timeout trop court, DNS cache, certificat expire, mauvais endpoint. Dire "c'est le reseau" sans preuve = arreter de chercher.
|
|
23
|
+
**Faire plutot :** debug methodique : `dig` (DNS), `curl -v` (TLS + HTTP), `traceroute` (routage), `telnet host port` (connectivite brute). Chaque couche se teste independamment. Le probleme est toujours sur UNE couche specifique.
|
|
24
|
+
|
|
25
|
+
### Firewall = apres coup
|
|
26
|
+
**Ce qu'on voit :** le firewall est configure "quand tout marche" (jamais). Tous les ports sont ouverts "pour pas etre bloque".
|
|
27
|
+
**Pourquoi c'est dangereux :** le firewall est la premiere ligne de defense. Sans regles strictes, une application vulnerable sur un port oublie = acces non autorise. Le firewall interne (entre services) est aussi important que l'externe.
|
|
28
|
+
**Faire plutot :** deny-all par defaut. Ouvrir uniquement les flux documentes. Chaque regle a un commentaire (pourquoi ce port, pour quel service). Revue trimestrielle des regles.
|
|
29
|
+
|
|
30
|
+
### DNS comme apres-pensee
|
|
31
|
+
**Ce qu'on voit :** TTL = 86400 (24h). Changement de serveur → 24h de propagation. Les utilisateurs voient l'ancienne IP. Ou pire : `CNAME` court-circuite avec un `A` record parce que "c'est plus simple".
|
|
32
|
+
**Pourquoi c'est dangereux :** DNS est le premier maillon de toute connexion. Un TTL trop long empeche le failover rapide. Un mauvais enregistrement = outage total. Le DNS est la fondation — tout repose dessus.
|
|
33
|
+
**Faire plutot :** TTL courts pour les endpoints critiques (60-300s). Records A/AAAA pour la racine, CNAME pour les sous-domaines. Monitoring de resolution DNS depuis plusieurs points geographiques.
|
|
34
|
+
|
|
35
|
+
## Patterns
|
|
36
|
+
### Defense en profondeur reseau
|
|
37
|
+
**Quand :** architecture multi-services.
|
|
38
|
+
**Comment :** WAF/CDN (couche 1) → Load Balancer + TLS termination (couche 2) → Network ACL/VPC firewall (couche 3) → Security Group par service (couche 4). Chaque couche suppose que la precedente a echoue. Aucune couche ne fait confiance a la precedente.
|
|
39
|
+
|
|
40
|
+
### Zero Trust networking
|
|
41
|
+
**Quand :** services distribues, multi-cloud, ou travailleurs distants.
|
|
42
|
+
**Comment :** pas de "reseau interne de confiance". Chaque appel est authentifie (mTLS, JWT, SPIFFE). Le reseau est hostile par defaut — les services ne se font pas plus confiance entre eux qu'a Internet. C'est le principe inverse du "perimetre de securite".
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: nosql
|
|
3
|
+
description: "NoSQL — MongoDB/DynamoDB/Redis, modeling around access patterns, single-table design, hot partition avoidance. À charger quand on choisit ou utilise du NoSQL."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# NoSQL
|
|
7
|
+
|
|
8
|
+
**Principe premier :** NoSQL n'est pas "SQL sans schéma" — c'est un trade-off fondamental : tu échanges la flexibilité des requêtes (tu ne peux pas tout JOINer) contre la scalabilité horizontale (tu peux sharder). Ce trade-off est le SEUL critère valide pour choisir NoSQL. Si tu n'as pas de problème de scale horizontal que SQL ne résout pas, NoSQL est un downgrade, pas une modernisation. Le modeling NoSQL se fait à l'envers du relationnel : tu pars des requêtes (qu'est-ce que je dois lire en une opération ?) et tu construis le modèle autour.
|
|
9
|
+
|
|
10
|
+
## Checklist
|
|
11
|
+
- [ ] Le choix NoSQL est justifié par le scale horizontal, pas par "c'est plus simple"
|
|
12
|
+
- [ ] Le modèle de données est conçu autour des access patterns (et pas l'inverse)
|
|
13
|
+
- [ ] La partition key a une haute cardinalité et une distribution uniforme
|
|
14
|
+
- [ ] Les index secondaires (GSI) sont justifiés — chaque GSI coûte de l'argent et de la latence
|
|
15
|
+
- [ ] La stratégie de dénormalisation est documentée : quelle donnée est dupliquée, où, pourquoi
|
|
16
|
+
- [ ] Les TTL sont configurés pour les données temporaires — pas de job de nettoyage manuel
|
|
17
|
+
|
|
18
|
+
## Anti-patterns
|
|
19
|
+
### Modélisation relationnelle dans NoSQL
|
|
20
|
+
**Ce qu'on voit :** 12 `$lookup` (MongoDB) pour reproduire un JOIN. 50 `GetItem` séquentiels (DynamoDB) parce que les données sont dans des items séparés.
|
|
21
|
+
**Pourquoi c'est dangereux :** NoSQL n'est pas optimisé pour les JOINs. Chaque `$lookup` est un scan coûteux. Chaque `GetItem` est une requête réseau. 50 requêtes séquentielles DynamoDB = 500ms de latence minimum contre 10ms pour un JOIN SQL. Tu paies le prix du NoSQL sans le bénéfice.
|
|
22
|
+
**Faire plutôt :** pre-joindre. Si les données sont lues ensemble, elles sont stockées ensemble (single document/item). Le modèle reflète les patterns d'accès — une requête = un read.
|
|
23
|
+
|
|
24
|
+
### Hot partition / hot key
|
|
25
|
+
**Ce qu'on voit :** partition key = `status` avec 90% des items à `status = "active"`. Ou pire, partition key = `tenant_id` et un tenant fait 80% du trafic.
|
|
26
|
+
**Pourquoi c'est dangereux :** en NoSQL, les partitions sont l'unité de scale. Une partition chaude = tout le trafic sur un seul shard = throttling (DynamoDB) ou performance dégradée (MongoDB). Le scale horizontal est neutralisé par une mauvaise clé.
|
|
27
|
+
**Faire plutôt :** partition key à haute cardinalité et distribution uniforme. `user_id`, `order_id`, pas de `status` ou `type`. Si un tenant est plus gros, sharder par `tenant_id#entity_id` (composite key).
|
|
28
|
+
|
|
29
|
+
### Redis comme source de vérité
|
|
30
|
+
**Ce qu'on voit :** toutes les données métier dans Redis. `FLUSHALL` ou reboot = toutes les données perdues. "Mais j'ai configuré la persistence" — qui n'a jamais été testée.
|
|
31
|
+
**Pourquoi c'est dangereux :** Redis est conçu comme un cache/queue/session store en mémoire. La persistence Redis (RDB/AOF) est asynchrone et non garantie. Même avec AOF everysec, tu peux perdre les 2 dernières secondes d'écritures.
|
|
32
|
+
**Faire plutôt :** PostgreSQL/MySQL/DynamoDB pour la source de vérité. Redis pour cache, sessions, rate limiting, queues temporaires. Si Redis est flush, l'app dégrade mais ne perd pas de données métier.
|
|
33
|
+
|
|
34
|
+
## Patterns
|
|
35
|
+
### Single-table design (DynamoDB)
|
|
36
|
+
**Quand :** plusieurs types d'entités avec des access patterns différents.
|
|
37
|
+
**Comment :** une table. PK = `TYPE#id`, SK = `RELATION#id`. Les GSI inversent PK/SK pour les autres patterns. Un user et ses orders sont dans la même table, lus en une query. Pas de JOIN.
|
|
38
|
+
|
|
39
|
+
### TTL index
|
|
40
|
+
**Quand :** données temporaires (sessions, cache, logs éphémères).
|
|
41
|
+
**Comment :** champ `expires_at` en epoch seconds + TTL index. La DB supprime automatiquement. Pas de cron job. Pas de nettoyage manuel. Gratuit (DynamoDB) ou quasi-gratuit.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: oop-solid
|
|
3
|
+
description: "OOP & SOLID — classes, objets, heritage, composition, encapsulation, principes SOLID comme garde-fous. A charger quand on travaille avec des classes."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# OOP & SOLID
|
|
7
|
+
|
|
8
|
+
**Principe premier :** SOLID n'est pas un dogme — c'est un systeme d'alerte precoce. Chaque principe ne te dit pas quoi faire, il te dit QUAND le design est en train de pourrir. Single Responsibility = ta classe a plus d'une raison de changer. Open/Closed = tu modifies du code existant au lieu d'etendre. Liskov = ta sous-classe ne peut pas remplacer la classe mere. Interface Segregation = tes clients dependent d'interfaces qu'ils n'utilisent pas. Dependency Inversion = tes modules de haut niveau dependent des bas niveau. Le but n'est pas un score SOLID parfait — c'est un code qui accepte le changement sans se briser. La composition est par defaut, l'heritage est l'exception.
|
|
9
|
+
|
|
10
|
+
## Checklist
|
|
11
|
+
- [ ] Chaque classe a une responsabilite unique (SRP) — decrire son job en une phrase sans "et"
|
|
12
|
+
- [ ] Les classes sont ouvertes a l'extension, fermees a la modification (OCP) — nouveau comportement = nouveau code, pas modification
|
|
13
|
+
- [ ] Les sous-classes sont substituables a leur classe mere (LSP) — pas de `if (obj instanceof SpecialCase)`
|
|
14
|
+
- [ ] Les interfaces sont minimales (ISP) — pas d'interface de 15 methodes dont 10 jettent `NotImplementedException`
|
|
15
|
+
- [ ] Les modules haut niveau ne dependent pas des bas niveau (DIP) — les deux dependent d'abstractions
|
|
16
|
+
- [ ] L'heritage est utilise pour "est-un", pas pour reutiliser du code — composition > heritage
|
|
17
|
+
- [ ] Le couplage est reduit : un changement dans une classe ne force pas une cascade de changements
|
|
18
|
+
|
|
19
|
+
## Anti-patterns
|
|
20
|
+
### SOLID comme religion
|
|
21
|
+
**Ce qu'on voit :** chaque classe est precedee de `interface IFoo`. Chaque `new` est remplace par une factory + DI container. 50 classes pour afficher "Hello World".
|
|
22
|
+
**Pourquoi c'est dangereux :** SOLID utilise en dogme produit l'inverse de son intention : code rigide, difficile a changer, difficile a comprendre. Une interface pour chaque classe = explosion du nombre de fichiers. DI partout = perdu dans les couches d'indirection.
|
|
23
|
+
**Faire plutot :** appliquer SOLID la ou le changement est PROBABLE. Un composant stable peut violer SOLID — c'est acceptable. Introduire une abstraction quand un deuxieme cas concret apparait (pas avant). SOLID est un outil de diagnostic, pas un objectif de design.
|
|
24
|
+
|
|
25
|
+
### Heritage deep chain
|
|
26
|
+
**Ce qu'on voit :** `Animal → Mammal → Canine → Dog → Labrador → GoldenLabrador`. Chaque classe ajoute un comportement. Pour comprendre `GoldenLabrador`, il faut lire 6 classes.
|
|
27
|
+
**Pourquoi c'est dangereux :** l'heritage profond cree un couplage vertical. Changer `Animal` affecte toutes les 200 sous-classes. Impossible de comprendre une classe isolement. Le YAGNI frappe fort : la plupart des classes intermediaires ne sont jamais utilisees directement.
|
|
28
|
+
**Faire plutot :** limiter a 1-2 niveaux d'heritage maximum. Composer les comportements (Strategy, Decorator) plutot qu'heriter. Si une classe a plus de 2 ancetres concrets, repenser le design.
|
|
29
|
+
|
|
30
|
+
### Classe "Manager" / "Utils" / "Helper"
|
|
31
|
+
**Ce qu'on voit :** `UserManager` (3000 lignes), `DateUtils` (150 fonctions statiques), `StringHelper` (tout le monde ajoute des trucs).
|
|
32
|
+
**Pourquoi c'est dangereux :** les noms en -Manager, -Utils, -Helper sont des aveux d'echec de design. Ils ne disent rien sur ce que fait la classe. Ils attirent le code non relie comme un aimant. Une classe qui s'appelle `Manager` n'a pas de responsabilite — elle en a 50.
|
|
33
|
+
**Faire plutot :** nommer les classes par leur responsabilite reelle. `UserRepository`, `UserAuthenticator`, `UserNotificationSender`. Si une classe a plus de 10 methodes publiques, la splitter par responsabilite. Les "utils" sont un signe qu'un concept manque dans le domaine.
|
|
34
|
+
|
|
35
|
+
## Patterns
|
|
36
|
+
### Composition over inheritance
|
|
37
|
+
**Quand :** quasi tout le temps.
|
|
38
|
+
**Comment :** au lieu de `class Duck extends Bird extends Animal`, injecter les comportements : `class Duck { constructor(flyBehavior, quackBehavior, swimBehavior) }`. Chaque comportement est interchangeable. Testable independamment. Le duck peut changer de FlyBehavior au runtime.
|
|
39
|
+
|
|
40
|
+
### Dependency injection par constructeur
|
|
41
|
+
**Quand :** toute classe qui depend d'un service externe (DB, API, file system).
|
|
42
|
+
**Comment :** `constructor(db: Database, logger: Logger)` — les dependances sont explicites. Pas de `new Database()` dans la classe. Pas de singleton global (`Database.getInstance()`). Le test peut injecter un mock/adaptateur. La classe ne sait pas CREER ses dependances, elle les RECOIT.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: performance
|
|
3
|
+
description: "Performance — mesurer avant d'optimiser, P95 > moyenne, performance budgets, profiling, N+1, slow queries. À charger quand on parle d'optimisation."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Performance
|
|
7
|
+
|
|
8
|
+
**Principe premier :** "Make it work, make it right, make it fast" — dans cet ordre. La performance est une feature, pas une propriété magique. Comme toute feature, elle a un coût et doit être mesurée. Le piège classique est l'optimisation prématurée : du code complexe et illisible pour gagner 5ms sur un endpoint appelé 10×/jour. La règle d'or : ne jamais optimiser sans avoir mesuré. Le bottleneck réel n'est presque jamais là où on pense. Et la métrique qui compte n'est pas la moyenne — c'est le P95 (ou P99). La moyenne ment parce qu'elle cache les outliers, et ce sont les outliers qui pourrissent l'expérience utilisateur.
|
|
9
|
+
|
|
10
|
+
## Checklist
|
|
11
|
+
- [ ] Profiling AVANT optimisation — jamais d'optimisation sur une intuition
|
|
12
|
+
- [ ] Métriques RED par endpoint : Rate, Errors, Duration (P50, P95, P99)
|
|
13
|
+
- [ ] Les requêtes N+1 sont identifiées et résolues (eager loading, batch, JOIN)
|
|
14
|
+
- [ ] Performance budget dans la CI : JS < 200KB, LCP < 2.5s, P95 < 500ms
|
|
15
|
+
- [ ] Les requêtes lentes sont loguées (> 100ms) avec EXPLAIN automatique
|
|
16
|
+
- [ ] Cache en place avec TTL explicite — pas de calcul redondant sur la hot path
|
|
17
|
+
|
|
18
|
+
## Anti-patterns
|
|
19
|
+
### Optimisation prématurée
|
|
20
|
+
**Ce qu'on voit :** micro-optimisations de boucles, bit-shifting, allocation pooling — sur un endpoint appelé 100×/jour. Le code est devenu illisible pour gagner 2ms.
|
|
21
|
+
**Pourquoi c'est dangereux :** l'optimisation prématurée a un double coût : le code devient plus dur à maintenir, et le temps passé à optimiser n'est pas passé sur des vrais problèmes. Pire : l'optimisation cible souvent le mauvais endroit parce qu'elle est basée sur l'intuition, pas sur la mesure.
|
|
22
|
+
**Faire plutôt :** "Make it work, make it right, make it fast." Mesurer. Profiler. Identifier le vrai bottleneck (souvent une requête DB, pas une boucle). Optimiser là où le profiling montre un gain. Si le gain est < 10%, se demander si la complexité ajoutée le justifie.
|
|
23
|
+
|
|
24
|
+
### Optimiser la moyenne
|
|
25
|
+
**Ce qu'on voit :** "la latence moyenne est de 200ms, c'est bon." Le P95 est à 8 secondes — 5% des utilisateurs attendent 8 secondes. Mais la moyenne est belle.
|
|
26
|
+
**Pourquoi c'est dangereux :** la moyenne est insensible aux outliers. 95% des requêtes à 50ms + 5% à 10s = moyenne de ~550ms. Tu regardes 550ms et tu penses "acceptable". Mais 5% de tes utilisateurs ont une expérience exécrable. Les percentiles existent pour cette raison précise.
|
|
27
|
+
**Faire plutôt :** P50 (médiane), P95, P99. Le P95 est l'expérience "normale dans le pire cas". Le P99 est l'expérience "vraiment mauvaise". Alerter et optimiser sur les percentiles, pas sur la moyenne.
|
|
28
|
+
|
|
29
|
+
### Cache sans stratégie
|
|
30
|
+
**Ce qu'on voit :** `cache.set(key, data)` sans TTL. Le cache garde des données stales indéfiniment. Ou pire : le cache est invalidé à chaque écriture mais jamais rechargé (cache toujours vide).
|
|
31
|
+
**Pourquoi c'est dangereux :** un cache mal conçu est pire que pas de cache — il ajoute de la latence (aller-retour Redis) pour servir des données périmées ou pour ne jamais avoir de hit. Le hit rate est la métrique qui dit si ton cache sert à quelque chose.
|
|
32
|
+
**Faire plutôt :** TTL explicite basé sur la fraîcheur acceptable. Surveiller le hit rate — si < 50%, le cache est probablement mal configuré. Cache-aside pour les lectures, write-through pour les lectures après écriture.
|
|
33
|
+
|
|
34
|
+
## Patterns
|
|
35
|
+
### Performance budget
|
|
36
|
+
**Quand :** application web ou mobile.
|
|
37
|
+
**Comment :** définir des seuils dans la CI. JS bundle < 200KB, page weight < 1MB, LCP < 2.5s, TTI < 3s, P95 API < 500ms. Si la PR dépasse, bloquer. Le budget force la discipline — comme un budget financier, tu ne peux pas ajouter sans enlever ailleurs.
|
|
38
|
+
|
|
39
|
+
### Slow query monitoring
|
|
40
|
+
**Quand :** toute application avec une base de données.
|
|
41
|
+
**Comment :** loguer toute requête > 100ms avec son EXPLAIN ANALYZE. Dashboard des slow queries. Alerte si une nouvelle slow query apparaît (requête qui était rapide avant, lente maintenant = probablement un index ou un volume de données). Chaque slow query est un ticket.
|