add Go sidecar and CLI skeleton
cmd/clide/main.go is the single entry; the same binary will later switch into sidecar-daemon mode via --daemon. internal/cli holds the dispatch (stdlib flag for now, Cobra arrives with the first real subcommand in Tier 2). internal/diag mirrors pql's exit-code contract so the two tools share one mental model for callers. internal/version exposes the build-info struct that the Makefile's -ldflags -X targets stamp; Info() is wired to --version so the binary reports both the declared project.yaml version and the commit it was built from. The daemon, pty, proc, git, ipc, and pql sub-packages ship as doc.go stubs naming the subsystem they will own. They keep the layout legible before the code lands so tier work has a home on arrival. Module path targets Gitea (git.schweitz.net/jpmschweitzer/clide/sidecar), matching where the repo lives. Go module resolution works if the host serves the meta tags; a vanity import path can be added later if needed. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
// Package diag defines the exit-code contract and emits structured
|
||||
// diagnostics to stderr as line-delimited JSON.
|
||||
//
|
||||
// Mirrors pql's diag contract so Claude (and any other tool that
|
||||
// consumes both CLIs) sees a single shape.
|
||||
package diag
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"os"
|
||||
)
|
||||
|
||||
// Exit codes. Same numeric space as pql's.
|
||||
const (
|
||||
OK = 0 // success
|
||||
NoMatch = 2 // success with zero matches / nothing to do
|
||||
Usage = 64 // EX_USAGE — bad CLI flag or missing subcommand
|
||||
DataErr = 65 // EX_DATAERR — malformed request
|
||||
NoInput = 66 // EX_NOINPUT — missing required resource (repo, socket, file)
|
||||
Unavail = 69 // EX_UNAVAILABLE — sidecar unreachable / subsystem down
|
||||
Software = 70 // EX_SOFTWARE — internal error
|
||||
)
|
||||
|
||||
type Level string
|
||||
|
||||
const (
|
||||
LevelWarn Level = "warn"
|
||||
LevelError Level = "error"
|
||||
)
|
||||
|
||||
// Diagnostic is one entry in the stderr JSON-per-line stream.
|
||||
type Diagnostic struct {
|
||||
Level Level `json:"level"`
|
||||
Code string `json:"code"`
|
||||
Msg string `json:"msg"`
|
||||
Hint string `json:"hint,omitempty"`
|
||||
}
|
||||
|
||||
// Emit writes a diagnostic as one JSON line to w.
|
||||
func Emit(w io.Writer, d Diagnostic) {
|
||||
b, err := json.Marshal(d)
|
||||
if err != nil {
|
||||
_, _ = io.WriteString(w, `{"level":"error","code":"diag.marshal","msg":"failed to marshal diagnostic"}`+"\n")
|
||||
return
|
||||
}
|
||||
_, _ = w.Write(append(b, '\n'))
|
||||
}
|
||||
|
||||
// Warn emits a warning diagnostic to stderr.
|
||||
func Warn(code, msg string) {
|
||||
Emit(os.Stderr, Diagnostic{Level: LevelWarn, Code: code, Msg: msg})
|
||||
}
|
||||
|
||||
// Error emits an error diagnostic to stderr.
|
||||
func Error(code, msg, hint string) {
|
||||
Emit(os.Stderr, Diagnostic{Level: LevelError, Code: code, Msg: msg, Hint: hint})
|
||||
}
|
||||
Reference in New Issue
Block a user