hook

package
v0.3.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 4, 2026 License: MIT Imports: 17 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func RunGovernanceCheck

func RunGovernanceCheck(
	repo vcs.Repository,
	status vcs.Status,
	index *knowledge.Index,
	scope analysis.Scope,
) (string, int)

RunGovernanceCheck runs the analyzer pipeline for scope against repo and returns a formatted findings block plus the number of findings behind it. status is the already-computed worktree status (avoids a redundant read). A commit message is never threaded through here: it is validated in exactly one place, the git commit-msg hook.

func TypedChecklist

func TypedChecklist(status vcs.Status) string

TypedChecklist builds the per-file-type reminder bullets for the extensions present in status, in a stable order with no duplicate bullets.

Types

type Deps

type Deps struct {
	// Templates provides the embedded hook contract text (hooks/*.txt).
	Templates fs.FS
	// Logger records one execution-summary line per dispatch; nil skips logging.
	Logger *slog.Logger
	// Index feeds rule-body injection in commit checks and post-edit skill
	// routing; nil skips both.
	Index *knowledge.Index
	// Out receives the emitted hook JSON; nil defaults to os.Stdout.
	Out io.Writer
	// ProjectDir is the repo root handlers resolve paths against; empty
	// defaults to os.Getenv("CLAUDE_PROJECT_DIR").
	ProjectDir string
	// Governance runs the analyzer pipeline for a dirty worktree; nil
	// defaults to the real pipeline (RunGovernanceCheck against Index).
	Governance func(repo vcs.Repository, status vcs.Status) (block string, count int)
}

Deps carries what the Dispatcher needs instead of constructing it, so a test can observe output and stub governance without touching global state.

type Dispatcher

type Dispatcher struct {
	// contains filtered or unexported fields
}

Dispatcher routes hook events to the correct handler, reading contract text from embedded templates. A hook must never block, so Dispatch always returns nil; internal failures are reported through logger instead.

func NewDispatcher

func NewDispatcher(deps Deps) *Dispatcher

NewDispatcher builds a Dispatcher from deps, defaulting Out to os.Stdout, ProjectDir to CLAUDE_PROJECT_DIR, and Governance to the real analyzer pipeline, so a production caller can omit whatever it does not override.

func (*Dispatcher) Dispatch

func (d *Dispatcher) Dispatch(mode string, payload []byte) error

Dispatch reads the event mode, executes the matching handler, and records the execution outcome. It always returns nil (non-blocking); a handler failure surfaces only through the execution log.

type Output

type Output struct {
	HookSpecificOutput Specific `json:"hookSpecificOutput"`
}

Output is the non-blocking JSON Claude Code reads from a hook's stdout.

type Router

type Router struct {
	// contains filtered or unexported fields
}

Router resolves which skills a hook event should announce from the knowledge index's own data - router.yaml's always-load baseline and dispatch table, plus each skill's own triggers - instead of a hardcoded per-extension map. Adding a skill to skills.yaml with a trigger naming the file extension or activity it covers makes the hook route it with no Go change.

func NewRouter

func NewRouter(index *knowledge.Index) *Router

NewRouter builds a Router over index. A nil index makes every lookup degrade to "no skills routed" rather than panicking, since a hook must never block a turn on a missing knowledge base.

func (*Router) SkillsForFile

func (r *Router) SkillsForFile(filePath string) []string

SkillsForFile returns the skill IDs relevant to editing filePath: the router.yaml always-load baseline for any .go file ("every Go change"), any skill whose trigger literally names the file's extension (e.g. database-persistence's ".sql" trigger, grpc-adapter's ".proto" trigger), and the "Any test work" dispatch row's skills when filePath is a Go test file. It returns nil for a nil Router/index or an extension with no match.

type SessionTracker

type SessionTracker struct {
	// contains filtered or unexported fields
}

SessionTracker manages per-session marker files used to deduplicate hook emissions within a single Claude Code session. Markers live in the OS temp directory and are keyed by event name and session ID.

func NewSessionTrackerFromID

func NewSessionTrackerFromID(sessionID string) *SessionTracker

NewSessionTrackerFromID builds a tracker from an already-known session id, defaulting to "nosession" when empty. Dispatch decodes the hook payload once and calls this instead of re-parsing the same bytes NewSessionTracker would.

func (*SessionTracker) Cleanup

func (s *SessionTracker) Cleanup()

Cleanup removes all per-session marker files for this session ID so a finished session leaves nothing behind in the temp directory. It scans the temp dir because each Dispatch call creates a fresh SessionTracker - the markers were recorded on prior instances that are no longer reachable.

func (*SessionTracker) FirstEmission

func (s *SessionTracker) FirstEmission(event, content string) bool

FirstEmission reports whether content differs from what was last emitted for this event and session, recording the new content hash. It returns false when identical content was already emitted, so a hook stays silent across turns until the underlying state actually changes.

func (*SessionTracker) OncePerSession

func (s *SessionTracker) OncePerSession(event string) bool

OncePerSession records that an event fired for this session and reports whether this is the first occurrence (true) or a repeat (false).

func (*SessionTracker) SessionID

func (s *SessionTracker) SessionID() string

SessionID returns the session identifier this tracker was built from.

type Specific

type Specific struct {
	HookEventName     string `json:"hookEventName"`
	AdditionalContext string `json:"additionalContext"`
}

Specific carries the event name and additional context for the agent.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL