Skip to content

feat: competitive parity with Copilot CLI and Claude Code#2

Merged
intel352 merged 34 commits intomasterfrom
feat/competitive-parity
Mar 14, 2026
Merged

feat: competitive parity with Copilot CLI and Claude Code#2
intel352 merged 34 commits intomasterfrom
feat/competitive-parity

Conversation

@intel352
Copy link
Contributor

Summary

Upgrades ratchet-cli to workflow v0.3.40 and adds 12 major features to achieve competitive parity with GitHub Copilot CLI and Claude Code.

New Features

  • Plan mode/plan, /approve, /reject: structured planning before execution with numbered step tracking
  • Fleet mode/fleet: auto-decompose plans into parallel workers with fan-out/fan-in
  • Team mode/team, Ctrl+T: named agents with roles and direct peer messaging
  • Context auto-compression — auto-summarize at 90% token threshold, /compact for manual trigger
  • Code review agent/review: built-in agent using CodeReviewTool with Critical/Important/Minor output
  • Cron/loop scheduling/loop <interval> <cmd>, /cron <expr> <cmd>: SQLite-persisted, pause/resume/stop
  • Enhanced hooks — 8 new lifecycle events (pre/post-plan, pre/post-fleet, on-agent-spawn/complete, on-token-limit, on-cron-tick)
  • MCP CLI discovery — auto-detect gh, docker, kubectl and register as tools
  • Per-agent model routing — agents specify provider+model; fleet workers auto-route by task complexity; /cost shows per-worker breakdown
  • Session actors — goakt v4 actor system with per-session persistent actors and approval workflows
  • Job control panelCtrl+J / /jobs: unified view of all sessions, fleet workers, team agents, cron jobs with pause/kill actions

Engine Upgrade

  • workflow v0.3.30 → v0.3.40 (parallel steps, actors, graphql, json_parse, secret_fetch, infra provisioner, interfaces refactor)

Bugs Found and Fixed During Development

  • Data race in fleet worker status (shared pointers after lock release)
  • Team kill key was a no-op (display name vs job ID routing)
  • Cron goroutines killed immediately (gRPC request context vs daemon context)
  • Shell injection risk in hooks (template data not escaped)
  • JobPanel never initialized (Init not batched)
  • ResumeJob was a functional no-op
  • Actor system ignored daemon shutdown context
  • Compression truncated at byte boundary (UTF-8 corruption)
  • MCP execute didn't split multi-word args

Test plan

  • go build ./... passes
  • go test ./... -race -count=1 — 13 packages, 0 failures, 0 data races
  • Integration tests for plan, fleet, team, cron, jobs lifecycle
  • TUI component tests for plan, fleet, jobpanel
  • Provider tests with mock HTTP
  • 3 parallel QA agents validated all features end-to-end
  • 2-stage code review (spec compliance + code quality) on every phase

🤖 Generated with Claude Code

intel352 and others added 30 commits March 13, 2026 19:28
- Upgrade github.com/GoCodeAlone/workflow to v0.3.40
- ratchet (v0.1.15) and workflow-plugin-agent (v0.3.1) already at latest
- No breaking API changes required (module.PipelineContext etc. unchanged)
- All tests pass

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add PlanStep, Plan, ApprovePlanReq, RejectPlanReq messages
- Add plan_proposed and plan_step_update to ChatEvent oneof
- Add ApprovePlan (streaming) and RejectPlan RPCs

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add CronJob, CreateCronReq, CronJobList, CronJobReq proto messages
- Add CreateCron/ListCrons/PauseCron/ResumeCron/StopCron RPCs
- Implement CronScheduler with SQLite persistence and goroutine-per-job
- Support Go duration strings ("5m") and simple cron expressions ("*/10 * * * *")
- Reload active jobs from DB on daemon restart (Start method)
- Add cron_jobs table to initDB
- Wire CronScheduler into Service; implement all 5 RPCs in service.go
- Add client methods for all cron RPCs
- Add /loop <interval> <cmd> and /cron subcommands to TUI commands
- Add 6 tests: CreateInterval, Pause, Resume, Stop, PersistReload, ParseSchedule

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…oken-limit)

Add 8 new event constants and AllEvents slice for documentation/validation.
Update Run() docs to list new template data keys (plan_id, fleet_id,
agent_name, agent_role, cron_id, tokens_used, tokens_limit).
Add tests: NewEvents, TemplateExpansion_NewKeys, AllEventsComplete.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add PlanManager with Create/Get/ForSession/Approve/Reject/UpdateStep
- Wire plans into Service struct (NewService initializes PlanManager)
- Implement ApprovePlan and RejectPlan RPCs on Service
- Add PlanView component with step navigation, skip toggle, approve/reject
  keybinds (↑↓/jk navigate, space toggle skip, Enter approve, Esc reject)
- Add ApprovePlan/RejectPlan client methods
- Handle ChatEvent_PlanProposed and ChatEvent_PlanStepUpdate in chat page
- Route PlanApproveMsg/PlanRejectMsg from PlanView to daemon RPCs
- Add /plan, /approve, /reject slash commands
- Fix cron_test.go field name: job.Id → job.ID
- Also fix proto regeneration to regenerate with fleet+cron types
- Fix build: remove duplicate cron function definitions

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
**Hooks (Task 16):**
- Add PrePlan, PostPlan, PreFleet, PostFleet, OnAgentSpawn, OnAgentComplete,
  OnTokenLimit, OnCronTick event constants
- Add AllEvents slice for documentation; update Run() docs for new template keys
- Tests: NewEvents, TemplateExpansion_NewKeys, AllEventsComplete

**MCP CLI discovery (Task 17):**
- New internal/mcp package: Discoverer checks exec.LookPath for gh, docker, kubectl
- Registers CLI-wrapping plugin.Tool implementations via ToolRegistry.RegisterMCP
- Caches discovery results; InvalidateCache/Enable/Disable for runtime control
- Wire MCPDiscoverer into EngineContext; runs discovery in background goroutine
- Add /mcp list|enable|disable slash commands
- Tests: GHFound, NoCLIs, CacheResults, Enable, Disable

**Model routing (Task 18):**
- Add ModelRouting{SimpleTaskModel, ComplexTaskModel, ReviewModel} to config.Config
- internal/daemon/model_routing.go: ClassifyStep heuristic + ModelForStep mapper
- FleetManager stores routing config; workers get model assigned at creation
- NewEngineContext loads ModelRouting from config; NewService passes to FleetManager
- Tests: Classification, ModelForStep, EmptyConfig

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add FleetPanel component (internal/tui/components/fleet.go) with:
  - Worker table: Name | Step | Status | Model | Elapsed
  - Spinner/checkmark/X status icons for running/completed/failed
  - Keybind K to kill selected worker
  - FleetWorkerKillMsg and FleetStatusUpdatedMsg messages
- Add fleet TUI tests (4 passing)
- Add config.ModelRouting struct (SimpleTaskModel, ComplexTaskModel, ReviewModel)
  for per-step model selection

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…k 13)

- Add LoadBuiltins() with go:embed for internal/agent/builtins/*.yaml
- Add code-reviewer.yaml with correct ratchetplugin tool names
- Add /compact and /review slash commands
- Fix teamStart() to use correct StartTeam client signature
- Add TestBuiltinAgents_CodeReviewerLoads, TestParseCompact, TestReviewCommand_Parse

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add Feedback field to Plan proto message (field 7)
- Reject(): add state guard (approved/executing/completed/rejected → error), store feedback
- Move ApprovePlan/RejectPlan RPC handlers from plans.go to service.go
- Update tests: verify feedback stored, verify state guard for reject

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add ContextCompressedEvent message to proto (field 13 in ChatEvent oneof)
- Add tokens *TokenTracker to Service struct, initialized in NewService
- Wire into handleChat: AddTokens after each exchange, ShouldCompress check,
  Compress + replaceHistory when threshold exceeded, stream context_compressed event
- Add replaceHistory() helper to persist compressed message history

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add Job/JobList/JobReq proto messages and ListJobs/PauseJob/ResumeJob/KillJob RPCs
- Implement JobRegistry with SessionJobProvider, FleetJobProvider, TeamJobProvider, CronJobProvider
- Add ListJobs/PauseJob/ResumeJob/KillJob service RPCs wired to job registry
- Create JobPanel TUI component with auto-refresh, navigation, pause/kill actions
- Add Ctrl+J toggle in app.go to show/hide job panel
- Add /jobs slash command to list active jobs

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Fixes UTF-8 multi-byte character truncation in buildFallbackSummary.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- cron.go: store parent context in CronScheduler; Resume now propagates
  it to restarted goroutines instead of using context.Background()
- hooks.go: escape template data values with single-quoting before
  sh -c substitution to prevent shell injection attacks
- discovery.go: split extra args via strings.Fields so multi-word args
  like "exec mycontainer ls" are passed as separate tokens, not one

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- fleet.go: deep-copy FleetWorker structs in GetStatus and sendFleetStatus
  to eliminate data race between goroutines sharing *FleetWorker pointers
- teams.go: use ag.mu.Lock() on write path when marking agents complete,
  consistent with ag.mu.RLock() used in GetStatus read path
- teams.go: set orchestrator model to "" instead of provider name string
- pages/team.go: wire 'k' key to emit KillAgentMsg (was shown in hint
  but never dispatched)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- integration_cron_test.go: full gRPC lifecycle test (create→list→
  pause→resume→stop) and tick test verifying run_count increments
- cron.go: fix startEntry to use parentCtx instead of the RPC request
  context; request context cancels on RPC return, killing the goroutine
  before any ticks fire
- cron.go: Stop now returns an error for non-existent job IDs

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Covers task 10 integration test coverage for fleet lifecycle and worker
kill, team agent spawning and message routing, cron create/pause/resume/stop
lifecycle, and job registry aggregate/unknown-type error paths.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Team view 'k' key now actually calls the daemon to kill the agent,
instead of dispatching a message that was never handled.
- Replace providerMessage with provider.Message from workflow-plugin-agent
- Replace compressMessages with Compress (exported function)
- Replace loadBuiltinAgentDefs with agent.LoadBuiltins()
- Add missing fmt and agent imports

All 8 QA tests (Tasks 29-32) pass; full race suite clean.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add qa_helpers_test.go with type aliases and wrapper functions
(providerMessage, compressMessages, loadBuiltinAgentDefs) so
qa_test.go can reference compression and agent builtin APIs
without import cycles in package daemon.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Also verifies KillAgentMsg handler in app.go is already wired to
client.KillAgent (confirmed present, no further change needed).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…r ctx

- pages/team.go: Add ID field to AgentCard, populate from Agent.Id in
  TeamStatusMsg, dispatch KillAgentMsg with "team_agent:<uuid>" so kill
  routes correctly through the job registry.
- daemon/jobs.go: Add ResumeJob to JobProvider interface; implement real
  resume for CronJobProvider (calls cs.Resume), no-op errors for others.
- tui/app.go: Call tea.Batch(chat.Init(), jobPanel.Init()) in
  transitionToChat so job panel ticker starts immediately.
- daemon/actors.go: Accept context.Context in NewActorManager and
  propagate to sys.Start and rehydrateSessions instead of Background().

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
intel352 and others added 2 commits March 13, 2026 20:57
Runs on push to master and PRs:
- Build: verifies compilation
- Test: race detector + coverage upload
- Lint: golangci-lint
- Vet: go vet

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…flow

1. oauth.go:115 — reflected XSS: user-controlled 'error' query param
   was rendered as raw HTML. Fixed with html.EscapeString().

2. fleet.go:22 — integer overflow: strconv.Atoi returns platform-dependent
   int, cast to int32 without bounds check. Added math.MaxInt32 guard.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds 12 major features to ratchet-cli for competitive parity with GitHub Copilot CLI and Claude Code, including plan mode, fleet mode, team mode, context auto-compression, code review agent, cron/loop scheduling, enhanced hooks, MCP CLI discovery, per-agent model routing, session actors (goakt v4), and a job control panel. It also upgrades the workflow dependency from v0.3.30 to v0.3.40.

Changes:

  • Adds new daemon subsystems: PlanManager, FleetManager, CronScheduler, TeamManager, TokenTracker, JobRegistry, ActorManager, and Discoverer with full gRPC service wiring
  • Adds TUI components (PlanView, FleetPanel, JobPanel) and slash commands (/plan, /approve, /reject, /fleet, /team, /loop, /cron, /jobs, /compact, /review, /mcp, /cost) with keyboard shortcuts (Ctrl+J, Ctrl+T)
  • Adds comprehensive test coverage across all new subsystems including unit, integration, and QA validation tests

Reviewed changes

Copilot reviewed 59 out of 60 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
internal/tui/components/plan.go, plan_test.go New PlanView TUI component with step navigation, skip toggle, approve/reject
internal/tui/components/fleet.go, fleet_test.go New FleetPanel TUI component for fleet worker status display
internal/tui/components/jobpanel.go, jobpanel_test.go New JobPanel TUI component for unified job control
internal/tui/pages/team.go Adds agent ID field, kill-agent support, TeamStatusMsg refresh
internal/tui/pages/chat.go Integrates PlanView into chat, handles plan approve/reject messages
internal/tui/app.go Adds JobPanel toggle (Ctrl+J), KillAgentMsg routing
internal/tui/commands/commands.go Adds 12 new slash commands and help entries
internal/tui/commands/plan.go, fleet.go, jobs.go, review.go New command handlers for plan, fleet, jobs, review, compact
internal/daemon/plans.go, plans_test.go PlanManager with create/approve/reject/update-step lifecycle
internal/daemon/fleet.go, fleet_test.go FleetManager with parallel worker execution and concurrency cap
internal/daemon/cron.go, cron_test.go CronScheduler with SQLite persistence, pause/resume/stop
internal/daemon/teams.go, teams_test.go TeamManager with agent spawning, message routing, kill
internal/daemon/jobs.go, jobs_test.go JobRegistry aggregating jobs from all providers
internal/daemon/compression.go, compression_test.go TokenTracker and Compress function for context window management
internal/daemon/actors.go, actors_test.go goakt v4 actor system with SessionActor and ApprovalActor
internal/daemon/model_routing.go, model_routing_test.go Step complexity classification and per-agent model routing
internal/daemon/service.go Wires all new managers and implements new gRPC RPCs
internal/daemon/chat.go Adds token tracking and auto-compression to chat flow
internal/daemon/engine.go Adds MCP discovery, actor system init, cron_jobs DDL
internal/daemon/integration_*.go Integration tests for plan, fleet, cron, team, jobs
internal/daemon/qa_test.go, qa_helpers_test.go QA validation tests for job control, cron, compression, review
internal/mcp/discovery.go, discovery_test.go MCP CLI tool discovery and registration
internal/hooks/hooks.go, hooks_test.go 8 new lifecycle events, shell injection prevention
internal/config/config.go Adds ModelRouting and ContextConfig structs
internal/client/client.go Client methods for all new gRPC RPCs
internal/agent/definitions.go, builtins_test.go Builtin agent loader with embedded code-reviewer YAML
internal/agent/builtins/code-reviewer.yaml Built-in code-reviewer agent definition
internal/provider/models_test.go, auth_test.go Provider model listing and auth tests
internal/proto/ratchet.proto New proto messages and RPCs for all features
go.mod Upgrade workflow to v0.3.40, add goakt/v4 dependency

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

- Fix help text indentation: /loop, /compact, /review, /exit lines had single
  tab instead of double tab in the help string slice
- Remove custom max() function from fleet.go; Go 1.26 has builtin max
- Add shell metachar validation in mcp/discovery.go for AI-supplied exec args;
  document the exec.Command vs shell boundary
- Fix TeamJobProvider.KillJob lock ordering: collect team instances under
  p.tm.mu.RLock then release before acquiring ti.mu.Lock to eliminate
  potential deadlock from lock order inversion
- /compact now calls CompactSession on the daemon (via TriggerCompact result
  flag + compactSession() Cmd in chat.go) instead of returning static text;
  daemon handleChat detects the sentinel and runs handleCompact directly
- /mcp list/enable/disable now call mcp.AvailableCLIs() and mcp.KnownCLINames()
  to show actual PATH-discovered tools instead of hardcoded strings
- Add .golangci.yml: exclude idiomatic defer Close/Rollback/Send patterns from
  errcheck; apply golangci-lint v2.11.3 auto-fixes across the codebase
- Pin golangci-lint-action to v8 with explicit version v2.11.3 in CI

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds 12 major features to ratchet-cli for competitive parity with GitHub Copilot CLI and Claude Code, including plan mode, fleet mode, team mode, context auto-compression, code review agent, cron/loop scheduling, enhanced hooks, MCP CLI discovery, per-agent model routing, session actors, and a job control panel. It also upgrades the workflow dependency from v0.3.30 to v0.3.40.

Changes:

  • Adds new daemon managers (PlanManager, FleetManager, CronScheduler, TeamManager, JobRegistry, TokenTracker, ActorManager) with gthis RPC endpoints and comprehensive test coverage
  • Adds new TUI components (PlanView, FleetPanel, JobPanel) with keyboard navigation and corresponding chat integration
  • Adds MCP CLI discovery, model routing, context compression, code-reviewer builtin agent, and CI workflow

Reviewed changes

Copilot reviewed 70 out of 71 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
internal/daemon/plans.go, plans_test.go Plan lifecycle management with approve/reject/step-update
internal/daemon/fleet.go, fleet_test.go Fleet worker management with concurrency cap and deep-copy safety
internal/daemon/cron.go, cron_test.go SQLite-persisted cron scheduler with pause/resume/stop
internal/daemon/teams.go, teams_test.go Team agent spawning with message routing
internal/daemon/jobs.go, jobs_test.go Unified job registry aggregating all manager types
internal/daemon/compression.go, compression_test.go Token tracking and context compression
internal/daemon/actors.go, actors_test.go goakt v4 actor system with session/approval actors
internal/daemon/model_routing.go, model_routing_test.go Step complexity classification and model routing
internal/daemon/service.go Wires all new managers into the gRPC service
internal/daemon/chat.go Auto-compression and manual compact support
internal/daemon/engine.go MCP discovery, actor system init, cron table DDL
internal/tui/components/plan.go, plan_test.go Plan view TUI component
internal/tui/components/fleet.go, fleet_test.go Fleet panel TUI component
internal/tui/components/jobpanel.go, jobpanel_test.go Job control panel TUI component
internal/tui/pages/chat.go Plan view integration and compact session support
internal/tui/pages/team.go Agent kill support and team status refresh
internal/tui/pages/splash.go Type switch cleanup
internal/tui/app.go Job panel toggle (Ctrl+J) and lifecycle
internal/tui/commands/*.go New slash commands: /fleet, /compact, /review, /jobs, /plan
internal/mcp/discovery.go, discovery_test.go CLI auto-detection with shell metachar validation
internal/hooks/hooks.go, hooks_test.go 8 new lifecycle events and shell escaping
internal/client/client.go Client methods for all new RPCs
internal/config/config.go ModelRouting and ContextConfig
internal/agent/definitions.go, builtins/ Embedded code-reviewer agent definition
internal/proto/ratchet.proto All new protobuf messages and RPCs
go.mod workflow v0.3.40, goakt v4 dependency
.golangci.yml Linter configuration
.github/workflows/ci.yml CI pipeline

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +145 to +146
if len(sessionID) > 8 && sessionID != "" {
sessionID = sessionID[:8]
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 0d6e731. Removed the redundant && sessionID != "" check — if len(sessionID) > 8 the string is guaranteed non-empty.

Comment on lines +228 to +230
// Track token usage (approximate: 1 token ≈ 4 chars)
inputTokens := (len(userMessage) + 3) / 4
outputTokens := (len(fullResponse) + 3) / 4
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 0d6e731. Changed len(userMessage) and len(fullResponse) to len([]rune(...)) so multi-byte UTF-8 characters count as a single unit rather than multiple bytes, making the estimate more accurate.

Comment on lines +313 to +314
ctx, cancel := context.WithCancel(m.ctx)
m.cancelChat = cancel
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 0d6e731. Added a chatCancelSetMsg{cancel} type. Both sendMessage and compactSession now use tea.Batch to immediately dispatch that message alongside the stream Cmd. The Update handler stores the cancel on the real model when it receives chatCancelSetMsg, avoiding the value-receiver copy problem.

if c == nil {
return &Result{Lines: []string{"Not connected to daemon"}}
}
planID := args[0]
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 0d6e731. Added an early len(args) == 0 guard at the top of fleetCmd that returns a usage message before any slice access.

Comment on lines +30 to +33
_, _ = c.StartFleet(context.Background(), &pb.StartFleetReq{
PlanId: planID,
MaxWorkers: maxWorkers,
})
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 0d6e731. Threaded sessionID through Parse (variadic param) → fleetCmdStartFleetReq.SessionId. The chat page already holds m.sessionID and now passes it when calling commands.Parse.

Comment on lines +58 to +68
@@ -64,12 +65,12 @@ func (m SplashModel) Update(msg tea.Msg) (SplashModel, tea.Cmd) {
return splashTickMsg(t)
})
case tea.KeyPressMsg:
_ = msg
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 0d6e731. Removed both _ = msg statements from the splashTickMsg and tea.KeyPressMsg cases in splash.go.

Comment on lines +46 to +51
func truncateStr(s string, n int) string {
if len([]rune(s)) <= n {
return s
}
return string([]rune(s)[:n-1]) + "…"
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 0d6e731. Moved truncateStr to a new internal/tui/commands/util.go shared within the commands package, and removed the duplicate definition from jobs.go.

Comment on lines +117 to +122
case "k":
if m.cursor < len(m.agents) {
idx := m.cursor
return m, func() tea.Msg {
return KillAgentMsg{AgentID: "team_agent:" + m.agents[idx].ID}
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 0d6e731. Removed the "team_agent:" prefix — KillJob expects the raw job ID as returned by the daemon, not a type-prefixed composite. Also added a guard that skips the kill when AgentCard.ID is empty (agents populated from TeamEvent_AgentSpawned before a TeamStatusMsg arrives don't have an ID yet).

Comment on lines +24 to +51
// reviewCmd runs the built-in code-reviewer agent on the current git diff.
func reviewCmd(c *client.Client) *Result {
diff, err := gitDiff()
if err != nil {
return &Result{Lines: []string{fmt.Sprintf("Error getting git diff: %v", err)}}
}
if diff == "" {
return &Result{Lines: []string{"No uncommitted changes to review."}}
}
lines := []string{
"Starting code review on current git diff...",
"",
"Diff summary:",
}
// Show a trimmed preview of the diff
diffLines := strings.Split(diff, "\n")
preview := diffLines
if len(preview) > 20 {
preview = diffLines[:20]
preview = append(preview, fmt.Sprintf("... (%d more lines)", len(diffLines)-20))
}
lines = append(lines, preview...)
lines = append(lines,
"",
"Use the code-reviewer agent via /agents to see full review results.",
)
return &Result{Lines: lines}
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 0d6e731. Added TriggerReview bool and ReviewDiff string to Result. reviewCmd now sets both fields. The chat page detects TriggerReview and calls m.sendMessage with the diff wrapped in a code-reviewer prompt, invoking the agent directly via the existing streaming message path.

- jobpanel.go: remove redundant `&& sessionID != ""` (len > 8 implies non-empty)
- daemon/chat.go: use len([]rune()) for token estimation to handle multi-byte UTF-8
- chat.go: fix cancel assigned to value receiver copy in sendMessage/compactSession
  by returning cancel via chatCancelSetMsg so it persists on the real model
- commands/fleet.go: add len(args) guard to prevent panic on bare /fleet
- commands/fleet.go: thread sessionID through Parse → fleetCmd → StartFleetReq
- splash.go: remove dead `_ = msg` statements on lines 58 and 68
- commands/jobs.go: extract truncateStr to commands/util.go, removing duplicate
- commands/review.go: wire /review to invoke code-reviewer agent via sendMessage
  with git diff as context (TriggerReview + ReviewDiff on Result)
- pages/team.go: remove "team_agent:" prefix from KillAgentMsg.AgentID since
  KillJob expects the raw job ID; guard against empty ID when not yet populated

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@intel352 intel352 merged commit 706496a into master Mar 14, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants