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 ¶
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.
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 ¶
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 ¶
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.