Skip to content

Commit 826c76b

Browse files
committed
chore: restore AGENTS.md — project instructions for AI agents
1 parent 6d3c0ea commit 826c76b

1 file changed

Lines changed: 244 additions & 0 deletions

File tree

AGENTS.md

Lines changed: 244 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,244 @@
1+
# AGENTS.md — Hawk Coding Agent
2+
3+
This file describes the hawk project for AI agents working in this codebase.
4+
The TUI `/memory` command references this file.
5+
6+
---
7+
8+
## Project Overview
9+
10+
hawk is an AI-powered coding agent for the terminal. It reads codebases, writes
11+
and edits files, runs tests, and manages git — all through natural language.
12+
Built in Go with zero CGO dependencies, it ships as a single static binary for
13+
linux/darwin/windows on amd64/arm64.
14+
15+
**Tagline:** AI coding agent for your terminal — built for developers, not teams
16+
or enterprises.
17+
18+
## Ecosystem
19+
20+
hawk is part of the hawk-eco mono-ecosystem:
21+
22+
| Component | Purpose |
23+
|-----------|---------|
24+
| **hawk** | AI coding agent (this repo) |
25+
| **eyrie** | LLM provider runtime — routing, streaming, retries, caching |
26+
| **yaad** | Graph-based persistent memory for coding agents |
27+
| **tok** | Tokenizer, compression, secrets scanning, rate limiting |
28+
| **sight** | Diff-based code review and static analysis |
29+
| **inspect** | Security audit library (CVE, API security, CI output) |
30+
| **trace** | Session capture and replay CLI |
31+
32+
Modules are pinned in `go.mod`. External checkouts live under `external/` with a
33+
`go.work` file for local development.
34+
35+
## Architecture
36+
37+
```
38+
hawk/
39+
├── cmd/ # CLI entry point (Cobra + Bubble Tea TUI)
40+
├── internal/
41+
│ ├── engine/ # Agent loop, compaction, context management
42+
│ │ ├── ctxmgr/ # Context providers, packing, visualization
43+
│ │ ├── token/ # Budget allocation, prediction
44+
│ │ ├── streaming/ # Response cache, stream optimizer, thinking
45+
│ │ ├── session/ # Compression, cross-session learning
46+
│ │ ├── memory/ # Knowledge distillation
47+
│ │ ├── planning/ # Goals, task decomposition
48+
│ │ ├── workflow/ # JSON-defined automation pipelines
49+
│ │ ├── review/ # Code review bot, quality scorer
50+
│ │ ├── observability/ # Profiler, debug recorder
51+
│ │ ├── validation/ # Lint loop, test loop
52+
│ │ └── ...
53+
│ ├── tool/ # 40+ built-in tools (file edit, git, codegen, etc.)
54+
│ ├── config/ # Settings, env manager, migration
55+
│ ├── session/ # SQLite persistence, search, export, replay
56+
│ ├── permissions/ # Guardian, rules DSL, boundary checker
57+
│ ├── sandbox/ # Seatbelt, landlock, net proxy
58+
│ ├── intelligence/ # Repo map, AST analysis, dependency graphs
59+
│ ├── multiagent/ # Personas, inter-agent messaging, sub-agents
60+
│ ├── hooks/ # Event-driven plugin system
61+
│ ├── mcp/ # Model Context Protocol client/server
62+
│ ├── daemon/ # Background HTTP/SSE server
63+
│ ├── resilience/ # Circuit breaker, rate limiting, health checks
64+
│ └── feature/ # Eval, fingerprint, scaffolding
65+
├── shared/types/ # Cross-repo exported types (severity, etc.)
66+
├── docs/ # Architecture docs, research notes
67+
└── testdata/ # Test fixtures
68+
```
69+
70+
## Key Design Decisions
71+
72+
- **Zero CGO:** Pure Go, cross-compilable. Tree-sitter is optional.
73+
- **`internal/` is private:** Other repos import `shared/types/` only.
74+
- **Tool safety layer:** Every tool call goes through permissions (guardian,
75+
rules DSL, boundary checker) before execution.
76+
- **Engine-first:** The agent loop in `internal/engine/` orchestrates context
77+
packing, tool dispatch, streaming, and session persistence.
78+
- **Ecosystem integration:** eyrie handles all LLM API communication. hawk
79+
never talks to LLM APIs directly.
80+
81+
## Development Guidelines
82+
83+
### Build & Test
84+
85+
```bash
86+
go build . # Build binary
87+
go test -race ./... # Run all tests with race detector
88+
make ci # Full CI suite (lint, test, security)
89+
make cover # Coverage report
90+
make path # Developer path verification
91+
make smoke # Build + quick verification
92+
```
93+
94+
### Go Conventions
95+
96+
- Standard Go project layout: `cmd/` for entry points, `internal/` for private
97+
- Tests live alongside source files (`foo.go``foo_test.go`)
98+
- Use table-driven tests where practical
99+
- Errors are values — wrap with `fmt.Errorf("context: %w", err)`
100+
- No global mutable state; prefer dependency injection
101+
102+
### Commit Conventions
103+
104+
Use [Conventional Commits](https://www.conventionalcommits.org/):
105+
```
106+
feat: add new tool
107+
fix: handle edge case in file edit
108+
docs: update AGENTS.md
109+
refactor: extract context packing logic
110+
test: add coverage for guardian
111+
```
112+
113+
### Code Style
114+
115+
- `gofmt` and `go vet` are mandatory (enforced by CI)
116+
- Keep functions focused; extract helpers for clarity
117+
- Prefer explicit error handling over panics
118+
- Comments on exported types/functions only (per Go convention)
119+
120+
### Adding a New Tool
121+
122+
1. Create `internal/tool/mytool.go`
123+
2. Implement the tool interface (name, description, parameters, execute)
124+
3. Register in the tool registry
125+
4. Add tests in `mytool_test.go`
126+
5. The tool automatically gets permission checking via the safety layer
127+
128+
### Adding a New Feature
129+
130+
1. Check FEATURES.md for the feature list and conventions
131+
2. Place code in the appropriate `internal/` package
132+
3. Follow existing patterns (e.g., context providers are pluggable)
133+
4. Add tests and update documentation
134+
135+
## File Organization Notes
136+
137+
- `FEATURES.md` — Complete feature reference with 100 features across 12 categories
138+
- `CONTRIBUTING.md` — PR process, commit conventions
139+
- `docs/` — Architecture details, security model, ecosystem message flow
140+
- `external/` — Ecosystem repo checkouts for `go.work` development
141+
- `shared/types/` — Types exported for sight/inspect/tok (they must not import `internal/`)
142+
143+
## Testing Philosophy
144+
145+
- Unit tests for all new code
146+
- Integration tests for tool execution and engine loop
147+
- Race detector enabled in CI (`-race`)
148+
- No test files committed with `t.Skip()` without a tracking issue
149+
150+
## Common Pitfalls
151+
152+
- Do not import `internal/` from other ecosystem repos — use `shared/types/`
153+
- Do not put API keys in `.env` or shell env for hawk — use `/config` (OS keychain)
154+
- The `external/` directory is for local dev only; CI clones repos separately
155+
- `go.work` is for local multi-repo development; it is not committed
156+
157+
## Naming Conventions
158+
159+
- **Tool types**: `FooTool` struct implementing the `Tool` interface (`Name()`, `Description()`, `Parameters()`, `Execute()`)
160+
- **Config types**: `Settings`, `MCPServerConfig`, `CustomProviderConfig` — no prefix, in `config` package
161+
- **Engine types**: `Session`, `CoreLoop`, `SafetyLayer`, `Intelligence`, `Optimizer` — in `engine` package
162+
- **Health checks**: `Checker` func type, `Check` struct with `Name`, `Status`, `Message`
163+
- **Resilience**: `Breaker` (circuit breaker), `Config` + `Do` (retry), `Limiter` (rate limit)
164+
- **Error types**: `ValidationError` with `Field`, `Message`, `Value`; `ValidationResult` with `Errors`, `Valid`
165+
- **Bridges**: `Ready() bool` method, `NewBridge()` constructor, graceful degradation when unavailable
166+
167+
## API Patterns
168+
169+
- **Tool registration**: `tool.NewRegistry(tools...)``registry.Get("ToolName")``tool.Execute(ctx, input)`
170+
- **Settings loading**: `config.LoadSettings()` merges global + project; `config.LoadGlobalSettings()` for global-only
171+
- **Session construction**: `engine.NewSessionWithClient(client, provider, model, systemPrompt, registry, deploymentRouting)`
172+
- **Service composition**: `engine.NewSessionServices(opts...)` with `WithProvider()`, `WithTools()`, `WithMemory()`, etc.
173+
- **Health checks**: `health.NewRegistry()``registry.Register("name", checker)``registry.Run(ctx)``registry.Status()`
174+
- **Circuit breaker**: `circuit.New(cfg)``breaker.Call(fn)` or `breaker.Allow()``breaker.State()`
175+
- **Retry**: `retry.Do(ctx, cfg, fn)` with exponential backoff + jitter; `retry.DoWithResult[T]` for typed returns
176+
- **Config validation**: `config.ValidateSettings(s)` returns `ValidationResult{Errors, Valid}`
177+
- **Ecosystem panel**: `config.FormatEcosystemPanel(ctx, provider, model)` for diagnostics
178+
179+
## Testing Patterns
180+
181+
- **Table-driven tests** with `t.Run(name, func(t *testing.T){...})` for all multi-case tests
182+
- **`t.Parallel()`** on all tests that don't share mutable state
183+
- **`t.TempDir()`** for filesystem isolation (auto-cleanup)
184+
- **`credentials.MapStore{}`** for credential isolation in tests:
185+
```go
186+
store := &credentials.MapStore{}
187+
credentials.SetDefaultStore(store)
188+
t.Cleanup(func() { credentials.SetDefaultStore(nil) })
189+
```
190+
- **`bytes.Buffer`** as `io.Writer` for logger output capture
191+
- **Fuzz tests** for input parsing robustness: `func FuzzFoo(f *testing.F) { ... }`
192+
- **No mocks framework** — use concrete types and test doubles
193+
- **Meta-audit tests** in `internal/testaudit/` enforce architectural invariants via go/ast
194+
195+
## Refactoring Guidelines
196+
197+
- **Safe to refactor**: `internal/resilience/` (retry, circuit, ratelimit, health) — no public API
198+
- **Safe to refactor**: `internal/observability/logger/` — internal only, no external consumers
199+
- **Safe to refactor**: `internal/system/` (bus, shutdown, retention, cron, staleness)
200+
- **Caution**: `internal/engine/session.go` Session struct — widely referenced across 30+ sub-packages
201+
- **Caution**: `internal/config/settings.go` Settings struct — serialized to JSON, dual-format (snake_case + camelCase)
202+
- **Caution**: `internal/tool/` Tool interface — implemented by 40+ tools
203+
- **Blocked**: `shared/types/` — exported to eyrie, sight, inspect, tok; changes break ecosystem
204+
205+
## Key File Locations
206+
207+
| What | Where |
208+
|---|---|
209+
| CLI entry point | `cmd/root.go` |
210+
| Agent loop | `internal/engine/session.go` (`Stream()`, `agentLoop()`) |
211+
| Session services | `internal/engine/session_services.go` |
212+
| Tool interface | `internal/tool/tool.go` (`Tool`, `Registry`) |
213+
| Tool context | `internal/tool/tool.go` (`ToolContext`, `WithToolContext`) |
214+
| Settings | `internal/config/settings.go` (`Settings`, `LoadSettings()`) |
215+
| Config validation | `internal/config/validator.go` (`ValidateSettings()`) |
216+
| Config migration | `internal/config/migrate.go` (`MigrationRegistry`) |
217+
| Env manager | `internal/config/envmanager.go` (`EnvManager`) |
218+
| Health checks | `internal/resilience/health/health.go` (`Registry`, `Checker`) |
219+
| Circuit breaker | `internal/resilience/circuit.go` (`Breaker`, `Manager`) |
220+
| Retry | `internal/resilience/retry/retry.go` (`Do()`, `DoWithResult()`) |
221+
| Rate limiter | `internal/resilience/ratelimit/ratelimit.go` (`Limiter`) |
222+
| Logger | `internal/observability/logger/logger.go` (`Logger`) |
223+
| Metrics | `internal/observability/metrics/metrics.go` (`Counter`, `Gauge`, `Timer`) |
224+
| OTEL tracing | `internal/observability/oteltrace/trace.go` |
225+
| Multi-agent missions | `internal/multiagent/mission.go` (`Mission`) |
226+
| Message bus | `internal/multiagent/messaging.go` (`MessageBus`) |
227+
| Shared memory | `internal/multiagent/shared_memory.go` (`SharedMemory`) |
228+
| Session persistence | `internal/session/persist.go` |
229+
| MCP client | `internal/mcp/mcp.go` |
230+
| MCP server | `internal/mcp/server.go` |
231+
| Provider routing | `internal/provider/routing/router.go` |
232+
| Bridges | `internal/bridge/{inspect,sight,sessioncapture}/bridge.go` |
233+
| Doctor diagnostics | `cmd/diagnostics.go` |
234+
| Meta-audit tests | `internal/testaudit/audit_test.go` |
235+
236+
## Anti-Patterns
237+
238+
- **No `os.Getenv` in `internal/`** — use `config.EnvManager` to centralize env access. Exception: `internal/observability/oteltrace/` for telemetry env vars.
239+
- **No `panic()` for error handling** — return `error` values. Exception: `init()` functions for package-level assertions.
240+
- **No `fmt.Print` for logging** — use `logger.Logger` with structured fields. Exception: `internal/onboarding/` and `internal/engine/scaffold/` for user-facing CLI output.
241+
- **No API keys in settings.json** — use OS secret store via `credentials` package and `/config` command.
242+
- **No importing `internal/` from other ecosystem repos** — use `shared/types/` for cross-repo types.
243+
- **No global mutable state** — prefer dependency injection via `deps` structs or `context.WithValue`.
244+
- **No `t.Skip()` without a tracking issue** — every skipped test needs a GitHub issue number.

0 commit comments

Comments
 (0)