docs(02): create phase 2 tier 1-2 provider plans

This commit is contained in:
salvacybersec
2026-04-05 14:08:04 +03:00
parent d0f9535852
commit 5079c65161
6 changed files with 1538 additions and 1 deletions

View File

@@ -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.) 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 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 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 ### 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 **Goal**: All 108+ LLM provider definitions exist — specialized models, Chinese/regional providers, infrastructure gateways, emerging tools, code assistants, self-hosted runtimes, and enterprise platforms

View File

@@ -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"
---
<objective>
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.
</objective>
<execution_context>
@$HOME/.claude/get-shit-done/workflows/execute-plan.md
@$HOME/.claude/get-shit-done/templates/summary.md
</execution_context>
<context>
@.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
<interfaces>
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/`.
</interfaces>
</context>
<tasks>
<task type="auto">
<name>Task 1: Upgrade OpenAI and Anthropic YAMLs</name>
<files>providers/openai.yaml, providers/anthropic.yaml, pkg/providers/definitions/openai.yaml, pkg/providers/definitions/anthropic.yaml</files>
<read_first>
- 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"
</read_first>
<action>
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/).
</action>
<verify>
<automated>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</automated>
</verify>
<acceptance_criteria>
- `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
</acceptance_criteria>
<done>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.</done>
</task>
<task type="auto">
<name>Task 2: Create Google AI, Vertex AI, AWS Bedrock, xAI YAMLs</name>
<files>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</files>
<read_first>
- 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"
</read_first>
<action>
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.
</action>
<verify>
<automated>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</automated>
</verify>
<acceptance_criteria>
- 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)
</acceptance_criteria>
<done>4 new providers created and dual-located. Registry loads 9 providers total (3 pre-existing + 6 upgraded/new). All regex patterns compile under RE2.</done>
</task>
</tasks>
<verification>
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.
</verification>
<success_criteria>
- 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
</success_criteria>
<output>
After completion, create `.planning/phases/02-tier-1-2-providers/02-01-SUMMARY.md`
</output>

View File

@@ -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"
---
<objective>
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.
</objective>
<execution_context>
@$HOME/.claude/get-shit-done/workflows/execute-plan.md
@$HOME/.claude/get-shit-done/templates/summary.md
</execution_context>
<context>
@.planning/ROADMAP.md
@.planning/phases/02-tier-1-2-providers/02-RESEARCH.md
@pkg/providers/schema.go
@providers/openai.yaml
<interfaces>
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.
</interfaces>
</context>
<tasks>
<task type="auto">
<name>Task 1: Azure OpenAI, Meta AI, Cohere YAMLs</name>
<files>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</files>
<read_first>
- pkg/providers/schema.go
- .planning/phases/02-tier-1-2-providers/02-RESEARCH.md sections "6. Azure OpenAI", "7. Meta AI", "9. Cohere"
</read_first>
<action>
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.
</action>
<verify>
<automated>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</automated>
</verify>
<acceptance_criteria>
- 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
</acceptance_criteria>
<done>3 providers dual-located, registry loads them without validation errors.</done>
</task>
<task type="auto">
<name>Task 2: Mistral, Inflection, AI21 YAMLs</name>
<files>providers/mistral.yaml, providers/inflection.yaml, providers/ai21.yaml, pkg/providers/definitions/mistral.yaml, pkg/providers/definitions/inflection.yaml, pkg/providers/definitions/ai21.yaml</files>
<read_first>
- pkg/providers/schema.go
- .planning/phases/02-tier-1-2-providers/02-RESEARCH.md sections "10. Mistral AI", "11. Inflection AI", "12. AI21 Labs"
</read_first>
<action>
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.
</action>
<verify>
<automated>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</automated>
</verify>
<acceptance_criteria>
- 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
</acceptance_criteria>
<done>3 providers dual-located. Tier 1 complete at 12/12.</done>
</task>
</tasks>
<verification>
Count providers with tier 1 after this plan runs: `grep -l 'tier: 1' providers/*.yaml | wc -l` should equal 12.
</verification>
<success_criteria>
- 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
</success_criteria>
<output>
After completion, create `.planning/phases/02-tier-1-2-providers/02-02-SUMMARY.md`
</output>

View File

@@ -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"
---
<objective>
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.
</objective>
<execution_context>
@$HOME/.claude/get-shit-done/workflows/execute-plan.md
@$HOME/.claude/get-shit-done/templates/summary.md
</execution_context>
<context>
@.planning/ROADMAP.md
@.planning/phases/02-tier-1-2-providers/02-RESEARCH.md
@pkg/providers/schema.go
<interfaces>
Schema: pkg/providers/schema.go. Dual-location required. RE2 regex only.
Tier = 2 for all providers in this plan.
</interfaces>
</context>
<tasks>
<task type="auto">
<name>Task 1: High-confidence prefixed Tier 2 — Groq, Replicate, Anyscale</name>
<files>providers/groq.yaml, providers/replicate.yaml, providers/anyscale.yaml, pkg/providers/definitions/groq.yaml, pkg/providers/definitions/replicate.yaml, pkg/providers/definitions/anyscale.yaml</files>
<read_first>
- pkg/providers/schema.go
- .planning/phases/02-tier-1-2-providers/02-RESEARCH.md sections "3. Groq", "4. Replicate", "5. Anyscale"
</read_first>
<action>
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.
</action>
<verify>
<automated>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</automated>
</verify>
<acceptance_criteria>
- `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
</acceptance_criteria>
<done>3 high-confidence Tier 2 providers created with verified regex patterns.</done>
</task>
<task type="auto">
<name>Task 2: Keyword-anchored Tier 2 — Together, Fireworks, Baseten, DeepInfra</name>
<files>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</files>
<read_first>
- 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"
</read_first>
<action>
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/.
</action>
<verify>
<automated>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</automated>
</verify>
<acceptance_criteria>
- 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
</acceptance_criteria>
<done>4 keyword-anchored Tier 2 providers dual-located and loading cleanly.</done>
</task>
</tasks>
<verification>
After plan completes: `grep -l 'tier: 2' providers/*.yaml | wc -l` should be at least 7.
</verification>
<success_criteria>
- 7 Tier 2 inference platform providers created
- 3 high-confidence (Groq/Replicate/Anyscale), 4 keyword-anchored
- Dual-location verified
- go test ./pkg/providers/... passes
</success_criteria>
<output>
After completion, create `.planning/phases/02-tier-1-2-providers/02-03-SUMMARY.md`
</output>

View File

@@ -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"
---
<objective>
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.
</objective>
<execution_context>
@$HOME/.claude/get-shit-done/workflows/execute-plan.md
@$HOME/.claude/get-shit-done/templates/summary.md
</execution_context>
<context>
@.planning/ROADMAP.md
@.planning/phases/02-tier-1-2-providers/02-RESEARCH.md
@pkg/providers/schema.go
<interfaces>
Schema: pkg/providers/schema.go. Dual-location required. Go RE2 regex only.
All providers in this plan: tier 2, confidence low (no distinctive prefix).
</interfaces>
</context>
<tasks>
<task type="auto">
<name>Task 1: Lepton, Modal, Cerebrium, Novita YAMLs</name>
<files>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</files>
<read_first>
- pkg/providers/schema.go
- .planning/phases/02-tier-1-2-providers/02-RESEARCH.md sections "7. Lepton", "8. Modal", "10. Cerebrium", "11. NovitaAI"
</read_first>
<action>
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/.
</action>
<verify>
<automated>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</automated>
</verify>
<acceptance_criteria>
- 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
</acceptance_criteria>
<done>4 providers created and dual-located.</done>
</task>
<task type="auto">
<name>Task 2: SambaNova, OctoAI, Friendli YAMLs</name>
<files>providers/sambanova.yaml, providers/octoai.yaml, providers/friendli.yaml, pkg/providers/definitions/sambanova.yaml, pkg/providers/definitions/octoai.yaml, pkg/providers/definitions/friendli.yaml</files>
<read_first>
- pkg/providers/schema.go
- .planning/phases/02-tier-1-2-providers/02-RESEARCH.md sections "12. SambaNova", "13. OctoAI", "14. Friendli"
</read_first>
<action>
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/.
</action>
<verify>
<automated>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</automated>
</verify>
<acceptance_criteria>
- 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)
</acceptance_criteria>
<done>Final 3 Tier 2 providers created. All 14 PROV-02 providers complete.</done>
</task>
</tasks>
<verification>
After plan: `grep -l 'tier: 2' providers/*.yaml | wc -l` equals 14.
</verification>
<success_criteria>
- 7 generic-format Tier 2 providers created
- Dual-location verified
- Registry loads cleanly
- Tier 2 total = 14 providers
</success_criteria>
<output>
After completion, create `.planning/phases/02-tier-1-2-providers/02-04-SUMMARY.md`
</output>

View File

@@ -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"
---
<objective>
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.
</objective>
<execution_context>
@$HOME/.claude/get-shit-done/workflows/execute-plan.md
@$HOME/.claude/get-shit-done/templates/summary.md
</execution_context>
<context>
@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
<interfaces>
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
}
```
</interfaces>
</context>
<tasks>
<task type="auto" tdd="true">
<name>Task 1: Write tier1/tier2 count + regex compilation guardrail test</name>
<files>pkg/providers/tier12_test.go</files>
<read_first>
- 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)
</read_first>
<behavior>
- 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
</behavior>
<action>
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.
</action>
<verify>
<automated>cd /home/salva/Documents/apikey && go test ./pkg/providers/... -run 'TestTier1Count|TestTier2Count|TestAllPatternsCompile|TestAllProvidersHaveKeywords|TestTier1ProviderNames|TestTier2ProviderNames' -v -count=1</automated>
</verify>
<acceptance_criteria>
- `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)
</acceptance_criteria>
<done>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.</done>
</task>
</tasks>
<verification>
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
</verification>
<success_criteria>
- 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
</success_criteria>
<output>
After completion, create `.planning/phases/02-tier-1-2-providers/02-05-SUMMARY.md`
</output>