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 + + + +After completion, create `.planning/phases/02-tier-1-2-providers/02-01-SUMMARY.md` + 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 + + + +After completion, create `.planning/phases/02-tier-1-2-providers/02-02-SUMMARY.md` + 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 + + + +After completion, create `.planning/phases/02-tier-1-2-providers/02-03-SUMMARY.md` + 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 + + + +After completion, create `.planning/phases/02-tier-1-2-providers/02-04-SUMMARY.md` + 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 + + + +After completion, create `.planning/phases/02-tier-1-2-providers/02-05-SUMMARY.md` +