From f6d750eeab6191ed20a0920d340344a79b6e68ef Mon Sep 17 00:00:00 2001 From: axisrow Date: Sat, 11 Jul 2026 15:47:10 +0800 Subject: [PATCH] style: satisfy golangci-lint + gofmt (CI build-test/lint) Fixes the 12 golangci-lint findings + gofmt that failed the build-test and lint checks on this branch: - goimports/gofmt: order sessionguard before skillassets in session_manager/manager.go imports. - nilerr: Send's best-effort confirm no longer returns nil on a store error; it logs a warning instead (confirmation never fails the send). - revive: add the missing doc comment for EmitsBlockedActivity; rewrite the five sessionguard.Outcome const comments in the standard "Name ..." form. - staticcheck QF1008: drop the redundant embedded fakeStore selector in blockOnNthGetStore / blockAfterFirstReadStore (lifecycle + session_manager tests). gofmt clean, golangci-lint v2: 0 issues, affected tests pass. Co-Authored-By: Claude --- .../adapters/agent/claudecode/claudecode.go | 5 +++++ backend/internal/lifecycle/manager_test.go | 4 ++-- backend/internal/session_manager/manager.go | 11 +++++++++-- .../internal/session_manager/manager_test.go | 4 ++-- backend/internal/sessionguard/guard.go | 18 +++++++++--------- 5 files changed, 27 insertions(+), 15 deletions(-) diff --git a/backend/internal/adapters/agent/claudecode/claudecode.go b/backend/internal/adapters/agent/claudecode/claudecode.go index 33368a194b..f37af34cd1 100644 --- a/backend/internal/adapters/agent/claudecode/claudecode.go +++ b/backend/internal/adapters/agent/claudecode/claudecode.go @@ -67,6 +67,11 @@ func New() *Plugin { // accepted. See ports.ActivitySignaler. func (p *Plugin) EmitsSubmitActivity() bool { return true } +// EmitsBlockedActivity signals that Claude Code fires both pre- and post-tool +// hooks, so Activity.State can flip to blocked mid-turn on a permission dialog +// and the guarded send loop can clear it once the tool completes. Only +// claude-code (and its hook-delegators) carry this trio; see +// ports.ActivitySignaler. func (p *Plugin) EmitsBlockedActivity() bool { return true } var _ adapters.Adapter = (*Plugin)(nil) diff --git a/backend/internal/lifecycle/manager_test.go b/backend/internal/lifecycle/manager_test.go index 865b34d015..4aa7f5b45f 100644 --- a/backend/internal/lifecycle/manager_test.go +++ b/backend/internal/lifecycle/manager_test.go @@ -1156,9 +1156,9 @@ type blockOnNthGetStore struct { func (s *blockOnNthGetStore) GetSession(ctx context.Context, id domain.SessionID) (domain.SessionRecord, bool, error) { s.reads++ if s.reads == s.flipAt { - if rec, ok := s.fakeStore.sessions[s.id]; ok { + if rec, ok := s.sessions[s.id]; ok { rec.Activity.State = domain.ActivityBlocked - s.fakeStore.sessions[s.id] = rec + s.sessions[s.id] = rec } } return s.fakeStore.GetSession(ctx, id) diff --git a/backend/internal/session_manager/manager.go b/backend/internal/session_manager/manager.go index eafe2eaff5..7454108d50 100644 --- a/backend/internal/session_manager/manager.go +++ b/backend/internal/session_manager/manager.go @@ -17,8 +17,8 @@ import ( "github.com/aoagents/agent-orchestrator/backend/internal/domain" "github.com/aoagents/agent-orchestrator/backend/internal/ports" aoprocess "github.com/aoagents/agent-orchestrator/backend/internal/process" - "github.com/aoagents/agent-orchestrator/backend/internal/skillassets" "github.com/aoagents/agent-orchestrator/backend/internal/sessionguard" + "github.com/aoagents/agent-orchestrator/backend/internal/skillassets" ) // Sentinel errors returned by the Session Manager; callers match them with @@ -1461,7 +1461,14 @@ func (m *Manager) Send(ctx context.Context, id domain.SessionID, message string) // satisfy both; every other harness opts out via EmitsBlockedActivity — // see ports.ActivitySignaler. rec, ok, err := m.store.GetSession(ctx, id) - if err != nil || !ok { + if err != nil { + // Confirmation is best-effort and never fails the send (the message + // was already delivered above); log so a store error is not swallowed + // silently. + m.logger.Warn("send: confirm skipped, session lookup failed", "sessionID", id, "error", err) + return nil + } + if !ok { return nil } if m.harnessNudgeSafe(rec.Harness) { diff --git a/backend/internal/session_manager/manager_test.go b/backend/internal/session_manager/manager_test.go index c94ffb91bf..901cc446e9 100644 --- a/backend/internal/session_manager/manager_test.go +++ b/backend/internal/session_manager/manager_test.go @@ -3606,9 +3606,9 @@ type blockAfterFirstReadStore struct { func (s *blockAfterFirstReadStore) GetSession(ctx context.Context, id domain.SessionID) (domain.SessionRecord, bool, error) { s.reads++ if s.reads >= 4 { - if rec, ok := s.fakeStore.sessions[s.id]; ok { + if rec, ok := s.sessions[s.id]; ok { rec.Activity.State = domain.ActivityBlocked - s.fakeStore.sessions[s.id] = rec + s.sessions[s.id] = rec } } return s.fakeStore.GetSession(ctx, id) diff --git a/backend/internal/sessionguard/guard.go b/backend/internal/sessionguard/guard.go index dc73d4cb92..394f54026b 100644 --- a/backend/internal/sessionguard/guard.go +++ b/backend/internal/sessionguard/guard.go @@ -30,19 +30,19 @@ type SessionReader interface { type Outcome int const ( - // SuppressedUnknown: the pre-write session read failed, so the state is - // unknown and the guard failed closed. Deliberately the zero value — a - // forgotten assignment must never read as a successful send. + // SuppressedUnknown is returned when the pre-write session read failed, so + // the state is unknown and the guard failed closed. Deliberately the zero + // value — a forgotten assignment must never read as a successful send. SuppressedUnknown Outcome = iota - // Sent: the message was written to the session's pane (a messenger failure - // surfaces as Sent plus a non-nil error: the write was attempted). + // Sent means the message was written to the session's pane (a messenger + // failure surfaces as Sent plus a non-nil error: the write was attempted). Sent - // SuppressedNotFound: no session row exists for the id. + // SuppressedNotFound means no session row exists for the id. SuppressedNotFound - // SuppressedTerminated: the session is terminated; its pane is gone or - // about to be reaped. + // SuppressedTerminated means the session is terminated; its pane is gone + // or about to be reaped. SuppressedTerminated - // SuppressedAwaitingUser: the session awaits the human — blocked on a + // SuppressedAwaitingUser means the session awaits the human — blocked on a // permission decision (Deliver and Nudge), or waiting at the prompt for // the next instruction (Nudge only). SuppressedAwaitingUser