Skip to content

Commit 1522cbf

Browse files
committed
rewrite with gates
1 parent 8b11445 commit 1522cbf

File tree

1 file changed

+82
-48
lines changed

1 file changed

+82
-48
lines changed

AGENTS.md

Lines changed: 82 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,84 +1,126 @@
11
# Agents
22

3-
This document helps AI agents work effectively in this codebase. It explains the philosophy, patterns, and pitfalls behind the code, so you can make good decisions on any task, not just scenarios explicitly covered. Apply these principles while reading the code for specifics.
3+
This document helps AI agents work effectively in this codebase. It explains the philosophy, patterns, and pitfalls behind the code, so you can make good decisions on any task, not just scenarios explicitly covered.
44

55
## Philosophy
66

7-
This is a minimal, idiomatic WebSocket library. Simplicity is a feature. Before adding code, consider whether it's necessary. Before adding a dependency, don't; tests requiring external packages are isolated in `internal/thirdparty`.
7+
This is a minimal, idiomatic WebSocket library. Simplicity is a feature.
88

9-
## Planning
9+
Before adding code, articulate why it's necessary in one sentence. If you cannot justify the addition, it probably isn't needed.
1010

11-
When asked to plan, write to `PLAN.md`. Write for someone else, not yourself; don't skip context you already know. Research deeply before proposing solutions.
11+
Before adding a dependency, don't. Tests requiring external packages are isolated in `internal/thirdparty`.
1212

13-
**Follow references.** If there's a link, issue, or RFC citation, read it. Document important findings in a research section so the implementer can verify.
13+
## Workflow
1414

15-
**Focus on what and why.** Provide enough context for the implementer to understand the problem and constraints. Code examples can illustrate intent, but don't over-specify; leave room for the implementer to find a better approach.
15+
Every task follows phases. Do not skip phases; if you realize you missed something, return to the appropriate phase.
1616

17-
**Tell them where to look.** Point to specific files, functions, or line numbers. Make claims verifiable.
17+
**Making changes:**
1818

19-
**Review before finishing.** Make a final pass to check for gaps in research or unanswered questions, then update the document.
19+
1. **Research** - Understand the problem and codebase before acting
20+
2. **Plan** - Articulate your approach before implementing (when asked, or for complex changes)
21+
3. **Implement** - Make changes in small, verifiable steps
22+
4. **Verify** - Confirm correctness using external tools
23+
24+
For trivial changes (typo fixes, comment updates), an abbreviated workflow is acceptable.
2025

2126
## Research
2227

23-
**If you were given a link, read it now.** Do not explore code, do not pass go. Fetch the linked issue or document first. Summarize what it asks for before proceeding. If you cannot restate the problem, you are not ready to solve it.
28+
Research in sequential passes. Each pass has one focus. Don't skip ahead to code until you've completed the earlier passes.
29+
30+
**Pass 1: Read the issue.** If you were given a link, read it now. Do not explore code, do not pass go. Fetch the linked issue or document first. Summarize what it asks for. If you cannot restate the problem, you are not ready to proceed.
31+
32+
**Pass 2: Read linked references.** Follow every link in the issue: related issues, RFCs, external docs. Document what you learn. Code comments reference RFC 6455 (WebSocket), RFC 7692 (compression), and RFC 8441 (HTTP/2).
33+
34+
**Pass 3: Trace the code.** Start from public API inward: `Accept` (server) or `Dial` (client) → `Conn``Reader`/`Writer`. Read tests for intent; the autobahn-testsuite (`autobahn_test.go`) validates protocol compliance.
35+
36+
**Pass 4: Check both platforms.** Native Go files have `//go:build !js`. WASM lives in `ws_js.go`. Same API, different implementations. WASM wraps browser APIs and cannot control framing, compression, or masking.
37+
38+
**Pass 5: Search exhaustively.** If the change affects a pattern used in multiple places, grep for all instances. Missing one creates inconsistent behavior.
39+
40+
**Pass 6: Document unknowns.** List what you still don't know. Unknown unknowns become known unknowns when you ask "what am I still unsure about?"
41+
42+
**After all passes:** Can you restate the problem in your own words? If not, return to Pass 1. Gaps in earlier passes will cause problems later.
43+
44+
## Plan
45+
46+
When asked to plan, write to `PLAN.md`. Write for someone else, not yourself; don't skip context you already know.
47+
48+
**Pass 1: Document research.** Summarize what you learned in Research. Follow every reference; document findings so the implementer can verify. If the research section is empty, you haven't researched enough.
49+
50+
**Pass 2: Consider approaches.** For non-trivial problems, enumerate at least two approaches. For each, note: what would change, what could go wrong, what's the tradeoff.
2451

25-
**Read the issue carefully.** Before designing a solution, verify you understand what's actually being requested. Restate the problem in your own words. A solution to the wrong problem wastes everyone's time.
52+
**Pass 3: Detail the chosen approach.** Explain what and why, not step-by-step how. Point to specific files, functions, line numbers. Make claims verifiable. Leave room for the implementer to find a better solution.
2653

27-
**Understand the protocol first.** Code comments reference RFC 6455 (WebSocket), RFC 7692 (compression), and RFC 8441 (HTTP/2). When behavior seems odd, check the RFC section cited nearby.
54+
**Pass 4: List open questions.** What's still unclear? What assumptions are you making? What would change your approach?
2855

29-
**Trace from public API inward.** Start with `Accept` (server) or `Dial` (client), then follow to `Conn`, then to `Reader`/`Writer`. The internal structure follows these paths.
56+
**After all passes:** Review from the implementer's perspective. Could they start work with only this document? If not, add what's missing.
3057

31-
**Read tests for intent.** Tests often reveal why code exists. The autobahn-testsuite (`autobahn_test.go`) validates protocol compliance; if you're unsure whether behavior is correct, that's the authority.
58+
## Implement
3259

33-
**Check both platforms.** Native Go files have `//go:build !js`. WASM lives in `ws_js.go` (imports `syscall/js`). They have the same API but different implementations. WASM wraps browser APIs and cannot control framing, compression, or masking, so don't try to implement those features there.
60+
Implement in sequential passes. Don't write code until you've completed the verification passes.
3461

35-
**Search exhaustively when modifying patterns.** When changing how something is done in multiple places, grep for all instances. Missing one creates inconsistent behavior.
62+
**Pass 1: Verify understanding.** Did you do your research? Can you state your approach in one sentence? If requirements are ambiguous, stop and ask. A wrong assumption wastes more time than a quick question.
3663

37-
## Making Changes
64+
**Pass 2: Check scope.** Does this need to exist? Check if it already exists in the API. Is this the library's job or the user's job? The library handles protocol correctness; application concerns (reconnection, auth, routing) belong in user code.
3865

39-
**Did you do your research?** If you haven't read the linked issue, traced the code paths, and verified your understanding, stop. Go back to Research.
66+
**Pass 3: Check invariants.** Walk through Key Invariants before writing code:
67+
- Reads: Will something still read from the connection?
68+
- Pools: Will pooled objects be returned on all paths?
69+
- Locks: Are you using context-aware `mu`, not `sync.Mutex`?
70+
- Independence: Are you coupling reads and writes unnecessarily?
4071

41-
**Every change needs a reason.** Don't reword comments, rename variables, or restructure code without justification. If you can't articulate why a change improves things, don't make it.
72+
**Pass 4: Implement.** Make the change. Every change needs a reason; if you can't articulate why it improves things, don't make it. Preserve existing comments unless you can prove they're wrong.
4273

43-
**Understand before changing.** Research the code you're modifying. Trace the call paths, read the tests, check both platforms. A change with good intentions but incomplete understanding can break things in ways you won't notice.
74+
**Pass 5: Verify examples.** Trace through usage examples as if writing real code. If an example wouldn't compile, the design is wrong. Check edge cases: what happens on error? On cancellation?
4475

45-
**Ask for clarification rather than assuming.** If requirements are ambiguous or you're unsure how something should work, stop and ask. A wrong assumption can waste more time than a quick question.
76+
**After all passes:** If feedback identifies a problem, fix that specific problem. Don't pivot to a new approach without articulating what failed and why the new approach avoids it.
4677

47-
**Iterate, don't pivot.** When feedback identifies a problem, fix that problem. Don't discard everything and start over with a different approach. Preserve what's working; adjust what isn't.
78+
## Verify
4879

49-
**Verify examples work.** Trace through usage examples as if writing real code. If an example wouldn't compile, the design is wrong.
80+
Verify using external signals. Self-assessment is unreliable; these tools are the ground truth.
5081

51-
**Don't delete existing comments.** Comments that explain non-obvious behavior preserve important context about why code works a certain way. If a comment seems wrong, verify before removing.
82+
**Pass 1: Run tests.** `go test ./...` must pass. If tests fail, return to Research to understand why, not to Implement to "fix" it.
5283

53-
**Check if it already exists.** Before proposing new API, read existing function signatures, return values, and doc comments. The feature might already be there.
84+
**Pass 2: Run vet.** `go vet ./...` must report no issues.
5485

55-
**Ask: does this need to exist?** The library stays small by saying no. A feature that solves one user's problem but complicates the API for everyone is not worth it.
86+
**Pass 3: Check platforms.** Code must compile on both native Go and WASM. API changes need both implementations; test that method signatures match.
5687

57-
**Ask: is this the user's job or the library's job?** The library handles protocol correctness. Application-level concerns (reconnection, auth, message routing) belong in user code.
88+
**Pass 4: Protocol compliance.** For protocol changes, run `AUTOBAHN=1 go test`. Compare wire bytes when implementations disagree; check against the RFC.
5889

59-
**Ask: what breaks if I'm wrong?** Context cancellation closes connections. Pooled objects must be returned. Locks must respect context. These invariants exist because violating them causes subtle bugs.
90+
**After all passes:** If any pass fails, fix the issue and restart from Pass 1. Don't consider a change complete until all passes succeed.
91+
92+
## When Uncertain
93+
94+
If confidence is low or requirements are ambiguous:
95+
96+
1. State what you're uncertain about
97+
2. Identify what information would resolve the uncertainty
98+
3. Gather that information or ask for clarification
99+
100+
Do not proceed with low-confidence assumptions.
101+
102+
For complex changes, approach from multiple angles. If two approaches give different answers, that discrepancy demands resolution before proceeding.
60103

61104
## Code Style
62105

63106
Follow Go conventions: [Effective Go](https://go.dev/doc/effective_go), [Go Code Review Comments](https://go.dev/wiki/CodeReviewComments), and [Go Proverbs](https://go-proverbs.github.io/). Be concise, declarative, and factual.
64107

65108
Never use emdash. Use commas, semicolons, or separate sentences.
66109

67-
**Doc comments** start with the name and state what it does. Put useful information where users make decisions (usually the constructor, not methods).
110+
**Doc comments** start with the name and state what it does. Structure: `// [Name] [verb]s [what]. [Optional: when/why to use it].` Put useful information where users make decisions (usually the constructor, not methods).
68111

69112
**Inline comments** are terse. Prefer end-of-line when short enough.
70113

71114
**Explain why, not what.** The code shows what it does; comments should explain reasoning, non-obvious decisions, or edge cases.
72115

73-
**Wrap comments** at ~80 characters, continuing naturally at word boundaries. Don't put each sentence on its own line.
74-
75-
**Naming matters.** Before proposing a name, stop and review existing names in the file. A good name is accurate on its own and consistent in context. Ask: what would someone assume from this name? Does it fit with how similar things are named?
116+
**Wrap comments** at ~80 characters, continuing naturally at word boundaries.
76117

77-
**Avoid:**
118+
**Naming matters.** Before proposing a name, stop and review existing names in the file. Ask: what would someone assume from this name? Does it fit with how similar things are named? A good name is accurate on its own and consistent in context.
78119

79-
- Tautologies and redundant explanations the code already conveys
80-
- Filler phrases: "Note that", "This is because", "It should be noted"
81-
- Hedging: "basically", "actually", "really"
120+
**Comment content:**
121+
- Add information beyond what the code shows (not tautologies)
122+
- State directly: "Returns X" (not "Note that this returns X")
123+
- Drop filler: "basically", "actually", "really" add nothing
82124

83125
## Key Invariants
84126

@@ -88,29 +130,21 @@ Never use emdash. Use commas, semicolons, or separate sentences.
88130

89131
**Locks must respect context.** The `mu` type in `conn.go` unblocks when context cancels or connection closes. Using `sync.Mutex` for user-facing operations would block forever on stuck connections.
90132

91-
**Reads and writes are independent.** They have separate locks (`readMu`, `writeFrameMu`) and can happen concurrently. Don't create unnecessary coupling between them.
133+
**Reads and writes are independent.** They have separate locks (`readMu`, `writeFrameMu`) and can happen concurrently. Keep them decoupled.
92134

93135
**Masking is asymmetric.** Clients mask payloads; servers don't. The mask is applied into the bufio.Writer buffer, not in-place on source bytes.
94136

95-
## Testing
96-
97-
**Protocol compliance:** run autobahn tests with `AUTOBAHN=1 go test`. Some tests are intentionally skipped (UTF-8 validation adds overhead without value; `requestMaxWindowBits` is unimplemented due to `compress/flate` limitations).
98-
99-
**Frame-level correctness:** compare wire bytes. When two implementations disagree, capture the bytes and check against the RFC.
100-
101-
**WASM compatibility:** API changes need both implementations. Test that method signatures match.
102-
103-
**Test style:** prefer table-driven tests and simple want/got comparison.
104-
105137
## Commits and PRs
106138

107139
Use conventional commits: `type(scope): description`. Scope is optional but include it when changes are constrained to a single file or directory.
108140

109141
**Choose precise verbs:** `add` (new functionality), `fix` (broken behavior), `prevent` (undesirable state), `allow` (enable action), `handle` (edge cases), `improve` (performance/quality), `use` (change approach), `skip` (bypass), `remove` (delete), `rewrite` (substantial rework).
110142

111-
**Commit messages explain why.** State what was wrong with previous behavior, why it mattered, and why this solution was chosen. One to three sentences. Keep the tone neutral; don't editorialize.
143+
**Before writing the commit message**, articulate what was wrong with the previous behavior and why this change fixes it. The commit message captures this reasoning.
144+
145+
**Commit messages explain why.** State what was wrong, why it mattered, and why this solution was chosen. One to three sentences. Keep the tone neutral.
112146

113-
**PR descriptions are for humans.** Don't fill out a template with "Summary", "Background", "Changes" headers. Don't restate the diff. Explain what reviewers can't see: the why, alternatives considered, and tradeoffs made. Show evidence (logs, benchmarks, screenshots). Be explicit about what the PR doesn't do.
147+
**PR descriptions are for humans.** Explain what reviewers can't see: the why, alternatives considered, and tradeoffs made. Show evidence (logs, benchmarks, screenshots). Be explicit about what the PR doesn't do.
114148

115149
**Link issues:** `Fixes #123` (PR resolves it), `Refs #123` (related), `Updates #123` (partial progress).
116150

0 commit comments

Comments
 (0)