Documentation
¶
Overview ¶
Package sessiongate holds the session gates the agent harness installs into every session it runs: structural checks Claude Code calls as hooks around a tool call. The wait gate rejects a Bash command that would wait on nothing (a shell poll loop, pgrep -f, a foreground sleep) and names the replacement; the ready gate runs tools/check-merge.sh in the worktree before a command marks a pull request ready and denies it on any consistency regression; the commit gate pushes the work branch after a git commit and opens its draft pull request, on the repository it pushed to, if none exists. Every decision is written to the run's event log under the run's trace.
A gate is a library. The binary Claude Code calls reads the hook's input, grants the process capability and writes the returned output.
Index ¶
Constants ¶
const ( GateWait = "wait" GateReady = "ready" GateCommit = "commit" DecisionAllow = "allow" DecisionDeny = "deny" DecisionSkip = "skip" DecisionMalformed = "malformed" DecisionOpened = "opened" DecisionExists = "exists" DecisionFailed = "failed" )
The gates and their decisions, as the event log records them.
Variables ¶
var ( // ErrInvalidOption reports a nil option or an option value the gate // cannot use. ErrInvalidOption = errors.New("session gate: invalid option") // ErrNoLauncher reports a gate built without the process capability. ErrNoLauncher = errors.New("session gate: a process launcher is required") // ErrNoRunDirectory reports a gate built without its run directory. ErrNoRunDirectory = errors.New("session gate: a run directory is required") // ErrMalformedHookInput reports hook input that is not the JSON object // Claude Code sends. ErrMalformedHookInput = errors.New("session gate: malformed hook input") // ErrUnknownEvent reports a hook event the harness installs no gate on. ErrUnknownEvent = errors.New("session gate: no gate for this hook event") // ErrPush reports a work branch git could not push. ErrPush = errors.New("session gate: could not push the work branch") // ErrPullRequest reports a draft pull request gh could not find or open. ErrPullRequest = errors.New("session gate: could not open the draft pull request") )
var ErrUnparsedCommand = errors.New("session gate: command is not valid shell")
ErrUnparsedCommand reports a command the shell parser could not read.
Functions ¶
func RunsGitCommit ¶
RunsGitCommit reports whether command runs git commit anywhere in it, including inside sh -c. Whether the commit succeeded is for git to say.
func RunsPullRequestReady ¶
RunsPullRequestReady reports whether command marks a pull request ready for review (gh pr ready, not gh pr ready --undo) anywhere in it, including inside sh -c.
Types ¶
type HookInput ¶
type HookInput struct {
SessionID string `json:"session_id"`
HookEventName string `json:"hook_event_name"`
ToolName string `json:"tool_name"`
ToolUseID string `json:"tool_use_id"`
ToolInput struct {
Command string `json:"command"`
RunInBackground bool `json:"run_in_background"`
} `json:"tool_input"`
}
HookInput is the part of a command hook's standard input the gates read.
type HookOutput ¶
type HookOutput struct {
HookSpecificOutput *HookSpecificOutput `json:"hookSpecificOutput,omitempty"`
}
HookOutput is a command hook's standard output.
type HookSpecificOutput ¶
type HookSpecificOutput struct {
HookEventName string `json:"hookEventName"`
PermissionDecision string `json:"permissionDecision,omitempty"`
PermissionDecisionReason string `json:"permissionDecisionReason,omitempty"`
AdditionalContext string `json:"additionalContext,omitempty"`
}
HookSpecificOutput is the event-specific decision Claude Code reads.
type Rule ¶
type Rule string
Rule names a shell shape the wait gate rejects.
const ( // RulePollLoop is a while, until or for loop whose body or condition // sleeps: a hand-rolled poll. RulePollLoop Rule = "poll_loop" // RuleSelfMatchingPgrep is pgrep -f (or --full): its pattern is matched // against whole command lines, including the shell that runs it. RuleSelfMatchingPgrep Rule = "pgrep_full" // RuleForegroundSleep is a sleep the turn waits for. RuleForegroundSleep Rule = "foreground_sleep" )
The rules of the wait gate. Each is a way an agent waits that cannot end on its own: nothing joins a poll loop, a pgrep -f pattern matches the loop's own command line, and a foreground sleep holds the turn while waiting on nothing.
type SessionGate ¶
type SessionGate struct {
// contains filtered or unexported fields
}
SessionGate answers the gated hooks of one run.
func NewSessionGate ¶
func NewSessionGate(options ...SessionGateOption) (*SessionGate, error)
NewSessionGate validates the whole option set before building the gate.
func (*SessionGate) Handle ¶
func (gate *SessionGate) Handle(ctx context.Context, event string, input []byte) (*HookOutput, error)
Handle answers one hook call: event is the hook event the harness installed the call on and input is the hook's standard input. A nil output means the call proceeds without a word from the gate. A gate that could not finish its work returns both the output telling the agent and the error.
type SessionGateOption ¶
type SessionGateOption func(gate *SessionGate) error
SessionGateOption configures a SessionGate.
func WithLauncher ¶
func WithLauncher(launcher proc.ILauncher) SessionGateOption
WithLauncher grants the process capability git and gh start through. Required.
func WithRunDirectory ¶
func WithRunDirectory(directory string) SessionGateOption
WithRunDirectory names the run the gate answers for: the directory the harness recorded it in. Required.
type ShellFinding ¶
ShellFinding is one rejected shape in a command.
func FindShellWaits ¶
func FindShellWaits(command string) ([]ShellFinding, error)
FindShellWaits parses command as bash and returns every shape the wait gate rejects, in source order. A literal script handed to sh -c or bash -c is parsed and checked the same way. Heredoc bodies and quoted text are data, not commands, and never match.
func (ShellFinding) Message ¶
func (finding ShellFinding) Message() string
Message is the rejection text the agent reads.
func (ShellFinding) Replacement ¶
func (finding ShellFinding) Replacement() string
Replacement is what to do instead, as the rejection message states it.