liteagents 2.12.0 → 2.14.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/CHANGELOG.md +56 -0
- package/README.md +6 -3
- package/installer/package-manager.js +1 -1
- package/package.json +1 -1
- package/packages/ampcode/agents/context-builder.md +1 -1
- package/packages/ampcode/commands/remember/AGENT_RULES.md +329 -0
- package/packages/ampcode/commands/{friction → remember}/friction.js +14 -14
- package/packages/ampcode/commands/remember.md +119 -27
- package/packages/ampcode/commands/stash.md +1 -1
- package/packages/claude/agents/context-builder.md +4 -4
- package/packages/claude/commands/remember/AGENT_RULES.md +329 -0
- package/packages/claude/commands/{friction → remember}/friction.js +14 -14
- package/packages/claude/commands/remember.md +119 -27
- package/packages/claude/commands/stash.md +1 -1
- package/packages/droid/commands/remember/AGENT_RULES.md +329 -0
- package/packages/droid/commands/{friction → remember}/friction.js +14 -14
- package/packages/droid/commands/remember.md +119 -27
- package/packages/droid/commands/stash.md +1 -1
- package/packages/droid/droids/context-builder.md +1 -1
- package/packages/opencode/agent/context-builder.md +1 -1
- package/packages/opencode/command/remember/AGENT_RULES.md +329 -0
- package/packages/opencode/command/{friction → remember}/friction.js +14 -14
- package/packages/opencode/command/remember.md +119 -27
- package/packages/opencode/command/stash.md +1 -1
- package/packages/subagentic-manual.md +9 -2
|
@@ -10,10 +10,17 @@ Run friction analysis, then consolidate session stashes + friction antigens into
|
|
|
10
10
|
- Favor straightforward, minimal implementations first and add complexity only when requested or clearly required.
|
|
11
11
|
- Keep changes tightly scoped to the requested outcome.
|
|
12
12
|
- **Precision over recall for hot memory.** A false antigen loaded into `@MEMORY.md` steers every future session. When unsure, record as a low-confidence episode — do not promote.
|
|
13
|
+
- **Mid-tier model, not hardcoded.** Steps 2/3/4a delegate to a mid-tier model — capable of
|
|
14
|
+
semantic judgment, cheaper/faster than your top reasoning tier (e.g. Claude's Sonnet vs
|
|
15
|
+
Opus). Use whatever your tool designates as that balanced default; never hardcode a
|
|
16
|
+
vendor-specific model name.
|
|
17
|
+
- **Batch independent subagent calls.** Step 2's per-stash extractions are independent of
|
|
18
|
+
each other — spawn them concurrently (parallel/background subagent calls in one turn)
|
|
19
|
+
where your tool supports it, instead of processing stashes one at a time.
|
|
13
20
|
|
|
14
21
|
**What it does**
|
|
15
22
|
|
|
16
|
-
Reads all raw material (`.amp/stash/*.md` + `.amp/friction/antigen_clusters.json`), extracts durable facts, episodes, and behavioral antigens into a single `.amp/
|
|
23
|
+
Reads all raw material (`.amp/stash/*.md` + `.amp/remember/friction/antigen_clusters.json`), extracts durable facts, episodes, and behavioral antigens into a single `.amp/remember/MEMORY.md`, then injects a managed memory section into `AGENT.md`.
|
|
17
24
|
|
|
18
25
|
**Steps**
|
|
19
26
|
|
|
@@ -23,7 +30,7 @@ Reads all raw material (`.amp/stash/*.md` + `.amp/friction/antigen_clusters.json
|
|
|
23
30
|
project are behavioral lessons worth keeping everywhere. So point it at the tool's
|
|
24
31
|
**global sessions root** (all projects), not a per-project directory.
|
|
25
32
|
|
|
26
|
-
- **Locate `friction.js`** — it is bundled next to this command at `
|
|
33
|
+
- **Locate `friction.js`** — it is bundled next to this command at `remember/friction.js`
|
|
27
34
|
(the same directory as `remember.md`, whether installed or run from the package). If it
|
|
28
35
|
exists nowhere, skip to step 1 (stash-only) and tell the user friction.js is missing.
|
|
29
36
|
- **Resolve the global sessions root** — probe this list top-to-bottom, use the first that
|
|
@@ -41,7 +48,7 @@ Reads all raw material (`.amp/stash/*.md` + `.amp/friction/antigen_clusters.json
|
|
|
41
48
|
> will resolve but yield no signals until friction learns their formats — open an issue
|
|
42
49
|
> to request one: https://github.com/hamr0/liteagents/issues
|
|
43
50
|
- **Run** `node <friction.js> "<resolved-root>"`. friction writes its output to
|
|
44
|
-
`.amp/friction/` in the current project.
|
|
51
|
+
`.amp/remember/friction/` in the current project.
|
|
45
52
|
- **On any miss — loud, never silent.** If no root resolves, or friction errors, or it
|
|
46
53
|
finds no usable sessions, print this and continue with stash-only consolidation:
|
|
47
54
|
> ⚠️ Friction didn't run — no sessions found. To enable it, open this command file
|
|
@@ -49,27 +56,41 @@ Reads all raw material (`.amp/stash/*.md` + `.amp/friction/antigen_clusters.json
|
|
|
49
56
|
> list in step 0, then re-run `/remember`. Consolidating stashes only this time.
|
|
50
57
|
|
|
51
58
|
1. **Gather sources**
|
|
59
|
+
- **Legacy layout migration (one-time, loud).** Older versions used `.amp/memory/` and
|
|
60
|
+
`.amp/friction/`. If either exists: move the pipeline files
|
|
61
|
+
`.amp/memory/{MEMORY.md,ledger.json,.processed}` → `.amp/remember/`, and **discard**
|
|
62
|
+
the old `.amp/friction/` contents entirely — friction regenerates all of its output
|
|
63
|
+
fresh every run (step 0 has already rebuilt it in `.amp/remember/friction/` by the time
|
|
64
|
+
migration runs; stale copies carry no unique information and moving them would overwrite
|
|
65
|
+
fresh output). **Move only those pipeline files** — anything else in `.amp/memory/`
|
|
66
|
+
(e.g. user-owned rule files) stays where it is. Remove the old dirs only if empty, update the managed MEMORY section in AGENT.md to
|
|
67
|
+
the new reference (step 5), and tell the user exactly what moved.
|
|
68
|
+
- **Bootstrap `AGENT_RULES.md` (one-time, silent-if-present).** If
|
|
69
|
+
`.amp/remember/AGENT_RULES.md` does not exist, copy it from the bundled template next
|
|
70
|
+
to this command (`remember/AGENT_RULES.md`, same directory as `friction.js`). If it
|
|
71
|
+
already exists, leave it untouched — never overwrite, even if the bundled template
|
|
72
|
+
changes in a later version; it becomes user-owned the moment it lands in the project.
|
|
52
73
|
- Read all `.amp/stash/*.md` files in the current project
|
|
53
|
-
- Read friction output written in step 0: `.amp/friction/antigen_clusters.json` (preferred) or `.amp/friction/antigen_review.md` (fallback)
|
|
54
|
-
- Read existing `.amp/
|
|
55
|
-
- Read processed manifest at `.amp/
|
|
74
|
+
- Read friction output written in step 0: `.amp/remember/friction/antigen_clusters.json` (preferred) or `.amp/remember/friction/antigen_review.md` (fallback)
|
|
75
|
+
- Read existing `.amp/remember/MEMORY.md` if it exists — create dir if missing
|
|
76
|
+
- Read processed manifest at `.amp/remember/.processed` — skip already-processed stashes
|
|
56
77
|
- If no unprocessed stashes AND friction produced no new antigens, report "nothing to consolidate" and stop
|
|
57
78
|
|
|
58
|
-
2. **Extract from unprocessed stashes** (
|
|
59
|
-
- For each unprocessed stash, call
|
|
79
|
+
2. **Extract from unprocessed stashes** (spawn one subagent per stash, in parallel — see Guardrails)
|
|
80
|
+
- For each unprocessed stash, call the mid-tier model (see Guardrails) to extract:
|
|
60
81
|
- **FACTS** (atomic, one-line): stable preferences, decisions, corrections, explicit "remember this"
|
|
61
82
|
- **EPISODE** (3-5 bullet narrative): what was the goal, what was tried, outcome, lesson
|
|
62
83
|
- **SKIP**: code details, file paths, errors, mechanical steps, LLM responses
|
|
63
84
|
- Collect all new facts and episodes
|
|
64
85
|
|
|
65
86
|
3. **Merge into MEMORY.md**
|
|
66
|
-
- Read existing `.amp/
|
|
67
|
-
- **Facts section**: call
|
|
87
|
+
- Read existing `.amp/remember/MEMORY.md` and parse its sections (## Facts, ## Episodes, ## Antigens)
|
|
88
|
+
- **Facts section**: call the mid-tier model with existing facts + newly extracted facts
|
|
68
89
|
- Rules: new updates replace old, contradictions keep new version, duplicates dropped
|
|
69
90
|
- Keep facts atomic, one line each
|
|
70
91
|
- **Episodes section**: append new episode entries (append-only, timestamped, no dedup)
|
|
71
92
|
- **Antigens section**: only update from friction output (step 4)
|
|
72
|
-
- Write merged result to `.amp/
|
|
93
|
+
- Write merged result to `.amp/remember/MEMORY.md` in the format under step 6.
|
|
73
94
|
|
|
74
95
|
4. **Distill friction into antigens** (only if friction output exists)
|
|
75
96
|
|
|
@@ -83,9 +104,9 @@ Reads all raw material (`.amp/stash/*.md` + `.amp/friction/antigen_clusters.json
|
|
|
83
104
|
> *themselves*). **You work from these short quotes — never re-read the session
|
|
84
105
|
> logs.** Friction's lexical grouping and flags are hints, not the verdict.
|
|
85
106
|
|
|
86
|
-
- Read `.amp/friction/antigen_clusters.json`.
|
|
107
|
+
- Read `.amp/remember/friction/antigen_clusters.json`.
|
|
87
108
|
- **4a. Classify target, then semantically consolidate** (the parts lexical matching can't do).
|
|
88
|
-
Call
|
|
109
|
+
Call the mid-tier model with the cluster quotes + their `preceding`/`projects`/`sessions`/`self_suspect`
|
|
89
110
|
(NOT the logs), and have it:
|
|
90
111
|
1. **Decide the target of each reaction — agent or self.** Drop *self/context*
|
|
91
112
|
corrections where the user redirected themselves ("wrong project", "wrong window",
|
|
@@ -114,21 +135,80 @@ Reads all raw material (`.amp/stash/*.md` + `.amp/friction/antigen_clusters.json
|
|
|
114
135
|
- **High** (5+ sessions) → loaded hot via `@MEMORY.md`
|
|
115
136
|
- **Medium** (3-4 sessions) → recorded under Antigens, *not* loaded hot
|
|
116
137
|
- **Low** (<3 sessions) → keep as Episode only
|
|
138
|
+
- **Recurrence tiers bind everything, including LLM-merged groups:** merging consolidates
|
|
139
|
+
evidence, it never elevates it — a merged group's tier comes from its combined
|
|
140
|
+
distinct-session count (e.g. a 2-session merged group is still Low → Episode + ledger
|
|
141
|
+
`observing`, not an antigen entry in MEMORY.md).
|
|
117
142
|
- **Never auto-promote.** Only High-confidence (5+ sessions) antigens load hot. A
|
|
118
143
|
single dramatic correction is an Episode, not an antigen.
|
|
119
144
|
- Update the Antigens section in MEMORY.md (promote/demote based on new recurrence).
|
|
145
|
+
- **4c. Update the antigen ledger** (`.amp/remember/ledger.json`) — the evidence trail
|
|
146
|
+
linking each rule to the mistake it targets and whether it is working. Create it as
|
|
147
|
+
`{"version": 1, "entries": []}` if missing. It is JSON for exact matching — bookkeeping
|
|
148
|
+
only, never injected into context as guidance (MEMORY.md is what gets read; the ledger
|
|
149
|
+
is what gets checked).
|
|
120
150
|
|
|
121
|
-
|
|
151
|
+
Entry shape:
|
|
152
|
+
```json
|
|
153
|
+
{ "id": "ag-001", "class": "claimed-done-not-verified",
|
|
154
|
+
"class_hints": ["says pushed but", "none got it"],
|
|
155
|
+
"status": "observing|hot|rejected|escalated",
|
|
156
|
+
"rule": "<current phrasing>",
|
|
157
|
+
"attempts": [{ "n": 1, "rule": "<phrasing>", "adopted": "YYYY-MM-DD", "outcome": "active|failed" }],
|
|
158
|
+
"evidence": { "sessions": 0, "projects": [], "quotes": [], "last_seen": "YYYY-MM-DD" },
|
|
159
|
+
"recurred_while_hot": 0,
|
|
160
|
+
"history": [{ "date": "YYYY-MM-DD", "event": "<transition>" }] }
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
For each surviving antigen from 4a/4b, match against existing entries by `class_hints`
|
|
164
|
+
(the mistake class, not the rule wording — rules change, the class doesn't):
|
|
165
|
+
- **No match** → new entry, `status: "observing"`, attempt 1, history "candidate (N sessions)".
|
|
166
|
+
- **Match, `observing`** → merge evidence (sessions, quotes, projects, last_seen).
|
|
167
|
+
Crosses the 4b hot threshold → `status: "hot"`, history "promoted to hot (N sessions)".
|
|
168
|
+
- **Match, `hot`** → the mistake happened *while its rule was loaded*:
|
|
169
|
+
`recurred_while_hot += 1`, merge evidence, history "recurred while hot (count)".
|
|
170
|
+
- At `recurred_while_hot >= 2`: the phrasing failed. Mark the current attempt
|
|
171
|
+
`outcome: "failed"`, draft attempt n+1 — it must differ from **every** prior
|
|
172
|
+
attempt's text in this entry (failed attempts are the rejected-edit buffer: never
|
|
173
|
+
re-propose one verbatim) — replace `rule`, update MEMORY.md's Antigens section,
|
|
174
|
+
reset `recurred_while_hot` to 0.
|
|
175
|
+
- If 2 attempts have already failed and the antigen persists → `status: "escalated"`:
|
|
176
|
+
remove the rule from MEMORY.md's hot section, record a Fact instead ("persistent
|
|
177
|
+
failure mode: <class> — no phrasing reduces it"), and flag it in the step-7 report.
|
|
178
|
+
**Flag, don't act** — the user decides: enforcement (a hook, where the tool has
|
|
179
|
+
them) or accepted limit.
|
|
180
|
+
- **Match, `escalated`/`rejected`** (rejected = user veto) → merge evidence only; never re-propose.
|
|
181
|
+
|
|
182
|
+
Consistency: MEMORY.md's Antigens section is the render; the ledger is the record —
|
|
183
|
+
after 4c every hot antigen in MEMORY.md has a matching `hot` ledger entry. Mutations
|
|
184
|
+
are append-friendly: merge evidence and change status, never delete entries or history
|
|
185
|
+
lines. If ledger.json is malformed, say so loudly, move it aside as
|
|
186
|
+
`ledger.json.bad-<date>`, and start fresh — never silently overwrite.
|
|
187
|
+
|
|
188
|
+
5. **Inject memory + rules references into AGENT.md**
|
|
122
189
|
- Compose the section between `<!-- MEMORY:START -->` and `<!-- MEMORY:END -->` markers:
|
|
123
190
|
```
|
|
124
191
|
<!-- MEMORY:START -->
|
|
125
|
-
|
|
192
|
+
@.amp/remember/MEMORY.md
|
|
126
193
|
<!-- MEMORY:END -->
|
|
127
194
|
```
|
|
128
|
-
- The
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
195
|
+
- The reference is an **explicit path** (`@.amp/remember/MEMORY.md`) — `@`-references
|
|
196
|
+
resolve relative to the file containing them, so a bare `@MEMORY.md` in the project root
|
|
197
|
+
would point at a nonexistent root-level file. Claude loads the full file directly, so no
|
|
198
|
+
inline duplication is needed
|
|
199
|
+
- If `.amp/remember/AGENT_RULES.md` exists (bootstrapped in step 1), compose a second,
|
|
200
|
+
independent section between `<!-- AGENT_RULES:START -->` and `<!-- AGENT_RULES:END -->`
|
|
201
|
+
markers:
|
|
202
|
+
```
|
|
203
|
+
<!-- AGENT_RULES:START -->
|
|
204
|
+
Consult when building something new or adding a feature — a standards guide, not hot
|
|
205
|
+
context like MEMORY.md above:
|
|
206
|
+
@.amp/remember/AGENT_RULES.md
|
|
207
|
+
<!-- AGENT_RULES:END -->
|
|
208
|
+
```
|
|
209
|
+
- Each marker pair is independent: if AGENT.md already has a given pair, replace the
|
|
210
|
+
section between them; if not, append it at the end; if no AGENT.md exists, create one
|
|
211
|
+
containing whichever section(s) apply
|
|
132
212
|
|
|
133
213
|
```markdown
|
|
134
214
|
# Project Memory
|
|
@@ -153,19 +233,31 @@ Reads all raw material (`.amp/stash/*.md` + `.amp/friction/antigen_clusters.json
|
|
|
153
233
|
```
|
|
154
234
|
|
|
155
235
|
6. **Update processed manifest**
|
|
156
|
-
- Append paths of newly processed stashes to `.amp/
|
|
236
|
+
- Append paths of newly processed stashes to `.amp/remember/.processed`
|
|
157
237
|
|
|
158
|
-
7. **Report to user**
|
|
238
|
+
7. **Report to user** — print it AND write the same content to `.amp/remember/report.md`
|
|
239
|
+
(overwritten each run; the ledger keeps history — the report is just the latest snapshot)
|
|
159
240
|
- Number of stashes processed
|
|
160
241
|
- Facts count (total, new)
|
|
161
242
|
- Episodes count (total, new)
|
|
162
243
|
- Antigens count by confidence tier, with how many newly promoted to hot
|
|
244
|
+
- Ledger lines — one per non-observing entry: id, short rule, status, recurrences since
|
|
245
|
+
adoption. Highlight rephrased (RECURRED) and ESCALATED entries; escalations need a
|
|
246
|
+
user decision, e.g.:
|
|
247
|
+
```
|
|
248
|
+
ledger: ag-001 "verify live after publish" hot, 0 recurrences since 2026-07-10
|
|
249
|
+
ledger: ag-003 "don't commit per change" RECURRED while hot (2/2) → rephrased, attempt 2
|
|
250
|
+
ledger: ag-002 "literal scoped ask" ESCALATED → Fact; 2 phrasings failed. Hook or accept?
|
|
251
|
+
```
|
|
252
|
+
- If AGENT_RULES.md was bootstrapped this run, say so (one line)
|
|
163
253
|
- Confirm MEMORY.md and AGENT.md updated
|
|
164
254
|
|
|
165
|
-
**File locations (all project-local)**
|
|
166
|
-
- Memory file: `.amp/memory/MEMORY.md` (single source of truth, referenced as @MEMORY.md)
|
|
255
|
+
**File locations (all project-local — two dirs: `/stash` owns `.amp/stash/`, `/remember` owns `.amp/remember/`)**
|
|
167
256
|
- Stash files: `.amp/stash/*.md`
|
|
168
|
-
-
|
|
169
|
-
-
|
|
170
|
-
-
|
|
171
|
-
-
|
|
257
|
+
- Memory file: `.amp/remember/MEMORY.md` (single source of truth, referenced as `@.amp/remember/MEMORY.md`)
|
|
258
|
+
- Rules template: `.amp/remember/AGENT_RULES.md` (bootstrapped once from the bundled package template on first `/remember` run, never overwritten again — user-owned after that; referenced as `@.amp/remember/AGENT_RULES.md`)
|
|
259
|
+
- Antigen ledger: `.amp/remember/ledger.json` (per-rule evidence trail: class, status, attempts/rejected-buffer, recurrence-while-hot)
|
|
260
|
+
- Consolidation report: `.amp/remember/report.md` (latest step-7 report, overwritten each run)
|
|
261
|
+
- Processed manifest: `.amp/remember/.processed`
|
|
262
|
+
- Friction output (transient, regenerated each run): `.amp/remember/friction/` — `antigen_clusters.json` (preferred input), `antigen_review.md` (fallback), plus raw analysis files
|
|
263
|
+
- Output: `AGENT.md` (managed MEMORY section, plus an AGENT_RULES section once bootstrapped)
|
|
@@ -18,7 +18,7 @@ Save session context for compaction recovery or handoffs.
|
|
|
18
18
|
4. Creates stash file in `.amp/stash/`
|
|
19
19
|
5. Enables context restoration after compaction
|
|
20
20
|
6. **Consolidation nudge** — after saving, count the unprocessed backlog:
|
|
21
|
-
`unprocessed = (files in .amp/stash/*.md) − (entries in .amp/
|
|
21
|
+
`unprocessed = (files in .amp/stash/*.md) − (entries in .amp/remember/.processed)`
|
|
22
22
|
(a missing `.processed` manifest means 0 processed). If `unprocessed >= 5`, end with one line:
|
|
23
23
|
> 📝 N stashes since last consolidation — run `/remember` to fold them into memory.
|
|
24
24
|
|
|
@@ -93,7 +93,7 @@ digraph ContextBuilder {
|
|
|
93
93
|
|
|
94
94
|
**Rule:** Plain text paths only (no @ triggers) in Tier 1 and 2, with ONE exception:
|
|
95
95
|
|
|
96
|
-
**Permanent reference:**
|
|
96
|
+
**Permanent reference:** the explicit-path `@` reference to `.claude/remember/MEMORY.md` — this is the only file allowed to use @ for direct loading. It contains project memory (facts, episodes, preferences) auto-generated by `/remember`. Always check for it during discovery. If it exists, include it as a source and ensure CLAUDE.md references it.
|
|
97
97
|
|
|
98
98
|
# Anti-Patterns
|
|
99
99
|
|
|
@@ -108,8 +108,8 @@ digraph ContextBuilder {
|
|
|
108
108
|
# Workflow
|
|
109
109
|
|
|
110
110
|
## 1. Discovery
|
|
111
|
-
Scan: README, /docs, *.md, `.claude/
|
|
112
|
-
If `.claude/
|
|
111
|
+
Scan: README, /docs, *.md, `.claude/remember/MEMORY.md` → Identify project type (app, lib, monorepo) → Ask what's needed every session
|
|
112
|
+
If `.claude/remember/MEMORY.md` exists, read it first — it contains accumulated project knowledge from previous sessions.
|
|
113
113
|
|
|
114
114
|
## 2. Tier 3: docs/*.md (Comprehensive)
|
|
115
115
|
Create detailed docs: `architecture.md`, `development.md`, `api-reference.md`, `troubleshooting.md`
|
|
@@ -118,7 +118,7 @@ Create detailed docs: `architecture.md`, `development.md`, `api-reference.md`, `
|
|
|
118
118
|
Format: `## Topic` + 1-2 sentence summary + `→ docs/file.md`
|
|
119
119
|
|
|
120
120
|
## 4. Tier 1: CLAUDE.md (Essentials)
|
|
121
|
-
Include: Project summary (2-3 sentences), Tech stack (list), Commands (essential only), Key patterns (top 3), Pointer to `docs/KNOWLEDGE_BASE.md`,
|
|
121
|
+
Include: Project summary (2-3 sentences), Tech stack (list), Commands (essential only), Key patterns (top 3), Pointer to `docs/KNOWLEDGE_BASE.md`, memory reference (if `.claude/remember/MEMORY.md` exists)
|
|
122
122
|
|
|
123
123
|
## 5. Update Existing (when CLAUDE.md exists)
|
|
124
124
|
Read existing → Preserve structure → Merge new info → Update Tier 2/3 if needed → Validate limits
|
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
# AI Agent Collaboration Guide
|
|
2
|
+
|
|
3
|
+
## Table of Contents
|
|
4
|
+
1. [Operating Flow](#operating-flow)
|
|
5
|
+
2. [Communication Protocol](#communication-protocol)
|
|
6
|
+
3. [Development Standards](#development-standards)
|
|
7
|
+
4. [Testing Standards](#testing-standards)
|
|
8
|
+
5. [Security & Robustness Invariants](#security--robustness-invariants)
|
|
9
|
+
6. [Guardrails (Enforced, Not Requested)](#guardrails-enforced-not-requested)
|
|
10
|
+
7. [Environment](#environment)
|
|
11
|
+
8. [Development Workflow](#development-workflow)
|
|
12
|
+
9. [Twelve-Factor Checklist](#twelve-factor-checklist)
|
|
13
|
+
10. [CLAUDE.md Stub](#claudemd-stub)
|
|
14
|
+
11. [AI Agent Instructions](#ai-agent-instructions)
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Operating Flow
|
|
19
|
+
|
|
20
|
+
Every task runs through three layers. Do not skip ahead to code.
|
|
21
|
+
|
|
22
|
+
1. **Spec — agree on intent before touching anything.** Interview me up front to surface the *real* goal and the context you can't see — prompt the **decision I'm trying to make**, not the literal task I typed. Break the scope into small buckets with checkpoints. **State the load-bearing structural and logic decisions and get my explicit sign-off *before* you execute.** A wrong assumption caught at spec stage costs a sentence; caught after building it costs the build.
|
|
23
|
+
2. **Verify — define "good" up front, then prove it.** Write down what success looks like *before* changing code. Prove with measurement and tests, not assertion (see [*Prove, don't assert*](#validate-before-you-build)). Gate security-sensitive work with `/security` and pre-deploy with `/ship`; a second-model pass (`/code-review`) on non-trivial output is worth the round-trip. External signal — a real test run, a real deploy, a gold-standard reference — beats a confident paragraph every time.
|
|
24
|
+
3. **Environment — the guardrails are enforced, not requested.** This file is the standing context that primes every session. Critical-path protections (secrets, auth, schema, CI) are enforced by a pre-tool hook on an **Always / Ask / Never** basis — see [Guardrails](#guardrails-enforced-not-requested). Where the hook isn't wired, the same rules still bind you.
|
|
25
|
+
|
|
26
|
+
> The model is brilliant at execution and blind to intent. You can outsource the typing; you cannot outsource the understanding. Surface assumptions — don't bury them.
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Communication Protocol
|
|
31
|
+
|
|
32
|
+
### Core Rules
|
|
33
|
+
- **Spec before build**: Don't wait for ambiguity to block you — interview me up front to extract the real goal and the context you can't see. Prompt the *decision*, not the literal task. Restate what you heard before building
|
|
34
|
+
- **Checkpoint before executing**: State the load-bearing structural and logic decisions and get my explicit sign-off *before* you write code. Never run ahead on an unverified assumption — flag it and stop
|
|
35
|
+
- **Fact-Based**: Base all recommendations on verified, current information. Prefer external signal (a real run, a real source) over a confident guess
|
|
36
|
+
- **Simplicity Advocate**: Call out overcomplications and suggest simpler alternatives
|
|
37
|
+
- **Safety First**: Never modify critical systems without explicit understanding and approval. Where the [guardrail hook](#guardrails-enforced-not-requested) is wired, this is enforced before the tool runs, not after
|
|
38
|
+
|
|
39
|
+
### User Profile
|
|
40
|
+
- **Technical Level**: Non-coder but technically savvy
|
|
41
|
+
- **Learning Style**: Understands concepts, needs executable instructions
|
|
42
|
+
- **Expects**: Step-by-step guidance with clear explanations
|
|
43
|
+
- **Comfortable with**: Command-line operations and scripts
|
|
44
|
+
- **Builds a lot of web apps** — assume any UI work will be consumed on phones as well as desktop
|
|
45
|
+
|
|
46
|
+
### Required Safeguards (Always / Ask / Never)
|
|
47
|
+
|
|
48
|
+
Not courtesies — where the [guardrail hook](#guardrails-enforced-not-requested) is wired these are enforced *before* the tool runs. When it isn't, they still bind you.
|
|
49
|
+
|
|
50
|
+
- **Always** identify affected files before making changes, and explain what will change and why
|
|
51
|
+
- **Ask first** — stop and get explicit sign-off — before modifying authentication systems, database schema or migrations, CI workflows, or `.claude/settings.json`
|
|
52
|
+
- **Never** write secrets into the tree (`.env`/`*.env`, keys, credentials). They load from the environment at runtime; only a value-less `.env.example` is committed
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## Development Standards
|
|
57
|
+
|
|
58
|
+
### Validate Before You Build
|
|
59
|
+
|
|
60
|
+
- **POC everything first.** Before committing to a design, build a quick proof-of-concept (~15 min) that validates the core logic. Keep it stupidly simple — manual steps are fine, hardcoded values are fine, no tests needed yet
|
|
61
|
+
- **POC scope:** Cover the happy path, 2-3 common edge cases, **and the riskiest assumption (see below) — not just the parts that are easy to check**. If those hold, the idea is sound
|
|
62
|
+
- **Graduation criteria:** POC validates logic and covers most common scenarios → stop, design properly, then build with structure, tests, and error handling. Never ship the POC — rewrite it
|
|
63
|
+
- **Aim the POC at the load-bearing claim — not the easy part.** Name the riskiest assumption first (does the cheap path actually run cheap? does the library really do X? does the perf hold?), then point the spike straight at *that*. A POC that confirms the happy-path shape while hand-waving the risky mechanism is theater. If you catch yourself writing "production would do X" instead of *doing* X in the spike, the POC has not validated X — go do X
|
|
64
|
+
- **Prove, don't assert — a POC's output is evidence you ran, not prose you wrote.** Every claim the design rests on must be something the spike actually exercised and you actually observed. **Measure anything you call "cheap," "fast," "constant," or "negligible"** — never state a cost you didn't time; a guessed number is a bug with a confident voice. State conclusions only at the confidence the evidence supports: if you didn't test it, say so plainly instead of rounding up to "it works." Better a small honest finding than a big-mouthed claim that measurement later falsifies
|
|
65
|
+
- **The test must be able to FAIL — pre-flight check, not an afterthought.** Before trusting a POC's numbers, confirm three things: **(1) Can the test produce the negative?** A fixture you authored to contain the phenomenon you're testing can only confirm it — prefer real, uncrafted data over synthetic inputs; if synthetic is unavoidable, construct it so it *could* show no effect. **(2) Is the harness free of confounds?** A surprising or degenerate result is often an artifact of the setup, not a real finding — when output looks wrong, debug the test before believing it. **(3) Did the test actually exercise the variable?** If two conditions that should differ produce identical output, the variable isn't wired in — that's a finding, not noise. Run this checklist every time, especially when a result confirms what you hoped
|
|
66
|
+
- **Build incrementally.** After POC graduates, break the work into small, independent modules. Focus on one at a time. Each piece must work on its own before integrating with the next
|
|
67
|
+
|
|
68
|
+
### Dependency Hierarchy
|
|
69
|
+
|
|
70
|
+
Always exhaust the simpler option before reaching for the next:
|
|
71
|
+
|
|
72
|
+
1. **Vanilla language** — Write it yourself using only language primitives. If it's <50 lines and not security-critical, this is the answer
|
|
73
|
+
2. **Standard library** — Use built-in modules (`os`, `json`, `pathlib`, `http`, `fs`, `crypto`). The stdlib is tested, maintained, and has zero supply chain risk
|
|
74
|
+
3. **External library** — Only when both vanilla and stdlib are insufficient. Must pass the checklist below
|
|
75
|
+
|
|
76
|
+
### External Dependency Checklist
|
|
77
|
+
|
|
78
|
+
Before adding any external dependency, all of these must be true:
|
|
79
|
+
- **Necessity:** Can't reasonably implement this with stdlib in <100 lines
|
|
80
|
+
- **Maintained:** Active commits in the last 6 months, responsive maintainer
|
|
81
|
+
- **Lightweight:** Few transitive dependencies (check the dep tree, not just the top-level)
|
|
82
|
+
- **Established:** Widely used, not a single-maintainer hobby project for production-critical code
|
|
83
|
+
- **Security-aware:** For security-critical domains (crypto, auth, sanitization, parsing untrusted input), a vetted library is *required* — never roll your own
|
|
84
|
+
|
|
85
|
+
### Language Selection
|
|
86
|
+
|
|
87
|
+
- **Use widely-adopted languages only** — Python, JavaScript/TypeScript, Go, Rust. No niche languages unless the domain demands it
|
|
88
|
+
- **Pick the lightest language that fits the domain:** shell scripts for automation, Python for data/backend/CLI, TypeScript for web, Go for systems/infra, Rust for performance-critical
|
|
89
|
+
- **Minimize the polyglot tax.** Every language in the stack adds CI config, tooling, and onboarding friction. Do not add a new language for one microservice — use what's already in the stack unless there's a compelling reason
|
|
90
|
+
- **Vanilla over frameworks.** Express over NestJS, Flask over Django, unless the project genuinely needs the framework's structure. Structure can always be added later; removing a framework is painful
|
|
91
|
+
|
|
92
|
+
### Build Rules
|
|
93
|
+
|
|
94
|
+
- **Open-source only.** Always use open-source solutions. No vendor lock-in
|
|
95
|
+
- **Lightweight over complex.** If two solutions solve the same problem, use the one with fewer moving parts, fewer dependencies, and less configuration
|
|
96
|
+
- **Every line must have a purpose.** No speculative code, no "might need this later", no abstractions for one use case
|
|
97
|
+
- **Simple > clever.** Readable code that a junior can follow beats elegant code that requires a PhD to debug
|
|
98
|
+
- **Containerize only when necessary.** Start with a virtualenv or bare metal. Docker adds value for deployment parity and isolation — not for running a script
|
|
99
|
+
- **Responsive web UI is mandatory in dev projects.** Any web UI must be usable on mobile by default — fluid layouts, viewport meta tag, breakpoints for narrow screens, no horizontal scroll. Test in DevTools device emulation before declaring a UI task done. POCs are exempt (validate the idea first), but the moment a POC graduates to a real project this becomes a hard requirement
|
|
100
|
+
- **Surgical changes only.** Touch what the task requires; nothing else. Don't "improve" adjacent code, comments, or formatting. Match existing style even if you'd do it differently. Only clean up orphans your own change created — leave pre-existing dead code alone unless asked. Every changed line should trace directly to the request
|
|
101
|
+
|
|
102
|
+
### Red Flags — Stop and Flag These
|
|
103
|
+
- Over-engineering simple problems
|
|
104
|
+
- Adding external dependencies for trivial operations
|
|
105
|
+
- Frameworks where a library or stdlib would suffice
|
|
106
|
+
- Vendor-specific implementations when open alternatives exist
|
|
107
|
+
- Skipping POC validation for unproven ideas
|
|
108
|
+
- POC-ing only the easy part while hand-waving the risky mechanism, or claiming a cost ("cheap"/"fast"/"constant") you never measured
|
|
109
|
+
- Authoring a fixture/corpus that *guarantees* the result (a test that can't return the negative), or trusting a degenerate-looking number without auditing the harness for confounds — use real uncrafted data; the test must be able to fail
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## Testing Standards
|
|
114
|
+
|
|
115
|
+
### Rules
|
|
116
|
+
|
|
117
|
+
**Test behavior, not implementation.** A test suite must give you confidence to refactor freely. If changing internal code (without changing behavior) breaks tests, those tests are liabilities, not assets.
|
|
118
|
+
|
|
119
|
+
**Follow the Testing Trophy** (not the Testing Pyramid):
|
|
120
|
+
- Few unit tests — only for pure logic, algorithms, and complex calculations
|
|
121
|
+
- Many integration tests — the sweet spot; test real components working together
|
|
122
|
+
- Some E2E tests — cover critical user journeys end-to-end
|
|
123
|
+
- Static analysis — types and linters catch bugs cheaper than tests
|
|
124
|
+
|
|
125
|
+
### When to Write Tests
|
|
126
|
+
|
|
127
|
+
- **After the design stabilizes, not during exploration.** Do not TDD a prototype — you'll write 500 tests for code you delete tomorrow. First make it work (POC), then make it right (refactor + tests), then make it fast
|
|
128
|
+
- **Write tests when the code has users.** If a function is called by other modules or exposed to users, it needs tests. Internal helpers that only serve one caller don't need their own test file
|
|
129
|
+
- **Write tests for bugs.** Every bug fix must include a regression test that fails before the fix and passes after. This is the highest-value test you can write
|
|
130
|
+
- **Write tests before refactoring.** Before changing working code, write characterization tests first to lock in current behavior, then refactor with confidence
|
|
131
|
+
- **Do not write tests for glue code.** Code that just wires components together (calls A then B then C) is tested at the integration level, not unit level
|
|
132
|
+
|
|
133
|
+
### TDD: When It Works and When It Doesn't
|
|
134
|
+
|
|
135
|
+
- **TDD works for:** Pure functions, algorithms, parsers, validators, data transformations — anything with clear inputs and outputs
|
|
136
|
+
- **TDD does not work for:** Exploring a design, building a POC, or unstable interfaces. Writing tests for unstable APIs creates churn and false confidence
|
|
137
|
+
- **The rule:** You must understand what you're building before you TDD it. TDD is a design tool for known problems, not a discovery tool for unknown ones
|
|
138
|
+
- **Red-green-refactor discipline:** If you do TDD, follow the cycle strictly. Write a failing test, write minimal code to pass, refactor. Do not write 20 tests then implement — that's front-loading waste
|
|
139
|
+
|
|
140
|
+
### What Makes a Good Test
|
|
141
|
+
|
|
142
|
+
- **Tests real behavior.** Call the public API, assert on observable output. Do not reach into internals
|
|
143
|
+
- **Fails for the right reason.** A good test fails when the feature is broken, not when the implementation changes
|
|
144
|
+
- **Reads like a spec.** Someone unfamiliar with the code must understand what the feature does by reading the test
|
|
145
|
+
- **Self-contained.** Each test sets up its own state, runs, and cleans up. No ordering dependencies between tests
|
|
146
|
+
- **Fast and deterministic.** Flaky tests erode trust. If a test depends on timing, network, or global state, fix that dependency
|
|
147
|
+
|
|
148
|
+
### Anti-Patterns — Do Not Do These
|
|
149
|
+
|
|
150
|
+
- **Mocking more than 60% of the test.** If most of the test is mock setup, you're testing mocks, not code. Use real implementations with `tmp_path`, `:memory:` SQLite, or test containers
|
|
151
|
+
- **Smoke tests.** `assert result is not None` proves nothing. Assert on specific values, structure, or side effects
|
|
152
|
+
- **Testing private methods.** If you need to test a private method, either it should be public or the public method's tests should cover it
|
|
153
|
+
- **Mirroring implementation.** Tests that replicate the source code line-by-line break on every refactor and catch zero bugs
|
|
154
|
+
- **Test-only production code.** Never add methods, flags, or branches to production code solely for testing. Use dependency injection instead
|
|
155
|
+
|
|
156
|
+
### Test Organization
|
|
157
|
+
|
|
158
|
+
- **Co-locate tests with packages:** `packages/<pkg>/tests/` not a root `tests/` directory. Each package owns its tests
|
|
159
|
+
- **Separate by type:**
|
|
160
|
+
```
|
|
161
|
+
packages/<pkg>/tests/
|
|
162
|
+
unit/ # Fast, isolated, mocked deps, <1s each
|
|
163
|
+
integration/ # Real DB, filesystem, multi-component, <10s each
|
|
164
|
+
e2e/ # Full workflows, subprocess calls, <60s each
|
|
165
|
+
conftest.py # Shared fixtures for this package
|
|
166
|
+
```
|
|
167
|
+
- **One test file per module** (not per function). `test_auth.py` tests the auth module, not `test_login.py` + `test_logout.py` + `test_session.py`
|
|
168
|
+
- **No duplicate test files.** Before creating a new test file, check if one already exists for that module
|
|
169
|
+
|
|
170
|
+
### Markers and Signals
|
|
171
|
+
|
|
172
|
+
| Marker | Purpose | CI Behavior |
|
|
173
|
+
|--------|---------|-------------|
|
|
174
|
+
| `@pytest.mark.slow` | Runtime > 5s | Run in full suite, skip in quick checks |
|
|
175
|
+
| `@pytest.mark.ml` | Requires ML deps (torch, etc.) | Skip if deps not installed |
|
|
176
|
+
| `@pytest.mark.real_api` | Calls external APIs | Skip in CI — run manually before release |
|
|
177
|
+
|
|
178
|
+
**CI runs for fast signals:**
|
|
179
|
+
- `pytest -m "not slow and not ml and not real_api"` — fast gate on every push (~30s)
|
|
180
|
+
- `pytest` — full suite on PR merge or nightly
|
|
181
|
+
- Package-level runs for targeted debugging: `pytest packages/core/tests/`
|
|
182
|
+
|
|
183
|
+
### Coverage and Ratios
|
|
184
|
+
|
|
185
|
+
- **Do not chase a coverage number.** 80% coverage with meaningless tests is worse than 40% with behavior-testing integration tests
|
|
186
|
+
- **Cover the critical path first.** Data layer, auth, payment, core business logic — before helper utilities
|
|
187
|
+
- **Coverage tells you what's NOT tested, not what IS tested.** High coverage with bad assertions is false confidence
|
|
188
|
+
- **Delete tests that don't catch bugs.** If a test has never failed (or only fails on refactors), it's not providing value
|
|
189
|
+
|
|
190
|
+
**Target ratio:** ~20% unit, ~60% integration, ~15% E2E, ~5% manual/exploratory
|
|
191
|
+
|
|
192
|
+
### Test Tooling Standards
|
|
193
|
+
|
|
194
|
+
- Use `tmp_path` for filesystem tests, `:memory:` or `tmp_path` SQLite for DB tests
|
|
195
|
+
- Use dependency injection over `@patch` — it's more readable and survives refactors
|
|
196
|
+
- Tests must be self-sufficient — no dependency on project directories, user config, or environment state
|
|
197
|
+
- Use factories or builders for test data, not raw constructors with 15 arguments
|
|
198
|
+
- Keep test fixtures close to where they're used. Shared fixtures in `conftest.py`, not a global test utilities package
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
## Security & Robustness Invariants
|
|
203
|
+
|
|
204
|
+
These are the failure classes that show up in nearly every quickly-built app, regardless of stack or language. Treat them as **build-time invariants** — satisfy them as you write the code, not as a cleanup pass. Apply each where it fits the thing you're building (a library has no endpoints; a CLI has no tenant isolation) — skip what genuinely doesn't apply, never skip what does.
|
|
205
|
+
|
|
206
|
+
Throwaway POCs are exempt while you validate logic (per **POC first** above) — hardcoded values and missing error handling are fine in a 15-minute spike. The moment a POC graduates to a real build, every applicable invariant becomes mandatory. The one item that holds even for a POC: never commit a real secret.
|
|
207
|
+
|
|
208
|
+
1. **No secrets in the repo.** Keys, tokens, and credentials load from the environment / a secret store at runtime — never hardcoded, never logged. `.env` is gitignored; only a value-less `.env.example` is committed. Scan history before trusting a repo. One leaked key is a breached database or a runaway bill.
|
|
209
|
+
2. **Scope every data access to its owner.** Each record read or written is constrained to the requesting principal — via DB-level rules (RLS / row policies) and/or an application-layer ownership check. Never trust a client-supplied id without a gate. If the storage layer offers row-level policies, enabling them is not optional, and "on but too broad" still fails.
|
|
210
|
+
3. **Bound every reachable endpoint.** Rate-limit public routes AND authenticated mutation/write routes AND abuse-prone inbound paths (mail, webhooks). An unbounded route is a free DoS and bill amplifier — a script in a loop should not be able to take the service down.
|
|
211
|
+
4. **Handle the unhappy path.** Every IO / network / DB / third-party call has an explicit failure path. Nothing fails silently. Internal detail (stack traces, queries, secrets) never reaches the client. Async/background work carries its own catch.
|
|
212
|
+
5. **Authorization is not authentication.** "Logged in" never implies "allowed". Every state-changing or privileged action checks ownership AND role/permission. If swapping an id in a request would expose or mutate someone else's data, it's a bug — return 403.
|
|
213
|
+
6. **Data access scales.** No queries inside loops, no per-render repeated round-trips, indexes on every filtered/joined column. Code that's fine at 10 users and collapses at 1,000 is a latent outage.
|
|
214
|
+
|
|
215
|
+
Also hold the line on: input validation at every trust boundary (untrusted uploads, inbound mail, webhooks, and spoofable headers like `X-Forwarded-For` — trust them only behind a vetted proxy); parameterized queries (never string-built SQL); vetted libraries for crypto / auth / sanitization (never roll your own); and least-privilege binding (loopback, not `0.0.0.0`, unless the port is deliberately public).
|
|
216
|
+
|
|
217
|
+
**Verify at two moments, not one.**
|
|
218
|
+
- **While building** — this list shapes the code as it's written.
|
|
219
|
+
- **Before deploy/merge** — run **`/security`** on security-sensitive changes and **`/ship`** as the pre-deploy gate. A Critical/High finding blocks the ship; lower-severity findings get logged and triaged, not silently shipped. Proactively remind the user to run them whenever a change touches auth, data access, endpoints, secrets, or untrusted input.
|
|
220
|
+
|
|
221
|
+
---
|
|
222
|
+
|
|
223
|
+
## Guardrails (Enforced, Not Requested)
|
|
224
|
+
|
|
225
|
+
A prompt rule is a request the model can rationalise past. For anything that actually matters — secrets, auth, schema — don't rely on soft instruction. Enforce it with a **pre-tool hook** that intercepts the call *before* it runs and decides on an **Always / Ask / Never** basis:
|
|
226
|
+
|
|
227
|
+
- **Never** — writing `.env`/`*.env`, keys, or credential files is blocked outright (secrets load from the environment, never the tree). Destructive shell (`rm -rf` of a root-ish target, redirecting into a secret) is blocked too.
|
|
228
|
+
- **Ask** — touching auth, DB schema/migrations, CI workflows, or `.claude/settings.json` forces a human confirmation. Same for force-push / push to a default branch.
|
|
229
|
+
- **Always / allow** — everything else proceeds through the normal permission flow; the hook stays out of the way.
|
|
230
|
+
|
|
231
|
+
The reference implementation ships in this repo at [`.claude/hooks/guardrails.py`](.claude/hooks/guardrails.py) — stdlib only, no deps, fails open on a malformed event so it can never wedge the agent. The Never/Ask lists are constants at the top; **tune them per project**. To wire it up, add to the project's `.claude/settings.json`:
|
|
232
|
+
|
|
233
|
+
```json
|
|
234
|
+
{
|
|
235
|
+
"hooks": {
|
|
236
|
+
"PreToolUse": [
|
|
237
|
+
{
|
|
238
|
+
"matcher": "Write|Edit|MultiEdit|NotebookEdit|Bash",
|
|
239
|
+
"hooks": [
|
|
240
|
+
{ "type": "command", "command": "python3 .claude/hooks/guardrails.py" }
|
|
241
|
+
]
|
|
242
|
+
}
|
|
243
|
+
]
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
The hook is the hard line; the prose rules above are why it exists. Keep them in sync — when you tighten one, tighten the other.
|
|
249
|
+
|
|
250
|
+
---
|
|
251
|
+
|
|
252
|
+
## Environment
|
|
253
|
+
|
|
254
|
+
- **OS**: Fedora Linux (use `dnf` for packages, `systemctl` for services)
|
|
255
|
+
- **Testing**: pytest (Python), Jest/Vitest (JS/TS), Playwright (browser automation)
|
|
256
|
+
|
|
257
|
+
---
|
|
258
|
+
|
|
259
|
+
## Development Workflow
|
|
260
|
+
|
|
261
|
+
### Environments
|
|
262
|
+
- **Development**: Local machines
|
|
263
|
+
- **Staging**: VPS with isolated database
|
|
264
|
+
- **Production**: VPS with containerized setup
|
|
265
|
+
|
|
266
|
+
### Deployment Strategy
|
|
267
|
+
|
|
268
|
+
**Simple Projects:** `Local → GitHub → VPS (direct deployment)`
|
|
269
|
+
|
|
270
|
+
**Complex Projects:** `Local → GitHub → GHCR → VPS (containerized)`
|
|
271
|
+
|
|
272
|
+
---
|
|
273
|
+
|
|
274
|
+
## Twelve-Factor Checklist
|
|
275
|
+
|
|
276
|
+
The [Twelve-Factor App](https://12factor.net) methodology for modern, scalable applications:
|
|
277
|
+
|
|
278
|
+
| # | Factor | Rule |
|
|
279
|
+
|---|--------|------|
|
|
280
|
+
| 1 | Codebase | One repo per app, multiple deploys from same codebase |
|
|
281
|
+
| 2 | Dependencies | Explicitly declare and isolate all dependencies |
|
|
282
|
+
| 3 | Config | Store config in environment variables, never in code |
|
|
283
|
+
| 4 | Backing Services | Treat databases, caches, queues as attached resources |
|
|
284
|
+
| 5 | Build, Release, Run | Strict separation between build, release, and run stages |
|
|
285
|
+
| 6 | Processes | Run as stateless processes, persist state externally |
|
|
286
|
+
| 7 | Port Binding | Apps are self-contained, export services via port binding |
|
|
287
|
+
| 8 | Concurrency | Scale out via the process model, not bigger instances |
|
|
288
|
+
| 9 | Disposability | Fast startup, graceful shutdown, idempotent operations |
|
|
289
|
+
| 10 | Dev/Prod Parity | Keep dev, staging, and production as similar as possible |
|
|
290
|
+
| 11 | Logs | Treat logs as event streams to stdout |
|
|
291
|
+
| 12 | Admin Processes | Run admin/maintenance tasks as one-off processes |
|
|
292
|
+
|
|
293
|
+
---
|
|
294
|
+
|
|
295
|
+
## CLAUDE.md Stub
|
|
296
|
+
|
|
297
|
+
Copy this to any project's CLAUDE.md. These are mandatory rules, not suggestions.
|
|
298
|
+
|
|
299
|
+
```markdown
|
|
300
|
+
## Dev Rules
|
|
301
|
+
|
|
302
|
+
**POC first.** Always validate logic with a ~15min proof-of-concept before building. Cover happy path + common edges. POC works → design properly → build with tests. Never ship the POC. **Aim the spike at the riskiest assumption, not the easy part; prove, don't assert — measure anything you call "cheap"/"fast"/"constant," and claim only what the evidence supports (no big-mouthed conclusions measurement can falsify). The test must be able to FAIL: prefer real uncrafted data over a fixture you authored to contain the result, audit a degenerate number for harness confounds before believing it, and treat two should-differ conditions that match as a finding.**
|
|
303
|
+
|
|
304
|
+
**Build incrementally.** Break work into small independent modules. One piece at a time, each must work on its own before integrating.
|
|
305
|
+
|
|
306
|
+
**Dependency hierarchy — follow strictly:** vanilla language → standard library → external (only when stdlib can't do it in <100 lines). External deps must be maintained, lightweight, and widely adopted. Exception: always use vetted libraries for security-critical code (crypto, auth, sanitization).
|
|
307
|
+
|
|
308
|
+
**Lightweight over complex.** Fewer moving parts, fewer deps, less config. Express over NestJS, Flask over Django, unless the project genuinely needs the framework. Simple > clever. Readable > elegant.
|
|
309
|
+
|
|
310
|
+
**Open-source only.** No vendor lock-in. Every line of code must have a purpose — no speculative code, no premature abstractions.
|
|
311
|
+
|
|
312
|
+
**Responsive web UI is mandatory.** Any web UI must work on mobile by default — fluid layouts, viewport meta, breakpoints, no horizontal scroll. Verify in DevTools device emulation before claiming a UI task is done. POCs exempt; real projects are not.
|
|
313
|
+
|
|
314
|
+
For full development and testing standards, see `.claude/memory/AGENT_RULES.md`.
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
---
|
|
318
|
+
|
|
319
|
+
## AI Agent Instructions
|
|
320
|
+
|
|
321
|
+
When working with this user:
|
|
322
|
+
1. **Interview before building** — extract the real goal and surface load-bearing decisions for sign-off before you execute (see [Operating Flow](#operating-flow))
|
|
323
|
+
2. **Provide step-by-step** instructions with clear explanations
|
|
324
|
+
3. **Include ready-to-run** scripts and commands
|
|
325
|
+
4. **Explain the "why"** behind technical recommendations
|
|
326
|
+
5. **Flag potential issues** before they become problems — name the assumption, don't bury it
|
|
327
|
+
6. **Suggest simpler alternatives** when appropriate
|
|
328
|
+
7. **Ask first** before touching auth, DB schema/migrations, CI, or settings; **never** commit secrets — enforced by the [guardrail hook](#guardrails-enforced-not-requested) where wired
|
|
329
|
+
8. **Always identify** which files will be affected by changes
|