instructions for LLMs
This commit is contained in:
parent
4d746027dc
commit
0f53e8f659
80
CLAUDE.md
Normal file
80
CLAUDE.md
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
# Repository Rules
|
||||||
|
|
||||||
|
Last Updated 2026-01-10
|
||||||
|
|
||||||
|
These rules MUST be followed at all times, it is very important.
|
||||||
|
|
||||||
|
* Do NOT stop working while there are still incomplete TODOs in the todo list
|
||||||
|
or in TODO.md. Continue implementing until all tasks are complete or you are
|
||||||
|
explicitly told to stop.
|
||||||
|
|
||||||
|
* Never use `git add -A` - add specific changes to a deliberate commit. A
|
||||||
|
commit should contain one change. After each change, make a commit with a
|
||||||
|
good one-line summary.
|
||||||
|
|
||||||
|
* NEVER modify the linter config without asking first.
|
||||||
|
|
||||||
|
* NEVER modify tests to exclude special cases or otherwise get them to pass
|
||||||
|
without asking first. In almost all cases, the code should be changed,
|
||||||
|
NOT the tests. If you think the test needs to be changed, make your case
|
||||||
|
for that and ask for permission to proceed, then stop. You need explicit
|
||||||
|
user approval to modify existing tests. (You do not need user approval
|
||||||
|
for writing NEW tests.)
|
||||||
|
|
||||||
|
* When linting, assume the linter config is CORRECT, and that each item
|
||||||
|
output by the linter is something that legitimately needs fixing in the
|
||||||
|
code.
|
||||||
|
|
||||||
|
* When running tests, use `make test`.
|
||||||
|
|
||||||
|
* Before commits, run `make check`. This runs `make lint` and `make test`
|
||||||
|
and `make check-fmt`. Any issues discovered MUST be resolved before
|
||||||
|
committing unless explicitly told otherwise.
|
||||||
|
|
||||||
|
* When fixing a bug, write a failing test for the bug FIRST. Add
|
||||||
|
appropriate logging to the test to ensure it is written correctly. Commit
|
||||||
|
that. Then go about fixing the bug until the test passes (without
|
||||||
|
modifying the test further). Then commit that.
|
||||||
|
|
||||||
|
* When adding a new feature, do the same - implement a test first (TDD). It
|
||||||
|
doesn't have to be super complex. Commit the test, then commit the
|
||||||
|
feature.
|
||||||
|
|
||||||
|
* When adding a new feature, use a feature branch. When the feature is
|
||||||
|
completely finished and the code is up to standards (passes `make check`)
|
||||||
|
then and only then can the feature branch be merged into `main` and the
|
||||||
|
branch deleted.
|
||||||
|
|
||||||
|
* Write godoc documentation comments for all exported types and functions as
|
||||||
|
you go along.
|
||||||
|
|
||||||
|
* ALWAYS be consistent in naming. If you name something one thing in one
|
||||||
|
place, name it the EXACT SAME THING in another place.
|
||||||
|
|
||||||
|
* Be descriptive and specific in naming. `wl` is bad;
|
||||||
|
`SourceHostWhitelist` is good. `ConnsPerHost` is bad;
|
||||||
|
`MaxConnectionsPerHost` is good.
|
||||||
|
|
||||||
|
* This is not prototype or teaching code - this is designed for production.
|
||||||
|
Any security issues (such as denial of service) or other web
|
||||||
|
vulnerabilities are P1 bugs and must be added to TODO.md at the top.
|
||||||
|
|
||||||
|
* As this is production code, no stubbing of implementations unless
|
||||||
|
specifically instructed. We need working implementations.
|
||||||
|
|
||||||
|
* NEVER silently fall back to a different setting when a user's parameter
|
||||||
|
explicitly specifies a value. If a user requests format=webp and WebP
|
||||||
|
encoding is not supported, return an error - do NOT silently output PNG
|
||||||
|
instead. If a user specifies fit=invalid and that fit mode doesn't exist,
|
||||||
|
return an error - do NOT silently default to "cover". Silent fallbacks
|
||||||
|
violate the principle of least surprise and mask bugs. The only acceptable
|
||||||
|
defaults are for OMITTED parameters, never for INVALID explicit values.
|
||||||
|
|
||||||
|
* Avoid vendoring deps unless specifically instructed to. NEVER commit
|
||||||
|
the vendor directory, NEVER commit compiled binaries. If these
|
||||||
|
directories or files exist, add them to .gitignore (and commit the
|
||||||
|
.gitignore) if they are not already in there. Keep the entire git
|
||||||
|
repository (with history) small - under 20MiB, unless you specifically
|
||||||
|
must commit larger files (e.g. test fixture example media files). Only
|
||||||
|
OUR source code and immediately supporting files (such as test examples)
|
||||||
|
goes into the repo/history.
|
||||||
@ -114,13 +114,11 @@ import (
|
|||||||
var (
|
var (
|
||||||
Appname string = "CHANGEME"
|
Appname string = "CHANGEME"
|
||||||
Version string
|
Version string
|
||||||
Buildarch string
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
globals.Appname = Appname
|
globals.Appname = Appname
|
||||||
globals.Version = Version
|
globals.Version = Version
|
||||||
globals.Buildarch = Buildarch
|
|
||||||
|
|
||||||
fx.New(
|
fx.New(
|
||||||
fx.Provide(
|
fx.Provide(
|
||||||
@ -453,6 +451,11 @@ func New(lc fx.Lifecycle, params HandlersParams) (*Handlers, error) {
|
|||||||
|
|
||||||
### Closure-Based Handler Pattern
|
### Closure-Based Handler Pattern
|
||||||
|
|
||||||
|
For JSON route handlers, both the request and the response structures are
|
||||||
|
defined in the scope of the method that returns the HandlerFunc. They can
|
||||||
|
be called simply `Request` and `Response` or slightly more descriptive
|
||||||
|
names.
|
||||||
|
|
||||||
All handlers return `http.HandlerFunc` using the closure pattern. This allows initialization logic to run once when the handler is created:
|
All handlers return `http.HandlerFunc` using the closure pattern. This allows initialization logic to run once when the handler is created:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
@ -477,6 +480,11 @@ func (s *Handlers) HandleIndex() http.HandlerFunc {
|
|||||||
```go
|
```go
|
||||||
// internal/handlers/now.go
|
// internal/handlers/now.go
|
||||||
func (s *Handlers) HandleNow() http.HandlerFunc {
|
func (s *Handlers) HandleNow() http.HandlerFunc {
|
||||||
|
|
||||||
|
type request struct {
|
||||||
|
// request format
|
||||||
|
}
|
||||||
|
|
||||||
// Response struct defined in closure scope
|
// Response struct defined in closure scope
|
||||||
type response struct {
|
type response struct {
|
||||||
Now time.Time `json:"now"`
|
Now time.Time `json:"now"`
|
||||||
@ -816,7 +824,6 @@ func (l *Logger) Identify() {
|
|||||||
l.log.Info("starting",
|
l.log.Info("starting",
|
||||||
"appname", l.params.Globals.Appname,
|
"appname", l.params.Globals.Appname,
|
||||||
"version", l.params.Globals.Version,
|
"version", l.params.Globals.Version,
|
||||||
"buildarch", l.params.Globals.Buildarch,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -938,20 +945,17 @@ import "go.uber.org/fx"
|
|||||||
var (
|
var (
|
||||||
Appname string
|
Appname string
|
||||||
Version string
|
Version string
|
||||||
Buildarch string
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Struct for DI
|
// Struct for DI
|
||||||
type Globals struct {
|
type Globals struct {
|
||||||
Appname string
|
Appname string
|
||||||
Version string
|
Version string
|
||||||
Buildarch string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(lc fx.Lifecycle) (*Globals, error) {
|
func New(lc fx.Lifecycle) (*Globals, error) {
|
||||||
n := &Globals{
|
n := &Globals{
|
||||||
Appname: Appname,
|
Appname: Appname,
|
||||||
Buildarch: Buildarch,
|
|
||||||
Version: Version,
|
Version: Version,
|
||||||
}
|
}
|
||||||
return n, nil
|
return n, nil
|
||||||
@ -965,13 +969,11 @@ func New(lc fx.Lifecycle) (*Globals, error) {
|
|||||||
var (
|
var (
|
||||||
Appname string = "CHANGEME" // Default, overridden by build
|
Appname string = "CHANGEME" // Default, overridden by build
|
||||||
Version string // Set at build time
|
Version string // Set at build time
|
||||||
Buildarch string // Set at build time
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
globals.Appname = Appname
|
globals.Appname = Appname
|
||||||
globals.Version = Version
|
globals.Version = Version
|
||||||
globals.Buildarch = Buildarch
|
|
||||||
// ...
|
// ...
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -982,10 +984,9 @@ Use ldflags to inject version information at build time:
|
|||||||
|
|
||||||
```makefile
|
```makefile
|
||||||
VERSION := $(shell git describe --tags --always)
|
VERSION := $(shell git describe --tags --always)
|
||||||
BUILDARCH := $(shell go env GOARCH)
|
|
||||||
|
|
||||||
build:
|
build:
|
||||||
go build -ldflags "-X main.Version=$(VERSION) -X main.Buildarch=$(BUILDARCH)" ./cmd/httpd
|
go build -ldflags "-X main.Version=$(VERSION)" ./cmd/httpd
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user