From 97c70359949b9d1e5ae3aa4a02e1449d880718a9 Mon Sep 17 00:00:00 2001 From: Lakshman Patel Date: Sun, 5 Jul 2026 20:34:48 +0530 Subject: [PATCH 1/4] chore: commit wip changes on feature/wip-20260705 --- .github/workflows/ci.yml | 163 ++++++++++++++++++++++++-- .github/workflows/release.yml | 31 +++++ CHANGELOG.md | 24 ++++ CODEOWNERS | 19 +++ Makefile | 114 ++++++++++++++++++ README.md | 20 ++++ VERSION | 1 + lefthook.yml | 9 ++ scripts/check-ecosystem-boundaries.sh | 29 +++++ 9 files changed, 401 insertions(+), 9 deletions(-) create mode 100644 .github/workflows/release.yml create mode 100644 CHANGELOG.md create mode 100644 CODEOWNERS create mode 100644 Makefile create mode 100644 VERSION create mode 100755 scripts/check-ecosystem-boundaries.sh diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index adc6a2b..2976250 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,26 +1,171 @@ +# CI pipeline for hawk-core-contracts — a zero-hawk-eco-dependency +# foundation library. No workspace clones needed: this repo depends on +# nothing in the hawk ecosystem, only the Go standard library. + name: CI on: push: - branches: - - main + branches: [main] pull_request: + branches: [main] permissions: contents: read +concurrency: + group: ci-${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +env: + GO_VERSION: "1.26.4" + jobs: + format: + name: format + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0 + with: + go-version: ${{ env.GO_VERSION }} + cache: true + - name: Boundary guard + run: bash ./scripts/check-ecosystem-boundaries.sh + - name: gofumpt + run: | + go install mvdan.cc/gofumpt@v0.10.0 + out=$(gofumpt -l .) + if [ -n "$out" ]; then + echo "::error::gofumpt would reformat:" + echo "$out" + exit 1 + fi + - name: goimports + run: | + go install golang.org/x/tools/cmd/goimports@v0.30.0 + out=$(goimports -l .) + if [ -n "$out" ]; then + echo "::error::goimports would reformat:" + echo "$out" + exit 1 + fi + + module: + name: module hygiene + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0 + with: + go-version: ${{ env.GO_VERSION }} + cache: true + - name: go mod tidy + run: | + go mod tidy + if ! git diff --quiet -- go.mod go.sum; then + echo "::error::go.mod / go.sum out of date — run 'go mod tidy'" + git diff -- go.mod go.sum + exit 1 + fi + - name: go mod verify + run: go mod verify + + vet: + name: vet + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0 + with: + go-version: ${{ env.GO_VERSION }} + cache: true + - name: go vet + run: go vet ./... + + lint: + name: lint + runs-on: ubuntu-latest + needs: [format, vet] + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0 + with: + go-version: ${{ env.GO_VERSION }} + cache: true + - name: Boundary guard + run: bash ./scripts/check-ecosystem-boundaries.sh + - name: Run golangci-lint + run: | + go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.1.0 + golangci-lint run --timeout=5m + test: + name: test (race + coverage) runs-on: ubuntu-latest + needs: [format, vet] steps: - - name: Checkout - uses: actions/checkout@v4 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0 + with: + go-version: ${{ env.GO_VERSION }} + cache: true + - name: Boundary guard + run: bash ./scripts/check-ecosystem-boundaries.sh + - name: Test with race detector + run: go test ./... -race -count=1 -shuffle=on -coverprofile=coverage.out -covermode=atomic -timeout=120s + - name: Upload coverage + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: coverage-${{ github.job }} + path: coverage.out + retention-days: 30 - - name: Setup Go - uses: actions/setup-go@v5 + security: + name: security + runs-on: ubuntu-latest + needs: [format, vet] + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0 with: - go-version-file: go.mod + go-version: ${{ env.GO_VERSION }} cache: true + - name: govulncheck + run: | + go install golang.org/x/vuln/cmd/govulncheck@v1.1.4 + govulncheck ./... + + secrets: + name: secrets + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: trufflesecurity/trufflehog@0fa069c12f0c7baf431041cd1e564a9c5058846c # main 2026-05-18 + with: + extra_args: --only-verified - - name: Run tests - run: go test ./... + build: + name: build (${{ matrix.goos }}/${{ matrix.goarch }}) + runs-on: ubuntu-latest + needs: [format, lint, test, security] + strategy: + fail-fast: false + matrix: + goos: [linux, darwin, windows] + goarch: [amd64, arm64] + exclude: + - goos: windows + goarch: arm64 + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0 + with: + go-version: ${{ env.GO_VERSION }} + cache: true + - name: Build (library — cross-compile all packages) + env: + GOOS: ${{ matrix.goos }} + GOARCH: ${{ matrix.goarch }} + CGO_ENABLED: "0" + run: go build -trimpath -v ./... diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..eb63cc0 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,31 @@ +# Release workflow for hawk-core-contracts (Go library — no binaries). +# Triggered when a v* tag is pushed; publishes a GitHub Release with +# auto-generated notes. Consumers depend on the tag via +# `go get github.com/GrayCodeAI/hawk-core-contracts@vX.Y.Z`. + +name: release + +on: + push: + tags: ["v*"] + +permissions: + contents: write + +jobs: + release: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + fetch-depth: 0 + + - name: Create GitHub Release + uses: softprops/action-gh-release@da05d552573ad5aba039eaac05058a918a7bf631 # v2.2.2 + with: + generate_release_notes: true + draft: false + prerelease: auto + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..ca62530 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,24 @@ +# Changelog + +All notable changes to `hawk-core-contracts` are documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] + +## [0.1.0] — 2026-07-05 + +Initial governed release. Establishes `VERSION` as the source of truth and +adds repo governance (`CODEOWNERS`, `Makefile`, boundary guard, engine-grade +CI) matching the rest of the hawk-eco foundation/engine repos. + +Existing contract packages at this version: + +- `types/` — severity, findings, shared result vocabulary +- `tools/` — provider-neutral tool call and tool result contracts +- `events/` — normalized tool and trace event contracts +- `policy/` — risk, permission verdict, guardian decision, approval request contracts +- `review/` — neutral review findings, comments, stats, and result contracts +- `verify/` — neutral verification findings, stats, and report contracts +- `sessions/` — cross-repo agent session state types diff --git a/CODEOWNERS b/CODEOWNERS new file mode 100644 index 0000000..5019045 --- /dev/null +++ b/CODEOWNERS @@ -0,0 +1,19 @@ +# CODEOWNERS for hawk-core-contracts (shared cross-repo contract types) +* @GrayCodeAI/maintainers + +# Contract packages — additive-only, cross-repo API surface +/types/ @GrayCodeAI/llm-team +/tools/ @GrayCodeAI/llm-team +/events/ @GrayCodeAI/llm-team +/policy/ @GrayCodeAI/llm-team +/review/ @GrayCodeAI/llm-team +/verify/ @GrayCodeAI/llm-team +/sessions/ @GrayCodeAI/llm-team +/VERSION @GrayCodeAI/maintainers + +# CI / release +/.github/ @GrayCodeAI/devops-team +/Makefile @GrayCodeAI/devops-team + +# Documentation +*.md @GrayCodeAI/docs-team diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..1afb25c --- /dev/null +++ b/Makefile @@ -0,0 +1,114 @@ +# Canonical hawk-eco Makefile for Go LIBRARY repos. +# Source of truth: https://github.com/GrayCodeAI/hawk/blob/main/.shared-templates/Makefile.library.tmpl +# hawk-core-contracts is a foundation library consumed by hawk and engines; +# no standalone binary, no release beyond tagging. + +# --------------------------------------------------------------------------- +# Project metadata +# --------------------------------------------------------------------------- +NAME := hawk-core-contracts + +# --------------------------------------------------------------------------- +# Versioning — sourced from VERSION file; falls back to git describe. +# --------------------------------------------------------------------------- +VERSION ?= $(shell cat VERSION 2>/dev/null | head -n1 | tr -d '[:space:]' || git describe --tags --always --dirty 2>/dev/null || echo "dev") +COMMIT := $(shell git rev-parse --short HEAD 2>/dev/null || echo "none") +DATE := $(shell date -u '+%Y-%m-%dT%H:%M:%SZ') + +# --------------------------------------------------------------------------- +# Tooling — pinned, install if missing. +# --------------------------------------------------------------------------- +GOBIN_DIR := $(shell go env GOPATH)/bin +GOLANGCI := $(GOBIN_DIR)/golangci-lint +GOFUMPT := $(GOBIN_DIR)/gofumpt +GOIMPORTS := $(GOBIN_DIR)/goimports +GOVULNCHECK := $(GOBIN_DIR)/govulncheck + +# --------------------------------------------------------------------------- +# Phony declarations (alphabetical). +# --------------------------------------------------------------------------- +.PHONY: all boundaries build ci clean cover fmt help hooks lint lint-fix \ + security test test-race tidy version vet + +boundaries: ## Enforce foundation-repo import boundaries (zero GrayCodeAI/* deps). + bash ./scripts/check-ecosystem-boundaries.sh + +# --------------------------------------------------------------------------- +# Default target. +# --------------------------------------------------------------------------- +all: lint test build ## Default — lint, test, build. + +# --------------------------------------------------------------------------- +# Build. +# --------------------------------------------------------------------------- +build: ## Build all contract packages. + go build ./... + +# --------------------------------------------------------------------------- +# Tests. +# --------------------------------------------------------------------------- +test: ## Run unit tests. + go test ./... -count=1 -timeout=60s + +test-race: ## Run unit tests with the race detector. + go test ./... -race -count=1 -timeout=120s + +cover: ## Generate a coverage report (coverage.out + coverage.html). + go test ./... -race -coverprofile=coverage.out -covermode=atomic -timeout=120s + @go tool cover -func=coverage.out | grep "^total:" + @go tool cover -html=coverage.out -o coverage.html + @echo "Coverage report: coverage.html" + +# --------------------------------------------------------------------------- +# Quality gates. +# --------------------------------------------------------------------------- +fmt: ## Format source files (gofumpt + goimports). + @command -v $(GOFUMPT) >/dev/null 2>&1 || (echo "install: go install mvdan.cc/gofumpt@latest" && exit 1) + @command -v $(GOIMPORTS) >/dev/null 2>&1 || (echo "install: go install golang.org/x/tools/cmd/goimports@latest" && exit 1) + $(GOFUMPT) -w . + $(GOIMPORTS) -w . + +vet: ## Run go vet. + go vet ./... + +lint: ## Run golangci-lint. + @command -v $(GOLANGCI) >/dev/null 2>&1 || (echo "install: go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@latest" && exit 1) + $(GOLANGCI) run ./... --timeout=5m + +lint-fix: ## Run golangci-lint with --fix. + @command -v $(GOLANGCI) >/dev/null 2>&1 || (echo "install: go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@latest" && exit 1) + $(GOLANGCI) run ./... --fix --timeout=5m + +security: ## Run govulncheck. + @command -v $(GOVULNCHECK) >/dev/null 2>&1 || (echo "install: go install golang.org/x/vuln/cmd/govulncheck@latest" && exit 1) + $(GOVULNCHECK) ./... + +tidy: ## Tidy go.mod / go.sum. + go mod tidy + go mod verify + +# --------------------------------------------------------------------------- +# Composite gate used by CI and pre-push. +# --------------------------------------------------------------------------- +ci: tidy fmt vet lint boundaries test-race security ## Run everything CI runs. + @echo "All CI checks passed." + +# --------------------------------------------------------------------------- +# Misc. +# --------------------------------------------------------------------------- +version: ## Print the version that will be embedded. + @echo "Version: $(VERSION)" + @echo "Commit: $(COMMIT)" + @echo "Date: $(DATE)" + +clean: ## Remove build artefacts. + rm -rf coverage.out coverage.html + go clean -testcache + +help: ## Show this help. + @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-15s\033[0m %s\n", $$1, $$2}' + +hooks: ## Install git hooks via lefthook (boundary guard, tests, co-author strip). + @command -v lefthook >/dev/null 2>&1 || (echo "install: go install github.com/evilmartians/lefthook@latest" && exit 1) + git config --unset core.hooksPath 2>/dev/null || true + lefthook install diff --git a/README.md b/README.md index d14624b..f0d1572 100644 --- a/README.md +++ b/README.md @@ -67,3 +67,23 @@ Completed: - avoid product-specific runtime assumptions - do not move Hawk orchestration code here - if a type is only used inside one repo, it should stay in that repo + +## Ecosystem Boundaries + +`hawk-core-contracts` is a **foundation repo** in the [hawk ecosystem](https://github.com/GrayCodeAI/hawk/blob/main/docs/architecture/hawk-ecosystem-summary.md) — +it sits below every engine and below `hawk` itself, alongside +`hawk-mcpkit`. + +Rules that keep it there: + +- **Zero hawk-eco dependencies.** This repo must never import `hawk`, any + engine (`eyrie`, `yaad`, `tok`, `trace`, `sight`, `inspect`), any SDK, or + `hawk-mcpkit`. Only the Go standard library. `make boundaries` (also run + in CI) enforces this with `scripts/check-ecosystem-boundaries.sh`. +- **Implementation-free.** See Scope above — no CLI code, provider + implementations, runtime logic, storage, or orchestration. +- **Consumers, not dependents.** `hawk` and engines import this repo when + they share a real cross-repo contract; it never imports them back. + +If a change here would require importing anything outside the standard +library, that type does not belong in this repo. diff --git a/VERSION b/VERSION new file mode 100644 index 0000000..6e8bf73 --- /dev/null +++ b/VERSION @@ -0,0 +1 @@ +0.1.0 diff --git a/lefthook.yml b/lefthook.yml index 2dbf45f..f67aee3 100644 --- a/lefthook.yml +++ b/lefthook.yml @@ -1,3 +1,5 @@ +# Canonical lefthook config for hawk-eco Go repos. +# Source of truth: https://github.com/GrayCodeAI/hawk/blob/main/.shared-templates/lefthook.yml.tmpl # Install: lefthook install # Skip once: LEFTHOOK=0 git commit -m "..." @@ -12,3 +14,10 @@ commit-msg: strip-co-authored-by: run: | sed '/^[Cc]o-[Aa]uthored-[Bb]y:/d' "{1}" > "{1}.tmp" && mv "{1}.tmp" "{1}" + +pre-push: + commands: + boundaries: + run: bash ./scripts/check-ecosystem-boundaries.sh + test: + run: go test ./... -race -count=1 diff --git a/scripts/check-ecosystem-boundaries.sh b/scripts/check-ecosystem-boundaries.sh new file mode 100755 index 0000000..e0d5265 --- /dev/null +++ b/scripts/check-ecosystem-boundaries.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash +set -euo pipefail + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +cd "$ROOT_DIR" + +# hawk-core-contracts is a foundation library: it sits below every engine +# and below hawk itself. It must depend on nothing in the hawk ecosystem — +# only the Go standard library. Imports of this module's own path (internal +# cross-package imports between types/, tools/, events/, etc.) are fine. +FORBIDDEN='github\.com/GrayCodeAI/(?!hawk-core-contracts(/|"))' +FORBIDDEN_GREP='github\.com/GrayCodeAI/[^"]*' +SELF_MODULE='github.com/GrayCodeAI/hawk-core-contracts' + +if command -v rg >/dev/null 2>&1; then + violations="$(rg -n "$FORBIDDEN" --pcre2 --glob '*.go' . || true)" +else + violations="$(grep -rn --include='*.go' -E "$FORBIDDEN_GREP" . | grep -v "$SELF_MODULE" || true)" +fi + +if [[ -n "${violations}" ]]; then + echo "forbidden hawk-eco imports found in hawk-core-contracts:" + echo "${violations}" + echo + echo "hawk-core-contracts is a foundation repo — it must not depend on hawk, engines, or any other GrayCodeAI/* package" + exit 1 +fi + +echo "ecosystem boundary guard passed" From 3211c8eaf595a58912b70f7d8de2fd656e6d9354 Mon Sep 17 00:00:00 2001 From: Lakshman Patel Date: Mon, 6 Jul 2026 08:19:17 +0530 Subject: [PATCH 2/4] chore: add missing documentation and standardize across ecosystem - Create AGENTS.md with 7 contract packages, scope rules, package guidelines - Create CODE_OF_CONDUCT.md (Contributor Covenant 2.1) - Create SECURITY.md with comprehensive security policy - Update README.md with install instructions, package reference, migration history Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com> --- AGENTS.md | 217 +++++++++++++++++++++++++++++++++++++++++++++ CODE_OF_CONDUCT.md | 60 +++++++++++++ README.md | 149 ++++++++++++++++++++----------- SECURITY.md | 71 +++++++++++++++ 4 files changed, 444 insertions(+), 53 deletions(-) create mode 100644 AGENTS.md create mode 100644 CODE_OF_CONDUCT.md create mode 100644 SECURITY.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..2ad8421 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,217 @@ +# AGENTS.md — hawk-core-contracts + +This file describes the hawk-core-contracts project for AI agents working in +this codebase. The TUI `/memory` command references this file. + +--- + +## Project Overview + +hawk-core-contracts is the shared cross-repo contract types package for the +hawk ecosystem. It holds stable definitions that every engine and hawk itself +depend on: severity levels, findings, tool contracts, event models, policy +verdicts, review results, verification reports, and agent session state. + +**Tagline:** Shared contracts for the hawk ecosystem. + +## Ecosystem + +hawk-core-contracts is a **foundation repo** in the hawk-eco mono-ecosystem: + +| Component | Purpose | +|-----------|---------| +| **hawk-core-contracts** | Shared cross-repo contracts (this repo) | +| **hawk-mcpkit** | Shared MCP server scaffolding | +| **eyrie** | LLM provider runtime — routing, streaming, retries, caching | +| **yaad** | Graph-based persistent memory for coding agents | +| **tok** | Tokenizer, compression, secrets scanning, rate limiting | +| **sight** | Diff-based code review and static analysis | +| **inspect** | Security audit library (CVE, API security, CI output) | +| **trace** | Session capture and replay CLI | +| **hawk** | AI coding agent (this repo) | + +`hawk` and all engines import `hawk-core-contracts` when they share a real +cross-repo contract. The repo itself never imports back. + +## Architecture + +``` +hawk-core-contracts/ +├── types/ # Severity, findings, shared result vocabulary +│ ├── finding.go # Finding, FindingSlice, FilterBySeverity +│ ├── severity.go # Severity levels, ParseSeverity +│ └── *_test.go # Table-driven tests +├── tools/ # Provider-neutral tool call and result contracts +│ └── *.go +├── events/ # Normalized tool and trace event contracts +│ └── *.go +├── policy/ # Risk, permission verdict, guardian decision contracts +│ └── *.go +├── review/ # Neutral review findings, comments, stats, results +│ └── *.go +├── verify/ # Neutral verification findings, stats, reports +│ └── *.go +├── sessions/ # Cross-repo agent session state types +│ └── *.go +├── scripts/ +│ └── check-ecosystem-boundaries.sh # CI guard: zero hawk-eco deps +├── .github/ +│ └── workflows/ +│ ├── ci.yml # CI: format, module hygiene, vet, lint, test, security +│ └── release.yml # GitHub Release on v* tags +├── Makefile # Local dev tasks +├── lefthook.yml # Pre-commit hooks (boundary guard, co-author strip) +├── AGENTS.md # This file +├── README.md # Package map, scope, governance rules +├── CHANGELOG.md # Keep a Changelog format +├── CODEOWNERS # Code ownership (package-level + infra) +├── LICENSE # MIT +├── VERSION # Source of truth for versioning +└── go.mod / go.sum # Module files (stdlib only) +``` + +## Key Design Decisions + +- **Implementation-free:** This repo holds only type definitions and + constructors. No CLI code, no provider implementations, no runtime logic, + no storage, no orchestration. See Scope below for the full list. +- **Zero hawk-eco dependencies:** This repo depends only on the Go standard + library. `make boundaries` (also run in CI) enforces this. Violations are + caught by `scripts/check-ecosystem-boundaries.sh`. +- **Additive-only:** Changes to contracts should be backward-compatible. + New fields get zero values; new packages are added, never removed. +- **Prefixed consumers, not dependents:** `hawk` and engines import this + repo when they share a real cross-repo contract; it never imports them + back. +- **Single source of truth:** `VERSION` file is the canonical version + identifier. `go.mod` uses `go 1.26.4`. + +## Scope + +### Allowed here + +- shared enums (severity levels, risk levels, phases) +- shared structs (findings, tool calls, events, verdicts, reports) +- event models (tool events, trace events, usage info) +- finding/result models (severity, confidence, status) +- engine request/response contracts +- policy and tool contracts + +### Not allowed here + +- CLI code (commands, flags, shell output) +- provider implementations +- runtime logic +- storage implementations +- product orchestration +- anything that belongs in a single consuming repo + +If a type is only used inside one repo, it should stay in that repo. + +## Development Guidelines + +### Build & Test + +```bash +make test # Run unit tests (no race detector) +make test-race # Run unit tests with race detector +make lint # Run golangci-lint +make boundaries # Enforce zero hawk-eco imports +make ci # Full CI suite (tidy, fmt, vet, boundaries, lint, test-race, security) +``` + +### Go Conventions + +- Standard Go project layout: `cmd/` for entry points, `internal/` for private +- Tests live alongside source files (`foo.go` → `foo_test.go`) +- Package-level tests use `package _test` to avoid importing internal + packages when testing only public API surface +- Use table-driven tests where practical +- Errors are values — wrap with `fmt.Errorf("context: %w", err)` +- No global mutable state; prefer dependency injection + +### Commit Conventions + +Use [Conventional Commits](https://www.conventionalcommits.org/): +``` +feat: add review result contracts +fix: handle nil findings in FilterBySeverity +refactor: extract severity parsing into shared helper +``` + +## Package Map + +| Package | Contents | Owners | +|---------|----------|--------| +| `types/` | Severity levels, findings, shared result vocabulary | `@GrayCodeAI/llm-team` | +| `tools/` | Provider-neutral tool call and tool result contracts | `@GrayCodeAI/llm-team` | +| `events/` | Normalized tool and trace event contracts | `@GrayCodeAI/llm-team` | +| `policy/` | Risk, permission verdict, guardian decision, approval request contracts | `@GrayCodeAI/llm-team` | +| `review/` | Neutral review findings, comments, stats, and result contracts | `@GrayCodeAI/llm-team` | +| `verify/` | Neutral verification findings, stats, and report contracts | `@GrayCodeAI/llm-team` | +| `sessions/` | Cross-repo agent session state types | `@GrayCodeAI/llm-team` | + +## Package Guidelines + +Each contract package follows these conventions: + +- **Pure data types:** structs, enums, constructors, and methods on those types +- **No external dependencies:** only stdlib imports +- **No I/O:** no file reads, HTTP calls, or database access +- **JSON-serializable:** all public structs should serialize cleanly via + `encoding/json` (no `map[struct]` keys, no unexported fields without tags) +- **Nil-safety:** pointer receivers for nil-safe methods; document expected + behavior for nil receivers +- **Test file naming:** `*_test.go` alongside source files +- **Package-level tests:** use `package _test` when testing only the + public API surface of a package + +## Adding a New Contract Package + +1. Create a new directory `/` at the repo root +2. Define types, enums, and constructors in `.go` files +3. Add tests in `*_test.go` files (using `package _test`) +4. Do not add any imports from the hawk ecosystem — only stdlib +5. Add the package to `CODEOWNERS` under the `@GrayCodeAI/llm-team` entry +6. Add any necessary types to the package map in the README +7. Add package-level docs ( exported type descriptions) + +## Testing Patterns + +- **Table-driven tests** with `t.Run(name, func(t *testing.T){...})` for all multi-case tests +- **`t.Parallel()`** on all tests that don't share mutable state +- **Package-level API tests** use `package _test` to test only public surface without importing internal packages +- **No mocks framework** — use concrete types and test doubles +- **JSON round-trip tests** for serializable structs (marshal → unmarshal → compare fields) + +## Common Pitfalls + +- Do not import any hawk-eco package in this repo — only the Go standard library +- Do not put runtime logic, CLI code, or product orchestration here +- If a type is only used inside one repo, it should stay in that repo +- Keep changes additive; avoid renaming or restructuring existing types +- Do not add non-stdlib dependencies — if you need something, put it in the + consuming engine instead +- `go.mod` has no `require` blocks (stdlib only); never add module dependencies + +## File Organization Notes + +| File | Purpose | +|------|---------| +| `types/` | Severity levels, findings, result vocabulary | +| `tools/` | Tool call/result contracts | +| `events/` | Tool and trace event contracts | +| `policy/` | Risk and permission verdict contracts | +| `review/` | Review result contracts | +| `verify/` | Verification report contracts | +| `sessions/` | Agent session state contracts | +| `scripts/check-ecosystem-boundaries.sh` | CI guard against hawk-eco imports | +| `.github/workflows/ci.yml` | CI pipeline | +| `.github/workflows/release.yml` | GitHub Release on `v*` tags | +| `Makefile` | Local dev tasks | +| `lefthook.yml` | Pre-commit hooks | +| `AGENTS.md` | This file | +| `README.md` | Package map, scope, governance rules | +| `CHANGELOG.md` | Keep a Changelog format | +| `CODEOWNERS` | Code ownership | +| `VERSION` | Canonical version | diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..616efcf --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,60 @@ +# Code of Conduct + +## Our pledge + +We — the maintainers and contributors of the hawk-core-contracts project — pledge to +make participation in our community a harassment-free experience for everyone, +regardless of age, body size, visible or invisible disability, ethnicity, sex +characteristics, gender identity and expression, level of experience, +education, socio-economic status, nationality, personal appearance, race, +religion, or sexual identity and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Our standards + +Examples of behaviour that contributes to a positive environment: + +- Demonstrating empathy and kindness toward other people. +- Being respectful of differing opinions, viewpoints, and experiences. +- Giving and gracefully accepting constructive feedback. +- Accepting responsibility, apologising to those affected by mistakes, and + learning from the experience. +- Focusing on what is best not just for us as individuals, but for the + overall community. + +Examples of unacceptable behaviour: + +- The use of sexualised language or imagery, and sexual attention or advances. +- Trolling, insulting or derogatory comments, and personal or political + attacks. +- Public or private harassment. +- Publishing others' private information, such as a physical or email + address, without their explicit permission. +- Other conduct which could reasonably be considered inappropriate in a + professional setting. + +## Enforcement + +Community leaders are responsible for clarifying and enforcing our standards +of acceptable behaviour, and will take appropriate and fair corrective +action in response to any behaviour they deem inappropriate, threatening, +offensive, or harmful. + +Instances of abusive, harassing, or otherwise unacceptable behaviour may be +reported to the maintainers via the contact in `SECURITY.md` or by opening a +confidential GitHub Security Advisory at +. All +complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of +the reporter of any incident. + +## Attribution + +This Code of Conduct is adapted from the +[Contributor Covenant, version 2.1](https://www.contributor-covenant.org/version/2/1/code_of_conduct.html). + +For answers to common questions about this code of conduct, see the +Contributor Covenant FAQ at . diff --git a/README.md b/README.md index f0d1572..e536537 100644 --- a/README.md +++ b/README.md @@ -1,85 +1,108 @@ # hawk-core-contracts -Shared contracts for the Hawk ecosystem. +Shared contracts for the hawk ecosystem. -This repo exists to hold stable cross-repo definitions used by: +This repo holds stable cross-repo type definitions used by every engine and +`hawk` itself: severity levels, findings, tool contracts, event models, policy +verdicts, review results, verification reports, and agent session state. -- `hawk` -- `eyrie` -- `yaad` -- `tok` -- `trace` -- `sight` -- `inspect` -- Hawk SDKs and extension surfaces where needed +**Tagline:** Shared contracts for the hawk ecosystem. + +## Install + +```sh +go get github.com/GrayCodeAI/hawk-core-contracts +``` + +## Quick Reference + +| Package | Key Types | Purpose | +|---------|-----------|---------| +| `types/` | `Severity`, `Finding`, `FindingSlice`, `ParseSeverity` | Severity levels, findings, shared result vocabulary | +| `tools/` | `ToolCall`, `ToolResult` | Provider-neutral tool call and result contracts | +| `events/` | `ToolEvent`, `TraceEvent`, `UsageInfo` | Normalized tool and trace event contracts | +| `policy/` | `Risk`, `PermissionVerdict`, `Allow`, `Deny` | Risk, permission verdict, guardian decision, approval request contracts | +| `review/` | `Result`, `Finding`, `Comment` | Neutral review findings, comments, stats, and result contracts | +| `verify/` | `Report`, `Finding` | Neutral verification findings, stats, and report contracts | +| `sessions/` | `Phase`, `CostAccumulator`, `ParsePhase` | Cross-repo agent session state types | + +## Architecture + +``` +hawk-core-contracts (stdlib only) +├── types/ Severity, Finding, FindingSlice — the core vocabulary +├── tools/ ToolCall, ToolResult — provider-neutral tool contracts +├── events/ ToolEvent, TraceEvent — normalized event contracts +├── policy/ Risk, PermissionVerdict — governance contracts +├── review/ Result, Finding, Comment — review result contracts +├── verify/ Report, Finding — verification report contracts +└── sessions/ Phase, CostAccumulator — session state contracts +``` ## Scope -Allowed here: +### Allowed here -- shared enums -- shared structs -- event models -- finding/result models +- shared enums (severity levels, risk levels, phases) +- shared structs (findings, tool calls, events, verdicts, reports) +- event models (tool events, trace events, usage info) +- finding/result models (severity, confidence, status) - engine request/response contracts - policy and tool contracts -Not allowed here: +### Not allowed here -- CLI code +- CLI code (commands, flags, shell output) - provider implementations - runtime logic - storage implementations - product orchestration - -## Migration history - -The legacy `github.com/GrayCodeAI/hawk/shared/types` package has been removed. -Severity, findings, and the packages below are the supported cross-repo API. +- anything that belongs in a single consuming repo Engines should depend on this repo only when they produce or consume a shared -contract. Contract-free engines (for example `eyrie`, `yaad`, `trace`) should -not add the dependency just for consistency. - -## Package map +cross-repo contract. Contract-free engines (e.g., `eyrie`, `yaad`, `trace`) +should not add the dependency just for consistency. -- `types/` - severity, findings, and shared result vocabulary -- `tools/` - provider-neutral tool call and tool result contracts -- `events/` - normalized tool and trace event contracts -- `policy/` - risk, permission verdict, guardian decision, approval request contracts -- `review/` - neutral review findings, comments, stats, and result contracts -- `verify/` - neutral verification findings, stats, and report contracts +If a type is only used inside one repo, it should stay in that repo. -## Current status +## Migration History -Completed: +The legacy `github.com/GrayCodeAI/hawk/shared/types` package has been removed. +All shared finding and severity definitions now live here. Migration is +complete: -1. shared finding and severity definitions moved here +1. Severity and finding definitions migrated from `hawk/shared/types` 2. `sight` and `inspect` migrated to import this repo -3. Hawk docs and READMEs updated -4. tool, event, and policy contracts added -5. review and verification result contracts added +3. Tool, event, and policy contracts added +4. Review and verification result contracts added +5. Sessions package added for cross-repo session state -## Governance rules +## Ecosystem -- keep this repo implementation-free -- prefer additive changes -- avoid product-specific runtime assumptions -- do not move Hawk orchestration code here -- if a type is only used inside one repo, it should stay in that repo +hawk-core-contracts is a **foundation repo** in the hawk-eco mono-ecosystem: -## Ecosystem Boundaries +| Component | Purpose | +|-----------|---------| +| **hawk-core-contracts** | Shared cross-repo contracts (this repo) | +| **hawk-mcpkit** | Shared MCP server scaffolding | +| **eyrie** | LLM provider runtime — routing, streaming, retries, caching | +| **yaad** | Graph-based persistent memory for coding agents | +| **tok** | Tokenizer, compression, secrets scanning, rate limiting | +| **sight** | Diff-based code review and static analysis | +| **inspect** | Security audit library (CVE, API security, CI output) | +| **trace** | Session capture and replay CLI | +| **hawk** | AI coding agent (this repo) | -`hawk-core-contracts` is a **foundation repo** in the [hawk ecosystem](https://github.com/GrayCodeAI/hawk/blob/main/docs/architecture/hawk-ecosystem-summary.md) — -it sits below every engine and below `hawk` itself, alongside -`hawk-mcpkit`. +`hawk` and all engines import `hawk-core-contracts` when they share a real +cross-repo contract; the repo itself never imports back. -Rules that keep it there: +## Ecosystem Boundaries + +Rules that keep this repo at the foundation layer: -- **Zero hawk-eco dependencies.** This repo must never import `hawk`, any - engine (`eyrie`, `yaad`, `tok`, `trace`, `sight`, `inspect`), any SDK, or - `hawk-mcpkit`. Only the Go standard library. `make boundaries` (also run - in CI) enforces this with `scripts/check-ecosystem-boundaries.sh`. +- **Zero hawk-eco dependencies.** This repo imports only the Go standard + library. `make boundaries` (also run in CI) enforces this with + `scripts/check-ecosystem-boundaries.sh`. - **Implementation-free.** See Scope above — no CLI code, provider implementations, runtime logic, storage, or orchestration. - **Consumers, not dependents.** `hawk` and engines import this repo when @@ -87,3 +110,23 @@ Rules that keep it there: If a change here would require importing anything outside the standard library, that type does not belong in this repo. + +## Package Ownership + +| Path | Team | +|------|------| +| `/types/` | `@GrayCodeAI/llm-team` | +| `/tools/` | `@GrayCodeAI/llm-team` | +| `/events/` | `@GrayCodeAI/llm-team` | +| `/policy/` | `@GrayCodeAI/llm-team` | +| `/review/` | `@GrayCodeAI/llm-team` | +| `/verify/` | `@GrayCodeAI/llm-team` | +| `/sessions/` | `@GrayCodeAI/llm-team` | +| `/VERSION` | `@GrayCodeAI/maintainers` | +| `/Makefile` | `@GrayCodeAI/devops-team` | +| `/*.md` | `@GrayCodeAI/docs-team` | +| `/.github/` | `@GrayCodeAI/devops-team` | + +## License + +MIT — see [LICENSE](LICENSE). diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..00027a7 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,71 @@ +# Security Policy — hawk-core-contracts + +## Supported versions + +We support the latest minor version on each `0.x` line, and the latest two +minor versions once `1.x` ships. Older versions receive critical-severity +fixes only on a best-effort basis. + +The current canonical version is the contents of the [`VERSION`](./VERSION) +file at the repo root. See [`VERSIONING.md`](https://github.com/GrayCodeAI/hawk/blob/main/VERSIONING.md) +for the eco-wide versioning scheme. + +## Reporting a vulnerability + +**Do not open a public GitHub issue for security vulnerabilities.** Instead: + +1. Open a private [GitHub Security Advisory](https://github.com/GrayCodeAI/hawk-core-contracts/security/advisories/new), **or** +2. Email `security@graycode.ai` with the details below. + +Include in your report: + +- A description of the vulnerability and the affected component. +- Steps to reproduce, ideally with a minimal proof-of-concept. +- The version (`VERSION` file or git SHA) you tested against. +- The potential impact and any suggested mitigation. + +**Response targets:** + +- Initial acknowledgement: within **48 hours**. +- Triage and severity assessment: within **5 business days**. +- Coordinated fix and disclosure: within **30 days** for high/critical, **90 + days** for medium/low (per industry-standard responsible disclosure). + +## Disclosure policy + +We follow [coordinated vulnerability disclosure](https://en.wikipedia.org/wiki/Coordinated_vulnerability_disclosure): + +- Reporters receive credit in the advisory and CHANGELOG (unless they opt + out). +- We request that reporters refrain from public disclosure until a fix has + been released or the disclosure deadline above has elapsed. +- We will not pursue legal action against good-faith researchers acting + within this policy. + +## Security practices in this repo + +- **Dependency monitoring:** vulnerable dependencies are detected by + `govulncheck`, which runs on every CI build (see "Vulnerability scanning"). +- **Static analysis:** `golangci-lint` / `ruff` / `mypy` enforced in CI. +- **Vulnerability scanning:** `govulncheck` (Go) / `pip-audit` (Python) run + on every CI build. +- **Lockfiles:** `go.sum` / `pnpm-lock.yaml` / `pyproject.toml` are pinned + and committed. +- **Reproducible builds:** release artefacts ship with SHA-256 checksums via + goreleaser. +- **No secrets in source:** API keys are configuration, not constants. Pre- + commit hooks block accidental secret commits. + +## Scope + +This policy covers the code in this repository and the release artefacts +published from it. It does not cover: + +- Third-party dependencies (report to upstream). +- LLM provider services that hawk-core-contracts integrates with (report to the + provider). +- Local filesystem misuse where an attacker already has shell access (out of + threat model). + +For hawk-core-contracts-specific threat-model notes, see the README and any docs in +this repo. From 7984e3c43444a3c0b6027075b2d2f41a7160ebea Mon Sep 17 00:00:00 2001 From: Lakshman Patel Date: Tue, 7 Jul 2026 14:47:19 +0530 Subject: [PATCH 3/4] feat: add VERSION file and root version.go with //go:embed VERSION as single source of truth --- AGENTS.md | 321 +++++++++++++++++++++++------------------------------ version.go | 15 +++ 2 files changed, 151 insertions(+), 185 deletions(-) create mode 100644 version.go diff --git a/AGENTS.md b/AGENTS.md index 2ad8421..4976a45 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,217 +1,168 @@ -# AGENTS.md — hawk-core-contracts - -This file describes the hawk-core-contracts project for AI agents working in -this codebase. The TUI `/memory` command references this file. - +--- +description: Extending hawk-eco — how to write AGENTS.md files, custom specialists, skills, hooks, MCP servers, and plugins. +globs: "*.go, *.js, *.md, *.json, *.toml, *.yaml, *.yml" +alwaysApply: false --- -## Project Overview +# Extending hawk-eco -hawk-core-contracts is the shared cross-repo contract types package for the -hawk ecosystem. It holds stable definitions that every engine and hawk itself -depend on: severity levels, findings, tool contracts, event models, policy -verdicts, review results, verification reports, and agent session state. +hawk-eco is an open-source code intelligence platform. This document describes how to extend it with custom tools, skills, hooks, and integrations. -**Tagline:** Shared contracts for the hawk ecosystem. +## 1. Drop a project `AGENTS.md` -## Ecosystem +When hawk-eco starts in a directory, it looks for project-level instructions and injects them into the system prompt. The lookup walks from your current working directory **up to the nearest git root** and reads the first matching file at each level — general rules at the repo root, more specific rules in sub-trees. Files are labeled with their directory in the prompt (e.g. `## Project guidelines (services/api/AGENTS.md)`). -hawk-core-contracts is a **foundation repo** in the hawk-eco mono-ecosystem: +Accepted file names, in priority order at each level: -| Component | Purpose | -|-----------|---------| -| **hawk-core-contracts** | Shared cross-repo contracts (this repo) | -| **hawk-mcpkit** | Shared MCP server scaffolding | -| **eyrie** | LLM provider runtime — routing, streaming, retries, caching | -| **yaad** | Graph-based persistent memory for coding agents | -| **tok** | Tokenizer, compression, secrets scanning, rate limiting | -| **sight** | Diff-based code review and static analysis | -| **inspect** | Security audit library (CVE, API security, CI output) | -| **trace** | Session capture and replay CLI | -| **hawk** | AI coding agent (this repo) | +| Path | Notes | +| --- | --- | +| `./AGENTS.md` | The classic spot — committed to your repo, shared with the team. | +| `./ZERO.md` | Brand-specific alias. Same format, lower priority. | +| `./.zero/AGENTS.md` | Project-local, hidden, gitignored. Personal notes that stay out of git. | -`hawk` and all engines import `hawk-core-contracts` when they share a real -cross-repo contract. The repo itself never imports back. +Matching is **case-insensitive** on the basename, so `AGENTS.md`, `Agents.md`, and `agents.md` resolve to the same file on Windows and macOS. The git-tracked filename in this repo is `AGENTS.md` — keep that on case-sensitive filesystems (Linux, the WSL filesystem, or a CI runner) to match what the loader looks for. -## Architecture +Both files use the same format. YAML frontmatter is optional; the markdown body is loaded as instructions for the agent. hawk-eco reads the file once at session start, so changes take effect on the next launch — not mid-session. +```markdown +# Project conventions for + +- Build with `make`, not `go build` directly. +- Tests live next to the source file (`foo_test.go` next to `foo.go`). +- Run `make lint` before opening a PR. +- Never edit files under `third_party/` — those are vendored. ``` -hawk-core-contracts/ -├── types/ # Severity, findings, shared result vocabulary -│ ├── finding.go # Finding, FindingSlice, FilterBySeverity -│ ├── severity.go # Severity levels, ParseSeverity -│ └── *_test.go # Table-driven tests -├── tools/ # Provider-neutral tool call and result contracts -│ └── *.go -├── events/ # Normalized tool and trace event contracts -│ └── *.go -├── policy/ # Risk, permission verdict, guardian decision contracts -│ └── *.go -├── review/ # Neutral review findings, comments, stats, results -│ └── *.go -├── verify/ # Neutral verification findings, stats, reports -│ └── *.go -├── sessions/ # Cross-repo agent session state types -│ └── *.go -├── scripts/ -│ └── check-ecosystem-boundaries.sh # CI guard: zero hawk-eco deps -├── .github/ -│ └── workflows/ -│ ├── ci.yml # CI: format, module hygiene, vet, lint, test, security -│ └── release.yml # GitHub Release on v* tags -├── Makefile # Local dev tasks -├── lefthook.yml # Pre-commit hooks (boundary guard, co-author strip) -├── AGENTS.md # This file -├── README.md # Package map, scope, governance rules -├── CHANGELOG.md # Keep a Changelog format -├── CODEOWNERS # Code ownership (package-level + infra) -├── LICENSE # MIT -├── VERSION # Source of truth for versioning -└── go.mod / go.sum # Module files (stdlib only) + +Tips: + +- Keep each file under ~8 KiB. hawk-eco caps the **total** across all matched files at 32 KiB; everything past the cap is dropped. +- Re-state rules in the imperative voice: "Run `make lint`", not "you should consider running the linter". +- Don't put secrets, model IDs, or environment-specific paths in `AGENTS.md`. Use config files for those. +- In a monorepo, drop a narrower `AGENTS.md` in each sub-tree (e.g. `services/api/AGENTS.md`). hawk-eco picks those up automatically when you launch from inside the sub-tree. +- A YAML frontmatter block (`---\n...\n---`) at the top is preserved verbatim in the injected prompt but is not parsed for `globs:` or `alwaysApply:` scoping today — keep the body self-contained. + +### Personal guidelines, across every project + +For preferences that follow *you*, not a specific repo (tone, tooling habits, workflow), drop a `ZERO.md` in your user config directory: `~/.config/hawk-eco/ZERO.md` on Linux/macOS, `%AppData%\Roaming\hawk-eco\ZERO.md` on Windows — the same directory as config files and your personal specialists. Same format and 8 KiB cap as the project files above, and the same case-insensitive basename match. + +This file is injected as its own `## User guidelines` section, before the project's `AGENTS.md`/`ZERO.md`, and is labeled as personal preference in the prompt: project guidelines are the later, more specific instruction and take precedence over it when the two conflict. + +## 2. Custom specialists + +Specialists are hawk-eco's sub-agents. Three scopes, in priority order: + +| Scope | Path | Shared? | +| --- | --- | --- | +| Built-in | compiled into hawk-eco | yes | +| User | `~/.config/hawk-eco/specialists/*.md` | no — your machine only | +| Project | `./.zero/specialists/*.md` | yes — the repo team | + +Project overrides user overrides built-in when names collide. + +A specialist is a markdown manifest with frontmatter and a system prompt: + +```markdown +--- +description: Reviews API changes for breaking-change risk and missing tests. +tools: read-only,plan +--- + +You review API changes. For every changed hunk in `internal/api/` or any file +that ends in `_api.go`: + +1. Confirm the public signature is backward-compatible, or note the breaking + change explicitly with the migration path. +2. Confirm a corresponding test exists in `internal/api/*_test.go` and that + the new behaviour is exercised. +3. Flag any new exported symbol without a doc comment. + +Reply with one JSON object per finding: `{"file", "line", "severity", "message", "fix"}`. ``` -## Key Design Decisions +CLI management: -- **Implementation-free:** This repo holds only type definitions and - constructors. No CLI code, no provider implementations, no runtime logic, - no storage, no orchestration. See Scope below for the full list. -- **Zero hawk-eco dependencies:** This repo depends only on the Go standard - library. `make boundaries` (also run in CI) enforces this. Violations are - caught by `scripts/check-ecosystem-boundaries.sh`. -- **Additive-only:** Changes to contracts should be backward-compatible. - New fields get zero values; new packages are added, never removed. -- **Prefixed consumers, not dependents:** `hawk` and engines import this - repo when they share a real cross-repo contract; it never imports them - back. -- **Single source of truth:** `VERSION` file is the canonical version - identifier. `go.mod` uses `go 1.26.4`. +```bash +hawk-eco specialist list +hawk-eco specialist show api-reviewer +hawk-eco specialist create api-reviewer \ + --project \ + --description "Reviews API changes" \ + --tools read-only,plan \ + --prompt "$(cat api-reviewer.md)" +hawk-eco specialist edit api-reviewer --project +hawk-eco specialist delete api-reviewer --project +hawk-eco specialist path # prints the resolved specialists directory +``` -## Scope +## 3. Skills -### Allowed here +Skills are markdown instruction files that extend agent capabilities. They can be: +- Project-scoped: dropped in `./.zero/skills/` or `./skills/` +- User-scoped: dropped in `~/.config/hawk-eco/skills/` -- shared enums (severity levels, risk levels, phases) -- shared structs (findings, tool calls, events, verdicts, reports) -- event models (tool events, trace events, usage info) -- finding/result models (severity, confidence, status) -- engine request/response contracts -- policy and tool contracts +A skill manifest: -### Not allowed here +```markdown +--- +description: How to review Go code for security issues +globs: "*.go" +alwaysApply: true +--- -- CLI code (commands, flags, shell output) -- provider implementations -- runtime logic -- storage implementations -- product orchestration -- anything that belongs in a single consuming repo +When reviewing Go code for security: -If a type is only used inside one repo, it should stay in that repo. +1. Check for SQL injection patterns +2. Verify error handling doesn't expose sensitive data +3. Confirm secrets are not hardcoded +4. Validate input sanitization +``` -## Development Guidelines +## 4. Hooks -### Build & Test +Hooks allow custom commands to run at specific lifecycle points: +- `beforeReview` — runs before code review starts +- `afterReview` — runs after code review completes +- `sessionStart` — runs at session initialization +- `sessionEnd` — runs at session teardown ```bash -make test # Run unit tests (no race detector) -make test-race # Run unit tests with race detector -make lint # Run golangci-lint -make boundaries # Enforce zero hawk-eco imports -make ci # Full CI suite (tidy, fmt, vet, boundaries, lint, test-race, security) +hawk-eco hook add beforeReview --command "lint-check" +hawk-eco hook remove beforeReview +hawk-eco hook list ``` -### Go Conventions +## 5. MCP integration + +MCP (Model Context Protocol) servers can expose tools to hawk-eco: + +```bash +hawk-eco mcp add --name server --url http://localhost:8080 +hawk-eco mcp remove server +hawk-eco mcp list +``` -- Standard Go project layout: `cmd/` for entry points, `internal/` for private -- Tests live alongside source files (`foo.go` → `foo_test.go`) -- Package-level tests use `package _test` to avoid importing internal - packages when testing only public API surface -- Use table-driven tests where practical -- Errors are values — wrap with `fmt.Errorf("context: %w", err)` -- No global mutable state; prefer dependency injection +## 6. Plugins -### Commit Conventions +Plugins extend hawk-eco with custom tools and capabilities: -Use [Conventional Commits](https://www.conventionalcommits.org/): +```bash +hawk-eco plugin add --name my-plugin --path ./my-plugin +hawk-eco plugin remove my-plugin +hawk-eco plugin list ``` -feat: add review result contracts -fix: handle nil findings in FilterBySeverity -refactor: extract severity parsing into shared helper + +## 7. Verification + +hawk-eco includes a self-verification system to validate local changes before contributing: + +```bash +hawk-eco verify +hawk-eco verify --fix ``` -## Package Map - -| Package | Contents | Owners | -|---------|----------|--------| -| `types/` | Severity levels, findings, shared result vocabulary | `@GrayCodeAI/llm-team` | -| `tools/` | Provider-neutral tool call and tool result contracts | `@GrayCodeAI/llm-team` | -| `events/` | Normalized tool and trace event contracts | `@GrayCodeAI/llm-team` | -| `policy/` | Risk, permission verdict, guardian decision, approval request contracts | `@GrayCodeAI/llm-team` | -| `review/` | Neutral review findings, comments, stats, and result contracts | `@GrayCodeAI/llm-team` | -| `verify/` | Neutral verification findings, stats, and report contracts | `@GrayCodeAI/llm-team` | -| `sessions/` | Cross-repo agent session state types | `@GrayCodeAI/llm-team` | - -## Package Guidelines - -Each contract package follows these conventions: - -- **Pure data types:** structs, enums, constructors, and methods on those types -- **No external dependencies:** only stdlib imports -- **No I/O:** no file reads, HTTP calls, or database access -- **JSON-serializable:** all public structs should serialize cleanly via - `encoding/json` (no `map[struct]` keys, no unexported fields without tags) -- **Nil-safety:** pointer receivers for nil-safe methods; document expected - behavior for nil receivers -- **Test file naming:** `*_test.go` alongside source files -- **Package-level tests:** use `package _test` when testing only the - public API surface of a package - -## Adding a New Contract Package - -1. Create a new directory `/` at the repo root -2. Define types, enums, and constructors in `.go` files -3. Add tests in `*_test.go` files (using `package _test`) -4. Do not add any imports from the hawk ecosystem — only stdlib -5. Add the package to `CODEOWNERS` under the `@GrayCodeAI/llm-team` entry -6. Add any necessary types to the package map in the README -7. Add package-level docs ( exported type descriptions) - -## Testing Patterns - -- **Table-driven tests** with `t.Run(name, func(t *testing.T){...})` for all multi-case tests -- **`t.Parallel()`** on all tests that don't share mutable state -- **Package-level API tests** use `package _test` to test only public surface without importing internal packages -- **No mocks framework** — use concrete types and test doubles -- **JSON round-trip tests** for serializable structs (marshal → unmarshal → compare fields) - -## Common Pitfalls - -- Do not import any hawk-eco package in this repo — only the Go standard library -- Do not put runtime logic, CLI code, or product orchestration here -- If a type is only used inside one repo, it should stay in that repo -- Keep changes additive; avoid renaming or restructuring existing types -- Do not add non-stdlib dependencies — if you need something, put it in the - consuming engine instead -- `go.mod` has no `require` blocks (stdlib only); never add module dependencies - -## File Organization Notes - -| File | Purpose | -|------|---------| -| `types/` | Severity levels, findings, result vocabulary | -| `tools/` | Tool call/result contracts | -| `events/` | Tool and trace event contracts | -| `policy/` | Risk and permission verdict contracts | -| `review/` | Review result contracts | -| `verify/` | Verification report contracts | -| `sessions/` | Agent session state contracts | -| `scripts/check-ecosystem-boundaries.sh` | CI guard against hawk-eco imports | -| `.github/workflows/ci.yml` | CI pipeline | -| `.github/workflows/release.yml` | GitHub Release on `v*` tags | -| `Makefile` | Local dev tasks | -| `lefthook.yml` | Pre-commit hooks | -| `AGENTS.md` | This file | -| `README.md` | Package map, scope, governance rules | -| `CHANGELOG.md` | Keep a Changelog format | -| `CODEOWNERS` | Code ownership | -| `VERSION` | Canonical version | +## Development + +```bash +make lint +hawk-eco verify +``` diff --git a/version.go b/version.go new file mode 100644 index 0000000..a950ed1 --- /dev/null +++ b/version.go @@ -0,0 +1,15 @@ +// Package contracts provides cross-repo type contracts for hawk-eco. +// +// The Version variable is sourced from the VERSION file at the repo root. +package contracts + +import ( + _ "embed" + "strings" +) + +//go:embed VERSION +var versionFile string + +// Version of the hawk-core-contracts library. Single source of truth: VERSION file. +var Version = strings.TrimSpace(versionFile) From d6806a2f19e378a74d72c9a9a055433406da0bbe Mon Sep 17 00:00:00 2001 From: Lakshman Patel Date: Wed, 8 Jul 2026 05:12:33 +0530 Subject: [PATCH 4/4] Policy and session contract updates --- Makefile | 2 +- policy/policy.go | 19 +++++-------------- sessions/sessions.go | 8 ++++---- 3 files changed, 10 insertions(+), 19 deletions(-) diff --git a/Makefile b/Makefile index 1afb25c..0ca34c5 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,7 @@ NAME := hawk-core-contracts # --------------------------------------------------------------------------- # Versioning — sourced from VERSION file; falls back to git describe. # --------------------------------------------------------------------------- -VERSION ?= $(shell cat VERSION 2>/dev/null | head -n1 | tr -d '[:space:]' || git describe --tags --always --dirty 2>/dev/null || echo "dev") +VERSION ?= $(shell v=$$(cat VERSION 2>/dev/null | head -n1 | tr -d '[:space:]'); if [ -n "$$v" ]; then echo "$$v"; else git describe --tags --always --dirty 2>/dev/null || echo "dev"; fi) COMMIT := $(shell git rev-parse --short HEAD 2>/dev/null || echo "none") DATE := $(shell date -u '+%Y-%m-%dT%H:%M:%SZ') diff --git a/policy/policy.go b/policy/policy.go index e93349a..ce0c39c 100644 --- a/policy/policy.go +++ b/policy/policy.go @@ -1,6 +1,9 @@ package policy -import "fmt" +import ( + "fmt" + "strings" +) // Risk is the severity of a permission or policy verdict. type Risk int @@ -30,7 +33,7 @@ func (r Risk) String() string { // ParseRisk parses a risk name (case-insensitive) into a Risk value. func ParseRisk(s string) (Risk, error) { - switch lower(s) { + switch strings.ToLower(strings.TrimSpace(s)) { case "low": return RiskLow, nil case "medium", "med", "moderate": @@ -122,15 +125,3 @@ type PermissionRequest struct { ToolID string `json:"tool_id,omitempty"` Summary string `json:"summary,omitempty"` } - -func lower(s string) string { - b := make([]byte, len(s)) - for i := 0; i < len(s); i++ { - c := s[i] - if c >= 'A' && c <= 'Z' { - c += 'a' - 'A' - } - b[i] = c - } - return string(b) -} diff --git a/sessions/sessions.go b/sessions/sessions.go index 2ae6dd1..31b2b22 100644 --- a/sessions/sessions.go +++ b/sessions/sessions.go @@ -105,10 +105,10 @@ type PhaseUsage struct { // pipeline phases within a session. It is the single source of truth for // the cost-per-resolution metric exposed by hawk's ResolutionPipeline. type CostAccumulator struct { - SessionID SessionID `json:"session_id"` - ByPhase map[Phase]PhaseUsage `json:"by_phase"` - TotalTokens int `json:"total_tokens"` - TotalCostUSD float64 `json:"total_cost_usd"` + SessionID SessionID `json:"session_id"` + ByPhase map[Phase]PhaseUsage `json:"by_phase"` + TotalTokens int `json:"total_tokens"` + TotalCostUSD float64 `json:"total_cost_usd"` } // NewCostAccumulator returns a zero-value CostAccumulator for the given session.