Documentation
¶
Overview ¶
Package ipc provides inter-process communication between the Forge daemon and CLI/TUI clients via platform-native mechanisms (named pipe on Windows, Unix domain socket on Linux/macOS).
Protocol: newline-delimited JSON messages.
Server side (daemon):
svr := ipc.NewServer()
svr.OnCommand(func(cmd Command) Response { ... })
svr.Start(ctx)
Client side (CLI/TUI):
client := ipc.NewClient()
resp, err := client.Send(Command{Type: "status"})
events := client.Subscribe(ctx) // stream events
Index ¶
- Constants
- func ForgeDir() string
- func SocketExists() bool
- func WorkerKindFromPhase(phase string) string
- type AnvilPollItem
- type AppendNotesPayload
- type ApproveAsIsPayload
- type AssayRerunPayload
- type ClarificationPayload
- type ClearBeadPayload
- type Client
- type CloseBeadPayload
- type Command
- type CommandHandler
- type CompletionResult
- type CrucibleActionPayload
- type CrucibleStatusItem
- type CruciblesResponse
- type DismissBeadPayload
- type Event
- type EventInfo
- type EventsResponse
- type ForceSmithPayload
- type GetIngotPayload
- type GetIngotsPayload
- type KillWorkerPayload
- type MergePRPayload
- type PRActionPayload
- type QueueActionPayload
- type QueueItem
- type QueueResponse
- type QueuedPayload
- type RequestTracker
- type ResolveOrphanPayload
- type Response
- type RetryBeadPayload
- type RunBeadPayload
- type Server
- type StatusPayload
- type StopBeadPayload
- type TagBeadPayload
- type UpdateLabelPayload
- type ViewLogsPayload
- type ViewLogsResponse
- type WardenRerunPayload
- type WicketStatusPayload
- type WorkerInfo
- type WorkersResponse
Constants ¶
const ( // DefaultReadTimeout is used when a Command leaves ReadTimeout unset. It is // tuned for fast daemon-local handlers (status, view_logs, DB-only ops). DefaultReadTimeout = 3 * time.Second // BdBackedReadTimeout covers handlers that synchronously shell out to bd // (bd show / bd ready) before replying. bd against remote Dolt plus // GitHub auto-sync can take 20-30s per call; run_bead may chain multiple // such calls. Two minutes leaves headroom while still bounding a hung // daemon well under executil.DefaultBdTimeout (5 min). BdBackedReadTimeout = 2 * time.Minute )
Per-command read-deadline presets applied by Client.Send.
Variables ¶
This section is empty.
Functions ¶
func SocketExists ¶
func SocketExists() bool
SocketExists checks whether the daemon's IPC socket file exists.
func WorkerKindFromPhase ¶ added in v0.16.0
WorkerKindFromPhase returns the coarse worker-class label used by the Hearth web UI to decide whether a worker card opens a log modal. Bellows PR-monitor rows return "bellows" (no underlying claude log); everything else — pipeline Smiths and the quench/burnish/rebase lifecycle workers — returns "smith".
Types ¶
type AnvilPollItem ¶ added in v0.16.0
type AnvilPollItem struct {
Anvil string `json:"anvil"`
Timestamp time.Time `json:"timestamp"`
OK bool `json:"ok"` // true when the last poll completed without error
Message string `json:"message,omitempty"` // human-readable summary, e.g. "5 ready" or the error text
}
AnvilPollItem reports the most recent poll outcome for a single anvil. It is carried inside StatusPayload.AnvilLastPoll and is the IPC-facing projection of the daemon's in-memory last-poll map.
type AppendNotesPayload ¶ added in v0.4.0
type AppendNotesPayload struct {
BeadID string `json:"bead_id"`
Anvil string `json:"anvil"`
Notes string `json:"notes"`
}
AppendNotesPayload is the payload for an "append_notes" command. Adds human notes to a bead's history via bd update.
type ApproveAsIsPayload ¶ added in v0.8.0
ApproveAsIsPayload is the payload for an "approve_as_is" command. Bypasses warden entirely and creates a PR from the current branch state.
type AssayRerunPayload ¶ added in v0.20.0
AssayRerunPayload is the payload for an "assay_rerun" command. Triggers a fresh Assay AI review pass over a PR's current head, bypassing the Bellows trigger gate's head-SHA debounce. PR is the state.db PR id (matching the {pr} path parameter the web rerun endpoint forwards, and the `pr` field the api.ts client posts); Anvil resolves the worktree/config for the re-review. The field shape mirrors api.ts RerunAssayParams so the web backend can forward the request without translation.
type ClarificationPayload ¶
type ClarificationPayload struct {
BeadID string `json:"bead_id"`
Anvil string `json:"anvil"` // Required: which anvil the bead belongs to
Reason string `json:"reason"` // Why clarification is needed (used when setting)
}
ClarificationPayload is the payload for "set_clarification" / "clear_clarification" commands.
type ClearBeadPayload ¶ added in v0.16.0
ClearBeadPayload is the payload for a "clear_bead" command. Clears the needs-attention flags from a bead's retry row without triggering a re-dispatch. Idempotent — succeeds even when the row is already clean or missing.
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client connects to the daemon's IPC socket.
type CloseBeadPayload ¶
CloseBeadPayload is the payload for a "close_bead" command that closes a bead via bd close.
type Command ¶
type Command struct {
Type string `json:"type"` // "status", "kill_worker", "refresh", "queue", "run_bead", "set_clarification", "clear_clarification", "assay_rerun"
Payload json.RawMessage `json:"payload"` // Type-specific data
// ReadTimeout is an optional client-side timeout for reading the response.
// Zero uses DefaultReadTimeout. Long-running commands that go through bd or
// gh (e.g. run_bead) should set BdBackedReadTimeout. This field is not sent
// on the wire — it only influences Client.Send's read deadline.
ReadTimeout time.Duration `json:"-"`
}
Command is a message sent from a client to the daemon.
type CommandHandler ¶
CommandHandler is called by the server for each incoming command.
type CompletionResult ¶ added in v0.14.0
CompletionResult is the outcome delivered when an async request finishes.
type CrucibleActionPayload ¶ added in v0.6.0
type CrucibleActionPayload struct {
ParentID string `json:"parent_id"` // Parent bead ID of the Crucible
Anvil string `json:"anvil"`
Action string `json:"action"` // "resume" | "stop"
}
CrucibleActionPayload is the payload for a "crucible_action" command. Triggers a resume or stop action on a paused Crucible.
type CrucibleStatusItem ¶
type CrucibleStatusItem struct {
ParentID string `json:"parent_id"`
ParentTitle string `json:"parent_title"`
Anvil string `json:"anvil"`
Branch string `json:"branch"`
Phase string `json:"phase"` // "started", "dispatching", "waiting", "final_pr", "complete", "paused"
TotalChildren int `json:"total_children"`
CompletedChildren int `json:"completed_children"`
CurrentChild string `json:"current_child"`
StartedAt string `json:"started_at"`
}
CrucibleStatusItem represents an active Crucible's current state.
type CruciblesResponse ¶
type CruciblesResponse struct {
Crucibles []CrucibleStatusItem `json:"crucibles"`
}
CruciblesResponse is the response payload for a "crucibles" command.
type DismissBeadPayload ¶
type DismissBeadPayload struct {
BeadID string `json:"bead_id"`
Anvil string `json:"anvil"`
PRID int `json:"pr_id,omitempty"`
}
DismissBeadPayload is the payload for a "dismiss_bead" command. Removes the bead from the Needs Attention list. When PRID > 0, the dismiss targets an exhausted PR (setting status to closed) rather than the retries table.
type Event ¶
type Event struct {
Type string `json:"type"`
Timestamp time.Time `json:"timestamp"`
Data json.RawMessage `json:"data"`
}
Event is a push notification from daemon to subscribed clients.
type EventInfo ¶ added in v0.16.0
type EventInfo struct {
ID int `json:"id"`
Timestamp string `json:"timestamp"`
Type string `json:"type"`
Message string `json:"message"`
BeadID string `json:"bead_id,omitempty"`
Anvil string `json:"anvil,omitempty"`
}
EventInfo is the IPC representation of a single event log entry.
type EventsResponse ¶ added in v0.16.0
type EventsResponse struct {
Events []EventInfo `json:"events"`
}
EventsResponse is the response payload for an "events" command.
type ForceSmithPayload ¶ added in v0.8.0
type ForceSmithPayload struct {
BeadID string `json:"bead_id"`
Anvil string `json:"anvil"`
UserNote string `json:"user_note,omitempty"`
}
ForceSmithPayload is the payload for a "force_smith" command. Pushes smith into another iteration on the same branch, keeping existing warden feedback attached. UserNote is optionally prepended to the prompt.
type GetIngotPayload ¶ added in v0.9.0
type GetIngotPayload struct {
BeadID string `json:"bead_id"`
Anvil string `json:"anvil,omitempty"`
}
GetIngotPayload is the payload for a "get_ingot" command.
type GetIngotsPayload ¶ added in v0.9.0
type GetIngotsPayload struct {
Anvil string `json:"anvil,omitempty"`
Status string `json:"status,omitempty"`
Limit int `json:"limit,omitempty"` // default 50
}
GetIngotsPayload is the payload for a "get_ingots" command.
type KillWorkerPayload ¶
KillWorkerPayload is the payload for a "kill_worker" command.
type MergePRPayload ¶
type MergePRPayload struct {
PRID int `json:"pr_id"`
PRNumber int `json:"pr_number"`
Anvil string `json:"anvil"`
}
MergePRPayload is the payload for a "merge_pr" command. Triggers a squash merge (or configured strategy) of a ready-to-merge PR.
type PRActionPayload ¶ added in v0.5.0
type PRActionPayload struct {
PRID int `json:"pr_id"`
PRNumber int `json:"pr_number"`
Anvil string `json:"anvil"`
BeadID string `json:"bead_id"`
Branch string `json:"branch"`
Action string `json:"action"` // "open_browser" | "merge" | "quench" | "burnish" | "rebase" | "close" | "approve" | "assign_bellows" | "unassign_bellows"
}
PRActionPayload is the payload for a "pr_action" command. Triggers an action on an open PR.
type QueueActionPayload ¶ added in v0.16.0
type QueueActionPayload struct {
BeadID string `json:"bead_id"`
ForgeID string `json:"forge_id,omitempty"`
AnvilName string `json:"anvil_name,omitempty"`
Note string `json:"note,omitempty"`
}
QueueActionPayload is the payload for the queue resolution verbs: "queue_clarify", "queue_unclarify", "queue_retry", "queue_clear", and "queue_stop". These are thin IPC wrappers around the shared queueactions package functions and accept a forge_id for multi-forge safety: when supplied the daemon rejects the request unless its local forge_id matches.
AnvilName uses the legacy "anvil" JSON tag so existing callers can reuse the same field name they pass to set_clarification / stop_bead.
type QueueItem ¶ added in v0.16.0
type QueueItem struct {
BeadID string `json:"bead_id"`
Anvil string `json:"anvil"`
Title string `json:"title"`
Description string `json:"description,omitempty"`
Priority int `json:"priority"`
Status string `json:"status"`
Labels []string `json:"labels"`
Section string `json:"section"`
Assignee string `json:"assignee,omitempty"`
CreatedAt string `json:"created_at"`
UpdatedAt string `json:"updated_at"`
// AutoDispatchTag is the anvil's configured dispatch label (forge.yaml
// `auto_dispatch_tag`). Surfaced on each queue row so the Hearth web UI
// can render a one-click "apply tag" button on Unlabeled beads without
// an extra round-trip to the anvil registry. Empty when the owning
// anvil has no tag configured.
AutoDispatchTag string `json:"auto_dispatch_tag,omitempty"`
}
QueueItem is the IPC representation of a single cached queue entry. It mirrors state.QueueItem but uses JSON-friendly tags and a parsed labels slice. CreatedAt and UpdatedAt are sourced from the in-memory poller snapshot (not the queue_cache table) so timestamps flow through without a SQLite schema migration; both are empty strings when the snapshot has no matching entry (e.g. before the first poll completes).
type QueueResponse ¶ added in v0.16.0
type QueueResponse struct {
Items []QueueItem `json:"items"`
}
QueueResponse is the response payload for a "queue" command.
type QueuedPayload ¶ added in v0.14.0
type QueuedPayload struct {
Message string `json:"message,omitempty"`
}
QueuedPayload is the payload for a "queued" response, indicating the command was accepted and will be processed asynchronously. The request ID is carried only at the top-level Response.RequestID field; it is not duplicated here to avoid diverging sources of truth.
type RequestTracker ¶ added in v0.14.0
type RequestTracker struct {
// contains filtered or unexported fields
}
RequestTracker maps request IDs to completion channels so the daemon can deliver results for asynchronously queued commands.
func NewRequestTracker ¶ added in v0.14.0
func NewRequestTracker(prefix string) *RequestTracker
NewRequestTracker creates a tracker. The prefix is prepended to generated request IDs (e.g. "forge-") for easy identification in logs.
func (*RequestTracker) Cancel ¶ added in v0.14.0
func (rt *RequestTracker) Cancel(requestID string)
Cancel removes a pending request without delivering a result, closing its channel so any waiter unblocks.
func (*RequestTracker) Complete ¶ added in v0.14.0
func (rt *RequestTracker) Complete(requestID string, result CompletionResult) bool
Complete delivers a result for the given request ID and removes it from the tracker. Returns false if the ID is not found (already completed or unknown).
func (*RequestTracker) Pending ¶ added in v0.14.0
func (rt *RequestTracker) Pending() int
Pending returns the number of in-flight requests.
func (*RequestTracker) Track ¶ added in v0.14.0
func (rt *RequestTracker) Track() (string, <-chan CompletionResult)
Track registers a new async request and returns its ID and a channel that will receive exactly one CompletionResult when the work finishes.
type ResolveOrphanPayload ¶ added in v0.4.0
type ResolveOrphanPayload struct {
BeadID string `json:"bead_id"`
Anvil string `json:"anvil"`
Action string `json:"action"` // "recover" | "close" | "discard"
}
ResolveOrphanPayload is the payload for a "resolve_orphan" command. Sent by Hearth to the daemon when the user picks an action for an orphaned bead. Action is one of "recover", "close", or "discard".
type Response ¶
type Response struct {
Type string `json:"type"` // "ok", "error", "status", "event", "queued"
Payload json.RawMessage `json:"payload"` // Type-specific data
RequestID string `json:"request_id,omitempty"` // Set when Type is "queued"; correlates async completion
}
Response is a message sent from the daemon to a client.
func NewQueuedResponse ¶ added in v0.14.0
NewQueuedResponse builds a Response of type "queued" for the given request ID. Returns an error if requestID is empty, since an empty ID breaks correlation.
type RetryBeadPayload ¶
type RetryBeadPayload struct {
BeadID string `json:"bead_id"`
Anvil string `json:"anvil"`
PRID int `json:"pr_id,omitempty"`
}
RetryBeadPayload is the payload for a "retry_bead" command. Clears needs_human flag and resets retry count so the bead re-enters the queue. When PRID > 0, the retry targets an exhausted PR (resetting fix counters and status back to open) rather than the retries table.
type RunBeadPayload ¶
type RunBeadPayload struct {
BeadID string `json:"bead_id"`
Anvil string `json:"anvil"` // Optional: narrows search if multiple anvils have same bead ID
ForceRun bool `json:"force_run"` // When true, fetch via bd show (bypass bd ready), skip crucible/parent checks
}
RunBeadPayload is the payload for a "run_bead" command.
type Server ¶
type Server struct {
// contains filtered or unexported fields
}
Server listens for IPC connections from CLI/TUI clients.
func (*Server) HasClients ¶ added in v0.4.0
HasClients reports whether any IPC clients are currently connected.
func (*Server) OnCommand ¶
func (s *Server) OnCommand(h CommandHandler)
OnCommand sets the handler for incoming commands.
type StatusPayload ¶
type StatusPayload struct {
Running bool `json:"running"`
PID int `json:"pid"`
Uptime string `json:"uptime"`
Workers int `json:"workers"`
QueueSize int `json:"queue_size"`
OpenPRs int `json:"open_prs"`
LastPoll string `json:"last_poll"`
Quotas map[string]provider.Quota `json:"quotas,omitempty"`
DailyCost float64 `json:"daily_cost"`
DailyCostLimit float64 `json:"daily_cost_limit,omitempty"`
// CostLimitPaused reports that cost-based auto-dispatch via the Poller is
// currently paused due to hitting the daily cost limit. Manual run_bead
// dispatch remains allowed while this flag is true.
CostLimitPaused bool `json:"cost_limit_paused,omitempty"`
// CopilotPremiumRequests is the weighted count of Copilot premium requests used today.
CopilotPremiumRequests float64 `json:"copilot_premium_requests,omitempty"`
// CopilotRequestLimit is the configured daily limit (0 = no limit).
CopilotRequestLimit int `json:"copilot_request_limit,omitempty"`
// CopilotLimitReached is true when the copilot daily request limit has been reached.
CopilotLimitReached bool `json:"copilot_limit_reached,omitempty"`
// AnvilLastPoll carries the most recent poll outcome per anvil, populated
// from the daemon's in-memory snapshot. Successful polls are no longer
// persisted as events, so Hearth and `forge status` consume this field for
// fresh per-anvil timestamps instead of querying the events table.
AnvilLastPoll []AnvilPollItem `json:"anvil_last_poll,omitempty"`
// MaxTotalSmiths is the configured global cap on concurrent Smith workers.
// Hearth 2.0 uses this to size the "Idle" placeholder slots in the
// Workers pane (max_total_smiths - active_workers).
MaxTotalSmiths int `json:"max_total_smiths,omitempty"`
}
StatusPayload is the response for a "status" command.
type StopBeadPayload ¶ added in v0.5.0
type StopBeadPayload struct {
BeadID string `json:"bead_id"`
Anvil string `json:"anvil"`
Reason string `json:"reason"` // Optional; defaults to "manually stopped"
}
StopBeadPayload is the payload for a "stop_bead" command. Stops all processing of a bead: kills any running worker, marks the bead as needing clarification (so the poller skips it), and releases it back to open. The bead will not be dispatched again until unclarified.
type TagBeadPayload ¶
TagBeadPayload is the payload for a "tag_bead" command that adds the anvil's configured auto-dispatch label to a bead via bd update. The daemon derives the tag from its own config; the client only needs to supply the bead identity.
type UpdateLabelPayload ¶ added in v0.16.0
type UpdateLabelPayload struct {
BeadID string `json:"bead_id"`
Anvil string `json:"anvil"`
Label string `json:"label"`
Action string `json:"action"` // "add" | "remove"
}
UpdateLabelPayload is the payload for an "update_label" command that adds or removes an arbitrary label on a bead via bd update --add-label / --remove-label. Used by Hearth 2.0 to manage labels from the web UI.
type ViewLogsPayload ¶
type ViewLogsPayload struct {
BeadID string `json:"bead_id"`
}
ViewLogsPayload is the payload for a "view_logs" command.
type ViewLogsResponse ¶
type ViewLogsResponse struct {
LogPath string `json:"log_path"`
LastLines []string `json:"last_lines"`
}
ViewLogsResponse is the response payload for a "view_logs" command.
type WardenRerunPayload ¶ added in v0.8.0
WardenRerunPayload is the payload for a "warden_rerun" command. Re-runs warden on the existing worktree branch. If warden approves, proceeds to PR creation normally.
type WicketStatusPayload ¶ added in v0.11.0
type WicketStatusPayload struct {
Enabled bool `json:"enabled"`
Interval string `json:"interval"`
MonitoredRepos []string `json:"monitored_repos"` // explicitly configured repos
DerivedAnvils int `json:"derived_anvils"` // anvil count deriving repo from git remote at runtime
IssueCounts map[string]int `json:"issue_counts"` // state -> count
LastScanAt *time.Time `json:"last_scan_at,omitempty"`
}
WicketStatusPayload is the response for a "wicket_status" command.
type WorkerInfo ¶ added in v0.16.0
type WorkerInfo struct {
ID string `json:"id"`
BeadID string `json:"bead_id"`
Anvil string `json:"anvil"`
Branch string `json:"branch,omitempty"`
Title string `json:"title,omitempty"`
Status string `json:"status"`
Phase string `json:"phase,omitempty"`
Kind string `json:"kind,omitempty"`
PID int `json:"pid,omitempty"`
StartedAt string `json:"started_at"`
CompletedAt string `json:"completed_at,omitempty"`
LogPath string `json:"log_path,omitempty"`
PRNumber int `json:"pr_number,omitempty"`
}
WorkerInfo is the IPC representation of a single active worker. Kind is a coarse worker-class label derived from Phase: "bellows" for the PR-monitor pseudo-workers (no log, no log-modal affordance) and "smith" for everything else — pipeline Smiths plus the lifecycle sub-workers (quench/burnish/rebase) that produce real claude log files.
type WorkersResponse ¶ added in v0.16.0
type WorkersResponse struct {
Workers []WorkerInfo `json:"workers"`
}
WorkersResponse is the response payload for a "workers" command.