litclaude-ai 0.3.6 → 0.3.8

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.
@@ -10,22 +10,61 @@ Go, shell glue, plugin manifests, and test harnesses. It is the Claude-native
10
10
  port of LitClaude programming discipline: strong types, small units, explicit
11
11
  boundaries, and tests that prove behavior before code is accepted.
12
12
 
13
- ## Phase 0: Language Gate
14
-
15
- Before editing, identify the language and the project-local conventions. Prefer
16
- the repository's existing tools over introducing a new stack. If the task spans
17
- multiple languages, write down the boundary between them before coding.
18
-
19
- - JavaScript/TypeScript: keep ESM when the package is ESM, use `node:test` or
20
- the repo's configured runner, avoid `any`, `as` narrowing, and hidden globals.
21
- - Python: prefer typed dataclasses/Pydantic boundaries, `pathlib`, explicit
22
- exception types, and deterministic scripts.
23
- - Rust: prefer typed errors, exhaustive matches, `?`, and no `unwrap` outside
24
- tests or tiny `main` wrappers.
25
- - Go: use `context.Context` at I/O boundaries, typed errors, no unchecked
26
- `err`, and focused packages.
27
- - Shell: quote variables, use `set -euo pipefail` in scripts, and make cleanup
28
- explicit.
13
+ This SKILL.md is an index. The hard per-language rules live under `references/`.
14
+ Treat it as a routing table: read the matching language reference **before**
15
+ writing a single line of code, then apply the shared philosophy on top.
16
+
17
+ ---
18
+
19
+ ## PHASE 0 LANGUAGE GATE (RUN THIS FIRST, EVERY TIME)
20
+
21
+ **Do not write or edit a single line of code before completing this gate.**
22
+
23
+ 1. **Identify the language** from the file extension or the user's request.
24
+ 2. **Stop** and read the matching reference set with the `Read` tool:
25
+
26
+ | File / Language | Mandatory reading |
27
+ |---|---|
28
+ | `.py`, `.pyi`, "Python" | `references/python/README.md` + every file under `references/python/` the README routes you to |
29
+ | `.rs`, `Cargo.toml`, "Rust" | `references/rust/README.md` + every file under `references/rust/` the README routes you to. **If the change touches `unsafe`, `*mut`, `*const`, `MaybeUninit`, FFI, `unsafe impl Send/Sync`, or a custom lock-free primitive, ALSO read `references/rust-ub/README.md` and every file under `references/rust-ub/`.** |
30
+ | `.ts`, `.tsx`, `.mts`, `.cts`, "TypeScript" | `references/typescript/README.md` + every file under `references/typescript/` the README routes you to |
31
+ | `.go`, `go.mod`, `go.sum`, `.golangci.yml`, `*.proto` next to a Go module, "Go" / "Golang" | `references/go/README.md` + every file under `references/go/` the README routes you to |
32
+
33
+ 3. Only after the references are loaded, apply the shared philosophy below plus
34
+ the per-language iron list from the reference.
35
+
36
+ Prefer the repository's existing tools over introducing a new stack. If the task
37
+ spans multiple languages, write the boundary between them down before coding.
38
+ **No exceptions for "small" or "one-off" code** — disposable scripts (`uv run`
39
+ + PEP 723, `rust-script`, `bun run`, `go run` + `//go:build ignore`) cost
40
+ nothing to write with full discipline, so they get the full treatment too.
41
+
42
+ ---
43
+
44
+ ## Shared philosophy
45
+
46
+ These are not style preferences. They are the axioms every recipe in
47
+ `references/` derives from.
48
+
49
+ 1. **The type system is your proof system.** Make illegal states unrepresentable.
50
+ The type checker is the cheapest test you will ever run. If a bug can be
51
+ expressed as a type error, express it as a type error.
52
+ 2. **Parse, don't validate.** Untrusted input crosses a boundary exactly once;
53
+ there it is parsed into a typed value. Inside the boundary, code receives
54
+ typed values and never re-validates. The boundary owns trust; the interior
55
+ owns logic.
56
+ 3. **One name = one concept.** A `UserId` is not a `string`; `Seconds` is not
57
+ `Milliseconds`. Use a branded primitive for every distinct semantic unit so
58
+ the compiler refuses to let two units mix.
59
+ 4. **Exhaustive variant matching, always.** Discriminated unions and enums are
60
+ matched exhaustively with a never-reached guard. `if`/`elif`/`else` to
61
+ discriminate a tagged variant is forbidden — it silently swallows new cases.
62
+ 5. **Trust framework guarantees; validate only at boundaries.** No null checks
63
+ for values the type system already proves non-null. No `try`/`catch` around
64
+ code that cannot raise. No escape hatch papering over a contract you should
65
+ have encoded in types.
66
+ 6. **Test-driven, with the right shape of test.** No production line ships
67
+ without a failing test that proves it was needed.
29
68
 
30
69
  ## Parse, don't validate
31
70
 
@@ -41,38 +80,217 @@ Examples:
41
80
  - Environment variables are read at the edge and converted into explicit paths,
42
81
  booleans, or enums.
43
82
 
44
- ## TDD DISCIPLINE
83
+ ---
84
+
85
+ ## TDD DISCIPLINE — NON-NEGOTIABLE
86
+
87
+ For production behavior, follow red -> green -> refactor. The order is mandatory;
88
+ reverse it and you have written speculative code.
89
+
90
+ 1. **Red.** Add a failing test that names the missing behavior and *fails for the
91
+ right reason* — not a typo, not an import error. A test that fails because the
92
+ function does not exist yet is the right reason; a missing import is not.
93
+ 2. **Green.** Write the smallest change that passes that test. Resist adding the
94
+ second case until the first passes — the second case is the next red.
95
+ 3. **Refactor.** Simplify with the tests still green. If the test is hard to
96
+ refactor against, the test is bad; fix the test before the code.
97
+
98
+ ### The test pyramid
99
+
100
+ Every feature ships with all three rungs, sized in this proportion:
101
+
102
+ | Rung | Count | Purpose | Speed budget |
103
+ |---|---|---|---|
104
+ | **Unit** | many | Pure-function correctness for every meaningful input class (happy + edges + boundaries + error paths) | < 10 ms each |
105
+ | **Integration** | some | The real adapter against the real downstream (file system, plugin manifest, CLI, DB, queue, HTTP). Never a unit test pretending to be integration. | < 1 s each |
106
+ | **E2E scenario** | few | One narrative per user-visible outcome: tmux transcript, HTTP status/body, browser screenshot, desktop automation log. Asserts the observable outcome, not internal state. | seconds, on CI |
107
+
108
+ Tests alone are not completion proof when the change affects user workflows.
109
+ Pair green tests with one real scenario artifact. If a user-facing feature has
110
+ zero E2E coverage, it is undone even when every unit test passes.
111
+
112
+ ### Given / When / Then is mandatory
113
+
114
+ Every test is structured by three blocks:
45
115
 
46
- For production behavior, use red -> green -> refactor.
116
+ ```
117
+ Given: the exact fixture and preconditions
118
+ When: the single action under test
119
+ Then: one observable outcome AND only that outcome
120
+ ```
47
121
 
48
- 1. Red: add a failing test that names the missing behavior and fails for the
49
- right reason.
50
- 2. Green: write the smallest change that passes that test.
51
- 3. Refactor: simplify with the tests still green.
122
+ One `When` per test. Multiple `When`s = multiple tests. The `Then` asserts only
123
+ what changed because of the `When`, not unrelated invariants.
52
124
 
53
- Tests should follow Given / When / Then:
125
+ ### Mock priority ladder less mock, the better
54
126
 
55
- - Given: exact fixture and preconditions.
56
- - When: one action.
57
- - Then: one observable outcome or one assertion class.
127
+ Mocks are a last resort, not a default. Walk down this ladder and stop at the
128
+ first rung that works:
129
+
130
+ 1. **Real object** — when constructable in under 1 ms (most domain types, pure
131
+ functions, value objects).
132
+ 2. **In-memory fake** — a real implementation of the interface backed by a
133
+ map/slice for stores, caches, queues. The fake has its OWN test proving it
134
+ behaves like the real one.
135
+ 3. **Sandbox / container** — real Postgres, real Redis, real S3-compatible, via
136
+ the project's container harness. Slow but truthful.
137
+ 4. **Wire-level fake** — fake at the HTTP wire, not at the SDK.
138
+ 5. **Mock** — only when 1–4 are genuinely infeasible (clock, randomness,
139
+ external SaaS with no sandbox). Mock the narrowest seam, never a whole
140
+ service. A mock that returns whatever the test wants is a tautology.
141
+
142
+ **The rule:** if your test fails when the production code's *implementation*
143
+ changes but its *behavior* did not, the test is over-mocked. Delete the mock and
144
+ assert on observable outputs.
145
+
146
+ ### Prompt and skill tests follow the same rule
58
147
 
59
148
  For prompt and skill text, assert on behavior-bearing rules and structure, not
60
149
  on fragile full-string snapshots. A good prompt test checks that a required
61
- decision, tool boundary, or safety rule is present.
150
+ decision, tool boundary, or safety rule is present — never that an exact
151
+ sentence survives verbatim.
62
152
 
63
- ## Test Shape
153
+ ---
64
154
 
65
- Use the fastest truthful surface:
155
+ ## Cross-language iron list
66
156
 
67
- - Unit tests for pure parsing and decision logic.
68
- - Integration tests for file-system state, plugin manifests, and CLI behavior.
69
- - Manual QA for the user-facing surface: tmux transcript, HTTP status/body,
70
- browser screenshot, or desktop automation log.
157
+ Apply unless the per-language reference overrides with something stricter.
71
158
 
72
- Tests alone are not completion proof when the change affects user workflows.
73
- Pair green tests with one real scenario artifact.
159
+ | Rule | Python | Rust | TypeScript | Go |
160
+ |---|---|---|---|---|
161
+ | Immutable by default | `@dataclass(frozen=True, slots=True)` / Pydantic `frozen=True` | every binding is `let` unless mutation is the documented purpose | every field is `readonly`; arrays are `readonly T[]` | value types, unexported fields, no mutation methods unless mutation is the purpose |
162
+ | Branded primitives | `UserId = NewType("UserId", int)` | `struct UserId(u64);` newtype tuple | `type UserId = Brand<string, "UserId">` | `type UserID string` + smart constructor with unexported field |
163
+ | Exhaustive variant matching | `match` + `assert_never` | `match` (compiler-enforced) | `switch` + `assertNever` | sealed interface + type switch + exhaustiveness linter |
164
+ | No untyped escape hatches | no `Any` in public sigs, no `cast`, no `# type: ignore` | no `unwrap`/`expect` outside `main`/tests, no `as` for narrowing | no `any`, no `as` (except `as const`, `satisfies`), no `!`, no `@ts-ignore` | no bare `any` in domain sigs; no `_ = err`; no unexplained lint suppression |
165
+ | No bare error strings | typed exception dataclass | `thiserror` enum (lib) or `anyhow` + `.context(...)` (app) | `Error` subclass with typed fields | sentinel + typed error struct; wrap with `%w`; check via `errors.Is/As` |
166
+ | Boundary catch only | catch the exact exception; broad catch only in `main()` with re-raise | `?` everywhere; never `panic!` in library code | `catch` narrows with `instanceof` then re-throws/converts; no empty catch | every `(T, error)` checked; `panic` only in `main`/tests |
167
+ | Resources via RAII / ownership | `with` / `async with` | `Drop` impl or RAII guard | `using` / `await using` | `defer x.Close()` immediately after acquisition |
168
+ | Async runtime choice | `anyio` (never bare `asyncio`) | `tokio` | platform-native async with `AbortSignal` cancellation | `context.Context` first param + `errgroup`; `-race` on every test |
169
+ | Modern HTTP client | typed HTTP/2 client with brotli + zstd | `reqwest` with rustls | `ky` / `undici` — never bare `fetch` in prod | stdlib `net/http.Client` with tuned `Transport` + retry/backoff |
170
+ | No parameter mutation | params are inputs; produce a new value | `&mut` only when mutation is documented | parameters never reassigned | value receivers unless mutation is the purpose |
171
+ | No helpers for one-off | inline a 3-line operation until the second caller | same | same | same |
172
+
173
+ ---
174
+
175
+ ## Canonical libraries by domain
176
+
177
+ Use these unless the project's manifest explicitly picks something else. A bare
178
+ default constructor (no timeouts, no pool tuning, no schema) is a bug — see the
179
+ per-language reference for production defaults.
180
+
181
+ | Domain | Python | Rust | TypeScript | Go |
182
+ |---|---|---|---|---|
183
+ | Boundary parse | Pydantic v2 | `serde` + `#[derive(Deserialize)]` | Zod | smart constructors + request validator |
184
+ | Internal value object | frozen dataclass | newtype tuple struct | `readonly` type alias | struct with unexported fields + constructor |
185
+ | Error types | typed exception dataclass | `thiserror` (lib) + `anyhow` (app) | `Error` subclass + Result | sentinel + typed error struct + `%w` wrap |
186
+ | Web framework | FastAPI | axum | Hono | gin / chi / connect-go |
187
+ | DB access | SQLAlchemy 2.x async | `sqlx` (compile-time checked) | Drizzle | sqlc + pgx + migrations |
188
+ | CLI | typer + rich | clap (derive) | commander | cobra + slog |
189
+ | Logging | structlog | tracing | pino | stdlib `log/slog` |
190
+ | Testing | pytest | nextest + proptest + insta | bun test / vitest | stdlib `testing` + container harness |
191
+ | Config from env | pydantic-settings | figment / config | zod + `process.env` | struct-tag env parser |
192
+
193
+ ## Modern toolchain
194
+
195
+ | Tool category | Python | Rust | TypeScript | Go |
196
+ |---|---|---|---|---|
197
+ | Project manager | uv | cargo + nextest + deny | Bun (pnpm if Node is forced) | go modules + `go work` |
198
+ | Type checker | strict pyright/basedpyright | rustc `-D warnings` + clippy pedantic | `tsc --noEmit` with the strict flag set | go compiler + strict golangci-lint + nil-deref static analysis |
199
+ | Linter + formatter | ruff | clippy + rustfmt | Biome | gofumpt + goimports + golangci-lint |
200
+ | Test runner | pytest | nextest | bun test / vitest | `go test -race -shuffle=on -count=1` |
201
+ | Soundness gate | (n/a) | nightly miri with strict provenance | (n/a) | `-race` + leak detector |
202
+
203
+ CI-gate one-liners — the command a pre-commit hook or CI lane runs:
204
+
205
+ - Python: `ruff check . && basedpyright && pytest`
206
+ - Rust: `cargo clippy -- -D warnings && cargo nextest run && cargo +nightly miri test`
207
+ - TypeScript: `bunx biome check . && bunx tsc --noEmit && bun test`
208
+ - Go: `gofumpt -l . && golangci-lint run ./... && go test -race -shuffle=on -count=1 ./...`
209
+
210
+ A `tsconfig.json` with `"strict": true` alone is not strict — the reference
211
+ enumerates the additional flags. The same holds for `pyproject.toml` and
212
+ `Cargo.toml`: the references carry the canonical full configuration.
213
+
214
+ ---
215
+
216
+ ## THE 250 PURE LOC CEILING (NON-NEGOTIABLE)
217
+
218
+ Treat 250 non-comment, non-blank lines in a source file as a hard design
219
+ warning. A file past this line is telling you the module does more than one
220
+ thing, that cohesive units got fused "to save a file", and that every future
221
+ reader pays a tax to find what they need.
222
+
223
+ ### Why 250
224
+
225
+ At 250 pure LOC a file still fits in one screen at a readable font. A reviewer
226
+ can hold the whole thing in working memory and spot a cross-cutting bug. The
227
+ number is the cognitive ceiling of a single reviewer who has not memorized the
228
+ file.
229
+
230
+ ### Measuring pure LOC
231
+
232
+ ```bash
233
+ # Quick (line-comment + blank exclusion):
234
+ awk '!/^[[:space:]]*$/ && !/^[[:space:]]*(\/\/|#|--)/' <file> | wc -l
235
+
236
+ # Authoritative (handles block comments):
237
+ cloc --by-file <file> # the "code" column is the number that matters
238
+ ```
74
239
 
75
- ## Type and Error Discipline
240
+ ### Required behavior
241
+
242
+ - **Creating a file that will exceed 250 pure LOC:** split it before the first
243
+ commit. Carve by responsibility, one cohesive unit per file. Use a barrel
244
+ (`__init__.py`, `mod.rs`, `index.ts`) for re-exports only, never for logic.
245
+ - **Editing a file already over 250 pure LOC when your edit adds lines:**
246
+ refactor the unit you are touching into its own file *before* adding the new
247
+ lines. The split is part of THIS task, not a follow-up nobody does.
248
+ - **Reading a file over 250 pure LOC while implementing a feature:** surface the
249
+ smell in your reply, propose a concrete split (which functions go where, one
250
+ line each), and ask whether to split now. Do not silently keep going.
251
+
252
+ ### Forbidden escapes
253
+
254
+ - Counting comments and blanks toward the budget. Pure LOC means code lines.
255
+ - Splitting by token count (`module_part_a`, `service-2`). Split by what each
256
+ file does and name it after the concept it owns.
257
+ - Catch-all dumps (`utils`, `helpers`, `common`, `shared`). They relocate the
258
+ smell, not remove it.
259
+ - "It's a test file with many cases." Split by subject-under-test or behavior
260
+ cluster, one file per cohesive group.
261
+ - "230 LOC, close enough." A 230-LOC file about to grow is already over the
262
+ line. Split now; do not race to the ceiling.
263
+
264
+ ### Before / after split example
265
+
266
+ Before — `user_service.py`, ~412 pure LOC, doing too much:
267
+
268
+ ```python
269
+ class UserRepository: ... # ~90 LOC of DB access
270
+ class UserValidator: ... # ~60 LOC of boundary parse + rules
271
+ class PasswordHasher: ... # ~40 LOC of hashing wrapper
272
+ class EmailSender: ... # ~50 LOC of HTTP client
273
+ class UserService: ... # ~130 LOC orchestrating the four above
274
+ ```
275
+
276
+ After — split by responsibility, every file under the ceiling:
277
+
278
+ ```
279
+ src/myapp/users/
280
+ ├── __init__.py # barrel: re-exports UserService only (~5 LOC)
281
+ ├── repository.py # UserRepository (~95 LOC)
282
+ ├── validator.py # UserValidator (~65 LOC)
283
+ ├── password.py # PasswordHasher (~45 LOC)
284
+ ├── notifier.py # EmailSender (named for the role) (~55 LOC)
285
+ └── service.py # UserService (thin orchestrator) (~135 LOC)
286
+ ```
287
+
288
+ Each file owns one concept. The barrel exposes the only public name. The
289
+ reviewer never scrolls through password hashing to understand mail retry policy.
290
+
291
+ ---
292
+
293
+ ## Type and error discipline
76
294
 
77
295
  - Make illegal states difficult to represent.
78
296
  - Use semantic names for IDs, paths, versions, plugin keys, and command names.
@@ -82,25 +300,138 @@ Pair green tests with one real scenario artifact.
82
300
  - Avoid defensive code that checks impossibilities. If a case is possible, name
83
301
  it and test it. If it is impossible, encode that in parsing or types.
84
302
 
85
- ## 250 LOC Ceiling
86
-
87
- Treat 250 non-comment lines in a source file as a design warning. If a touched
88
- file is already too large and the change adds logic, split the cohesive unit you
89
- are modifying before adding more. Keep orchestrators thin, parsing isolated,
90
- and command implementations focused.
91
-
92
- ## Resource and State Hygiene
303
+ ## Resource and state hygiene
93
304
 
94
305
  Every spawned process, tmux session, temp directory, port, browser context, or
95
306
  container needs a cleanup receipt. Register cleanup when the resource is
96
307
  created, not after the test passes. A leftover process means the work is not
97
308
  done.
98
309
 
99
- ## Claude Code Adaptation
310
+ ---
311
+
312
+ ## MANDATORY POST-WRITE SELF-REVIEW LOOP
313
+
314
+ This runs every time you finish writing or substantively editing code, before
315
+ you claim the task is done.
316
+
317
+ ### Step 1 — measure
318
+
319
+ For every file you created or modified, run the pure-LOC count above.
320
+
321
+ ### Step 2 — interpret
322
+
323
+ | Pure LOC | Verdict | Required action |
324
+ |---|---|---|
325
+ | ≤ 200 | Healthy | continue |
326
+ | 200–250 | Warning band | state the fact explicitly and propose a split if the next edit adds lines |
327
+ | > 250 | Defect | do not commit; refactor into smaller cohesive units now, in this same task |
328
+
329
+ ### Step 3 — architectural self-review (always, even at 80 LOC)
330
+
331
+ Answer these in your reply before declaring done:
332
+
333
+ 1. **Single responsibility?** Can you name what the file owns in one noun
334
+ phrase? If the answer needs "and", split.
335
+ 2. **Boundary purity?** Did you parse untrusted input into a typed value, or
336
+ pass an untyped blob past the boundary?
337
+ 3. **Variant discrimination?** Any non-exhaustive branch on a tagged type?
338
+ 4. **Escape hatches?** Any untyped cast, suppression, or `unwrap`/`!` outside
339
+ `main`/tests?
340
+ 5. **Defensive layer?** Any guard for a value the type system already proves?
341
+ 6. **Helpers for one-off?** Any abstraction with a single caller that will never
342
+ get a second?
343
+ 7. **Tests?** Is the new behavior locked by a test that fails if you revert it?
344
+
345
+ If any answer fails, fix it before declaring done.
346
+
347
+ ### Step 4 — hand off to the recovery skills
348
+
349
+ - The file you just wrote (or an adjacent one) is over 250 pure LOC, or step 3
350
+ surfaced more than two issues: **load the `refactor` skill** and run its
351
+ safe-refactor protocol (codemap, plan, characterization tests, edits with
352
+ tests after each step). Do not improvise a structural change under pressure.
353
+ - You inherited code with AI-generated patterns (broad catches, redundant null
354
+ checks, vague TODOs, oversized modules, dead helpers): **load the
355
+ `remove-ai-slops` skill** to do a categorized cleanup with regression tests
356
+ pinned first.
357
+
358
+ These are the recovery path for the defects this loop is designed to catch, not
359
+ optional cosmetics.
360
+
361
+ ---
362
+
363
+ ## Per-language jump table
364
+
365
+ Stop. Read the matching reference fully before writing code.
366
+
367
+ ### Python (`.py`, `.pyi`)
368
+
369
+ Read `references/python/README.md` first, then load on demand:
370
+
371
+ | Need | Load |
372
+ |---|---|
373
+ | Strict pyproject / type checker / ruff config | `references/python/pyproject-strict.md` |
374
+ | Type patterns (`NewType`, `Final`, `Protocol`) | `references/python/type-patterns.md` |
375
+ | Data modeling (Pydantic vs dataclass vs TypedDict) | `references/python/data-modeling.md` |
376
+ | Error handling (typed exceptions, exhaustive match) | `references/python/error-handling.md` |
377
+ | Async with anyio | `references/python/async-anyio.md` |
378
+ | FastAPI + async DB stack | `references/python/fastapi-stack.md` |
379
+ | Canonical library defaults | `references/python/libraries.md` |
380
+ | Disposable PEP 723 scripts | `references/python/one-liners.md` |
381
+
382
+ ### Rust (`.rs`, `Cargo.toml`)
383
+
384
+ Read `references/rust/README.md` first, then load on demand:
385
+
386
+ | Need | Load |
387
+ |---|---|
388
+ | Strict `Cargo.toml` lints + profile | `references/rust/cargo-strict.md` |
389
+ | Type-state and newtype patterns | `references/rust/type-state.md` |
390
+ | `unsafe` discipline (safe wrapper + SAFETY comment + miri proof) | `references/rust/unsafe-discipline.md` |
391
+ | Async with tokio | `references/rust/async-tokio.md` |
392
+ | Concurrency primitives | `references/rust/concurrency.md` |
393
+ | axum HTTP stack | `references/rust/axum-stack.md` |
394
+ | Canonical library defaults | `references/rust/libraries.md` |
395
+ | Any `unsafe` / FFI / `MaybeUninit` / lock-free work | `references/rust-ub/` (full directory) |
396
+
397
+ ### TypeScript (`.ts`, `.tsx`, `.mts`, `.cts`)
398
+
399
+ Read `references/typescript/README.md` first, then load on demand:
400
+
401
+ | Need | Load |
402
+ |---|---|
403
+ | Strict tsconfig + Biome config | `references/typescript/tsconfig-strict.md` |
404
+ | Type patterns (branded types, `satisfies`, `assertNever`) | `references/typescript/type-patterns.md` |
405
+ | Data modeling (type vs interface vs Zod, parse-don't-validate) | `references/typescript/data-modeling.md` |
406
+ | Error handling (Result, typed errors, AbortSignal timeouts) | `references/typescript/error-handling.md` |
407
+ | Bootstrapping a new project | `references/typescript/bootstrap.md` |
408
+ | Hono backend stack | `references/typescript/backend-hono.md` |
409
+
410
+ ### Go (`.go`, `go.mod`, `go.sum`, `.golangci.yml`, `*.proto`)
411
+
412
+ Read `references/go/README.md` first, then load on demand:
413
+
414
+ | Need | Load |
415
+ |---|---|
416
+ | Library defaults (gin vs chi, sqlc, slog) | `references/go/libraries.md` |
417
+ | Canonical strict `.golangci.yml` | `references/go/golangci-strict.md` |
418
+ | Project layout, CI, `go.mod` template | `references/go/bootstrap.md` |
419
+ | Type patterns (named types, smart constructors, sealed interfaces) | `references/go/type-patterns.md` |
420
+ | Error handling (`errors.Is/As`, `%w` wrapping, no panic) | `references/go/error-handling.md` |
421
+ | Concurrency (`context.Context`, `errgroup`, `-race`) | `references/go/concurrency.md` |
422
+ | HTTP backend stack | `references/go/backend-stack.md` |
423
+ | Testing (Given/When/Then, table-driven, fakes-over-mocks) | `references/go/testing.md` |
424
+
425
+ ---
426
+
427
+ ## Claude Code adaptation
428
+
429
+ Prefer Claude Code's available tools and project conventions. If a private
430
+ reference instruction names a tool from another agent runtime, translate the
431
+ principle instead of copying the tool name. For example, goal tools become
432
+ conditional `get_goal` / `create_goal` / `update_goal` guidance only when
433
+ exposed; workflow isolation uses `Workflow`, `EnterWorktree`, or an explicit
434
+ `claude --worktree ...` operator path when that is the available Claude surface.
100
435
 
101
- Prefer Claude Code's available tools and project conventions. If a Private reference
102
- instruction names a Codex-only tool, translate the principle instead of copying
103
- the tool name. For example, goal tools become conditional `get_goal` /
104
- `create_goal` / `update_goal` guidance only when exposed; workflow isolation
105
- uses `Workflow`, `EnterWorktree`, or an explicit `claude --worktree ...`
106
- operator path when that is the available Claude surface.
436
+ The references contain the recipes. Read them before writing code, and re-read
437
+ them when the model drifts. The post-write self-review loop is non-negotiable.