Six fixes from the second code review pass — none load-bearing but all improve the contract honesty or prevent future churn. Tests pass with -race (49 in package, 299 across the backend). 1. Preflight: atomic.Bool fast-path before the mutex so cached-success calls don't contend on the lock. Double-checked locking on the mutex side so concurrent first-callers still serialize the single GET /user request. 2. Preflight godoc: tighten to say it verifies token validity, not repo authorization — Get/List against a specific repo may still return ErrAuthFailed after a green Preflight if the token lacks the scope or the repo isn't visible. 3. domain.ListFilter.Limit godoc: explicitly note that exceeding the provider per-page max is SILENTLY capped (no error, no truncation signal) and that auto-pagination is deferred to #35. 4. Extract issueFromGH helper. Get and List were duplicating the identical ghIssue -> domain.Issue projection; consolidating now prevents a 3-way merge when #40 (Comment/Transition) lands. 5. parseGitHubRepo: reject whitespace and # in both owner and repo segments. Leading dots stay legal (the "owner/.github" repo convention). New test cases cover the rejections plus a positive guard for the leading-dot case. 6. fakeGH test helper: lock the handlers map on both read and write, so future tests registering handlers from goroutines won't trip -race. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> |
||
|---|---|---|
| .github/workflows | ||
| backend | ||
| docs | ||
| frontend | ||
| .gitignore | ||
| README.md | ||
README.md
agent-orchestrator
Rewrite of the agent-orchestrator: a long-running Go backend daemon (backend/)
paired with an Electron + TypeScript frontend (frontend/).
See docs/ for architecture and status — start with the
Lifecycle Manager + Session Manager lane in docs/architecture.md.
Backend daemon
The Go binary in backend/ is the HTTP daemon — a loopback-only
sidecar the Electron supervisor will spawn (Phase 1c). Phase 1a landed the
skeleton: chi router, middleware stack (recoverer → request-id → logger →
real-ip), /healthz + /readyz, atomic running.json PID/port handshake,
graceful shutdown on SIGINT/SIGTERM.
Run
cd backend
go run . # binds 127.0.0.1:3001 with all defaults
AO_PORT=3019 go run . # override per invocation
Health check:
curl localhost:3001/healthz # {"status":"ok"}
curl localhost:3001/readyz # {"status":"ready"}
Configuration (env only)
The bind host is always 127.0.0.1: the daemon is a loopback-only sidecar
and binding any other interface would be a security regression, so the host
is intentionally not env-configurable.
| Var | Default | Purpose |
|---|---|---|
AO_PORT |
3001 |
bind port; fails fast if taken |
AO_REQUEST_TIMEOUT |
60s |
per-request timeout (Go duration) |
AO_SHUTDOWN_TIMEOUT |
10s |
graceful-shutdown hard cap |
AO_RUN_FILE |
<UserConfigDir>/agent-orchestrator/running.json |
PID + port handshake path |
Test
cd backend
gofmt -l . && go build ./... && go vet ./... && go test -race ./...