The #35 data gate could never fill: a real review call routed cleanly to qwen36 but /pass-rate stayed total:0 under every key. Root cause was three independent defects in the session_log path, each alone fatal: - A: a successful routed call logged final_status "skip", never "pass". /pass-rate computes pass/(pass+fail) and skips count as neither, so the >=0.90 gate was mathematically unreachable. Success now logs "pass". - B: every record was written under skill "_routing", so /pass-rate?skill= review|debug (what #35 measures) always read zero. Now uses the real e.Skill; routing decisions stay groupable via session_id "_routing". - C: the session_log POST to the bearer-gated ingestion /mcp carried no Authorization header → silent 401, swallowed by best-effort logging (the documented mcpclient-empty-token-silent-401 footgun). Logger now takes a token (BRAIN_MCP_TOKEN) and sets the bearer when non-empty. Tests rewritten to assert correct behavior (they had encoded the bugs: "skip" on success, "_routing" skill). New test covers the auth header and the empty-token path. Infra (BRAIN_MCP_TOKEN ExternalSecret + env on the routing deployment) and redeploy follow separately. Refs #73, #35. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+19
-6
@@ -17,19 +17,24 @@ type LogEntry struct {
|
||||
Message string // free-form, e.g. "model=qwen35, pass_rate=0.94"
|
||||
ProjectRoot string
|
||||
DurationMs int64
|
||||
Failed bool // true → final_status: "fail"; false → "skip"
|
||||
Failed bool // true → final_status: "fail"; false → "pass"
|
||||
}
|
||||
|
||||
// Logger posts session_log entries to a brain MCP at BrainURL + /mcp.
|
||||
type Logger struct {
|
||||
BrainURL string
|
||||
Token string // bearer for the (auth-gated) ingestion /mcp; empty = no header
|
||||
HTTP *http.Client
|
||||
}
|
||||
|
||||
// NewLogger creates a Logger with a 2-second HTTP timeout.
|
||||
func NewLogger(brainURL string) *Logger {
|
||||
// NewLogger creates a Logger with a 2-second HTTP timeout. token authenticates
|
||||
// to the bearer-gated ingestion /mcp; an empty token sends no Authorization
|
||||
// header (and silently 401s against a gated server — see brain
|
||||
// mcpclient-empty-token-silent-401-envfrom-missing-key).
|
||||
func NewLogger(brainURL, token string) *Logger {
|
||||
return &Logger{
|
||||
BrainURL: brainURL,
|
||||
Token: token,
|
||||
HTTP: &http.Client{Timeout: 2 * time.Second},
|
||||
}
|
||||
}
|
||||
@@ -37,7 +42,10 @@ func NewLogger(brainURL string) *Logger {
|
||||
// LogDecision posts a session_log MCP call. Errors are returned but the caller
|
||||
// MUST NOT block real work on them — logging is best-effort.
|
||||
func (l *Logger) LogDecision(ctx context.Context, e LogEntry) error {
|
||||
status := "skip"
|
||||
// A completed routed call is a pass (liveness); only an execution error is a
|
||||
// fail. There is no "skip" for routing — the prior default-to-"skip" meant a
|
||||
// successful call never counted toward pass_rate, so the gate was unreachable.
|
||||
status := "pass"
|
||||
if e.Failed {
|
||||
status = "fail"
|
||||
}
|
||||
@@ -48,8 +56,10 @@ func (l *Logger) LogDecision(ctx context.Context, e LogEntry) error {
|
||||
"params": map[string]any{
|
||||
"name": "session_log",
|
||||
"arguments": map[string]any{
|
||||
"session_id": e.SessionID,
|
||||
"skill": "_routing",
|
||||
"session_id": e.SessionID,
|
||||
// The real skill, so /pass-rate?skill=review|debug sees these
|
||||
// records; routing decisions stay groupable via session_id "_routing".
|
||||
"skill": e.Skill,
|
||||
"phase": "decide",
|
||||
"final_status": status,
|
||||
"message": fmt.Sprintf("%s: %s — %s", e.Skill, e.Decision, e.Message),
|
||||
@@ -67,6 +77,9 @@ func (l *Logger) LogDecision(ctx context.Context, e LogEntry) error {
|
||||
return fmt.Errorf("log: build request: %w", err)
|
||||
}
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
if l.Token != "" {
|
||||
req.Header.Set("Authorization", "Bearer "+l.Token)
|
||||
}
|
||||
resp, err := l.HTTP.Do(req)
|
||||
if err != nil {
|
||||
return fmt.Errorf("log: request: %w", err)
|
||||
|
||||
Reference in New Issue
Block a user