Scaffold GitManager multi-repo dashboard

Runnable skeleton per AGENT.md: Echo server (/, /help, /healthz, /api/repos), read-only repo scanner with in-memory index, the internal/git boundary, the <repo-list> web component with design tokens, and dev tooling (Dockerfile, docker-compose, air, .env.example).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-09-19 16:34:43 -04:00
parent c24604fe65
commit 1a2ad98c33
20 changed files with 1527 additions and 0 deletions
+35
View File
@@ -0,0 +1,35 @@
// Package logging builds the application's slog logger. Logs go to stderr
// (readable console in dev, structured JSON otherwise) and, optionally, to a
// file. There is no database sink — see AGENT.md §7.
package logging
import (
"io"
"log/slog"
"os"
)
// Setup returns a configured *slog.Logger and, if a file sink was opened, an
// io.Closer to flush/close it on shutdown (nil when no file sink is used).
func Setup(dev bool, logFile string) (*slog.Logger, io.Closer, error) {
var w io.Writer = os.Stderr
var closer io.Closer
if logFile != "" {
f, err := os.OpenFile(logFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0o644)
if err != nil {
return nil, nil, err
}
w = io.MultiWriter(os.Stderr, f)
closer = f
}
var handler slog.Handler
if dev {
handler = slog.NewTextHandler(w, &slog.HandlerOptions{Level: slog.LevelDebug})
} else {
handler = slog.NewJSONHandler(w, &slog.HandlerOptions{Level: slog.LevelInfo})
}
return slog.New(handler), closer, nil
}