diff --git a/.planning/ROADMAP.md b/.planning/ROADMAP.md
index eb0ddfc..1bd20d9 100644
--- a/.planning/ROADMAP.md
+++ b/.planning/ROADMAP.md
@@ -61,7 +61,14 @@ Plans:
2. `keyhunter scan` correctly identifies keys from all 14 Tier 2 inference platform providers (Groq gsk_, Replicate r8_, Fireworks fw_, Perplexity pplx-, etc.)
3. Each provider YAML includes a `keywords` list that enables Aho-Corasick pre-filtering to skip files with no matching context
4. `keyhunter providers stats` shows 26 providers loaded with pattern and keyword counts
-**Plans**: TBD
+**Plans**: 5 plans
+
+Plans:
+- [ ] 02-01-PLAN.md — Tier 1 high-confidence prefixed providers (OpenAI upgrade, Anthropic upgrade, Google AI, Vertex AI, AWS Bedrock, xAI)
+- [ ] 02-02-PLAN.md — Tier 1 keyword-anchored providers (Azure OpenAI, Meta AI, Cohere, Mistral, Inflection, AI21)
+- [ ] 02-03-PLAN.md — Tier 2 inference platforms batch 1 (Groq, Replicate, Anyscale, Together, Fireworks, Baseten, DeepInfra)
+- [ ] 02-04-PLAN.md — Tier 2 inference platforms batch 2 (Lepton, Modal, Cerebrium, Novita, SambaNova, OctoAI, Friendli)
+- [ ] 02-05-PLAN.md — Registry guardrail test: assert 12 Tier 1 + 14 Tier 2 + regex compilation
### Phase 3: Tier 3-9 Providers
**Goal**: All 108+ LLM provider definitions exist — specialized models, Chinese/regional providers, infrastructure gateways, emerging tools, code assistants, self-hosted runtimes, and enterprise platforms
diff --git a/.planning/phases/02-tier-1-2-providers/02-01-PLAN.md b/.planning/phases/02-tier-1-2-providers/02-01-PLAN.md
new file mode 100644
index 0000000..96069c4
--- /dev/null
+++ b/.planning/phases/02-tier-1-2-providers/02-01-PLAN.md
@@ -0,0 +1,341 @@
+---
+phase: 02-tier-1-2-providers
+plan: 01
+type: execute
+wave: 1
+depends_on: []
+files_modified:
+ - providers/openai.yaml
+ - providers/anthropic.yaml
+ - providers/google-ai.yaml
+ - providers/vertex-ai.yaml
+ - providers/aws-bedrock.yaml
+ - providers/xai.yaml
+ - pkg/providers/definitions/openai.yaml
+ - pkg/providers/definitions/anthropic.yaml
+ - pkg/providers/definitions/google-ai.yaml
+ - pkg/providers/definitions/vertex-ai.yaml
+ - pkg/providers/definitions/aws-bedrock.yaml
+ - pkg/providers/definitions/xai.yaml
+autonomous: true
+requirements: [PROV-01]
+must_haves:
+ truths:
+ - "Registry loads 6 high-confidence Tier 1 providers with valid schemas"
+ - "All regex patterns compile under Go RE2"
+ - "Each provider YAML exists in BOTH providers/ and pkg/providers/definitions/"
+ artifacts:
+ - path: "providers/google-ai.yaml"
+ provides: "Google AI (Gemini) AIzaSy pattern"
+ contains: "AIzaSy"
+ - path: "providers/xai.yaml"
+ provides: "xAI Grok xai- pattern"
+ contains: "xai-"
+ - path: "providers/aws-bedrock.yaml"
+ provides: "AWS Bedrock ABSK pattern"
+ contains: "ABSK"
+ - path: "pkg/providers/definitions/google-ai.yaml"
+ provides: "Embedded Google AI definition"
+ contains: "AIzaSy"
+ key_links:
+ - from: "pkg/providers/definitions/*.yaml"
+ to: "pkg/providers/loader.go"
+ via: "go:embed definitions/*.yaml"
+ pattern: "go:embed"
+---
+
+
+Create or upgrade the 6 high-confidence Tier 1 LLM provider YAML definitions with distinctive key prefixes: OpenAI (upgrade), Anthropic (upgrade), Google AI (Gemini), Google Vertex AI, AWS Bedrock, xAI (Grok).
+
+Purpose: These providers have well-documented, distinctive key prefixes (sk-proj-, sk-ant-api03-, AIzaSy, ABSK, xai-) — they anchor the detection engine with HIGH confidence patterns validated by TruffleHog/gitleaks.
+
+Output: 12 YAML files (6 provider definitions x 2 locations).
+
+Addresses PROV-01 requirement.
+
+
+
+@$HOME/.claude/get-shit-done/workflows/execute-plan.md
+@$HOME/.claude/get-shit-done/templates/summary.md
+
+
+
+@.planning/PROJECT.md
+@.planning/ROADMAP.md
+@.planning/STATE.md
+@.planning/phases/02-tier-1-2-providers/02-RESEARCH.md
+@pkg/providers/schema.go
+@providers/openai.yaml
+@providers/anthropic.yaml
+
+
+The Provider YAML schema (from pkg/providers/schema.go):
+
+```go
+type Provider struct {
+ FormatVersion int `yaml:"format_version"` // must be >= 1
+ Name string `yaml:"name"`
+ DisplayName string `yaml:"display_name"`
+ Tier int `yaml:"tier"`
+ LastVerified string `yaml:"last_verified"` // required, non-empty
+ Keywords []string `yaml:"keywords"`
+ Patterns []Pattern `yaml:"patterns"`
+ Verify VerifySpec `yaml:"verify"`
+}
+type Pattern struct {
+ Regex string `yaml:"regex"`
+ EntropyMin float64 `yaml:"entropy_min"`
+ Confidence string `yaml:"confidence"` // "high" | "medium" | "low"
+}
+type VerifySpec struct {
+ Method string
+ URL string
+ Headers map[string]string
+ ValidStatus []int
+ InvalidStatus []int
+}
+```
+
+Note: schema has NO `category` field. Do not include category in YAML.
+Loader uses `go:embed definitions/*.yaml` — files must be in `pkg/providers/definitions/`.
+
+
+
+
+
+
+ Task 1: Upgrade OpenAI and Anthropic YAMLs
+ providers/openai.yaml, providers/anthropic.yaml, pkg/providers/definitions/openai.yaml, pkg/providers/definitions/anthropic.yaml
+
+ - providers/openai.yaml (current baseline)
+ - providers/anthropic.yaml (current baseline)
+ - pkg/providers/schema.go (validation rules)
+ - .planning/phases/02-tier-1-2-providers/02-RESEARCH.md sections "1. OpenAI", "2. Anthropic"
+
+
+Overwrite providers/openai.yaml with:
+
+```yaml
+format_version: 1
+name: openai
+display_name: OpenAI
+tier: 1
+last_verified: "2026-04-05"
+keywords:
+ - "sk-proj-"
+ - "sk-svcacct-"
+ - "sk-none-"
+ - "openai"
+ - "t3blbkfj"
+patterns:
+ - regex: 'sk-proj-[A-Za-z0-9_\-]{48,}'
+ entropy_min: 3.5
+ confidence: high
+ - regex: 'sk-svcacct-[A-Za-z0-9_\-]{48,}'
+ entropy_min: 3.5
+ confidence: high
+ - regex: 'sk-[A-Za-z0-9]{20,}T3BlbkFJ[A-Za-z0-9_\-]{20,}'
+ entropy_min: 3.5
+ confidence: high
+verify:
+ method: GET
+ url: https://api.openai.com/v1/models
+ headers:
+ Authorization: "Bearer {KEY}"
+ valid_status: [200]
+ invalid_status: [401, 403]
+```
+
+Overwrite providers/anthropic.yaml with:
+
+```yaml
+format_version: 1
+name: anthropic
+display_name: Anthropic
+tier: 1
+last_verified: "2026-04-05"
+keywords:
+ - "sk-ant-api03-"
+ - "sk-ant-admin01-"
+ - "anthropic"
+patterns:
+ - regex: 'sk-ant-api03-[A-Za-z0-9_\-]{93}AA'
+ entropy_min: 3.5
+ confidence: high
+ - regex: 'sk-ant-admin01-[A-Za-z0-9_\-]{93}AA'
+ entropy_min: 3.5
+ confidence: high
+verify:
+ method: GET
+ url: https://api.anthropic.com/v1/models
+ headers:
+ x-api-key: "{KEY}"
+ anthropic-version: "2023-06-01"
+ valid_status: [200]
+ invalid_status: [401, 403]
+```
+
+Copy both files VERBATIM to pkg/providers/definitions/openai.yaml and pkg/providers/definitions/anthropic.yaml (dual-location sync required — Go embed only reads pkg/providers/definitions/).
+
+
+ cd /home/salva/Documents/apikey && diff providers/openai.yaml pkg/providers/definitions/openai.yaml && diff providers/anthropic.yaml pkg/providers/definitions/anthropic.yaml && go test ./pkg/providers/... -run TestRegistry -count=1
+
+
+ - `grep -q 'sk-svcacct-' providers/openai.yaml` exits 0
+ - `grep -q 'T3BlbkFJ' providers/openai.yaml` exits 0
+ - `grep -q 'AA$\|AA'"'" providers/anthropic.yaml | grep -q api03` (AA suffix present)
+ - `grep -q 'sk-ant-admin01-' providers/anthropic.yaml` exits 0
+ - `diff providers/openai.yaml pkg/providers/definitions/openai.yaml` returns no diff
+ - `diff providers/anthropic.yaml pkg/providers/definitions/anthropic.yaml` returns no diff
+ - `go test ./pkg/providers/... -count=1` passes
+
+ OpenAI YAML has 3 patterns (sk-proj-, sk-svcacct-, legacy T3BlbkFJ). Anthropic YAML has 2 patterns (api03, admin01) with AA suffix. Both files dual-located and registry loads cleanly.
+
+
+
+ Task 2: Create Google AI, Vertex AI, AWS Bedrock, xAI YAMLs
+ providers/google-ai.yaml, providers/vertex-ai.yaml, providers/aws-bedrock.yaml, providers/xai.yaml, pkg/providers/definitions/google-ai.yaml, pkg/providers/definitions/vertex-ai.yaml, pkg/providers/definitions/aws-bedrock.yaml, pkg/providers/definitions/xai.yaml
+
+ - pkg/providers/schema.go (validation rules)
+ - providers/openai.yaml (template style after Task 1)
+ - .planning/phases/02-tier-1-2-providers/02-RESEARCH.md sections "3. Google AI", "4. Google Vertex AI", "5. AWS Bedrock", "8. xAI"
+
+
+Create providers/google-ai.yaml:
+
+```yaml
+format_version: 1
+name: google-ai
+display_name: Google AI (Gemini)
+tier: 1
+last_verified: "2026-04-05"
+keywords:
+ - "AIzaSy"
+ - "gemini"
+ - "google_api"
+ - "generativelanguage"
+patterns:
+ - regex: 'AIzaSy[A-Za-z0-9_\-]{33}'
+ entropy_min: 3.5
+ confidence: high
+verify:
+ method: GET
+ url: https://generativelanguage.googleapis.com/v1/models?key={KEY}
+ headers: {}
+ valid_status: [200]
+ invalid_status: [400, 401, 403]
+```
+
+Create providers/vertex-ai.yaml:
+
+```yaml
+format_version: 1
+name: vertex-ai
+display_name: Google Vertex AI
+tier: 1
+last_verified: "2026-04-05"
+keywords:
+ - "vertex"
+ - "vertex_ai"
+ - "google_cloud"
+ - "aiplatform.googleapis.com"
+ - "AIzaSy"
+patterns:
+ - regex: 'AIzaSy[A-Za-z0-9_\-]{33}'
+ entropy_min: 3.5
+ confidence: medium
+verify:
+ method: GET
+ url: https://aiplatform.googleapis.com/v1/projects
+ headers:
+ Authorization: "Bearer {KEY}"
+ valid_status: [200]
+ invalid_status: [401, 403]
+```
+
+Create providers/aws-bedrock.yaml:
+
+```yaml
+format_version: 1
+name: aws-bedrock
+display_name: AWS Bedrock
+tier: 1
+last_verified: "2026-04-05"
+keywords:
+ - "ABSK"
+ - "bedrock"
+ - "aws_bedrock"
+ - "bedrock-runtime"
+ - "AKIA"
+patterns:
+ - regex: 'ABSK[A-Za-z0-9+/]{109,269}={0,2}'
+ entropy_min: 4.0
+ confidence: high
+ - regex: 'AKIA[0-9A-Z]{16}'
+ entropy_min: 3.0
+ confidence: medium
+verify:
+ method: GET
+ url: ""
+ headers: {}
+ valid_status: []
+ invalid_status: []
+```
+
+Create providers/xai.yaml:
+
+```yaml
+format_version: 1
+name: xai
+display_name: xAI (Grok)
+tier: 1
+last_verified: "2026-04-05"
+keywords:
+ - "xai-"
+ - "xai"
+ - "grok"
+patterns:
+ - regex: 'xai-[0-9a-zA-Z_]{80}'
+ entropy_min: 3.5
+ confidence: high
+verify:
+ method: GET
+ url: https://api.x.ai/v1/api-key
+ headers:
+ Authorization: "Bearer {KEY}"
+ valid_status: [200]
+ invalid_status: [401, 403]
+```
+
+Copy ALL FOUR files VERBATIM to pkg/providers/definitions/ with same names. The loader uses `go:embed definitions/*.yaml` — files in providers/ are user-visible only.
+
+
+ cd /home/salva/Documents/apikey && for f in google-ai vertex-ai aws-bedrock xai; do diff providers/$f.yaml pkg/providers/definitions/$f.yaml || exit 1; done && go test ./pkg/providers/... -count=1
+
+
+ - All 8 files exist: `test -f providers/google-ai.yaml -a -f providers/vertex-ai.yaml -a -f providers/aws-bedrock.yaml -a -f providers/xai.yaml -a -f pkg/providers/definitions/google-ai.yaml -a -f pkg/providers/definitions/vertex-ai.yaml -a -f pkg/providers/definitions/aws-bedrock.yaml -a -f pkg/providers/definitions/xai.yaml`
+ - `grep -q 'AIzaSy\[A-Za-z0-9_' providers/google-ai.yaml`
+ - `grep -q 'ABSK\[A-Za-z0-9' providers/aws-bedrock.yaml`
+ - `grep -q 'xai-\[0-9a-zA-Z_' providers/xai.yaml`
+ - `diff providers/xai.yaml pkg/providers/definitions/xai.yaml` returns no diff
+ - `go test ./pkg/providers/... -count=1` passes (registry loads all new YAMLs without schema errors)
+
+ 4 new providers created and dual-located. Registry loads 9 providers total (3 pre-existing + 6 upgraded/new). All regex patterns compile under RE2.
+
+
+
+
+
+Run `go test ./pkg/providers/... -count=1` and confirm registry loads at least 9 providers (existing 3 + 6 from this plan, noting openai/anthropic were already counted). Count provider files in both directories — they must match.
+
+
+
+- 6 Tier 1 high-confidence providers defined (2 upgraded, 4 new)
+- Every YAML dual-located
+- All regex patterns are RE2-compatible and compile
+- go test ./pkg/providers/... passes
+
+
+
diff --git a/.planning/phases/02-tier-1-2-providers/02-02-PLAN.md b/.planning/phases/02-tier-1-2-providers/02-02-PLAN.md
new file mode 100644
index 0000000..30e1010
--- /dev/null
+++ b/.planning/phases/02-tier-1-2-providers/02-02-PLAN.md
@@ -0,0 +1,297 @@
+---
+phase: 02-tier-1-2-providers
+plan: 02
+type: execute
+wave: 1
+depends_on: []
+files_modified:
+ - providers/azure-openai.yaml
+ - providers/meta-ai.yaml
+ - providers/cohere.yaml
+ - providers/mistral.yaml
+ - providers/inflection.yaml
+ - providers/ai21.yaml
+ - pkg/providers/definitions/azure-openai.yaml
+ - pkg/providers/definitions/meta-ai.yaml
+ - pkg/providers/definitions/cohere.yaml
+ - pkg/providers/definitions/mistral.yaml
+ - pkg/providers/definitions/inflection.yaml
+ - pkg/providers/definitions/ai21.yaml
+autonomous: true
+requirements: [PROV-01]
+must_haves:
+ truths:
+ - "Registry loads 6 medium/low-confidence Tier 1 providers"
+ - "Each provider relies on keyword-context matching (weak prefix)"
+ - "All regex patterns compile under Go RE2"
+ artifacts:
+ - path: "providers/azure-openai.yaml"
+ provides: "Azure OpenAI 32-hex pattern"
+ contains: "azure"
+ - path: "providers/cohere.yaml"
+ provides: "Cohere 40-char token pattern"
+ contains: "cohere"
+ - path: "providers/mistral.yaml"
+ provides: "Mistral AI keyword-anchored pattern"
+ contains: "mistral"
+ key_links:
+ - from: "provider keywords[]"
+ to: "Registry Aho-Corasick automaton"
+ via: "NewRegistry()"
+ pattern: "keywords"
+---
+
+
+Create the 6 medium/low-confidence Tier 1 LLM provider YAML definitions: Azure OpenAI, Meta AI (Llama), Cohere, Mistral AI, Inflection AI, AI21 Labs. These providers use generic key formats — detection leans on strong keyword lists for Aho-Corasick pre-filtering.
+
+Purpose: Close out Tier 1 coverage (12/12). These providers require careful keyword anchoring since their key formats are opaque tokens.
+
+Output: 12 YAML files (6 providers x 2 locations).
+
+Addresses PROV-01 requirement.
+
+
+
+@$HOME/.claude/get-shit-done/workflows/execute-plan.md
+@$HOME/.claude/get-shit-done/templates/summary.md
+
+
+
+@.planning/ROADMAP.md
+@.planning/phases/02-tier-1-2-providers/02-RESEARCH.md
+@pkg/providers/schema.go
+@providers/openai.yaml
+
+
+Schema: see pkg/providers/schema.go. NO `category` field. `confidence` must be one of: high, medium, low.
+Files must be dual-located (providers/ AND pkg/providers/definitions/).
+Go RE2 regex only — no lookahead, lookbehind, or backreferences.
+
+
+
+
+
+
+ Task 1: Azure OpenAI, Meta AI, Cohere YAMLs
+ providers/azure-openai.yaml, providers/meta-ai.yaml, providers/cohere.yaml, pkg/providers/definitions/azure-openai.yaml, pkg/providers/definitions/meta-ai.yaml, pkg/providers/definitions/cohere.yaml
+
+ - pkg/providers/schema.go
+ - .planning/phases/02-tier-1-2-providers/02-RESEARCH.md sections "6. Azure OpenAI", "7. Meta AI", "9. Cohere"
+
+
+Create providers/azure-openai.yaml:
+
+```yaml
+format_version: 1
+name: azure-openai
+display_name: Azure OpenAI
+tier: 1
+last_verified: "2026-04-05"
+keywords:
+ - "azure"
+ - "openai.azure.com"
+ - "azure_openai"
+ - "cognitiveservices"
+ - "AZURE_OPENAI_API_KEY"
+ - "AZURE_OPENAI_KEY"
+patterns:
+ - regex: '[a-f0-9]{32}'
+ entropy_min: 3.5
+ confidence: low
+verify:
+ method: GET
+ url: ""
+ headers: {}
+ valid_status: []
+ invalid_status: []
+```
+
+Create providers/meta-ai.yaml:
+
+```yaml
+format_version: 1
+name: meta-ai
+display_name: Meta AI (Llama API)
+tier: 1
+last_verified: "2026-04-05"
+keywords:
+ - "meta_llama"
+ - "llama_api"
+ - "META_LLAMA_API_KEY"
+ - "api.llama.com"
+patterns:
+ - regex: 'LLM\|[A-Za-z0-9_\-]{30,}'
+ entropy_min: 3.5
+ confidence: low
+verify:
+ method: GET
+ url: https://api.llama.com/v1/models
+ headers:
+ Authorization: "Bearer {KEY}"
+ valid_status: [200]
+ invalid_status: [401, 403]
+```
+
+Create providers/cohere.yaml:
+
+```yaml
+format_version: 1
+name: cohere
+display_name: Cohere
+tier: 1
+last_verified: "2026-04-05"
+keywords:
+ - "cohere"
+ - "CO_API_KEY"
+ - "COHERE_API_KEY"
+ - "cohere_api"
+ - "api.cohere.ai"
+patterns:
+ - regex: '[a-zA-Z0-9]{40}'
+ entropy_min: 4.0
+ confidence: low
+verify:
+ method: GET
+ url: https://api.cohere.ai/v1/models
+ headers:
+ Authorization: "Bearer {KEY}"
+ valid_status: [200]
+ invalid_status: [401, 403]
+```
+
+Copy all three files VERBATIM to pkg/providers/definitions/ with same names.
+
+
+ cd /home/salva/Documents/apikey && for f in azure-openai meta-ai cohere; do diff providers/$f.yaml pkg/providers/definitions/$f.yaml || exit 1; done && go test ./pkg/providers/... -count=1
+
+
+ - All 6 files exist
+ - `grep -q 'openai.azure.com' providers/azure-openai.yaml`
+ - `grep -q 'CO_API_KEY' providers/cohere.yaml`
+ - `grep -q 'api.llama.com' providers/meta-ai.yaml`
+ - `diff providers/cohere.yaml pkg/providers/definitions/cohere.yaml` returns no diff
+ - `go test ./pkg/providers/... -count=1` passes
+
+ 3 providers dual-located, registry loads them without validation errors.
+
+
+
+ Task 2: Mistral, Inflection, AI21 YAMLs
+ providers/mistral.yaml, providers/inflection.yaml, providers/ai21.yaml, pkg/providers/definitions/mistral.yaml, pkg/providers/definitions/inflection.yaml, pkg/providers/definitions/ai21.yaml
+
+ - pkg/providers/schema.go
+ - .planning/phases/02-tier-1-2-providers/02-RESEARCH.md sections "10. Mistral AI", "11. Inflection AI", "12. AI21 Labs"
+
+
+Create providers/mistral.yaml:
+
+```yaml
+format_version: 1
+name: mistral
+display_name: Mistral AI
+tier: 1
+last_verified: "2026-04-05"
+keywords:
+ - "mistral"
+ - "mistral.ai"
+ - "MISTRAL_API_KEY"
+ - "la_plateforme"
+ - "api.mistral.ai"
+patterns:
+ - regex: '[a-zA-Z0-9]{32}'
+ entropy_min: 4.0
+ confidence: low
+verify:
+ method: GET
+ url: https://api.mistral.ai/v1/models
+ headers:
+ Authorization: "Bearer {KEY}"
+ valid_status: [200]
+ invalid_status: [401, 403]
+```
+
+Create providers/inflection.yaml:
+
+```yaml
+format_version: 1
+name: inflection
+display_name: Inflection AI (Pi)
+tier: 1
+last_verified: "2026-04-05"
+keywords:
+ - "inflection"
+ - "pi_api"
+ - "PI_API_KEY"
+ - "INFLECTION_API_KEY"
+ - "inflection.ai"
+patterns:
+ - regex: '[A-Za-z0-9_\-]{40,}'
+ entropy_min: 4.0
+ confidence: low
+verify:
+ method: GET
+ url: ""
+ headers: {}
+ valid_status: []
+ invalid_status: []
+```
+
+Create providers/ai21.yaml:
+
+```yaml
+format_version: 1
+name: ai21
+display_name: AI21 Labs
+tier: 1
+last_verified: "2026-04-05"
+keywords:
+ - "ai21"
+ - "AI21_API_KEY"
+ - "jamba"
+ - "jurassic"
+ - "api.ai21.com"
+patterns:
+ - regex: '[a-zA-Z0-9]{32,}'
+ entropy_min: 4.0
+ confidence: low
+verify:
+ method: GET
+ url: https://api.ai21.com/studio/v1/models
+ headers:
+ Authorization: "Bearer {KEY}"
+ valid_status: [200]
+ invalid_status: [401, 403]
+```
+
+Copy all three files VERBATIM to pkg/providers/definitions/ with same names.
+
+
+ cd /home/salva/Documents/apikey && for f in mistral inflection ai21; do diff providers/$f.yaml pkg/providers/definitions/$f.yaml || exit 1; done && go test ./pkg/providers/... -count=1
+
+
+ - All 6 files exist
+ - `grep -q 'MISTRAL_API_KEY' providers/mistral.yaml`
+ - `grep -q 'jamba' providers/ai21.yaml`
+ - `grep -q 'PI_API_KEY' providers/inflection.yaml`
+ - `diff providers/mistral.yaml pkg/providers/definitions/mistral.yaml` returns no diff
+ - `go test ./pkg/providers/... -count=1` passes
+
+ 3 providers dual-located. Tier 1 complete at 12/12.
+
+
+
+
+
+Count providers with tier 1 after this plan runs: `grep -l 'tier: 1' providers/*.yaml | wc -l` should equal 12.
+
+
+
+- 6 Tier 1 medium/low-confidence providers created
+- Dual-location sync verified
+- Registry loads them without validation errors (go test passes)
+- Tier 1 total = 12 providers
+
+
+
diff --git a/.planning/phases/02-tier-1-2-providers/02-03-PLAN.md b/.planning/phases/02-tier-1-2-providers/02-03-PLAN.md
new file mode 100644
index 0000000..a8f7b57
--- /dev/null
+++ b/.planning/phases/02-tier-1-2-providers/02-03-PLAN.md
@@ -0,0 +1,324 @@
+---
+phase: 02-tier-1-2-providers
+plan: 03
+type: execute
+wave: 1
+depends_on: []
+files_modified:
+ - providers/groq.yaml
+ - providers/replicate.yaml
+ - providers/anyscale.yaml
+ - providers/together.yaml
+ - providers/fireworks.yaml
+ - providers/baseten.yaml
+ - providers/deepinfra.yaml
+ - pkg/providers/definitions/groq.yaml
+ - pkg/providers/definitions/replicate.yaml
+ - pkg/providers/definitions/anyscale.yaml
+ - pkg/providers/definitions/together.yaml
+ - pkg/providers/definitions/fireworks.yaml
+ - pkg/providers/definitions/baseten.yaml
+ - pkg/providers/definitions/deepinfra.yaml
+autonomous: true
+requirements: [PROV-02]
+must_haves:
+ truths:
+ - "Registry loads 7 Tier 2 inference platform providers"
+ - "Groq, Replicate, Anyscale use distinctive prefix patterns (high confidence)"
+ - "Together, Fireworks, Baseten, DeepInfra use keyword-context matching"
+ artifacts:
+ - path: "providers/groq.yaml"
+ provides: "Groq gsk_ prefix pattern"
+ contains: "gsk_"
+ - path: "providers/replicate.yaml"
+ provides: "Replicate r8_ prefix pattern"
+ contains: "r8_"
+ - path: "providers/anyscale.yaml"
+ provides: "Anyscale esecret_ pattern"
+ contains: "esecret_"
+ key_links:
+ - from: "pkg/providers/definitions/*.yaml"
+ to: "go:embed in loader.go"
+ via: "compile-time embed"
+ pattern: "definitions"
+---
+
+
+Create 7 Tier 2 inference platform provider YAMLs: Groq, Replicate, Anyscale, Together AI, Fireworks AI, Baseten, DeepInfra. Groq/Replicate/Anyscale have verified prefixes (HIGH confidence); the rest rely on keyword context.
+
+Purpose: First half of Tier 2 inference platforms (PROV-02). These are OpenAI-compatible providers hosting open-weight models — high-value detection targets.
+
+Output: 14 YAML files (7 providers x 2 locations).
+
+Addresses PROV-02 requirement.
+
+
+
+@$HOME/.claude/get-shit-done/workflows/execute-plan.md
+@$HOME/.claude/get-shit-done/templates/summary.md
+
+
+
+@.planning/ROADMAP.md
+@.planning/phases/02-tier-1-2-providers/02-RESEARCH.md
+@pkg/providers/schema.go
+
+
+Schema: pkg/providers/schema.go. Dual-location required. RE2 regex only.
+Tier = 2 for all providers in this plan.
+
+
+
+
+
+
+ Task 1: High-confidence prefixed Tier 2 — Groq, Replicate, Anyscale
+ providers/groq.yaml, providers/replicate.yaml, providers/anyscale.yaml, pkg/providers/definitions/groq.yaml, pkg/providers/definitions/replicate.yaml, pkg/providers/definitions/anyscale.yaml
+
+ - pkg/providers/schema.go
+ - .planning/phases/02-tier-1-2-providers/02-RESEARCH.md sections "3. Groq", "4. Replicate", "5. Anyscale"
+
+
+Create providers/groq.yaml:
+
+```yaml
+format_version: 1
+name: groq
+display_name: Groq
+tier: 2
+last_verified: "2026-04-05"
+keywords:
+ - "gsk_"
+ - "groq"
+ - "GROQ_API_KEY"
+ - "api.groq.com"
+patterns:
+ - regex: 'gsk_[a-zA-Z0-9]{52}'
+ entropy_min: 3.5
+ confidence: high
+verify:
+ method: GET
+ url: https://api.groq.com/openai/v1/models
+ headers:
+ Authorization: "Bearer {KEY}"
+ valid_status: [200]
+ invalid_status: [401, 403]
+```
+
+Create providers/replicate.yaml:
+
+```yaml
+format_version: 1
+name: replicate
+display_name: Replicate
+tier: 2
+last_verified: "2026-04-05"
+keywords:
+ - "r8_"
+ - "replicate"
+ - "REPLICATE_API_TOKEN"
+ - "api.replicate.com"
+patterns:
+ - regex: 'r8_[0-9A-Za-z\-_]{37}'
+ entropy_min: 3.5
+ confidence: high
+verify:
+ method: GET
+ url: https://api.replicate.com/v1/predictions
+ headers:
+ Authorization: "Bearer {KEY}"
+ valid_status: [200]
+ invalid_status: [401, 403]
+```
+
+Create providers/anyscale.yaml:
+
+```yaml
+format_version: 1
+name: anyscale
+display_name: Anyscale Endpoints
+tier: 2
+last_verified: "2026-04-05"
+keywords:
+ - "esecret_"
+ - "anyscale"
+ - "ANYSCALE_API_KEY"
+ - "api.endpoints.anyscale.com"
+patterns:
+ - regex: 'esecret_[A-Za-z0-9_\-]{20,}'
+ entropy_min: 3.5
+ confidence: high
+verify:
+ method: GET
+ url: https://api.endpoints.anyscale.com/v1/models
+ headers:
+ Authorization: "Bearer {KEY}"
+ valid_status: [200]
+ invalid_status: [401, 403]
+```
+
+Copy all three to pkg/providers/definitions/ VERBATIM.
+
+
+ cd /home/salva/Documents/apikey && for f in groq replicate anyscale; do diff providers/$f.yaml pkg/providers/definitions/$f.yaml || exit 1; done && go test ./pkg/providers/... -count=1
+
+
+ - `grep -q 'gsk_\[a-zA-Z0-9\]{52}' providers/groq.yaml`
+ - `grep -q 'r8_\[0-9A-Za-z' providers/replicate.yaml`
+ - `grep -q 'esecret_' providers/anyscale.yaml`
+ - All 3 dual-location diffs empty
+ - `go test ./pkg/providers/... -count=1` passes
+
+ 3 high-confidence Tier 2 providers created with verified regex patterns.
+
+
+
+ Task 2: Keyword-anchored Tier 2 — Together, Fireworks, Baseten, DeepInfra
+ providers/together.yaml, providers/fireworks.yaml, providers/baseten.yaml, providers/deepinfra.yaml, pkg/providers/definitions/together.yaml, pkg/providers/definitions/fireworks.yaml, pkg/providers/definitions/baseten.yaml, pkg/providers/definitions/deepinfra.yaml
+
+ - pkg/providers/schema.go
+ - .planning/phases/02-tier-1-2-providers/02-RESEARCH.md sections "1. Together AI", "2. Fireworks AI", "9. Baseten", "6. DeepInfra"
+
+
+Create providers/together.yaml:
+
+```yaml
+format_version: 1
+name: together
+display_name: Together AI
+tier: 2
+last_verified: "2026-04-05"
+keywords:
+ - "together"
+ - "togetherai"
+ - "TOGETHER_API_KEY"
+ - "api.together.xyz"
+ - "api.together.ai"
+patterns:
+ - regex: '[a-f0-9]{64}'
+ entropy_min: 3.5
+ confidence: low
+verify:
+ method: GET
+ url: https://api.together.xyz/v1/models
+ headers:
+ Authorization: "Bearer {KEY}"
+ valid_status: [200]
+ invalid_status: [401, 403]
+```
+
+Create providers/fireworks.yaml:
+
+```yaml
+format_version: 1
+name: fireworks
+display_name: Fireworks AI
+tier: 2
+last_verified: "2026-04-05"
+keywords:
+ - "fireworks"
+ - "fireworks.ai"
+ - "FIREWORKS_API_KEY"
+ - "api.fireworks.ai"
+ - "fw_"
+patterns:
+ - regex: 'fw_[A-Za-z0-9]{20,}'
+ entropy_min: 3.5
+ confidence: medium
+ - regex: '[A-Za-z0-9]{40,}'
+ entropy_min: 4.0
+ confidence: low
+verify:
+ method: GET
+ url: https://api.fireworks.ai/inference/v1/models
+ headers:
+ Authorization: "Bearer {KEY}"
+ valid_status: [200]
+ invalid_status: [401, 403]
+```
+
+Create providers/baseten.yaml:
+
+```yaml
+format_version: 1
+name: baseten
+display_name: Baseten
+tier: 2
+last_verified: "2026-04-05"
+keywords:
+ - "baseten"
+ - "BASETEN_API_KEY"
+ - "api.baseten.co"
+ - "Api-Key"
+patterns:
+ - regex: '[A-Za-z0-9]{40,}'
+ entropy_min: 4.0
+ confidence: low
+verify:
+ method: GET
+ url: https://api.baseten.co/v1/models
+ headers:
+ Authorization: "Api-Key {KEY}"
+ valid_status: [200]
+ invalid_status: [401, 403]
+```
+
+Create providers/deepinfra.yaml:
+
+```yaml
+format_version: 1
+name: deepinfra
+display_name: DeepInfra
+tier: 2
+last_verified: "2026-04-05"
+keywords:
+ - "deepinfra"
+ - "DEEPINFRA_API_KEY"
+ - "deepinfra.com"
+ - "api.deepinfra.com"
+patterns:
+ - regex: '[A-Za-z0-9]{32,}'
+ entropy_min: 4.0
+ confidence: low
+verify:
+ method: GET
+ url: https://api.deepinfra.com/v1/openai/models
+ headers:
+ Authorization: "Bearer {KEY}"
+ valid_status: [200]
+ invalid_status: [401, 403]
+```
+
+Copy all four files VERBATIM to pkg/providers/definitions/.
+
+
+ cd /home/salva/Documents/apikey && for f in together fireworks baseten deepinfra; do diff providers/$f.yaml pkg/providers/definitions/$f.yaml || exit 1; done && go test ./pkg/providers/... -count=1
+
+
+ - All 8 files exist
+ - `grep -q 'api.together' providers/together.yaml`
+ - `grep -q 'fw_' providers/fireworks.yaml`
+ - `grep -q 'Api-Key' providers/baseten.yaml`
+ - `grep -q 'api.deepinfra.com' providers/deepinfra.yaml`
+ - All dual-location diffs empty
+ - `go test ./pkg/providers/... -count=1` passes
+
+ 4 keyword-anchored Tier 2 providers dual-located and loading cleanly.
+
+
+
+
+
+After plan completes: `grep -l 'tier: 2' providers/*.yaml | wc -l` should be at least 7.
+
+
+
+- 7 Tier 2 inference platform providers created
+- 3 high-confidence (Groq/Replicate/Anyscale), 4 keyword-anchored
+- Dual-location verified
+- go test ./pkg/providers/... passes
+
+
+
diff --git a/.planning/phases/02-tier-1-2-providers/02-04-PLAN.md b/.planning/phases/02-tier-1-2-providers/02-04-PLAN.md
new file mode 100644
index 0000000..dbd99ab
--- /dev/null
+++ b/.planning/phases/02-tier-1-2-providers/02-04-PLAN.md
@@ -0,0 +1,328 @@
+---
+phase: 02-tier-1-2-providers
+plan: 04
+type: execute
+wave: 1
+depends_on: []
+files_modified:
+ - providers/lepton.yaml
+ - providers/modal.yaml
+ - providers/cerebrium.yaml
+ - providers/novita.yaml
+ - providers/sambanova.yaml
+ - providers/octoai.yaml
+ - providers/friendli.yaml
+ - pkg/providers/definitions/lepton.yaml
+ - pkg/providers/definitions/modal.yaml
+ - pkg/providers/definitions/cerebrium.yaml
+ - pkg/providers/definitions/novita.yaml
+ - pkg/providers/definitions/sambanova.yaml
+ - pkg/providers/definitions/octoai.yaml
+ - pkg/providers/definitions/friendli.yaml
+autonomous: true
+requirements: [PROV-02]
+must_haves:
+ truths:
+ - "Registry loads final 7 Tier 2 inference platform providers"
+ - "All 14 Tier 2 providers from PROV-02 are defined after this plan"
+ - "Generic-format providers use strong keyword lists for AC pre-filtering"
+ artifacts:
+ - path: "providers/modal.yaml"
+ provides: "Modal token_id/token_secret keyword anchors"
+ contains: "MODAL_TOKEN"
+ - path: "providers/sambanova.yaml"
+ provides: "SambaNova keyword-anchored pattern"
+ contains: "sambanova"
+ - path: "providers/novita.yaml"
+ provides: "NovitaAI keyword-anchored pattern"
+ contains: "novita"
+ key_links:
+ - from: "keywords[]"
+ to: "Aho-Corasick pre-filter"
+ via: "NewRegistry"
+ pattern: "keywords"
+---
+
+
+Create the remaining 7 Tier 2 inference platform provider YAMLs: Lepton AI, Modal, Cerebrium, NovitaAI, SambaNova, OctoAI, Friendli. All are generic-format providers requiring strong keyword lists.
+
+Purpose: Complete PROV-02 (14/14 Tier 2 providers).
+
+Output: 14 YAML files (7 providers x 2 locations).
+
+Addresses PROV-02 requirement.
+
+
+
+@$HOME/.claude/get-shit-done/workflows/execute-plan.md
+@$HOME/.claude/get-shit-done/templates/summary.md
+
+
+
+@.planning/ROADMAP.md
+@.planning/phases/02-tier-1-2-providers/02-RESEARCH.md
+@pkg/providers/schema.go
+
+
+Schema: pkg/providers/schema.go. Dual-location required. Go RE2 regex only.
+All providers in this plan: tier 2, confidence low (no distinctive prefix).
+
+
+
+
+
+
+ Task 1: Lepton, Modal, Cerebrium, Novita YAMLs
+ providers/lepton.yaml, providers/modal.yaml, providers/cerebrium.yaml, providers/novita.yaml, pkg/providers/definitions/lepton.yaml, pkg/providers/definitions/modal.yaml, pkg/providers/definitions/cerebrium.yaml, pkg/providers/definitions/novita.yaml
+
+ - pkg/providers/schema.go
+ - .planning/phases/02-tier-1-2-providers/02-RESEARCH.md sections "7. Lepton", "8. Modal", "10. Cerebrium", "11. NovitaAI"
+
+
+Create providers/lepton.yaml:
+
+```yaml
+format_version: 1
+name: lepton
+display_name: Lepton AI (DGX Cloud Lepton)
+tier: 2
+last_verified: "2026-04-05"
+keywords:
+ - "lepton"
+ - "lepton.ai"
+ - "LEPTON_API_TOKEN"
+ - "dgx-cloud-lepton"
+patterns:
+ - regex: '[A-Za-z0-9]{32,}'
+ entropy_min: 4.0
+ confidence: low
+verify:
+ method: GET
+ url: ""
+ headers: {}
+ valid_status: []
+ invalid_status: []
+```
+
+Create providers/modal.yaml:
+
+```yaml
+format_version: 1
+name: modal
+display_name: Modal
+tier: 2
+last_verified: "2026-04-05"
+keywords:
+ - "modal"
+ - "modal.com"
+ - "MODAL_TOKEN_ID"
+ - "MODAL_TOKEN_SECRET"
+ - "ak-"
+ - "as-"
+patterns:
+ - regex: 'ak-[A-Za-z0-9]{20,}'
+ entropy_min: 3.5
+ confidence: medium
+ - regex: 'as-[A-Za-z0-9]{20,}'
+ entropy_min: 3.5
+ confidence: medium
+verify:
+ method: GET
+ url: ""
+ headers: {}
+ valid_status: []
+ invalid_status: []
+```
+
+Create providers/cerebrium.yaml:
+
+```yaml
+format_version: 1
+name: cerebrium
+display_name: Cerebrium
+tier: 2
+last_verified: "2026-04-05"
+keywords:
+ - "cerebrium"
+ - "cerebrium.ai"
+ - "CEREBRIUM_API_KEY"
+ - "api.cortex.cerebrium.ai"
+patterns:
+ - regex: '[A-Za-z0-9]{32,}'
+ entropy_min: 4.0
+ confidence: low
+verify:
+ method: GET
+ url: ""
+ headers: {}
+ valid_status: []
+ invalid_status: []
+```
+
+Create providers/novita.yaml:
+
+```yaml
+format_version: 1
+name: novita
+display_name: NovitaAI
+tier: 2
+last_verified: "2026-04-05"
+keywords:
+ - "novita"
+ - "novita.ai"
+ - "NOVITA_API_KEY"
+ - "api.novita.ai"
+patterns:
+ - regex: '[A-Za-z0-9_\-]{32,}'
+ entropy_min: 4.0
+ confidence: low
+verify:
+ method: GET
+ url: https://api.novita.ai/v3/openai/models
+ headers:
+ Authorization: "Bearer {KEY}"
+ valid_status: [200]
+ invalid_status: [401, 403]
+```
+
+Copy all four VERBATIM to pkg/providers/definitions/.
+
+
+ cd /home/salva/Documents/apikey && for f in lepton modal cerebrium novita; do diff providers/$f.yaml pkg/providers/definitions/$f.yaml || exit 1; done && go test ./pkg/providers/... -count=1
+
+
+ - All 8 files exist
+ - `grep -q 'MODAL_TOKEN_ID' providers/modal.yaml`
+ - `grep -q 'cerebrium.ai' providers/cerebrium.yaml`
+ - `grep -q 'api.novita.ai' providers/novita.yaml`
+ - `grep -q 'lepton.ai' providers/lepton.yaml`
+ - All dual-location diffs empty
+ - `go test ./pkg/providers/... -count=1` passes
+
+ 4 providers created and dual-located.
+
+
+
+ Task 2: SambaNova, OctoAI, Friendli YAMLs
+ providers/sambanova.yaml, providers/octoai.yaml, providers/friendli.yaml, pkg/providers/definitions/sambanova.yaml, pkg/providers/definitions/octoai.yaml, pkg/providers/definitions/friendli.yaml
+
+ - pkg/providers/schema.go
+ - .planning/phases/02-tier-1-2-providers/02-RESEARCH.md sections "12. SambaNova", "13. OctoAI", "14. Friendli"
+
+
+Create providers/sambanova.yaml:
+
+```yaml
+format_version: 1
+name: sambanova
+display_name: SambaNova
+tier: 2
+last_verified: "2026-04-05"
+keywords:
+ - "sambanova"
+ - "sambanova.ai"
+ - "SAMBANOVA_API_KEY"
+ - "sambastudio"
+ - "api.sambanova.ai"
+patterns:
+ - regex: '[a-f0-9\-]{36}'
+ entropy_min: 3.5
+ confidence: low
+ - regex: '[A-Za-z0-9]{40,}'
+ entropy_min: 4.0
+ confidence: low
+verify:
+ method: GET
+ url: https://api.sambanova.ai/v1/models
+ headers:
+ Authorization: "Bearer {KEY}"
+ valid_status: [200]
+ invalid_status: [401, 403]
+```
+
+Create providers/octoai.yaml:
+
+```yaml
+format_version: 1
+name: octoai
+display_name: OctoAI
+tier: 2
+last_verified: "2026-04-05"
+keywords:
+ - "octoai"
+ - "octo.ai"
+ - "OCTOAI_TOKEN"
+ - "OCTOAI_API_KEY"
+patterns:
+ - regex: '[A-Za-z0-9\-_\.]{40,}'
+ entropy_min: 4.0
+ confidence: low
+verify:
+ method: GET
+ url: ""
+ headers: {}
+ valid_status: []
+ invalid_status: []
+```
+
+Create providers/friendli.yaml:
+
+```yaml
+format_version: 1
+name: friendli
+display_name: Friendli
+tier: 2
+last_verified: "2026-04-05"
+keywords:
+ - "friendli"
+ - "friendli.ai"
+ - "FRIENDLI_TOKEN"
+ - "flp_"
+patterns:
+ - regex: 'flp_[A-Za-z0-9]{20,}'
+ entropy_min: 3.5
+ confidence: medium
+ - regex: '[A-Za-z0-9]{32,}'
+ entropy_min: 4.0
+ confidence: low
+verify:
+ method: GET
+ url: ""
+ headers: {}
+ valid_status: []
+ invalid_status: []
+```
+
+Copy all three VERBATIM to pkg/providers/definitions/.
+
+
+ cd /home/salva/Documents/apikey && for f in sambanova octoai friendli; do diff providers/$f.yaml pkg/providers/definitions/$f.yaml || exit 1; done && go test ./pkg/providers/... -count=1
+
+
+ - All 6 files exist
+ - `grep -q 'sambanova' providers/sambanova.yaml`
+ - `grep -q 'octo.ai' providers/octoai.yaml`
+ - `grep -q 'FRIENDLI_TOKEN' providers/friendli.yaml`
+ - All dual-location diffs empty
+ - `go test ./pkg/providers/... -count=1` passes
+ - After this task: `ls pkg/providers/definitions/*.yaml | wc -l` >= 27 (huggingface + 26 tier1/2)
+
+ Final 3 Tier 2 providers created. All 14 PROV-02 providers complete.
+
+
+
+
+
+After plan: `grep -l 'tier: 2' providers/*.yaml | wc -l` equals 14.
+
+
+
+- 7 generic-format Tier 2 providers created
+- Dual-location verified
+- Registry loads cleanly
+- Tier 2 total = 14 providers
+
+
+
diff --git a/.planning/phases/02-tier-1-2-providers/02-05-PLAN.md b/.planning/phases/02-tier-1-2-providers/02-05-PLAN.md
new file mode 100644
index 0000000..01981a1
--- /dev/null
+++ b/.planning/phases/02-tier-1-2-providers/02-05-PLAN.md
@@ -0,0 +1,240 @@
+---
+phase: 02-tier-1-2-providers
+plan: 05
+type: execute
+wave: 2
+depends_on: ["02-01", "02-02", "02-03", "02-04"]
+files_modified:
+ - pkg/providers/tier12_test.go
+autonomous: true
+requirements: [PROV-01, PROV-02]
+must_haves:
+ truths:
+ - "Registry loads exactly 26 Tier 1+2 providers plus any pre-existing extras"
+ - "Tier 1 count = 12, Tier 2 count = 14"
+ - "Every regex pattern in the registry compiles under Go RE2"
+ - "`keyhunter providers stats` (via Registry.Stats()) returns correct counts"
+ artifacts:
+ - path: "pkg/providers/tier12_test.go"
+ provides: "Integration test asserting tier counts and regex compilation"
+ min_lines: 50
+ key_links:
+ - from: "tier12_test.go"
+ to: "pkg/providers/registry.go NewRegistry()"
+ via: "load-all + count-by-tier"
+ pattern: "NewRegistry"
+---
+
+
+Write a guardrail integration test that verifies the Phase 2 deliverable: exactly 12 Tier 1 and 14 Tier 2 providers are loaded by the registry, every regex pattern compiles, and no keywords are empty.
+
+Purpose: Goal-backward verification. Phase 2 success criteria state "26 providers loaded with pattern and keyword counts" — this test locks that in so regressions in Phase 3+ cannot quietly break Phase 2 coverage.
+
+Output: Single test file that runs in the existing `go test ./pkg/providers/...` pipeline.
+
+Addresses PROV-01 and PROV-02 verification.
+
+
+
+@$HOME/.claude/get-shit-done/workflows/execute-plan.md
+@$HOME/.claude/get-shit-done/templates/summary.md
+
+
+
+@pkg/providers/schema.go
+@pkg/providers/registry.go
+@pkg/providers/registry_test.go
+@.planning/phases/02-tier-1-2-providers/02-01-PLAN.md
+@.planning/phases/02-tier-1-2-providers/02-02-PLAN.md
+@.planning/phases/02-tier-1-2-providers/02-03-PLAN.md
+@.planning/phases/02-tier-1-2-providers/02-04-PLAN.md
+
+
+From pkg/providers/registry.go (verify exact API via Read during execution):
+- `NewRegistry() (*Registry, error)` or similar factory
+- `Registry.Stats() RegistryStats` returning ByTier map[int]int
+- `Registry.All() []Provider` or iteration helper
+
+RegistryStats (from schema.go):
+```go
+type RegistryStats struct {
+ Total int
+ ByTier map[int]int
+ ByConfidence map[string]int
+}
+```
+
+
+
+
+
+
+ Task 1: Write tier1/tier2 count + regex compilation guardrail test
+ pkg/providers/tier12_test.go
+
+ - pkg/providers/registry.go (to find exact NewRegistry constructor + accessor names)
+ - pkg/providers/registry_test.go (to mirror existing test style)
+ - pkg/providers/schema.go (Pattern, Provider, RegistryStats types)
+
+
+ - Test 1: TestTier1Count — registry.Stats().ByTier[1] == 12
+ - Test 2: TestTier2Count — registry.Stats().ByTier[2] == 14
+ - Test 3: TestAllPatternsCompile — every Pattern.Regex across all providers compiles via regexp.Compile without error
+ - Test 4: TestAllProvidersHaveKeywords — every Provider.Keywords slice has len > 0 (Aho-Corasick pre-filter requires keywords)
+ - Test 5: TestTier1ProviderNames — registry contains providers with these names: openai, anthropic, google-ai, vertex-ai, aws-bedrock, azure-openai, meta-ai, xai, cohere, mistral, inflection, ai21
+ - Test 6: TestTier2ProviderNames — registry contains: groq, replicate, anyscale, together, fireworks, baseten, deepinfra, lepton, modal, cerebrium, novita, sambanova, octoai, friendli
+
+
+Create pkg/providers/tier12_test.go. Use the existing registry_test.go for the exact constructor name and iteration API — likely `providers.NewRegistry()` returning `(*Registry, error)`.
+
+Skeleton:
+
+```go
+package providers
+
+import (
+ "regexp"
+ "testing"
+)
+
+// expectedTier1 lists all 12 Tier 1 Frontier provider names (PROV-01).
+var expectedTier1 = []string{
+ "openai", "anthropic", "google-ai", "vertex-ai", "aws-bedrock",
+ "azure-openai", "meta-ai", "xai", "cohere", "mistral",
+ "inflection", "ai21",
+}
+
+// expectedTier2 lists all 14 Tier 2 Inference Platform provider names (PROV-02).
+var expectedTier2 = []string{
+ "groq", "replicate", "anyscale", "together", "fireworks",
+ "baseten", "deepinfra", "lepton", "modal", "cerebrium",
+ "novita", "sambanova", "octoai", "friendli",
+}
+
+func TestTier1Count(t *testing.T) {
+ reg, err := NewRegistry()
+ if err != nil {
+ t.Fatalf("NewRegistry failed: %v", err)
+ }
+ stats := reg.Stats()
+ if got := stats.ByTier[1]; got != 12 {
+ t.Errorf("Tier 1 count = %d, want 12", got)
+ }
+}
+
+func TestTier2Count(t *testing.T) {
+ reg, err := NewRegistry()
+ if err != nil {
+ t.Fatalf("NewRegistry failed: %v", err)
+ }
+ stats := reg.Stats()
+ if got := stats.ByTier[2]; got != 14 {
+ t.Errorf("Tier 2 count = %d, want 14", got)
+ }
+}
+
+func TestAllPatternsCompile(t *testing.T) {
+ reg, err := NewRegistry()
+ if err != nil {
+ t.Fatalf("NewRegistry failed: %v", err)
+ }
+ for _, p := range reg.All() { // adjust to real accessor name
+ for i, pat := range p.Patterns {
+ if _, err := regexp.Compile(pat.Regex); err != nil {
+ t.Errorf("provider %q pattern[%d] regex %q failed to compile: %v",
+ p.Name, i, pat.Regex, err)
+ }
+ }
+ }
+}
+
+func TestAllProvidersHaveKeywords(t *testing.T) {
+ reg, err := NewRegistry()
+ if err != nil {
+ t.Fatalf("NewRegistry failed: %v", err)
+ }
+ for _, p := range reg.All() {
+ if len(p.Keywords) == 0 {
+ t.Errorf("provider %q has no keywords (breaks AC pre-filter)", p.Name)
+ }
+ }
+}
+
+func TestTier1ProviderNames(t *testing.T) {
+ reg, err := NewRegistry()
+ if err != nil {
+ t.Fatalf("NewRegistry failed: %v", err)
+ }
+ for _, name := range expectedTier1 {
+ p, ok := reg.Get(name) // adjust to real accessor
+ if !ok {
+ t.Errorf("Tier 1 provider %q not found in registry", name)
+ continue
+ }
+ if p.Tier != 1 {
+ t.Errorf("provider %q tier = %d, want 1", name, p.Tier)
+ }
+ }
+}
+
+func TestTier2ProviderNames(t *testing.T) {
+ reg, err := NewRegistry()
+ if err != nil {
+ t.Fatalf("NewRegistry failed: %v", err)
+ }
+ for _, name := range expectedTier2 {
+ p, ok := reg.Get(name)
+ if !ok {
+ t.Errorf("Tier 2 provider %q not found in registry", name)
+ continue
+ }
+ if p.Tier != 2 {
+ t.Errorf("provider %q tier = %d, want 2", name, p.Tier)
+ }
+ }
+}
+```
+
+IMPORTANT: Before writing the file, Read pkg/providers/registry.go to confirm the EXACT names of:
+1. Constructor (NewRegistry? LoadRegistry?)
+2. Iteration method (All? Providers? Each?)
+3. Lookup method (Get? Find? Lookup?)
+
+If the real API differs, adjust the skeleton above to use the real method names. The behavior and assertions must stay the same.
+
+
+ cd /home/salva/Documents/apikey && go test ./pkg/providers/... -run 'TestTier1Count|TestTier2Count|TestAllPatternsCompile|TestAllProvidersHaveKeywords|TestTier1ProviderNames|TestTier2ProviderNames' -v -count=1
+
+
+ - `test -f pkg/providers/tier12_test.go`
+ - `grep -q 'expectedTier1' pkg/providers/tier12_test.go`
+ - `grep -q 'expectedTier2' pkg/providers/tier12_test.go`
+ - All six test functions present: `grep -c '^func Test' pkg/providers/tier12_test.go` >= 6
+ - `go test ./pkg/providers/... -run TestTier1Count -count=1` passes (Tier 1 = 12)
+ - `go test ./pkg/providers/... -run TestTier2Count -count=1` passes (Tier 2 = 14)
+ - `go test ./pkg/providers/... -run TestAllPatternsCompile -count=1` passes (all regex compile)
+ - `go test ./pkg/providers/... -count=1` passes (full suite green)
+
+ Guardrail test locks in 12 Tier 1 + 14 Tier 2 providers, regex compilation, and keyword presence. Future phase regressions that drop a provider will fail this test.
+
+
+
+
+
+Final phase sanity:
+- `go test ./... -count=1` passes
+- `ls providers/*.yaml | wc -l` >= 27 (26 new + huggingface)
+- `ls pkg/providers/definitions/*.yaml | wc -l` matches providers/ directory count
+- `diff <(ls providers/*.yaml | xargs -n1 basename) <(ls pkg/providers/definitions/*.yaml | xargs -n1 basename)` returns empty
+
+
+
+- Registry loads exactly 12 Tier 1 + 14 Tier 2 providers (+ pre-existing tier-less huggingface)
+- All patterns compile under RE2
+- All providers have non-empty keywords
+- Test file committed and passing
+
+
+