From 1cc255a75f361bc0f35186d46588d188dbda4c9a Mon Sep 17 00:00:00 2001 From: Lakshman Patel Date: Sun, 21 Jun 2026 06:22:42 +0530 Subject: [PATCH 1/7] refactor(types): re-export hawk-core-contracts and enforce ecosystem boundary tok was the original host of the ecosystem's shared types. Now that hawk-core-contracts owns those contracts, tok/types still carried a full duplicate of Severity/Finding (and friends) that nothing imported. Convert tok/types into a deprecated compatibility shim that re-exports github.com/GrayCodeAI/hawk-core-contracts/types via type aliases, mirroring hawk/shared/types. This makes contracts the single source of truth and removes the duplicate definitions while keeping any existing importer compiling. Also wires the ecosystem boundary guard (scripts/check-ecosystem-boundaries.sh) into the Makefile and CI, and aligns the README/ARCHITECTURE docs. - go.mod: depend on hawk-core-contracts via local replace (engine-tier pattern) - types/{severity,finding}.go: alias contracts types, mark deprecated - build, vet, and types tests pass; boundary guard passes --- .github/workflows/ci.yml | 6 + ARCHITECTURE.md | 2 +- Makefile | 7 +- README.md | 8 ++ go.mod | 3 + scripts/check-ecosystem-boundaries.sh | 21 ++++ types/finding.go | 155 ++------------------------ types/severity.go | 75 +++++-------- 8 files changed, 82 insertions(+), 195 deletions(-) create mode 100644 scripts/check-ecosystem-boundaries.sh diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7284c67eb..02efc8517 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -47,6 +47,8 @@ jobs: with: go-version: ${{ env.GO_VERSION }} cache: true + - name: Boundary guard + run: bash ./scripts/check-ecosystem-boundaries.sh - name: gofumpt diff run: | go install mvdan.cc/gofumpt@v0.10.0 @@ -71,6 +73,8 @@ jobs: with: go-version: ${{ env.GO_VERSION }} cache: true + - name: Boundary guard + run: bash ./scripts/check-ecosystem-boundaries.sh - uses: golangci/golangci-lint-action@4afd733a84b1f43292c63897423277bb7f4313a9 # v7.0.0 with: version: v2.1.0 @@ -90,6 +94,8 @@ jobs: with: go-version: ${{ env.GO_VERSION }} cache: true + - name: Boundary guard + run: bash ./scripts/check-ecosystem-boundaries.sh - name: Tidy check run: | go mod tidy diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index ca2cfac40..5852d0552 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -246,7 +246,7 @@ type PipelineContext struct { | `skills/` | 5 Claude-style agent skills (`tok`, `tok-commit`, `tok-compress`, `tok-help`, `tok-review`) | `SKILL.md` per skill | | `benchmarks/` | Benchmark harness (run.sh + results.md template) | `run.sh` | | `evals/` | Prompt-compression eval | `pipeline-bench.sh`, `prompts/en.txt` | -| `types/` | Cross-eco exported types (mirrors hawk's `shared/types/`) | `finding.go`, `severity.go` | +| `types/` | Deprecated compatibility shim that re-exports `hawk-core-contracts/types` (kept for existing importers) | `finding.go`, `severity.go` | --- diff --git a/Makefile b/Makefile index 1292bd73f..203dcddbd 100644 --- a/Makefile +++ b/Makefile @@ -27,9 +27,12 @@ GOVULNCHECK := $(GOBIN_DIR)/govulncheck # --------------------------------------------------------------------------- # Phony declarations (alphabetical). # --------------------------------------------------------------------------- -.PHONY: all bench build ci clean cover cover-new fmt help lint lint-fix \ +.PHONY: all bench boundaries build ci clean cover cover-new fmt help lint lint-fix \ security test test-10x test-new test-race tidy version vet +boundaries: ## Enforce support-repo import boundaries. + bash ./scripts/check-ecosystem-boundaries.sh + # --------------------------------------------------------------------------- # Default target. # --------------------------------------------------------------------------- @@ -99,7 +102,7 @@ tidy: ## Tidy go.mod / go.sum. # --------------------------------------------------------------------------- # Composite gate used by CI and pre-push. # --------------------------------------------------------------------------- -ci: tidy fmt vet lint test-race security ## Run everything CI runs. +ci: tidy fmt vet lint boundaries test-race security ## Run everything CI runs. @echo "All CI checks passed." # --------------------------------------------------------------------------- diff --git a/README.md b/README.md index 5dc549d58..c5b942975 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,14 @@ tok is a **library**, not a CLI. It exposes token-efficiency primitives as a cle It is consumed directly as a Go module, and it powers the `tok` commands inside [Hawk](https://github.com/GrayCodeAI/hawk) (`hawk tok ...`), which imports it as a library. +## Ecosystem Boundaries + +tok is a Hawk support engine. Keep the dependency edge one-way: + +- depend on `hawk-core-contracts` when a stable cross-repo contract is needed +- do not import `hawk/internal/*` +- do not add new imports of `hawk/shared/types`; that path is compatibility-only + --- ## Install diff --git a/go.mod b/go.mod index 0c505ec67..1773fd8d2 100644 --- a/go.mod +++ b/go.mod @@ -2,8 +2,11 @@ module github.com/GrayCodeAI/tok go 1.26.4 +replace github.com/GrayCodeAI/hawk-core-contracts => ../hawk-core-contracts + require ( github.com/BurntSushi/toml v1.6.0 + github.com/GrayCodeAI/hawk-core-contracts v0.0.0 github.com/spf13/viper v1.21.0 github.com/tiktoken-go/tokenizer v0.8.0 golang.org/x/sys v0.45.0 diff --git a/scripts/check-ecosystem-boundaries.sh b/scripts/check-ecosystem-boundaries.sh new file mode 100644 index 000000000..ba7de0bff --- /dev/null +++ b/scripts/check-ecosystem-boundaries.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env bash +set -euo pipefail + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +cd "$ROOT_DIR" + +violations="$( + rg -n 'github\.com/GrayCodeAI/hawk/(internal/|shared/types)' \ + --glob '*.go' \ + . || true +)" + +if [[ -n "${violations}" ]]; then + echo "forbidden Hawk imports found:" + echo "${violations}" + echo + echo "support repos must use hawk-core-contracts or local contracts, not hawk/internal or hawk/shared/types" + exit 1 +fi + +echo "ecosystem boundary guard passed" diff --git a/types/finding.go b/types/finding.go index 3589f1ca7..c1c4968ec 100644 --- a/types/finding.go +++ b/types/finding.go @@ -1,156 +1,23 @@ package types -import ( - "fmt" - "time" -) +import contracts "github.com/GrayCodeAI/hawk-core-contracts/types" +// Deprecated: use github.com/GrayCodeAI/hawk-core-contracts/types.Finding. // Finding represents a unified code-analysis concern sourced from sight, inspect, or manual review. -type Finding struct { - ID string `json:"id"` - Source string `json:"source"` // sight, inspect, manual - Concern string `json:"concern"` // e.g. "sql-injection", "broken-auth" - Severity Severity `json:"severity"` - File string `json:"file,omitempty"` - URL string `json:"url,omitempty"` - Line int `json:"line,omitempty"` - EndLine int `json:"end_line,omitempty"` - Message string `json:"message"` - CWE string `json:"cwe,omitempty"` - Confidence float64 `json:"confidence"` - Fix string `json:"fix,omitempty"` - Reasoning string `json:"reasoning,omitempty"` - Tags []string `json:"tags,omitempty"` - Metadata map[string]string `json:"metadata,omitempty"` - CreatedAt time.Time `json:"created_at"` -} +type Finding = contracts.Finding +// Deprecated: use github.com/GrayCodeAI/hawk-core-contracts/types.FindingSlice. // FindingSlice is a sortable slice of Findings. -// Sort order: severity descending, then confidence descending. -type FindingSlice []Finding - -func (s FindingSlice) Len() int { return len(s) } - -func (s FindingSlice) Less(i, j int) bool { - if s[i].Severity != s[j].Severity { - return s[i].Severity > s[j].Severity // higher severity first - } - return s[i].Confidence > s[j].Confidence // higher confidence first -} - -func (s FindingSlice) Swap(i, j int) { s[i], s[j] = s[j], s[i] } - -// FilterBySource returns findings whose Source matches the given value. -func (s FindingSlice) FilterBySource(source string) FindingSlice { - out := make(FindingSlice, 0, len(s)) - for _, f := range s { - if f.Source == source { - out = append(out, f) - } - } - return out -} - -// FilterBySeverity returns findings whose Severity is at least min. -func (s FindingSlice) FilterBySeverity(min Severity) FindingSlice { - out := make(FindingSlice, 0, len(s)) - for _, f := range s { - if f.Severity.AtLeast(min) { - out = append(out, f) - } - } - return out -} - -// FilterByConfidence returns findings whose Confidence is >= min. -func (s FindingSlice) FilterByConfidence(min float64) FindingSlice { - out := make(FindingSlice, 0, len(s)) - for _, f := range s { - if f.Confidence >= min { - out = append(out, f) - } - } - return out -} - -// ByFile groups findings by their File field. -func (s FindingSlice) ByFile() map[string]FindingSlice { - m := make(map[string]FindingSlice, len(s)) - for _, f := range s { - m[f.File] = append(m[f.File], f) - } - return m -} +type FindingSlice = contracts.FindingSlice +// Deprecated: use github.com/GrayCodeAI/hawk-core-contracts/types.FindingSummary. // FindingSummary provides aggregate counts over a set of findings. -type FindingSummary struct { - Total int `json:"total"` - BySource map[string]int `json:"by_source"` - BySeverity map[string]int `json:"by_severity"` - AvgConfidence float64 `json:"avg_confidence"` -} - -// Summary returns a FindingSummary for the slice. -func (s FindingSlice) Summary() FindingSummary { - bySrc := make(map[string]int) - bySev := make(map[string]int) - var confSum float64 - - for _, f := range s { - bySrc[f.Source]++ - bySev[f.Severity.String()]++ - confSum += f.Confidence - } - - avg := 0.0 - if len(s) > 0 { - avg = confSum / float64(len(s)) - } - - return FindingSummary{ - Total: len(s), - BySource: bySrc, - BySeverity: bySev, - AvgConfidence: avg, - } -} +type FindingSummary = contracts.FindingSummary // FindingFromSight constructs a Finding from a sight (AST/static-analysis) result. -func FindingFromSight( - concern, file string, - line int, - message, cwe string, - sev Severity, - confidence float64, -) Finding { - return Finding{ - ID: fmt.Sprintf("sight:%s:%s:%d", concern, file, line), - Source: "sight", - Concern: concern, - Severity: sev, - File: file, - Line: line, - Message: message, - CWE: cwe, - Confidence: confidence, - CreatedAt: time.Now(), - } -} +// Deprecated: use github.com/GrayCodeAI/hawk-core-contracts/types.FindingFromSight. +var FindingFromSight = contracts.FindingFromSight // FindingFromInspect constructs a Finding from an inspect (linting/analysis) result. -func FindingFromInspect( - concern, url, message string, - sev Severity, - tags []string, -) Finding { - return Finding{ - ID: fmt.Sprintf("inspect:%s:%s", concern, url), - Source: "inspect", - Concern: concern, - Severity: sev, - URL: url, - Message: message, - Tags: tags, - CreatedAt: time.Now(), - } -} +// Deprecated: use github.com/GrayCodeAI/hawk-core-contracts/types.FindingFromInspect. +var FindingFromInspect = contracts.FindingFromInspect diff --git a/types/severity.go b/types/severity.go index 4bb6c6e37..0774d06ad 100644 --- a/types/severity.go +++ b/types/severity.go @@ -1,67 +1,46 @@ -// Package types defines stable, dependency-free shared types for the GrayCodeAI -// ecosystem (sight, inspect, hawk, …). It lives in tok — a pure leaf library that -// depends on nothing — so any module can import these types without depending on -// the hawk umbrella product, which would otherwise create an import cycle. +// Package types is a deprecated compatibility layer for shared GrayCodeAI +// ecosystem types. The canonical definitions now live in +// github.com/GrayCodeAI/hawk-core-contracts/types; this package re-exports them +// so existing tok importers keep compiling during the migration. +// +// Deprecated: import github.com/GrayCodeAI/hawk-core-contracts/types directly. package types -import "strings" +import contracts "github.com/GrayCodeAI/hawk-core-contracts/types" +// Deprecated: use github.com/GrayCodeAI/hawk-core-contracts/types.Severity. // Severity represents the impact level of a finding. -type Severity int +type Severity = contracts.Severity const ( - SeverityInfo Severity = iota - SeverityLow - SeverityMedium - SeverityHigh - SeverityCritical + SeverityInfo = contracts.SeverityInfo + SeverityLow = contracts.SeverityLow + SeverityMedium = contracts.SeverityMedium + SeverityHigh = contracts.SeverityHigh + SeverityCritical = contracts.SeverityCritical ) -var severityNames = [...]string{"info", "low", "medium", "high", "critical"} - -func (s Severity) String() string { - if int(s) < len(severityNames) { - return severityNames[s] - } - return "unknown" -} - // ParseSeverity converts a string to a Severity. -func ParseSeverity(s string) Severity { - switch strings.ToLower(strings.TrimSpace(s)) { - case "critical": - return SeverityCritical - case "high": - return SeverityHigh - case "medium": - return SeverityMedium - case "low": - return SeverityLow - default: - return SeverityInfo - } -} - -// AtLeast returns true if s >= threshold. -func (s Severity) AtLeast(threshold Severity) bool { - return s >= threshold -} +// Deprecated: use github.com/GrayCodeAI/hawk-core-contracts/types.ParseSeverity. +var ParseSeverity = contracts.ParseSeverity +// Deprecated: use github.com/GrayCodeAI/hawk-core-contracts/types.TokenSeverity. // TokenSeverity defines rule severity for compression error patterns. -type TokenSeverity string +type TokenSeverity = contracts.TokenSeverity const ( - TokenSeverityCritical TokenSeverity = "critical" - TokenSeverityHigh TokenSeverity = "high" - TokenSeverityMedium TokenSeverity = "medium" - TokenSeverityLow TokenSeverity = "low" + TokenSeverityCritical = contracts.TokenSeverityCritical + TokenSeverityHigh = contracts.TokenSeverityHigh + TokenSeverityMedium = contracts.TokenSeverityMedium + TokenSeverityLow = contracts.TokenSeverityLow ) +// Deprecated: use github.com/GrayCodeAI/hawk-core-contracts/types.AuditSeverity. // AuditSeverity indicates how dangerous a security audit finding is. -type AuditSeverity string +type AuditSeverity = contracts.AuditSeverity const ( - AuditSeverityCritical AuditSeverity = "CRITICAL" - AuditSeverityWarning AuditSeverity = "WARNING" - AuditSeverityInfo AuditSeverity = "INFO" + AuditSeverityCritical = contracts.AuditSeverityCritical + AuditSeverityWarning = contracts.AuditSeverityWarning + AuditSeverityInfo = contracts.AuditSeverityInfo ) From 48692870de1e6b25f02a55a93421beacdc12ec86 Mon Sep 17 00:00:00 2001 From: Lakshman Patel Date: Sun, 21 Jun 2026 09:47:18 +0530 Subject: [PATCH 2/7] build(contracts): require hawk-core-contracts v0.1.0, drop go.mod replace Match the ecosystem binding convention: depend on the published module version; local-dev resolution lives in a gitignored go.work, not in committed go.mod. - go.mod: require hawk-core-contracts v0.1.0 (was v0.0.0), remove the `replace => ../hawk-core-contracts` --- go.mod | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 1773fd8d2..e2c9ccbe4 100644 --- a/go.mod +++ b/go.mod @@ -2,11 +2,9 @@ module github.com/GrayCodeAI/tok go 1.26.4 -replace github.com/GrayCodeAI/hawk-core-contracts => ../hawk-core-contracts - require ( github.com/BurntSushi/toml v1.6.0 - github.com/GrayCodeAI/hawk-core-contracts v0.0.0 + github.com/GrayCodeAI/hawk-core-contracts v0.1.0 github.com/spf13/viper v1.21.0 github.com/tiktoken-go/tokenizer v0.8.0 golang.org/x/sys v0.45.0 From 5645472f739b5ebab5360890f8c39022fe6bd23f Mon Sep 17 00:00:00 2001 From: Lakshman Patel Date: Sun, 21 Jun 2026 10:03:34 +0530 Subject: [PATCH 3/7] build(contracts): pin hawk-core-contracts v0.1.0 checksums in go.sum Now that hawk-core-contracts v0.1.0 is published, record its module checksums so CI (which has no local go.work override) resolves it from the network. Verified: GOWORK=off go build ./... passes. --- go.sum | 2 ++ 1 file changed, 2 insertions(+) diff --git a/go.sum b/go.sum index 0ad84aa52..22d43752a 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,7 @@ github.com/BurntSushi/toml v1.6.0 h1:dRaEfpa2VI55EwlIW72hMRHdWouJeRF7TPYhI+AUQjk= github.com/BurntSushi/toml v1.6.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= +github.com/GrayCodeAI/hawk-core-contracts v0.1.0 h1:w4Y6jBFzjXJ8zmAtfCWuKtODlHKosn9TStADxHE/LsU= +github.com/GrayCodeAI/hawk-core-contracts v0.1.0/go.mod h1:Oq7h+CGkmI3HFTHBVGaWHQuhvtGt6e8UYz5zwF4cM2Q= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dlclark/regexp2/v2 v2.1.0 h1:jHXRmHRZGbuQzDZjMlCAXOvQb75iv3HyLDzXGj5H1AY= From ea5e5221c8ef3d2022833aba304fe6da5d299812 Mon Sep 17 00:00:00 2001 From: Lakshman Patel Date: Sun, 21 Jun 2026 14:40:22 +0530 Subject: [PATCH 4/7] docs: remove legacy shared types references --- README.md | 2 +- scripts/check-ecosystem-boundaries.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c5b942975..f565e2e9c 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ tok is a Hawk support engine. Keep the dependency edge one-way: - depend on `hawk-core-contracts` when a stable cross-repo contract is needed - do not import `hawk/internal/*` -- do not add new imports of `hawk/shared/types`; that path is compatibility-only +- do not import removed legacy path `hawk/shared/types`; use `hawk-core-contracts/types` --- diff --git a/scripts/check-ecosystem-boundaries.sh b/scripts/check-ecosystem-boundaries.sh index ba7de0bff..04bb18782 100644 --- a/scripts/check-ecosystem-boundaries.sh +++ b/scripts/check-ecosystem-boundaries.sh @@ -14,7 +14,7 @@ if [[ -n "${violations}" ]]; then echo "forbidden Hawk imports found:" echo "${violations}" echo - echo "support repos must use hawk-core-contracts or local contracts, not hawk/internal or hawk/shared/types" + echo "support repos must use hawk-core-contracts or local contracts, not hawk/internal or removed hawk/shared/types" exit 1 fi From 9b3bbdfa2e2e9b0d8a40638c058f10110ad6b456 Mon Sep 17 00:00:00 2001 From: Lakshman Patel Date: Sun, 21 Jun 2026 15:36:03 +0530 Subject: [PATCH 5/7] chore: strip Co-authored-by trailers in lefthook hooks --- lefthook.yml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/lefthook.yml b/lefthook.yml index ba5700d84..7d5bdaf09 100644 --- a/lefthook.yml +++ b/lefthook.yml @@ -110,3 +110,18 @@ commit-msg: echo " full guide: https://www.conventionalcommits.org/" exit 1 fi + + strip-co-authored-by: + run: | + # Strip Co-authored-by: trailers that AI tools (Claude, Cursor, etc.) add. + # This enforces the rule that commits list only the human author. + sed '/^[Cc]o-[Aa]uthored-[Bb]y:/d' "{1}" > "{1}.tmp" && mv "{1}.tmp" "{1}" + +# --------------------------------------------------------------------------- +# prepare-commit-msg — strip AI co-author trailers after tools inject them. +# --------------------------------------------------------------------------- +prepare-commit-msg: + commands: + strip-co-authored-by: + run: | + sed '/^[Cc]o-[Aa]uthored-[Bb]y:/d' "{1}" > "{1}.tmp" && mv "{1}.tmp" "{1}" From 83cfc55199ac759a2d66ec5b952cacb05b6f8102 Mon Sep 17 00:00:00 2001 From: Lakshman Patel Date: Sun, 21 Jun 2026 17:31:19 +0530 Subject: [PATCH 6/7] refactor: remove tok types compatibility shim --- ARCHITECTURE.md | 1 - go.mod | 1 - go.sum | 2 - types/finding.go | 23 ----- types/finding_test.go | 225 ----------------------------------------- types/severity.go | 46 --------- types/severity_test.go | 27 ----- 7 files changed, 325 deletions(-) delete mode 100644 types/finding.go delete mode 100644 types/finding_test.go delete mode 100644 types/severity.go delete mode 100644 types/severity_test.go diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 5852d0552..91d1b7cba 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -246,7 +246,6 @@ type PipelineContext struct { | `skills/` | 5 Claude-style agent skills (`tok`, `tok-commit`, `tok-compress`, `tok-help`, `tok-review`) | `SKILL.md` per skill | | `benchmarks/` | Benchmark harness (run.sh + results.md template) | `run.sh` | | `evals/` | Prompt-compression eval | `pipeline-bench.sh`, `prompts/en.txt` | -| `types/` | Deprecated compatibility shim that re-exports `hawk-core-contracts/types` (kept for existing importers) | `finding.go`, `severity.go` | --- diff --git a/go.mod b/go.mod index e2c9ccbe4..0c505ec67 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,6 @@ go 1.26.4 require ( github.com/BurntSushi/toml v1.6.0 - github.com/GrayCodeAI/hawk-core-contracts v0.1.0 github.com/spf13/viper v1.21.0 github.com/tiktoken-go/tokenizer v0.8.0 golang.org/x/sys v0.45.0 diff --git a/go.sum b/go.sum index 22d43752a..0ad84aa52 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,5 @@ github.com/BurntSushi/toml v1.6.0 h1:dRaEfpa2VI55EwlIW72hMRHdWouJeRF7TPYhI+AUQjk= github.com/BurntSushi/toml v1.6.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= -github.com/GrayCodeAI/hawk-core-contracts v0.1.0 h1:w4Y6jBFzjXJ8zmAtfCWuKtODlHKosn9TStADxHE/LsU= -github.com/GrayCodeAI/hawk-core-contracts v0.1.0/go.mod h1:Oq7h+CGkmI3HFTHBVGaWHQuhvtGt6e8UYz5zwF4cM2Q= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dlclark/regexp2/v2 v2.1.0 h1:jHXRmHRZGbuQzDZjMlCAXOvQb75iv3HyLDzXGj5H1AY= diff --git a/types/finding.go b/types/finding.go deleted file mode 100644 index c1c4968ec..000000000 --- a/types/finding.go +++ /dev/null @@ -1,23 +0,0 @@ -package types - -import contracts "github.com/GrayCodeAI/hawk-core-contracts/types" - -// Deprecated: use github.com/GrayCodeAI/hawk-core-contracts/types.Finding. -// Finding represents a unified code-analysis concern sourced from sight, inspect, or manual review. -type Finding = contracts.Finding - -// Deprecated: use github.com/GrayCodeAI/hawk-core-contracts/types.FindingSlice. -// FindingSlice is a sortable slice of Findings. -type FindingSlice = contracts.FindingSlice - -// Deprecated: use github.com/GrayCodeAI/hawk-core-contracts/types.FindingSummary. -// FindingSummary provides aggregate counts over a set of findings. -type FindingSummary = contracts.FindingSummary - -// FindingFromSight constructs a Finding from a sight (AST/static-analysis) result. -// Deprecated: use github.com/GrayCodeAI/hawk-core-contracts/types.FindingFromSight. -var FindingFromSight = contracts.FindingFromSight - -// FindingFromInspect constructs a Finding from an inspect (linting/analysis) result. -// Deprecated: use github.com/GrayCodeAI/hawk-core-contracts/types.FindingFromInspect. -var FindingFromInspect = contracts.FindingFromInspect diff --git a/types/finding_test.go b/types/finding_test.go deleted file mode 100644 index 1cf05fa6e..000000000 --- a/types/finding_test.go +++ /dev/null @@ -1,225 +0,0 @@ -package types_test - -import ( - "sort" - "testing" - - "github.com/GrayCodeAI/tok/types" -) - -func TestFindingSlice_SortBySeverityThenConfidence(t *testing.T) { - t.Parallel() - findings := types.FindingSlice{ - {ID: "a", Severity: types.SeverityLow, Confidence: 0.9}, - {ID: "b", Severity: types.SeverityCritical, Confidence: 0.7}, - {ID: "c", Severity: types.SeverityCritical, Confidence: 0.95}, - {ID: "d", Severity: types.SeverityMedium, Confidence: 0.8}, - } - sort.Sort(findings) - - if findings[0].ID != "c" { - t.Fatalf("expected first finding to be c (critical, 0.95), got %s", findings[0].ID) - } - if findings[1].ID != "b" { - t.Fatalf("expected second finding to be b (critical, 0.7), got %s", findings[1].ID) - } - if findings[2].ID != "d" { - t.Fatalf("expected third finding to be d (medium), got %s", findings[2].ID) - } - if findings[3].ID != "a" { - t.Fatalf("expected fourth finding to be a (low), got %s", findings[3].ID) - } -} - -func TestFilterBySource(t *testing.T) { - t.Parallel() - findings := types.FindingSlice{ - {ID: "1", Source: "sight"}, - {ID: "2", Source: "inspect"}, - {ID: "3", Source: "sight"}, - {ID: "4", Source: "manual"}, - } - - got := findings.FilterBySource("sight") - if len(got) != 2 { - t.Fatalf("expected 2 sight findings, got %d", len(got)) - } - for _, f := range got { - if f.Source != "sight" { - t.Fatalf("expected source sight, got %s", f.Source) - } - } -} - -func TestFilterBySeverity(t *testing.T) { - t.Parallel() - findings := types.FindingSlice{ - {ID: "1", Severity: types.SeverityInfo}, - {ID: "2", Severity: types.SeverityHigh}, - {ID: "3", Severity: types.SeverityCritical}, - {ID: "4", Severity: types.SeverityLow}, - {ID: "5", Severity: types.SeverityMedium}, - } - - got := findings.FilterBySeverity(types.SeverityHigh) - if len(got) != 2 { - t.Fatalf("expected 2 findings >= high, got %d", len(got)) - } -} - -func TestFilterByConfidence(t *testing.T) { - t.Parallel() - findings := types.FindingSlice{ - {ID: "1", Confidence: 0.9}, - {ID: "2", Confidence: 0.5}, - {ID: "3", Confidence: 0.7}, - {ID: "4", Confidence: 0.3}, - } - - got := findings.FilterByConfidence(0.7) - if len(got) != 2 { - t.Fatalf("expected 2 findings with confidence >= 0.7, got %d", len(got)) - } - for _, f := range got { - if f.Confidence < 0.7 { - t.Fatalf("expected confidence >= 0.7, got %f", f.Confidence) - } - } -} - -func TestByFile(t *testing.T) { - t.Parallel() - findings := types.FindingSlice{ - {ID: "1", File: "a.go"}, - {ID: "2", File: "b.go"}, - {ID: "3", File: "a.go"}, - {ID: "4", File: ""}, - } - - grouped := findings.ByFile() - if len(grouped["a.go"]) != 2 { - t.Fatalf("expected 2 findings in a.go, got %d", len(grouped["a.go"])) - } - if len(grouped["b.go"]) != 1 { - t.Fatalf("expected 1 finding in b.go, got %d", len(grouped["b.go"])) - } - if len(grouped[""]) != 1 { - t.Fatalf("expected 1 finding with empty file, got %d", len(grouped[""])) - } -} - -func TestSummary(t *testing.T) { - t.Parallel() - findings := types.FindingSlice{ - {ID: "1", Source: "sight", Severity: types.SeverityHigh, Confidence: 0.8}, - {ID: "2", Source: "sight", Severity: types.SeverityLow, Confidence: 0.6}, - {ID: "3", Source: "inspect", Severity: types.SeverityHigh, Confidence: 1.0}, - } - - summary := findings.Summary() - if summary.Total != 3 { - t.Fatalf("expected total 3, got %d", summary.Total) - } - if summary.BySource["sight"] != 2 { - t.Fatalf("expected 2 sight findings, got %d", summary.BySource["sight"]) - } - if summary.BySource["inspect"] != 1 { - t.Fatalf("expected 1 inspect finding, got %d", summary.BySource["inspect"]) - } - if summary.BySeverity["high"] != 2 { - t.Fatalf("expected 2 high severity, got %d", summary.BySeverity["high"]) - } - if summary.BySeverity["low"] != 1 { - t.Fatalf("expected 1 low severity, got %d", summary.BySeverity["low"]) - } - // avg confidence = (0.8 + 0.6 + 1.0) / 3 = 0.8 - if summary.AvgConfidence < 0.79 || summary.AvgConfidence > 0.81 { - t.Fatalf("expected avg confidence ~0.8, got %f", summary.AvgConfidence) - } -} - -func TestFindingFromSight(t *testing.T) { - t.Parallel() - f := types.FindingFromSight("sql-injection", "db.go", 42, "unparameterized query", "CWE-89", types.SeverityCritical, 0.95) - - if f.ID != "sight:sql-injection:db.go:42" { - t.Fatalf("unexpected ID: %s", f.ID) - } - if f.Source != "sight" { - t.Fatalf("expected source sight, got %s", f.Source) - } - if f.Concern != "sql-injection" { - t.Fatalf("expected concern sql-injection, got %s", f.Concern) - } - if f.Severity != types.SeverityCritical { - t.Fatalf("expected severity critical, got %v", f.Severity) - } - if f.File != "db.go" { - t.Fatalf("expected file db.go, got %s", f.File) - } - if f.Line != 42 { - t.Fatalf("expected line 42, got %d", f.Line) - } - if f.CWE != "CWE-89" { - t.Fatalf("expected CWE-89, got %s", f.CWE) - } - if f.Confidence != 0.95 { - t.Fatalf("expected confidence 0.95, got %f", f.Confidence) - } - if f.CreatedAt.IsZero() { - t.Fatal("expected CreatedAt to be set") - } -} - -func TestFindingFromInspect(t *testing.T) { - t.Parallel() - tags := []string{"security", "injection"} - f := types.FindingFromInspect("broken-auth", "https://example.com/api", "missing auth header", types.SeverityHigh, tags) - - if f.ID != "inspect:broken-auth:https://example.com/api" { - t.Fatalf("unexpected ID: %s", f.ID) - } - if f.Source != "inspect" { - t.Fatalf("expected source inspect, got %s", f.Source) - } - if f.URL != "https://example.com/api" { - t.Fatalf("expected url, got %s", f.URL) - } - if f.Severity != types.SeverityHigh { - t.Fatalf("expected severity high, got %v", f.Severity) - } - if len(f.Tags) != 2 || f.Tags[0] != "security" { - t.Fatalf("unexpected tags: %v", f.Tags) - } - if f.CreatedAt.IsZero() { - t.Fatal("expected CreatedAt to be set") - } -} - -func TestEmptySliceHandling(t *testing.T) { - t.Parallel() - var empty types.FindingSlice - - if empty.Len() != 0 { - t.Fatalf("expected len 0, got %d", empty.Len()) - } - if len(empty.FilterBySource("x")) != 0 { - t.Fatal("expected empty filter result") - } - if len(empty.FilterBySeverity(types.SeverityCritical)) != 0 { - t.Fatal("expected empty filter result") - } - if len(empty.FilterByConfidence(0.5)) != 0 { - t.Fatal("expected empty filter result") - } - if len(empty.ByFile()) != 0 { - t.Fatal("expected empty ByFile map") - } - summary := empty.Summary() - if summary.Total != 0 { - t.Fatalf("expected total 0, got %d", summary.Total) - } - if summary.AvgConfidence != 0.0 { - t.Fatalf("expected avg confidence 0, got %f", summary.AvgConfidence) - } -} diff --git a/types/severity.go b/types/severity.go deleted file mode 100644 index 0774d06ad..000000000 --- a/types/severity.go +++ /dev/null @@ -1,46 +0,0 @@ -// Package types is a deprecated compatibility layer for shared GrayCodeAI -// ecosystem types. The canonical definitions now live in -// github.com/GrayCodeAI/hawk-core-contracts/types; this package re-exports them -// so existing tok importers keep compiling during the migration. -// -// Deprecated: import github.com/GrayCodeAI/hawk-core-contracts/types directly. -package types - -import contracts "github.com/GrayCodeAI/hawk-core-contracts/types" - -// Deprecated: use github.com/GrayCodeAI/hawk-core-contracts/types.Severity. -// Severity represents the impact level of a finding. -type Severity = contracts.Severity - -const ( - SeverityInfo = contracts.SeverityInfo - SeverityLow = contracts.SeverityLow - SeverityMedium = contracts.SeverityMedium - SeverityHigh = contracts.SeverityHigh - SeverityCritical = contracts.SeverityCritical -) - -// ParseSeverity converts a string to a Severity. -// Deprecated: use github.com/GrayCodeAI/hawk-core-contracts/types.ParseSeverity. -var ParseSeverity = contracts.ParseSeverity - -// Deprecated: use github.com/GrayCodeAI/hawk-core-contracts/types.TokenSeverity. -// TokenSeverity defines rule severity for compression error patterns. -type TokenSeverity = contracts.TokenSeverity - -const ( - TokenSeverityCritical = contracts.TokenSeverityCritical - TokenSeverityHigh = contracts.TokenSeverityHigh - TokenSeverityMedium = contracts.TokenSeverityMedium - TokenSeverityLow = contracts.TokenSeverityLow -) - -// Deprecated: use github.com/GrayCodeAI/hawk-core-contracts/types.AuditSeverity. -// AuditSeverity indicates how dangerous a security audit finding is. -type AuditSeverity = contracts.AuditSeverity - -const ( - AuditSeverityCritical = contracts.AuditSeverityCritical - AuditSeverityWarning = contracts.AuditSeverityWarning - AuditSeverityInfo = contracts.AuditSeverityInfo -) diff --git a/types/severity_test.go b/types/severity_test.go deleted file mode 100644 index f9bac0674..000000000 --- a/types/severity_test.go +++ /dev/null @@ -1,27 +0,0 @@ -package types_test - -import ( - "testing" - - "github.com/GrayCodeAI/tok/types" -) - -func TestParseSeverity_forwarded(t *testing.T) { - t.Parallel() - cases := []struct { - in string - want types.Severity - }{ - {"critical", types.SeverityCritical}, - {"high", types.SeverityHigh}, - {"medium", types.SeverityMedium}, - {"low", types.SeverityLow}, - {"info", types.SeverityInfo}, - {"unknown", types.SeverityInfo}, - } - for _, tc := range cases { - if got := types.ParseSeverity(tc.in); got != tc.want { - t.Fatalf("ParseSeverity(%q) = %v, want %v", tc.in, got, tc.want) - } - } -} From 06d3121dbb2acc6d33ccf72c554e26c556264ec1 Mon Sep 17 00:00:00 2001 From: Lakshman Patel Date: Sun, 21 Jun 2026 18:35:40 +0530 Subject: [PATCH 7/7] fix(boundary): fall back to grep when rg is unavailable Co-Authored-By: Claude Sonnet 4.6 --- scripts/check-ecosystem-boundaries.sh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/scripts/check-ecosystem-boundaries.sh b/scripts/check-ecosystem-boundaries.sh index 04bb18782..57f81ba4d 100644 --- a/scripts/check-ecosystem-boundaries.sh +++ b/scripts/check-ecosystem-boundaries.sh @@ -4,11 +4,11 @@ set -euo pipefail ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" cd "$ROOT_DIR" -violations="$( - rg -n 'github\.com/GrayCodeAI/hawk/(internal/|shared/types)' \ - --glob '*.go' \ - . || true -)" +if command -v rg >/dev/null 2>&1; then + violations="$(rg -n 'github\.com/GrayCodeAI/hawk/(internal/|shared/types)' --glob '*.go' . || true)" +else + violations="$(grep -rn --include='*.go' -E 'github\.com/GrayCodeAI/hawk/(internal/|shared/types)' . || true)" +fi if [[ -n "${violations}" ]]; then echo "forbidden Hawk imports found:"