diff --git a/.planning/ROADMAP.md b/.planning/ROADMAP.md
index 50ad8e6..7398f0b 100644
--- a/.planning/ROADMAP.md
+++ b/.planning/ROADMAP.md
@@ -79,7 +79,17 @@ Plans:
2. Chinese/regional provider keys (DeepSeek, Zhipu, Moonshot, Qwen, Baidu, ByteDance, etc.) are detected using keyword-based matching since they use generic key formats
3. Self-hosted provider definitions (Ollama, vLLM, LocalAI, etc.) include patterns for API key authentication when applicable
4. `keyhunter providers list --tier=enterprise` returns Salesforce, ServiceNow, SAP, Palantir, Databricks, Snowflake, Oracle, HPE providers
-**Plans**: TBD
+**Plans**: 8 plans
+
+Plans:
+- [ ] 03-01-PLAN.md — Tier 4 Chinese/regional providers (DeepSeek, Zhipu, Moonshot, Qwen, Baidu, ByteDance, 01.AI, MiniMax, Baichuan, StepFun, SenseTime, iFlytek, Tencent, SiliconFlow, 360 AI, Kuaishou)
+- [ ] 03-02-PLAN.md — Tier 3 Specialized (Perplexity, You.com, Voyage, Jina, Unstructured, AssemblyAI, Deepgram, ElevenLabs, Stability, Runway, Midjourney)
+- [ ] 03-03-PLAN.md — Tier 5 Infrastructure/Gateway (OpenRouter, LiteLLM, Cloudflare AI, Vercel AI, Portkey, Helicone, Martian, Kong, BricksAI, Aether, Not Diamond)
+- [ ] 03-04-PLAN.md — Tier 7 Code/Dev Tools (GitHub Copilot, Cursor, Tabnine, Codeium, Sourcegraph, CodeWhisperer, Replit AI, Codestral, watsonx, Oracle AI)
+- [ ] 03-05-PLAN.md — Tier 8 Self-Hosted runtimes (Ollama, vLLM, LocalAI, LM Studio, llama.cpp, GPT4All, text-gen-webui, TensorRT-LLM, Triton, Jan)
+- [ ] 03-06-PLAN.md — Tier 9 Enterprise (Salesforce Einstein, ServiceNow, SAP AI Core, Palantir, Databricks, Snowflake, Oracle GenAI, HPE GreenLake)
+- [ ] 03-07-PLAN.md — Tier 6 Emerging/Niche (Reka, Aleph Alpha, Lamini, Writer, Jasper, Typeface, Comet, W&B, LangSmith, Pinecone, Weaviate, Qdrant, Chroma, Milvus, Neon)
+- [ ] 03-08-PLAN.md — Tier 3-9 guardrail test: lock 108 total providers, per-tier counts, and name sets
### Phase 4: Input Sources
**Goal**: Users can point KeyHunter at any content source — local files, git history across all branches, piped content, remote URLs, and the clipboard — and all are scanned through the same detection pipeline
diff --git a/.planning/phases/03-tier-3-9-providers/03-01-PLAN.md b/.planning/phases/03-tier-3-9-providers/03-01-PLAN.md
new file mode 100644
index 0000000..999538b
--- /dev/null
+++ b/.planning/phases/03-tier-3-9-providers/03-01-PLAN.md
@@ -0,0 +1,544 @@
+---
+phase: 03-tier-3-9-providers
+plan: 01
+type: execute
+wave: 1
+depends_on: []
+files_modified:
+ - providers/deepseek.yaml
+ - providers/zhipu.yaml
+ - providers/moonshot.yaml
+ - providers/qwen.yaml
+ - providers/baidu.yaml
+ - providers/bytedance.yaml
+ - providers/01ai.yaml
+ - providers/minimax.yaml
+ - providers/baichuan.yaml
+ - providers/stepfun.yaml
+ - providers/sensetime.yaml
+ - providers/iflytek.yaml
+ - providers/tencent.yaml
+ - providers/siliconflow.yaml
+ - providers/360ai.yaml
+ - providers/kuaishou.yaml
+ - pkg/providers/definitions/deepseek.yaml
+ - pkg/providers/definitions/zhipu.yaml
+ - pkg/providers/definitions/moonshot.yaml
+ - pkg/providers/definitions/qwen.yaml
+ - pkg/providers/definitions/baidu.yaml
+ - pkg/providers/definitions/bytedance.yaml
+ - pkg/providers/definitions/01ai.yaml
+ - pkg/providers/definitions/minimax.yaml
+ - pkg/providers/definitions/baichuan.yaml
+ - pkg/providers/definitions/stepfun.yaml
+ - pkg/providers/definitions/sensetime.yaml
+ - pkg/providers/definitions/iflytek.yaml
+ - pkg/providers/definitions/tencent.yaml
+ - pkg/providers/definitions/siliconflow.yaml
+ - pkg/providers/definitions/360ai.yaml
+ - pkg/providers/definitions/kuaishou.yaml
+autonomous: true
+requirements: [PROV-04]
+must_haves:
+ truths:
+ - "Registry loads 16 Tier 4 Chinese/regional provider YAMLs"
+ - "Providers without documented key formats use keyword-only detection (no patterns entry)"
+ - "DeepSeek uses documented sk- prefix pattern"
+ - "All YAMLs are dual-located and diff-clean"
+ artifacts:
+ - path: "providers/deepseek.yaml"
+ provides: "DeepSeek sk- prefix pattern + keywords"
+ contains: "deepseek"
+ - path: "providers/qwen.yaml"
+ provides: "Alibaba Qwen/DashScope keyword-only detection"
+ contains: "dashscope"
+ - path: "providers/baidu.yaml"
+ provides: "Baidu ERNIE/Wenxin keyword detection"
+ contains: "wenxin"
+ key_links:
+ - from: "provider keywords[]"
+ to: "Registry Aho-Corasick automaton"
+ via: "NewRegistry()"
+ pattern: "keywords"
+---
+
+
+Create 16 Tier 4 Chinese/regional LLM provider YAML definitions. These providers mostly lack documented key formats, so detection relies on strong keyword lists anchored to their SDK envs, domains, and API hostnames — not on generic regex (which caused false positives in Phase 2).
+
+Purpose: Satisfy PROV-04 (16 Tier 4 providers). Chinese/regional providers are high-value targets but low-signal for regex detection — keyword-only matching is the correct mitigation.
+
+Output: 32 YAML files (16 providers × 2 locations).
+
+Addresses PROV-04.
+
+
+
+@$HOME/.claude/get-shit-done/workflows/execute-plan.md
+@$HOME/.claude/get-shit-done/templates/summary.md
+
+
+
+@.planning/ROADMAP.md
+@.planning/phases/03-tier-3-9-providers/03-CONTEXT.md
+@pkg/providers/schema.go
+@providers/mistral.yaml
+@providers/cohere.yaml
+
+
+Provider schema (pkg/providers/schema.go): FormatVersion, Name, DisplayName, Tier, LastVerified, Keywords, Patterns, Verify. NO `category` field. Confidence values: high|medium|low.
+
+Patterns array MAY be empty/omitted — registry allows keyword-only providers. Keywords list MUST have ≥3 entries (Aho-Corasick pre-filter requirement).
+
+Files must be dual-located: providers/X.yaml AND pkg/providers/definitions/X.yaml (Go embed cannot use '..' paths).
+
+Phase 2 lesson: generic regex like `[A-Za-z0-9]{32,64}` causes false positives. For providers without distinctive prefixes, OMIT the patterns field entirely (keyword-only detection).
+
+
+
+
+
+
+ Task 1: DeepSeek, Zhipu, Moonshot, Qwen, Baidu, ByteDance, 01.AI, MiniMax YAMLs
+ providers/deepseek.yaml, providers/zhipu.yaml, providers/moonshot.yaml, providers/qwen.yaml, providers/baidu.yaml, providers/bytedance.yaml, providers/01ai.yaml, providers/minimax.yaml, pkg/providers/definitions/deepseek.yaml, pkg/providers/definitions/zhipu.yaml, pkg/providers/definitions/moonshot.yaml, pkg/providers/definitions/qwen.yaml, pkg/providers/definitions/baidu.yaml, pkg/providers/definitions/bytedance.yaml, pkg/providers/definitions/01ai.yaml, pkg/providers/definitions/minimax.yaml
+
+ - pkg/providers/schema.go
+ - providers/mistral.yaml (reference: keyword-anchored generic pattern)
+ - .planning/phases/03-tier-3-9-providers/03-CONTEXT.md (lessons from Phase 2)
+
+
+Create each file in providers/ AND pkg/providers/definitions/ (verbatim copy). DeepSeek has a documented sk- prefix so it gets a pattern; all others are keyword-only (omit patterns entirely).
+
+providers/deepseek.yaml:
+```yaml
+format_version: 1
+name: deepseek
+display_name: DeepSeek
+tier: 4
+last_verified: "2026-04-05"
+keywords:
+ - "deepseek"
+ - "DEEPSEEK_API_KEY"
+ - "api.deepseek.com"
+ - "deepseek-chat"
+ - "deepseek-coder"
+patterns:
+ - regex: 'sk-[a-f0-9]{32}'
+ entropy_min: 3.5
+ confidence: medium
+verify:
+ method: GET
+ url: https://api.deepseek.com/v1/models
+ headers:
+ Authorization: "Bearer {KEY}"
+ valid_status: [200]
+ invalid_status: [401, 403]
+```
+
+providers/zhipu.yaml:
+```yaml
+format_version: 1
+name: zhipu
+display_name: Zhipu AI (GLM)
+tier: 4
+last_verified: "2026-04-05"
+keywords:
+ - "zhipu"
+ - "ZHIPU_API_KEY"
+ - "ZHIPUAI_API_KEY"
+ - "bigmodel.cn"
+ - "open.bigmodel.cn"
+ - "glm-4"
+ - "chatglm"
+verify:
+ method: GET
+ url: https://open.bigmodel.cn/api/paas/v4/models
+ headers:
+ Authorization: "Bearer {KEY}"
+ valid_status: [200]
+ invalid_status: [401, 403]
+```
+
+providers/moonshot.yaml:
+```yaml
+format_version: 1
+name: moonshot
+display_name: Moonshot AI (Kimi)
+tier: 4
+last_verified: "2026-04-05"
+keywords:
+ - "moonshot"
+ - "MOONSHOT_API_KEY"
+ - "api.moonshot.cn"
+ - "kimi"
+ - "moonshot-v1"
+patterns:
+ - regex: 'sk-[A-Za-z0-9]{48}'
+ entropy_min: 4.0
+ confidence: medium
+verify:
+ method: GET
+ url: https://api.moonshot.cn/v1/models
+ headers:
+ Authorization: "Bearer {KEY}"
+ valid_status: [200]
+ invalid_status: [401, 403]
+```
+
+providers/qwen.yaml:
+```yaml
+format_version: 1
+name: qwen
+display_name: Alibaba Qwen (DashScope)
+tier: 4
+last_verified: "2026-04-05"
+keywords:
+ - "dashscope"
+ - "DASHSCOPE_API_KEY"
+ - "qwen"
+ - "qwen-turbo"
+ - "qwen-max"
+ - "dashscope.aliyuncs.com"
+patterns:
+ - regex: 'sk-[a-f0-9]{32}'
+ entropy_min: 3.5
+ confidence: medium
+verify:
+ method: GET
+ url: https://dashscope.aliyuncs.com/api/v1/services/aigc/text-generation/generation
+ headers:
+ Authorization: "Bearer {KEY}"
+ valid_status: [200, 400]
+ invalid_status: [401, 403]
+```
+
+providers/baidu.yaml:
+```yaml
+format_version: 1
+name: baidu
+display_name: Baidu ERNIE (Wenxin)
+tier: 4
+last_verified: "2026-04-05"
+keywords:
+ - "wenxin"
+ - "ernie"
+ - "BAIDU_API_KEY"
+ - "QIANFAN_AK"
+ - "QIANFAN_SK"
+ - "aip.baidubce.com"
+ - "qianfan"
+verify:
+ method: POST
+ url: ""
+ headers: {}
+ valid_status: []
+ invalid_status: []
+```
+
+providers/bytedance.yaml:
+```yaml
+format_version: 1
+name: bytedance
+display_name: ByteDance Doubao (Volcengine)
+tier: 4
+last_verified: "2026-04-05"
+keywords:
+ - "doubao"
+ - "volcengine"
+ - "VOLC_ACCESSKEY"
+ - "VOLC_SECRETKEY"
+ - "ARK_API_KEY"
+ - "ark.cn-beijing.volces.com"
+verify:
+ method: GET
+ url: ""
+ headers: {}
+ valid_status: []
+ invalid_status: []
+```
+
+providers/01ai.yaml:
+```yaml
+format_version: 1
+name: 01ai
+display_name: 01.AI (Yi)
+tier: 4
+last_verified: "2026-04-05"
+keywords:
+ - "01.ai"
+ - "yi-large"
+ - "yi-34b"
+ - "YI_API_KEY"
+ - "api.lingyiwanwu.com"
+ - "lingyiwanwu"
+verify:
+ method: GET
+ url: https://api.lingyiwanwu.com/v1/models
+ headers:
+ Authorization: "Bearer {KEY}"
+ valid_status: [200]
+ invalid_status: [401, 403]
+```
+
+providers/minimax.yaml:
+```yaml
+format_version: 1
+name: minimax
+display_name: MiniMax
+tier: 4
+last_verified: "2026-04-05"
+keywords:
+ - "minimax"
+ - "MINIMAX_API_KEY"
+ - "MINIMAX_GROUP_ID"
+ - "api.minimax.chat"
+ - "abab6"
+verify:
+ method: GET
+ url: https://api.minimax.chat/v1/text/chatcompletion_v2
+ headers:
+ Authorization: "Bearer {KEY}"
+ valid_status: [200, 400]
+ invalid_status: [401, 403]
+```
+
+Copy each file VERBATIM to pkg/providers/definitions/ with the same basename.
+
+
+ cd /home/salva/Documents/apikey && for f in deepseek zhipu moonshot qwen baidu bytedance 01ai minimax; do diff providers/$f.yaml pkg/providers/definitions/$f.yaml || exit 1; done && go test ./pkg/providers/... -count=1 && go test ./pkg/engine/... -count=1
+
+
+ - All 16 files exist (8 providers × 2 locations)
+ - `grep -q 'DEEPSEEK_API_KEY' providers/deepseek.yaml`
+ - `grep -q 'dashscope' providers/qwen.yaml`
+ - `grep -q 'wenxin' providers/baidu.yaml`
+ - `grep -q 'lingyiwanwu' providers/01ai.yaml`
+ - `grep -L 'patterns:' providers/zhipu.yaml providers/baidu.yaml providers/bytedance.yaml` returns all three (keyword-only, no patterns field)
+ - `diff providers/deepseek.yaml pkg/providers/definitions/deepseek.yaml` returns no diff
+ - `go test ./pkg/providers/... -count=1` passes
+ - `go test ./pkg/engine/... -count=1` passes (no regression from new providers)
+
+ 8 Chinese/regional providers dual-located, registry loads them, engine tests pass.
+
+
+
+ Task 2: Baichuan, StepFun, SenseTime, iFlytek, Tencent, SiliconFlow, 360 AI, Kuaishou YAMLs
+ providers/baichuan.yaml, providers/stepfun.yaml, providers/sensetime.yaml, providers/iflytek.yaml, providers/tencent.yaml, providers/siliconflow.yaml, providers/360ai.yaml, providers/kuaishou.yaml, pkg/providers/definitions/baichuan.yaml, pkg/providers/definitions/stepfun.yaml, pkg/providers/definitions/sensetime.yaml, pkg/providers/definitions/iflytek.yaml, pkg/providers/definitions/tencent.yaml, pkg/providers/definitions/siliconflow.yaml, pkg/providers/definitions/360ai.yaml, pkg/providers/definitions/kuaishou.yaml
+
+ - pkg/providers/schema.go
+ - providers/deepseek.yaml (created in Task 1, reference for format)
+
+
+All 8 of these providers lack publicly documented key formats. Use KEYWORD-ONLY detection — omit the patterns field entirely.
+
+providers/baichuan.yaml:
+```yaml
+format_version: 1
+name: baichuan
+display_name: Baichuan AI
+tier: 4
+last_verified: "2026-04-05"
+keywords:
+ - "baichuan"
+ - "BAICHUAN_API_KEY"
+ - "api.baichuan-ai.com"
+ - "baichuan2"
+ - "baichuan-turbo"
+verify:
+ method: GET
+ url: https://api.baichuan-ai.com/v1/chat/completions
+ headers:
+ Authorization: "Bearer {KEY}"
+ valid_status: [200, 400]
+ invalid_status: [401, 403]
+```
+
+providers/stepfun.yaml:
+```yaml
+format_version: 1
+name: stepfun
+display_name: StepFun (阶跃星辰)
+tier: 4
+last_verified: "2026-04-05"
+keywords:
+ - "stepfun"
+ - "STEP_API_KEY"
+ - "STEPFUN_API_KEY"
+ - "api.stepfun.com"
+ - "step-1v"
+verify:
+ method: GET
+ url: https://api.stepfun.com/v1/models
+ headers:
+ Authorization: "Bearer {KEY}"
+ valid_status: [200]
+ invalid_status: [401, 403]
+```
+
+providers/sensetime.yaml:
+```yaml
+format_version: 1
+name: sensetime
+display_name: SenseTime SenseNova
+tier: 4
+last_verified: "2026-04-05"
+keywords:
+ - "sensetime"
+ - "sensenova"
+ - "SENSETIME_API_KEY"
+ - "SENSENOVA_API_KEY"
+ - "api.sensenova.cn"
+verify:
+ method: GET
+ url: ""
+ headers: {}
+ valid_status: []
+ invalid_status: []
+```
+
+providers/iflytek.yaml:
+```yaml
+format_version: 1
+name: iflytek
+display_name: iFlytek Spark (讯飞星火)
+tier: 4
+last_verified: "2026-04-05"
+keywords:
+ - "iflytek"
+ - "xf_yun"
+ - "spark_desk"
+ - "XFYUN_API_KEY"
+ - "XFYUN_API_SECRET"
+ - "XFYUN_APPID"
+ - "spark-api.xf-yun.com"
+verify:
+ method: GET
+ url: ""
+ headers: {}
+ valid_status: []
+ invalid_status: []
+```
+
+providers/tencent.yaml:
+```yaml
+format_version: 1
+name: tencent
+display_name: Tencent Hunyuan
+tier: 4
+last_verified: "2026-04-05"
+keywords:
+ - "hunyuan"
+ - "TENCENTCLOUD_SECRET_ID"
+ - "TENCENTCLOUD_SECRET_KEY"
+ - "hunyuan.tencentcloudapi.com"
+ - "tencent-hunyuan"
+verify:
+ method: GET
+ url: ""
+ headers: {}
+ valid_status: []
+ invalid_status: []
+```
+
+providers/siliconflow.yaml:
+```yaml
+format_version: 1
+name: siliconflow
+display_name: SiliconFlow
+tier: 4
+last_verified: "2026-04-05"
+keywords:
+ - "siliconflow"
+ - "SILICONFLOW_API_KEY"
+ - "api.siliconflow.cn"
+ - "siliconflow.cn"
+patterns:
+ - regex: 'sk-[a-z]{20,}'
+ entropy_min: 3.5
+ confidence: low
+verify:
+ method: GET
+ url: https://api.siliconflow.cn/v1/models
+ headers:
+ Authorization: "Bearer {KEY}"
+ valid_status: [200]
+ invalid_status: [401, 403]
+```
+
+providers/360ai.yaml:
+```yaml
+format_version: 1
+name: 360ai
+display_name: 360 AI Brain
+tier: 4
+last_verified: "2026-04-05"
+keywords:
+ - "360gpt"
+ - "QIHOO_API_KEY"
+ - "api.360.cn"
+ - "ai.360.com"
+ - "360-ai"
+verify:
+ method: GET
+ url: ""
+ headers: {}
+ valid_status: []
+ invalid_status: []
+```
+
+providers/kuaishou.yaml:
+```yaml
+format_version: 1
+name: kuaishou
+display_name: Kuaishou KwaiYii
+tier: 4
+last_verified: "2026-04-05"
+keywords:
+ - "kuaishou"
+ - "kwaiyii"
+ - "KUAISHOU_API_KEY"
+ - "KWAI_API_KEY"
+ - "kwai-ai"
+verify:
+ method: GET
+ url: ""
+ headers: {}
+ valid_status: []
+ invalid_status: []
+```
+
+Copy each file VERBATIM to pkg/providers/definitions/.
+
+
+ cd /home/salva/Documents/apikey && for f in baichuan stepfun sensetime iflytek tencent siliconflow 360ai kuaishou; do diff providers/$f.yaml pkg/providers/definitions/$f.yaml || exit 1; done && go test ./pkg/providers/... -count=1 && go test ./pkg/engine/... -count=1
+
+
+ - All 16 files exist (8 providers × 2 locations)
+ - `grep -q 'baichuan-ai.com' providers/baichuan.yaml`
+ - `grep -q 'hunyuan' providers/tencent.yaml`
+ - `grep -q 'spark_desk' providers/iflytek.yaml`
+ - 7 of 8 files have NO patterns field: `grep -L 'patterns:' providers/{baichuan,stepfun,sensetime,iflytek,tencent,360ai,kuaishou}.yaml` returns all 7
+ - `go test ./pkg/providers/... -count=1` passes
+ - `go test ./pkg/engine/... -count=1` passes
+ - Total Tier 4 provider count = 16: `grep -l 'tier: 4' providers/*.yaml | wc -l` → 16
+
+ All 16 Tier 4 Chinese/regional providers exist dual-located. PROV-04 satisfied.
+
+
+
+
+
+`grep -l 'tier: 4' providers/*.yaml | wc -l` returns 16.
+`go test ./pkg/providers/... ./pkg/engine/... -count=1` passes.
+
+
+
+- 16 Tier 4 providers dual-located
+- 13 use keyword-only detection (no patterns field)
+- 3 use documented prefix patterns (deepseek, moonshot, qwen, siliconflow — note: 4 with patterns, adjust count)
+- Registry loads all without validation errors
+- No engine test regressions
+
+
+
diff --git a/.planning/phases/03-tier-3-9-providers/03-02-PLAN.md b/.planning/phases/03-tier-3-9-providers/03-02-PLAN.md
new file mode 100644
index 0000000..b6478c6
--- /dev/null
+++ b/.planning/phases/03-tier-3-9-providers/03-02-PLAN.md
@@ -0,0 +1,418 @@
+---
+phase: 03-tier-3-9-providers
+plan: 02
+type: execute
+wave: 1
+depends_on: []
+files_modified:
+ - providers/perplexity.yaml
+ - providers/you.yaml
+ - providers/voyage.yaml
+ - providers/jina.yaml
+ - providers/unstructured.yaml
+ - providers/assemblyai.yaml
+ - providers/deepgram.yaml
+ - providers/elevenlabs.yaml
+ - providers/stability.yaml
+ - providers/runway.yaml
+ - providers/midjourney.yaml
+ - pkg/providers/definitions/perplexity.yaml
+ - pkg/providers/definitions/you.yaml
+ - pkg/providers/definitions/voyage.yaml
+ - pkg/providers/definitions/jina.yaml
+ - pkg/providers/definitions/unstructured.yaml
+ - pkg/providers/definitions/assemblyai.yaml
+ - pkg/providers/definitions/deepgram.yaml
+ - pkg/providers/definitions/elevenlabs.yaml
+ - pkg/providers/definitions/stability.yaml
+ - pkg/providers/definitions/runway.yaml
+ - pkg/providers/definitions/midjourney.yaml
+autonomous: true
+requirements: [PROV-03]
+must_haves:
+ truths:
+ - "11 new Tier 3 Specialized provider YAMLs load (huggingface already exists → 12 total)"
+ - "Providers with documented prefixes (pplx-, xai-voyage, sk-, jina_) use tight regex"
+ - "Voice/image providers without documented prefixes use keyword-only"
+ artifacts:
+ - path: "providers/perplexity.yaml"
+ provides: "Perplexity pplx- prefix pattern"
+ contains: "pplx-"
+ - path: "providers/elevenlabs.yaml"
+ provides: "ElevenLabs API key keyword detection"
+ contains: "elevenlabs"
+ - path: "providers/assemblyai.yaml"
+ provides: "AssemblyAI keyword detection"
+ contains: "assemblyai"
+ key_links:
+ - from: "provider keywords[]"
+ to: "Registry Aho-Corasick automaton"
+ via: "NewRegistry()"
+ pattern: "keywords"
+---
+
+
+Create 11 Tier 3 Specialized LLM/AI provider YAMLs — search (Perplexity, You.com), embeddings (Voyage, Jina, Unstructured), voice (AssemblyAI, Deepgram, ElevenLabs), and image/video (Stability, Runway, Midjourney). Huggingface is pre-existing from Phase 2 and must NOT be recreated. Total Tier 3 = 12 after this plan.
+
+Purpose: Satisfy PROV-03 (12 Tier 3 Specialized providers).
+
+Output: 22 YAML files (11 providers × 2 locations).
+
+Addresses PROV-03.
+
+
+
+@$HOME/.claude/get-shit-done/workflows/execute-plan.md
+@$HOME/.claude/get-shit-done/templates/summary.md
+
+
+
+@.planning/ROADMAP.md
+@.planning/phases/03-tier-3-9-providers/03-CONTEXT.md
+@pkg/providers/schema.go
+@providers/huggingface.yaml
+@providers/cohere.yaml
+
+
+Schema: pkg/providers/schema.go. No `category` field. Confidence: high|medium|low.
+Patterns field may be omitted for keyword-only providers. Keywords ≥3 required.
+Dual-location required (providers/ + pkg/providers/definitions/).
+RE2 regex only.
+
+IMPORTANT: providers/huggingface.yaml ALREADY EXISTS (tier: 3). Do NOT modify or recreate it.
+
+
+
+
+
+
+ Task 1: Search + embeddings providers (Perplexity, You.com, Voyage, Jina, Unstructured, AssemblyAI)
+ providers/perplexity.yaml, providers/you.yaml, providers/voyage.yaml, providers/jina.yaml, providers/unstructured.yaml, providers/assemblyai.yaml, pkg/providers/definitions/perplexity.yaml, pkg/providers/definitions/you.yaml, pkg/providers/definitions/voyage.yaml, pkg/providers/definitions/jina.yaml, pkg/providers/definitions/unstructured.yaml, pkg/providers/definitions/assemblyai.yaml
+
+ - pkg/providers/schema.go
+ - providers/huggingface.yaml (existing tier 3 reference — DO NOT MODIFY)
+
+
+Create each file in providers/ AND copy verbatim to pkg/providers/definitions/.
+
+providers/perplexity.yaml:
+```yaml
+format_version: 1
+name: perplexity
+display_name: Perplexity AI
+tier: 3
+last_verified: "2026-04-05"
+keywords:
+ - "perplexity"
+ - "PERPLEXITY_API_KEY"
+ - "pplx-"
+ - "api.perplexity.ai"
+patterns:
+ - regex: 'pplx-[A-Za-z0-9]{48,}'
+ entropy_min: 4.0
+ confidence: high
+verify:
+ method: POST
+ url: https://api.perplexity.ai/chat/completions
+ headers:
+ Authorization: "Bearer {KEY}"
+ valid_status: [200, 400]
+ invalid_status: [401, 403]
+```
+
+providers/you.yaml:
+```yaml
+format_version: 1
+name: you
+display_name: You.com
+tier: 3
+last_verified: "2026-04-05"
+keywords:
+ - "you.com"
+ - "YDC_API_KEY"
+ - "YOU_API_KEY"
+ - "api.ydc-index.io"
+verify:
+ method: GET
+ url: https://api.ydc-index.io/search
+ headers:
+ X-API-Key: "{KEY}"
+ valid_status: [200, 400]
+ invalid_status: [401, 403]
+```
+
+providers/voyage.yaml:
+```yaml
+format_version: 1
+name: voyage
+display_name: Voyage AI
+tier: 3
+last_verified: "2026-04-05"
+keywords:
+ - "voyage"
+ - "VOYAGE_API_KEY"
+ - "voyageai"
+ - "api.voyageai.com"
+patterns:
+ - regex: 'pa-[A-Za-z0-9_\-]{40,}'
+ entropy_min: 4.0
+ confidence: medium
+verify:
+ method: POST
+ url: https://api.voyageai.com/v1/embeddings
+ headers:
+ Authorization: "Bearer {KEY}"
+ valid_status: [200, 400]
+ invalid_status: [401, 403]
+```
+
+providers/jina.yaml:
+```yaml
+format_version: 1
+name: jina
+display_name: Jina AI
+tier: 3
+last_verified: "2026-04-05"
+keywords:
+ - "jina"
+ - "JINA_API_KEY"
+ - "api.jina.ai"
+ - "jinaai"
+patterns:
+ - regex: 'jina_[A-Za-z0-9]{40,}'
+ entropy_min: 4.0
+ confidence: high
+verify:
+ method: GET
+ url: https://api.jina.ai/v1/models
+ headers:
+ Authorization: "Bearer {KEY}"
+ valid_status: [200]
+ invalid_status: [401, 403]
+```
+
+providers/unstructured.yaml:
+```yaml
+format_version: 1
+name: unstructured
+display_name: Unstructured.io
+tier: 3
+last_verified: "2026-04-05"
+keywords:
+ - "unstructured"
+ - "UNSTRUCTURED_API_KEY"
+ - "api.unstructured.io"
+ - "unstructuredio"
+verify:
+ method: GET
+ url: https://api.unstructured.io/general/v0/general
+ headers:
+ unstructured-api-key: "{KEY}"
+ valid_status: [200, 400]
+ invalid_status: [401, 403]
+```
+
+providers/assemblyai.yaml:
+```yaml
+format_version: 1
+name: assemblyai
+display_name: AssemblyAI
+tier: 3
+last_verified: "2026-04-05"
+keywords:
+ - "assemblyai"
+ - "ASSEMBLYAI_API_KEY"
+ - "api.assemblyai.com"
+ - "assembly.ai"
+patterns:
+ - regex: '[a-f0-9]{32}'
+ entropy_min: 4.0
+ confidence: low
+verify:
+ method: GET
+ url: https://api.assemblyai.com/v2/transcript
+ headers:
+ authorization: "{KEY}"
+ valid_status: [200]
+ invalid_status: [401, 403]
+```
+
+Copy all 6 files verbatim to pkg/providers/definitions/.
+
+
+ cd /home/salva/Documents/apikey && for f in perplexity you voyage jina unstructured assemblyai; do diff providers/$f.yaml pkg/providers/definitions/$f.yaml || exit 1; done && go test ./pkg/providers/... -count=1 && go test ./pkg/engine/... -count=1
+
+
+ - All 12 files exist (6 providers × 2 locations)
+ - `grep -q 'pplx-' providers/perplexity.yaml`
+ - `grep -q 'jina_' providers/jina.yaml`
+ - `grep -q 'api.voyageai.com' providers/voyage.yaml`
+ - `diff providers/perplexity.yaml pkg/providers/definitions/perplexity.yaml` returns no diff
+ - `go test ./pkg/providers/... -count=1` passes
+ - `go test ./pkg/engine/... -count=1` passes
+
+ 6 search/embeddings providers dual-located.
+
+
+
+ Task 2: Voice + image/video providers (Deepgram, ElevenLabs, Stability, Runway, Midjourney)
+ providers/deepgram.yaml, providers/elevenlabs.yaml, providers/stability.yaml, providers/runway.yaml, providers/midjourney.yaml, pkg/providers/definitions/deepgram.yaml, pkg/providers/definitions/elevenlabs.yaml, pkg/providers/definitions/stability.yaml, pkg/providers/definitions/runway.yaml, pkg/providers/definitions/midjourney.yaml
+
+ - pkg/providers/schema.go
+
+
+providers/deepgram.yaml:
+```yaml
+format_version: 1
+name: deepgram
+display_name: Deepgram
+tier: 3
+last_verified: "2026-04-05"
+keywords:
+ - "deepgram"
+ - "DEEPGRAM_API_KEY"
+ - "api.deepgram.com"
+ - "dg-api"
+patterns:
+ - regex: '[a-f0-9]{40}'
+ entropy_min: 4.0
+ confidence: low
+verify:
+ method: GET
+ url: https://api.deepgram.com/v1/projects
+ headers:
+ Authorization: "Token {KEY}"
+ valid_status: [200]
+ invalid_status: [401, 403]
+```
+
+providers/elevenlabs.yaml:
+```yaml
+format_version: 1
+name: elevenlabs
+display_name: ElevenLabs
+tier: 3
+last_verified: "2026-04-05"
+keywords:
+ - "elevenlabs"
+ - "ELEVENLABS_API_KEY"
+ - "ELEVEN_API_KEY"
+ - "XI_API_KEY"
+ - "api.elevenlabs.io"
+patterns:
+ - regex: '[a-f0-9]{32}'
+ entropy_min: 4.0
+ confidence: low
+verify:
+ method: GET
+ url: https://api.elevenlabs.io/v1/user
+ headers:
+ xi-api-key: "{KEY}"
+ valid_status: [200]
+ invalid_status: [401, 403]
+```
+
+providers/stability.yaml:
+```yaml
+format_version: 1
+name: stability
+display_name: Stability AI
+tier: 3
+last_verified: "2026-04-05"
+keywords:
+ - "stability"
+ - "STABILITY_API_KEY"
+ - "STABILITY_KEY"
+ - "api.stability.ai"
+ - "stable-diffusion"
+patterns:
+ - regex: 'sk-[A-Za-z0-9]{48}'
+ entropy_min: 4.0
+ confidence: medium
+verify:
+ method: GET
+ url: https://api.stability.ai/v1/user/account
+ headers:
+ Authorization: "Bearer {KEY}"
+ valid_status: [200]
+ invalid_status: [401, 403]
+```
+
+providers/runway.yaml:
+```yaml
+format_version: 1
+name: runway
+display_name: Runway
+tier: 3
+last_verified: "2026-04-05"
+keywords:
+ - "runway"
+ - "runwayml"
+ - "RUNWAY_API_KEY"
+ - "RUNWAYML_API_SECRET"
+ - "api.runwayml.com"
+ - "dev.runwayml.com"
+verify:
+ method: GET
+ url: https://api.dev.runwayml.com/v1/tasks
+ headers:
+ Authorization: "Bearer {KEY}"
+ valid_status: [200, 400]
+ invalid_status: [401, 403]
+```
+
+providers/midjourney.yaml:
+```yaml
+format_version: 1
+name: midjourney
+display_name: Midjourney
+tier: 3
+last_verified: "2026-04-05"
+keywords:
+ - "midjourney"
+ - "MIDJOURNEY_API_KEY"
+ - "MJ_API_KEY"
+ - "midjourney.com"
+ - "useapi.net"
+verify:
+ method: GET
+ url: ""
+ headers: {}
+ valid_status: []
+ invalid_status: []
+```
+
+Copy all 5 files verbatim to pkg/providers/definitions/.
+
+
+ cd /home/salva/Documents/apikey && for f in deepgram elevenlabs stability runway midjourney; do diff providers/$f.yaml pkg/providers/definitions/$f.yaml || exit 1; done && go test ./pkg/providers/... -count=1 && go test ./pkg/engine/... -count=1
+
+
+ - All 10 files exist
+ - `grep -q 'XI_API_KEY' providers/elevenlabs.yaml`
+ - `grep -q 'stable-diffusion' providers/stability.yaml`
+ - `grep -q 'runwayml' providers/runway.yaml`
+ - `grep -L 'patterns:' providers/runway.yaml providers/midjourney.yaml` returns both (keyword-only)
+ - Total Tier 3 count: `grep -l 'tier: 3' providers/*.yaml | wc -l` → 12 (11 new + pre-existing huggingface)
+ - `go test ./pkg/providers/... -count=1` passes
+ - `go test ./pkg/engine/... -count=1` passes
+
+ All 11 new Tier 3 Specialized providers dual-located. PROV-03 satisfied (12 total with pre-existing huggingface).
+
+
+
+
+
+`grep -l 'tier: 3' providers/*.yaml | wc -l` returns 12.
+
+
+
+- 11 new Tier 3 providers added (huggingface pre-existing, total 12)
+- All dual-located
+- Documented prefixes use tight regex; undocumented use keyword-only
+- No engine regression
+
+
+
diff --git a/.planning/phases/03-tier-3-9-providers/03-03-PLAN.md b/.planning/phases/03-tier-3-9-providers/03-03-PLAN.md
new file mode 100644
index 0000000..c103519
--- /dev/null
+++ b/.planning/phases/03-tier-3-9-providers/03-03-PLAN.md
@@ -0,0 +1,393 @@
+---
+phase: 03-tier-3-9-providers
+plan: 03
+type: execute
+wave: 1
+depends_on: []
+files_modified:
+ - providers/openrouter.yaml
+ - providers/litellm.yaml
+ - providers/cloudflare-ai.yaml
+ - providers/vercel-ai.yaml
+ - providers/portkey.yaml
+ - providers/helicone.yaml
+ - providers/martian.yaml
+ - providers/kong.yaml
+ - providers/bricksai.yaml
+ - providers/aether.yaml
+ - providers/notdiamond.yaml
+ - pkg/providers/definitions/openrouter.yaml
+ - pkg/providers/definitions/litellm.yaml
+ - pkg/providers/definitions/cloudflare-ai.yaml
+ - pkg/providers/definitions/vercel-ai.yaml
+ - pkg/providers/definitions/portkey.yaml
+ - pkg/providers/definitions/helicone.yaml
+ - pkg/providers/definitions/martian.yaml
+ - pkg/providers/definitions/kong.yaml
+ - pkg/providers/definitions/bricksai.yaml
+ - pkg/providers/definitions/aether.yaml
+ - pkg/providers/definitions/notdiamond.yaml
+autonomous: true
+requirements: [PROV-05]
+must_haves:
+ truths:
+ - "11 Tier 5 infrastructure/gateway provider YAMLs load"
+ - "OpenRouter sk-or- and Helicone sk-helicone- prefixes use high-confidence regex"
+ - "Gateway providers have strong keyword anchors to their SDK envs"
+ artifacts:
+ - path: "providers/openrouter.yaml"
+ provides: "OpenRouter sk-or- prefix pattern"
+ contains: "sk-or-"
+ - path: "providers/helicone.yaml"
+ provides: "Helicone sk-helicone- prefix pattern"
+ contains: "helicone"
+ - path: "providers/litellm.yaml"
+ provides: "LiteLLM proxy keyword detection"
+ contains: "litellm"
+ key_links:
+ - from: "provider keywords[]"
+ to: "Registry Aho-Corasick automaton"
+ via: "NewRegistry()"
+ pattern: "keywords"
+---
+
+
+Create 11 Tier 5 Infrastructure/Gateway provider YAMLs — LLM routers, proxies, and observability gateways (OpenRouter, LiteLLM, Cloudflare AI, Vercel AI, Portkey, Helicone, Martian, Kong, BricksAI, Aether, Not Diamond).
+
+Purpose: Satisfy PROV-05 (11 Tier 5 Infrastructure/Gateway providers). Several of these have documented key prefixes (sk-or-, sk-helicone-) that support high-confidence detection.
+
+Output: 22 YAML files.
+
+Addresses PROV-05.
+
+
+
+@$HOME/.claude/get-shit-done/workflows/execute-plan.md
+@$HOME/.claude/get-shit-done/templates/summary.md
+
+
+
+@.planning/ROADMAP.md
+@.planning/phases/03-tier-3-9-providers/03-CONTEXT.md
+@pkg/providers/schema.go
+@providers/groq.yaml
+
+
+Schema per pkg/providers/schema.go. No category field. Dual-location required. RE2 regex only.
+Keyword-only detection for providers without documented key formats.
+
+
+
+
+
+
+ Task 1: OpenRouter, LiteLLM, Cloudflare, Vercel, Portkey, Helicone YAMLs
+ providers/openrouter.yaml, providers/litellm.yaml, providers/cloudflare-ai.yaml, providers/vercel-ai.yaml, providers/portkey.yaml, providers/helicone.yaml, pkg/providers/definitions/openrouter.yaml, pkg/providers/definitions/litellm.yaml, pkg/providers/definitions/cloudflare-ai.yaml, pkg/providers/definitions/vercel-ai.yaml, pkg/providers/definitions/portkey.yaml, pkg/providers/definitions/helicone.yaml
+
+ - pkg/providers/schema.go
+
+
+providers/openrouter.yaml:
+```yaml
+format_version: 1
+name: openrouter
+display_name: OpenRouter
+tier: 5
+last_verified: "2026-04-05"
+keywords:
+ - "openrouter"
+ - "OPENROUTER_API_KEY"
+ - "openrouter.ai"
+ - "sk-or-"
+patterns:
+ - regex: 'sk-or-v1-[a-f0-9]{64}'
+ entropy_min: 4.0
+ confidence: high
+ - regex: 'sk-or-[A-Za-z0-9]{40,}'
+ entropy_min: 4.0
+ confidence: medium
+verify:
+ method: GET
+ url: https://openrouter.ai/api/v1/auth/key
+ headers:
+ Authorization: "Bearer {KEY}"
+ valid_status: [200]
+ invalid_status: [401, 403]
+```
+
+providers/litellm.yaml:
+```yaml
+format_version: 1
+name: litellm
+display_name: LiteLLM Proxy
+tier: 5
+last_verified: "2026-04-05"
+keywords:
+ - "litellm"
+ - "LITELLM_API_KEY"
+ - "LITELLM_MASTER_KEY"
+ - "LITELLM_PROXY_API_KEY"
+patterns:
+ - regex: 'sk-[A-Za-z0-9_\-]{20,}'
+ entropy_min: 4.0
+ confidence: low
+verify:
+ method: GET
+ url: ""
+ headers: {}
+ valid_status: []
+ invalid_status: []
+```
+
+providers/cloudflare-ai.yaml:
+```yaml
+format_version: 1
+name: cloudflare-ai
+display_name: Cloudflare Workers AI
+tier: 5
+last_verified: "2026-04-05"
+keywords:
+ - "cloudflare"
+ - "workers-ai"
+ - "CLOUDFLARE_API_TOKEN"
+ - "CLOUDFLARE_ACCOUNT_ID"
+ - "CF_API_TOKEN"
+ - "api.cloudflare.com"
+patterns:
+ - regex: '[A-Za-z0-9_\-]{40}'
+ entropy_min: 4.5
+ confidence: low
+verify:
+ method: GET
+ url: https://api.cloudflare.com/client/v4/user/tokens/verify
+ headers:
+ Authorization: "Bearer {KEY}"
+ valid_status: [200]
+ invalid_status: [401, 403]
+```
+
+providers/vercel-ai.yaml:
+```yaml
+format_version: 1
+name: vercel-ai
+display_name: Vercel AI Gateway
+tier: 5
+last_verified: "2026-04-05"
+keywords:
+ - "vercel"
+ - "VERCEL_AI_GATEWAY"
+ - "AI_GATEWAY_API_KEY"
+ - "vercel.ai"
+ - "ai-sdk"
+verify:
+ method: GET
+ url: ""
+ headers: {}
+ valid_status: []
+ invalid_status: []
+```
+
+providers/portkey.yaml:
+```yaml
+format_version: 1
+name: portkey
+display_name: Portkey
+tier: 5
+last_verified: "2026-04-05"
+keywords:
+ - "portkey"
+ - "PORTKEY_API_KEY"
+ - "api.portkey.ai"
+ - "portkey-ai"
+verify:
+ method: GET
+ url: https://api.portkey.ai/v1/feedback
+ headers:
+ x-portkey-api-key: "{KEY}"
+ valid_status: [200, 400]
+ invalid_status: [401, 403]
+```
+
+providers/helicone.yaml:
+```yaml
+format_version: 1
+name: helicone
+display_name: Helicone
+tier: 5
+last_verified: "2026-04-05"
+keywords:
+ - "helicone"
+ - "HELICONE_API_KEY"
+ - "sk-helicone-"
+ - "api.helicone.ai"
+patterns:
+ - regex: 'sk-helicone-[a-z0-9]{7}-[a-z0-9]{7}-[a-z0-9]{7}-[a-z0-9]{7}'
+ entropy_min: 3.5
+ confidence: high
+verify:
+ method: GET
+ url: https://api.helicone.ai/v1/key/verify
+ headers:
+ Authorization: "Bearer {KEY}"
+ valid_status: [200]
+ invalid_status: [401, 403]
+```
+
+Copy all 6 files verbatim to pkg/providers/definitions/.
+
+
+ cd /home/salva/Documents/apikey && for f in openrouter litellm cloudflare-ai vercel-ai portkey helicone; do diff providers/$f.yaml pkg/providers/definitions/$f.yaml || exit 1; done && go test ./pkg/providers/... -count=1 && go test ./pkg/engine/... -count=1
+
+
+ - All 12 files exist
+ - `grep -q 'sk-or-v1-' providers/openrouter.yaml`
+ - `grep -q 'sk-helicone-' providers/helicone.yaml`
+ - `grep -q 'LITELLM_MASTER_KEY' providers/litellm.yaml`
+ - `go test ./pkg/providers/... -count=1` passes
+ - `go test ./pkg/engine/... -count=1` passes
+
+ 6 major gateway providers dual-located.
+
+
+
+ Task 2: Martian, Kong, BricksAI, Aether, Not Diamond YAMLs
+ providers/martian.yaml, providers/kong.yaml, providers/bricksai.yaml, providers/aether.yaml, providers/notdiamond.yaml, pkg/providers/definitions/martian.yaml, pkg/providers/definitions/kong.yaml, pkg/providers/definitions/bricksai.yaml, pkg/providers/definitions/aether.yaml, pkg/providers/definitions/notdiamond.yaml
+
+ - pkg/providers/schema.go
+
+
+All 5 use keyword-only detection (no documented public key formats). Omit patterns field.
+
+providers/martian.yaml:
+```yaml
+format_version: 1
+name: martian
+display_name: Martian (Model Router)
+tier: 5
+last_verified: "2026-04-05"
+keywords:
+ - "withmartian"
+ - "MARTIAN_API_KEY"
+ - "withmartian.com"
+ - "martian-router"
+verify:
+ method: GET
+ url: ""
+ headers: {}
+ valid_status: []
+ invalid_status: []
+```
+
+providers/kong.yaml:
+```yaml
+format_version: 1
+name: kong
+display_name: Kong AI Gateway
+tier: 5
+last_verified: "2026-04-05"
+keywords:
+ - "kong"
+ - "KONG_API_KEY"
+ - "kong-ai-gateway"
+ - "konghq.com"
+ - "ai-proxy"
+verify:
+ method: GET
+ url: ""
+ headers: {}
+ valid_status: []
+ invalid_status: []
+```
+
+providers/bricksai.yaml:
+```yaml
+format_version: 1
+name: bricksai
+display_name: BricksAI
+tier: 5
+last_verified: "2026-04-05"
+keywords:
+ - "bricksai"
+ - "BRICKS_API_KEY"
+ - "trybricks.ai"
+ - "bricksllm"
+verify:
+ method: GET
+ url: ""
+ headers: {}
+ valid_status: []
+ invalid_status: []
+```
+
+providers/aether.yaml:
+```yaml
+format_version: 1
+name: aether
+display_name: Aether AI
+tier: 5
+last_verified: "2026-04-05"
+keywords:
+ - "aether"
+ - "AETHER_API_KEY"
+ - "aether.ai"
+ - "aetherplatform"
+verify:
+ method: GET
+ url: ""
+ headers: {}
+ valid_status: []
+ invalid_status: []
+```
+
+providers/notdiamond.yaml:
+```yaml
+format_version: 1
+name: notdiamond
+display_name: Not Diamond
+tier: 5
+last_verified: "2026-04-05"
+keywords:
+ - "notdiamond"
+ - "NOTDIAMOND_API_KEY"
+ - "not-diamond"
+ - "notdiamond.ai"
+verify:
+ method: GET
+ url: ""
+ headers: {}
+ valid_status: []
+ invalid_status: []
+```
+
+Copy all 5 files verbatim to pkg/providers/definitions/.
+
+
+ cd /home/salva/Documents/apikey && for f in martian kong bricksai aether notdiamond; do diff providers/$f.yaml pkg/providers/definitions/$f.yaml || exit 1; done && go test ./pkg/providers/... -count=1 && go test ./pkg/engine/... -count=1 && test "$(grep -l 'tier: 5' providers/*.yaml | wc -l)" = "11"
+
+
+ - All 10 files exist
+ - `grep -q 'withmartian' providers/martian.yaml`
+ - `grep -q 'konghq.com' providers/kong.yaml`
+ - All 5 omit patterns field: `grep -L 'patterns:' providers/{martian,kong,bricksai,aether,notdiamond}.yaml` returns all 5
+ - Total Tier 5 count = 11: `grep -l 'tier: 5' providers/*.yaml | wc -l` → 11
+ - `go test ./pkg/providers/... -count=1` passes
+
+ All 11 Tier 5 gateway providers dual-located. PROV-05 satisfied.
+
+
+
+
+
+`grep -l 'tier: 5' providers/*.yaml | wc -l` returns 11.
+
+
+
+- 11 Tier 5 gateway providers created
+- Documented prefixes use tight high-confidence regex (openrouter, helicone)
+- Undocumented providers use keyword-only detection
+- No engine test regressions
+
+
+
diff --git a/.planning/phases/03-tier-3-9-providers/03-04-PLAN.md b/.planning/phases/03-tier-3-9-providers/03-04-PLAN.md
new file mode 100644
index 0000000..fee7500
--- /dev/null
+++ b/.planning/phases/03-tier-3-9-providers/03-04-PLAN.md
@@ -0,0 +1,382 @@
+---
+phase: 03-tier-3-9-providers
+plan: 04
+type: execute
+wave: 1
+depends_on: []
+files_modified:
+ - providers/github-copilot.yaml
+ - providers/cursor.yaml
+ - providers/tabnine.yaml
+ - providers/codeium.yaml
+ - providers/sourcegraph.yaml
+ - providers/codewhisperer.yaml
+ - providers/replit-ai.yaml
+ - providers/codestral.yaml
+ - providers/watsonx.yaml
+ - providers/oracle-ai.yaml
+ - pkg/providers/definitions/github-copilot.yaml
+ - pkg/providers/definitions/cursor.yaml
+ - pkg/providers/definitions/tabnine.yaml
+ - pkg/providers/definitions/codeium.yaml
+ - pkg/providers/definitions/sourcegraph.yaml
+ - pkg/providers/definitions/codewhisperer.yaml
+ - pkg/providers/definitions/replit-ai.yaml
+ - pkg/providers/definitions/codestral.yaml
+ - pkg/providers/definitions/watsonx.yaml
+ - pkg/providers/definitions/oracle-ai.yaml
+autonomous: true
+requirements: [PROV-07]
+must_haves:
+ truths:
+ - "10 Tier 7 Code/Dev Tools provider YAMLs load"
+ - "Sourcegraph Cody uses documented sgp_ prefix pattern"
+ - "GitHub Copilot uses ghu_/gho_ token patterns"
+ artifacts:
+ - path: "providers/github-copilot.yaml"
+ provides: "GitHub Copilot token pattern"
+ contains: "copilot"
+ - path: "providers/sourcegraph.yaml"
+ provides: "Sourcegraph Cody sgp_ pattern"
+ contains: "sgp_"
+ - path: "providers/codestral.yaml"
+ provides: "Codestral (Mistral) keyword detection"
+ contains: "codestral"
+ key_links:
+ - from: "provider keywords[]"
+ to: "Registry Aho-Corasick automaton"
+ via: "NewRegistry()"
+ pattern: "keywords"
+---
+
+
+Create 10 Tier 7 Code/Dev Tools provider YAMLs — AI coding assistants and IDE plugins (GitHub Copilot, Cursor, Tabnine, Codeium, Sourcegraph Cody, Amazon CodeWhisperer, Replit AI, Codestral, IBM watsonx, Oracle AI).
+
+Purpose: Satisfy PROV-07 (10 Tier 7 Code/Dev Tools providers).
+
+Output: 20 YAML files.
+
+Addresses PROV-07.
+
+
+
+@$HOME/.claude/get-shit-done/workflows/execute-plan.md
+@$HOME/.claude/get-shit-done/templates/summary.md
+
+
+
+@.planning/ROADMAP.md
+@.planning/phases/03-tier-3-9-providers/03-CONTEXT.md
+@pkg/providers/schema.go
+
+
+Schema per pkg/providers/schema.go. Dual-location required. RE2 regex only.
+GitHub Copilot uses standard GitHub token formats (ghu_, gho_) — keyword anchoring to "copilot" disambiguates from generic GitHub tokens.
+
+
+
+
+
+
+ Task 1: GitHub Copilot, Cursor, Tabnine, Codeium, Sourcegraph YAMLs
+ providers/github-copilot.yaml, providers/cursor.yaml, providers/tabnine.yaml, providers/codeium.yaml, providers/sourcegraph.yaml, pkg/providers/definitions/github-copilot.yaml, pkg/providers/definitions/cursor.yaml, pkg/providers/definitions/tabnine.yaml, pkg/providers/definitions/codeium.yaml, pkg/providers/definitions/sourcegraph.yaml
+
+ - pkg/providers/schema.go
+
+
+providers/github-copilot.yaml:
+
+```yaml
+format_version: 1
+name: github-copilot
+display_name: GitHub Copilot
+tier: 7
+last_verified: "2026-04-05"
+keywords:
+ - "copilot"
+ - "github-copilot"
+ - "GITHUB_COPILOT_TOKEN"
+ - "api.githubcopilot.com"
+ - "copilot-internal"
+patterns:
+ - regex: 'ghu_[A-Za-z0-9]{36}'
+ entropy_min: 4.0
+ confidence: medium
+ - regex: 'gho_[A-Za-z0-9]{36}'
+ entropy_min: 4.0
+ confidence: medium
+verify:
+ method: GET
+ url: https://api.github.com/user
+ headers:
+ Authorization: "token {KEY}"
+ valid_status: [200]
+ invalid_status: [401, 403]
+```
+
+providers/cursor.yaml:
+
+```yaml
+format_version: 1
+name: cursor
+display_name: Cursor AI
+tier: 7
+last_verified: "2026-04-05"
+keywords:
+ - "cursor"
+ - "CURSOR_API_KEY"
+ - "cursor.sh"
+ - "cursor.com"
+ - "cursor-ide"
+verify:
+ method: GET
+ url: ""
+ headers: {}
+ valid_status: []
+ invalid_status: []
+```
+
+providers/tabnine.yaml:
+
+```yaml
+format_version: 1
+name: tabnine
+display_name: Tabnine
+tier: 7
+last_verified: "2026-04-05"
+keywords:
+ - "tabnine"
+ - "TABNINE_API_KEY"
+ - "api.tabnine.com"
+ - "tabnine-pro"
+verify:
+ method: GET
+ url: ""
+ headers: {}
+ valid_status: []
+ invalid_status: []
+```
+
+providers/codeium.yaml:
+
+```yaml
+format_version: 1
+name: codeium
+display_name: Codeium (Windsurf)
+tier: 7
+last_verified: "2026-04-05"
+keywords:
+ - "codeium"
+ - "windsurf"
+ - "CODEIUM_API_KEY"
+ - "WINDSURF_API_KEY"
+ - "codeium.com"
+verify:
+ method: GET
+ url: ""
+ headers: {}
+ valid_status: []
+ invalid_status: []
+```
+
+providers/sourcegraph.yaml:
+
+```yaml
+format_version: 1
+name: sourcegraph
+display_name: Sourcegraph Cody
+tier: 7
+last_verified: "2026-04-05"
+keywords:
+ - "sourcegraph"
+ - "cody"
+ - "SRC_ACCESS_TOKEN"
+ - "SOURCEGRAPH_TOKEN"
+ - "sourcegraph.com"
+ - "sgp_"
+patterns:
+ - regex: 'sgp_[A-Fa-f0-9]{16,}_[A-Fa-f0-9]{40}'
+ entropy_min: 4.0
+ confidence: high
+ - regex: 'sgp_[A-Fa-f0-9]{40}'
+ entropy_min: 4.0
+ confidence: medium
+verify:
+ method: GET
+ url: https://sourcegraph.com/.api/graphql
+ headers:
+ Authorization: "token {KEY}"
+ valid_status: [200]
+ invalid_status: [401, 403]
+```
+
+Copy all 5 files verbatim to pkg/providers/definitions/.
+
+
+ cd /home/salva/Documents/apikey && for f in github-copilot cursor tabnine codeium sourcegraph; do diff providers/$f.yaml pkg/providers/definitions/$f.yaml || exit 1; done && go test ./pkg/providers/... -count=1 && go test ./pkg/engine/... -count=1
+
+
+ - All 10 files exist
+ - `grep -q 'ghu_' providers/github-copilot.yaml`
+ - `grep -q 'sgp_' providers/sourcegraph.yaml`
+ - `grep -q 'windsurf' providers/codeium.yaml`
+ - `go test ./pkg/providers/... -count=1` passes
+ - `go test ./pkg/engine/... -count=1` passes
+
+ 5 code assistant providers dual-located.
+
+
+
+ Task 2: CodeWhisperer, Replit AI, Codestral, watsonx, Oracle AI YAMLs
+ providers/codewhisperer.yaml, providers/replit-ai.yaml, providers/codestral.yaml, providers/watsonx.yaml, providers/oracle-ai.yaml, pkg/providers/definitions/codewhisperer.yaml, pkg/providers/definitions/replit-ai.yaml, pkg/providers/definitions/codestral.yaml, pkg/providers/definitions/watsonx.yaml, pkg/providers/definitions/oracle-ai.yaml
+
+ - pkg/providers/schema.go
+
+
+providers/codewhisperer.yaml:
+
+```yaml
+format_version: 1
+name: codewhisperer
+display_name: Amazon CodeWhisperer / Q Developer
+tier: 7
+last_verified: "2026-04-05"
+keywords:
+ - "codewhisperer"
+ - "q-developer"
+ - "amazonq"
+ - "codewhisperer.us-east-1.amazonaws.com"
+ - "CODEWHISPERER_PROFILE_ARN"
+verify:
+ method: GET
+ url: ""
+ headers: {}
+ valid_status: []
+ invalid_status: []
+```
+
+providers/replit-ai.yaml:
+
+```yaml
+format_version: 1
+name: replit-ai
+display_name: Replit AI (Ghostwriter)
+tier: 7
+last_verified: "2026-04-05"
+keywords:
+ - "replit"
+ - "ghostwriter"
+ - "REPLIT_TOKEN"
+ - "REPLIT_DB_URL"
+ - "replit.com"
+verify:
+ method: GET
+ url: ""
+ headers: {}
+ valid_status: []
+ invalid_status: []
+```
+
+providers/codestral.yaml:
+
+```yaml
+format_version: 1
+name: codestral
+display_name: Codestral (Mistral Code)
+tier: 7
+last_verified: "2026-04-05"
+keywords:
+ - "codestral"
+ - "CODESTRAL_API_KEY"
+ - "codestral.mistral.ai"
+ - "codestral-latest"
+patterns:
+ - regex: '[a-zA-Z0-9]{32}'
+ entropy_min: 4.5
+ confidence: low
+verify:
+ method: GET
+ url: https://codestral.mistral.ai/v1/models
+ headers:
+ Authorization: "Bearer {KEY}"
+ valid_status: [200]
+ invalid_status: [401, 403]
+```
+
+providers/watsonx.yaml:
+
+```yaml
+format_version: 1
+name: watsonx
+display_name: IBM watsonx
+tier: 7
+last_verified: "2026-04-05"
+keywords:
+ - "watsonx"
+ - "WATSONX_API_KEY"
+ - "WATSONX_PROJECT_ID"
+ - "IBM_CLOUD_API_KEY"
+ - "us-south.ml.cloud.ibm.com"
+ - "watsonx.ai"
+verify:
+ method: POST
+ url: https://iam.cloud.ibm.com/identity/token
+ headers: {}
+ valid_status: [200]
+ invalid_status: [400, 401]
+```
+
+providers/oracle-ai.yaml:
+
+```yaml
+format_version: 1
+name: oracle-ai
+display_name: Oracle Generative AI
+tier: 7
+last_verified: "2026-04-05"
+keywords:
+ - "oci-genai"
+ - "oracle-genai"
+ - "OCI_GENAI"
+ - "generativeai.oci.oraclecloud.com"
+ - "oraclecloud.com"
+verify:
+ method: GET
+ url: ""
+ headers: {}
+ valid_status: []
+ invalid_status: []
+```
+
+Copy all 5 files verbatim to pkg/providers/definitions/.
+
+
+ cd /home/salva/Documents/apikey && for f in codewhisperer replit-ai codestral watsonx oracle-ai; do diff providers/$f.yaml pkg/providers/definitions/$f.yaml || exit 1; done && go test ./pkg/providers/... -count=1 && go test ./pkg/engine/... -count=1 && test $(grep -l 'tier: 7' providers/*.yaml | wc -l) -eq 10
+
+
+ - All 10 files exist
+ - `grep -q 'codewhisperer' providers/codewhisperer.yaml`
+ - `grep -q 'watsonx.ai' providers/watsonx.yaml`
+ - `grep -q 'oraclecloud' providers/oracle-ai.yaml`
+ - Total Tier 7 count = 10
+ - `go test ./pkg/providers/... -count=1` passes
+
+ All 10 Tier 7 code/dev tools providers dual-located. PROV-07 satisfied.
+
+
+
+
+
+`grep -l 'tier: 7' providers/*.yaml | wc -l` returns 10.
+
+
+
+- 10 Tier 7 code/dev tools providers created
+- Sourcegraph uses documented sgp_ high-confidence pattern
+- Undocumented providers (cursor, tabnine, codeium, codewhisperer, replit-ai, oracle-ai) use keyword-only
+- No engine regression
+
+
+
diff --git a/.planning/phases/03-tier-3-9-providers/03-05-PLAN.md b/.planning/phases/03-tier-3-9-providers/03-05-PLAN.md
new file mode 100644
index 0000000..c197552
--- /dev/null
+++ b/.planning/phases/03-tier-3-9-providers/03-05-PLAN.md
@@ -0,0 +1,364 @@
+---
+phase: 03-tier-3-9-providers
+plan: 05
+type: execute
+wave: 1
+depends_on: []
+files_modified:
+ - providers/ollama.yaml
+ - providers/vllm.yaml
+ - providers/localai.yaml
+ - providers/lmstudio.yaml
+ - providers/llamacpp.yaml
+ - providers/gpt4all.yaml
+ - providers/text-gen-webui.yaml
+ - providers/tensorrt-llm.yaml
+ - providers/triton.yaml
+ - providers/jan.yaml
+ - pkg/providers/definitions/ollama.yaml
+ - pkg/providers/definitions/vllm.yaml
+ - pkg/providers/definitions/localai.yaml
+ - pkg/providers/definitions/lmstudio.yaml
+ - pkg/providers/definitions/llamacpp.yaml
+ - pkg/providers/definitions/gpt4all.yaml
+ - pkg/providers/definitions/text-gen-webui.yaml
+ - pkg/providers/definitions/tensorrt-llm.yaml
+ - pkg/providers/definitions/triton.yaml
+ - pkg/providers/definitions/jan.yaml
+autonomous: true
+requirements: [PROV-08]
+must_haves:
+ truths:
+ - "10 Tier 8 Self-Hosted runtime provider YAMLs load"
+ - "Self-hosted runtimes mostly use keyword-only detection (local auth, not API keys)"
+ - "Runtimes exposing API key auth (vLLM --api-key, LocalAI) include env var keywords"
+ artifacts:
+ - path: "providers/ollama.yaml"
+ provides: "Ollama localhost endpoint keywords"
+ contains: "ollama"
+ - path: "providers/vllm.yaml"
+ provides: "vLLM --api-key detection keywords"
+ contains: "vllm"
+ key_links:
+ - from: "provider keywords[]"
+ to: "Registry Aho-Corasick automaton"
+ via: "NewRegistry()"
+ pattern: "keywords"
+---
+
+
+Create 10 Tier 8 Self-Hosted LLM runtime provider YAMLs — local inference servers (Ollama, vLLM, LocalAI, LM Studio, llama.cpp, GPT4All, text-generation-webui, TensorRT-LLM, Triton, Jan AI).
+
+Purpose: Satisfy PROV-08 (10 Tier 8 Self-Hosted providers). Self-hosted runtimes are interesting for OSINT (exposed endpoints via Shodan) even without API keys — keyword anchors enable later recon phases to correlate.
+
+Output: 20 YAML files.
+
+Addresses PROV-08.
+
+
+
+@$HOME/.claude/get-shit-done/workflows/execute-plan.md
+@$HOME/.claude/get-shit-done/templates/summary.md
+
+
+
+@.planning/ROADMAP.md
+@.planning/phases/03-tier-3-9-providers/03-CONTEXT.md
+@pkg/providers/schema.go
+
+
+Self-hosted runtimes rarely use bearer tokens. Detection relies on config env vars, localhost endpoints (11434, 8000, 1234), CLI flags. All use keyword-only — omit patterns entirely.
+
+
+
+
+
+
+ Task 1: Ollama, vLLM, LocalAI, LM Studio, llama.cpp YAMLs
+ providers/ollama.yaml, providers/vllm.yaml, providers/localai.yaml, providers/lmstudio.yaml, providers/llamacpp.yaml, pkg/providers/definitions/ollama.yaml, pkg/providers/definitions/vllm.yaml, pkg/providers/definitions/localai.yaml, pkg/providers/definitions/lmstudio.yaml, pkg/providers/definitions/llamacpp.yaml
+
+ - pkg/providers/schema.go
+
+
+All 5 use keyword-only detection — omit patterns field.
+
+providers/ollama.yaml:
+
+```yaml
+format_version: 1
+name: ollama
+display_name: Ollama
+tier: 8
+last_verified: "2026-04-05"
+keywords:
+ - "ollama"
+ - "OLLAMA_HOST"
+ - "OLLAMA_API_KEY"
+ - "OLLAMA_MODELS"
+ - "localhost:11434"
+ - "127.0.0.1:11434"
+ - "api/generate"
+verify:
+ method: GET
+ url: ""
+ headers: {}
+ valid_status: []
+ invalid_status: []
+```
+
+providers/vllm.yaml:
+
+```yaml
+format_version: 1
+name: vllm
+display_name: vLLM
+tier: 8
+last_verified: "2026-04-05"
+keywords:
+ - "vllm"
+ - "VLLM_API_KEY"
+ - "vllm-openai"
+ - "--api-key"
+ - "openai.api_server"
+ - "vllm.entrypoints"
+verify:
+ method: GET
+ url: ""
+ headers: {}
+ valid_status: []
+ invalid_status: []
+```
+
+providers/localai.yaml:
+
+```yaml
+format_version: 1
+name: localai
+display_name: LocalAI
+tier: 8
+last_verified: "2026-04-05"
+keywords:
+ - "localai"
+ - "LOCALAI_API_KEY"
+ - "go-skynet"
+ - "localai.io"
+ - "localhost:8080"
+verify:
+ method: GET
+ url: ""
+ headers: {}
+ valid_status: []
+ invalid_status: []
+```
+
+providers/lmstudio.yaml:
+
+```yaml
+format_version: 1
+name: lmstudio
+display_name: LM Studio
+tier: 8
+last_verified: "2026-04-05"
+keywords:
+ - "lmstudio"
+ - "lm-studio"
+ - "LMSTUDIO_API_KEY"
+ - "localhost:1234"
+ - "lmstudio.ai"
+verify:
+ method: GET
+ url: ""
+ headers: {}
+ valid_status: []
+ invalid_status: []
+```
+
+providers/llamacpp.yaml:
+
+```yaml
+format_version: 1
+name: llamacpp
+display_name: llama.cpp server
+tier: 8
+last_verified: "2026-04-05"
+keywords:
+ - "llama.cpp"
+ - "llama-cpp"
+ - "llama_cpp"
+ - "LLAMA_API_KEY"
+ - "ggml"
+ - "gguf"
+verify:
+ method: GET
+ url: ""
+ headers: {}
+ valid_status: []
+ invalid_status: []
+```
+
+Copy all 5 files verbatim to pkg/providers/definitions/.
+
+
+ cd /home/salva/Documents/apikey && for f in ollama vllm localai lmstudio llamacpp; do diff providers/$f.yaml pkg/providers/definitions/$f.yaml || exit 1; done && go test ./pkg/providers/... -count=1 && go test ./pkg/engine/... -count=1
+
+
+ - All 10 files exist
+ - `grep -q 'localhost:11434' providers/ollama.yaml`
+ - `grep -q 'vllm.entrypoints' providers/vllm.yaml`
+ - `grep -q 'gguf' providers/llamacpp.yaml`
+ - All 5 omit patterns field: `grep -L 'patterns:' providers/{ollama,vllm,localai,lmstudio,llamacpp}.yaml` returns all 5
+ - `go test ./pkg/providers/... -count=1` passes
+
+ 5 self-hosted runtimes dual-located, keyword-only.
+
+
+
+ Task 2: GPT4All, text-gen-webui, TensorRT-LLM, Triton, Jan AI YAMLs
+ providers/gpt4all.yaml, providers/text-gen-webui.yaml, providers/tensorrt-llm.yaml, providers/triton.yaml, providers/jan.yaml, pkg/providers/definitions/gpt4all.yaml, pkg/providers/definitions/text-gen-webui.yaml, pkg/providers/definitions/tensorrt-llm.yaml, pkg/providers/definitions/triton.yaml, pkg/providers/definitions/jan.yaml
+
+ - pkg/providers/schema.go
+
+
+All keyword-only (no patterns field).
+
+providers/gpt4all.yaml:
+
+```yaml
+format_version: 1
+name: gpt4all
+display_name: GPT4All
+tier: 8
+last_verified: "2026-04-05"
+keywords:
+ - "gpt4all"
+ - "nomic-ai"
+ - "GPT4ALL_API_KEY"
+ - "gpt4all.io"
+verify:
+ method: GET
+ url: ""
+ headers: {}
+ valid_status: []
+ invalid_status: []
+```
+
+providers/text-gen-webui.yaml:
+
+```yaml
+format_version: 1
+name: text-gen-webui
+display_name: text-generation-webui (oobabooga)
+tier: 8
+last_verified: "2026-04-05"
+keywords:
+ - "text-generation-webui"
+ - "oobabooga"
+ - "TEXTGEN_API_KEY"
+ - "text-gen-webui"
+ - "localhost:5000"
+verify:
+ method: GET
+ url: ""
+ headers: {}
+ valid_status: []
+ invalid_status: []
+```
+
+providers/tensorrt-llm.yaml:
+
+```yaml
+format_version: 1
+name: tensorrt-llm
+display_name: NVIDIA TensorRT-LLM
+tier: 8
+last_verified: "2026-04-05"
+keywords:
+ - "tensorrt-llm"
+ - "trtllm"
+ - "TRTLLM_API_KEY"
+ - "tensorrt_llm"
+ - "nvidia-nim"
+verify:
+ method: GET
+ url: ""
+ headers: {}
+ valid_status: []
+ invalid_status: []
+```
+
+providers/triton.yaml:
+
+```yaml
+format_version: 1
+name: triton
+display_name: NVIDIA Triton Inference Server
+tier: 8
+last_verified: "2026-04-05"
+keywords:
+ - "triton-inference-server"
+ - "tritonserver"
+ - "TRITON_API_KEY"
+ - "triton_grpc"
+ - "v2/models"
+verify:
+ method: GET
+ url: ""
+ headers: {}
+ valid_status: []
+ invalid_status: []
+```
+
+providers/jan.yaml:
+
+```yaml
+format_version: 1
+name: jan
+display_name: Jan AI
+tier: 8
+last_verified: "2026-04-05"
+keywords:
+ - "jan-ai"
+ - "janhq"
+ - "JAN_API_KEY"
+ - "jan.ai"
+ - "cortex-cpp"
+verify:
+ method: GET
+ url: ""
+ headers: {}
+ valid_status: []
+ invalid_status: []
+```
+
+Copy all 5 files verbatim to pkg/providers/definitions/.
+
+
+ cd /home/salva/Documents/apikey && for f in gpt4all text-gen-webui tensorrt-llm triton jan; do diff providers/$f.yaml pkg/providers/definitions/$f.yaml || exit 1; done && go test ./pkg/providers/... -count=1 && go test ./pkg/engine/... -count=1 && test $(grep -l 'tier: 8' providers/*.yaml | wc -l) -eq 10
+
+
+ - All 10 files exist
+ - `grep -q 'oobabooga' providers/text-gen-webui.yaml`
+ - `grep -q 'tritonserver' providers/triton.yaml`
+ - `grep -q 'janhq' providers/jan.yaml`
+ - Total Tier 8 count = 10
+ - `go test ./pkg/providers/... -count=1` passes
+
+ All 10 Tier 8 self-hosted runtimes dual-located. PROV-08 satisfied.
+
+
+
+
+
+`grep -l 'tier: 8' providers/*.yaml | wc -l` returns 10.
+
+
+
+- 10 Tier 8 self-hosted runtimes created
+- All keyword-only (no regex patterns — avoids false positives)
+- Localhost endpoints and env vars captured as keywords
+- No engine regression
+
+
+
diff --git a/.planning/phases/03-tier-3-9-providers/03-06-PLAN.md b/.planning/phases/03-tier-3-9-providers/03-06-PLAN.md
new file mode 100644
index 0000000..0054b41
--- /dev/null
+++ b/.planning/phases/03-tier-3-9-providers/03-06-PLAN.md
@@ -0,0 +1,331 @@
+---
+phase: 03-tier-3-9-providers
+plan: 06
+type: execute
+wave: 1
+depends_on: []
+files_modified:
+ - providers/salesforce-einstein.yaml
+ - providers/servicenow.yaml
+ - providers/sap-ai-core.yaml
+ - providers/palantir.yaml
+ - providers/databricks.yaml
+ - providers/snowflake.yaml
+ - providers/oracle-genai.yaml
+ - providers/hpe-greenlake.yaml
+ - pkg/providers/definitions/salesforce-einstein.yaml
+ - pkg/providers/definitions/servicenow.yaml
+ - pkg/providers/definitions/sap-ai-core.yaml
+ - pkg/providers/definitions/palantir.yaml
+ - pkg/providers/definitions/databricks.yaml
+ - pkg/providers/definitions/snowflake.yaml
+ - pkg/providers/definitions/oracle-genai.yaml
+ - pkg/providers/definitions/hpe-greenlake.yaml
+autonomous: true
+requirements: [PROV-09]
+must_haves:
+ truths:
+ - "8 Tier 9 Enterprise provider YAMLs load"
+ - "Databricks dapi-prefix and Snowflake JWT keywords captured"
+ - "All enterprise providers have strong env var keyword anchors"
+ artifacts:
+ - path: "providers/databricks.yaml"
+ provides: "Databricks dapi token pattern"
+ contains: "dapi"
+ - path: "providers/snowflake.yaml"
+ provides: "Snowflake Cortex keyword detection"
+ contains: "snowflake"
+ - path: "providers/palantir.yaml"
+ provides: "Palantir AIP keyword detection"
+ contains: "palantir"
+ key_links:
+ - from: "provider keywords[]"
+ to: "Registry Aho-Corasick automaton"
+ via: "NewRegistry()"
+ pattern: "keywords"
+---
+
+
+Create 8 Tier 9 Enterprise AI platform provider YAMLs — enterprise SaaS AI (Salesforce Einstein, ServiceNow Now Assist, SAP Joule, Palantir AIP, Databricks, Snowflake Cortex, Oracle GenAI, HPE GreenLake).
+
+Purpose: Satisfy PROV-09 (8 Tier 9 Enterprise providers). These target regulated enterprise estates where leaked keys carry high blast radius.
+
+Output: 16 YAML files.
+
+Addresses PROV-09.
+
+Note: `oracle-genai` here is distinct from `oracle-ai` in plan 03-04 (which is Tier 7 code tools). Tier 9 entry uses name `oracle-genai` to avoid collision.
+
+
+
+@$HOME/.claude/get-shit-done/workflows/execute-plan.md
+@$HOME/.claude/get-shit-done/templates/summary.md
+
+
+
+@.planning/ROADMAP.md
+@.planning/phases/03-tier-3-9-providers/03-CONTEXT.md
+@pkg/providers/schema.go
+
+
+Dual-location required. Keyword-only for most; databricks has a documented `dapi` prefix.
+
+
+
+
+
+
+ Task 1: Salesforce, ServiceNow, SAP, Palantir YAMLs
+ providers/salesforce-einstein.yaml, providers/servicenow.yaml, providers/sap-ai-core.yaml, providers/palantir.yaml, pkg/providers/definitions/salesforce-einstein.yaml, pkg/providers/definitions/servicenow.yaml, pkg/providers/definitions/sap-ai-core.yaml, pkg/providers/definitions/palantir.yaml
+
+ - pkg/providers/schema.go
+
+
+All 4 use keyword-only detection (no public key formats documented).
+
+providers/salesforce-einstein.yaml:
+
+```yaml
+format_version: 1
+name: salesforce-einstein
+display_name: Salesforce Einstein GPT
+tier: 9
+last_verified: "2026-04-05"
+keywords:
+ - "einstein-gpt"
+ - "einsteinGPT"
+ - "SALESFORCE_CONSUMER_KEY"
+ - "SALESFORCE_CONSUMER_SECRET"
+ - "api.salesforce.com"
+ - "einstein.ai"
+ - "salesforce-einstein"
+verify:
+ method: GET
+ url: ""
+ headers: {}
+ valid_status: []
+ invalid_status: []
+```
+
+providers/servicenow.yaml:
+
+```yaml
+format_version: 1
+name: servicenow
+display_name: ServiceNow Now Assist
+tier: 9
+last_verified: "2026-04-05"
+keywords:
+ - "servicenow"
+ - "now-assist"
+ - "SERVICENOW_INSTANCE"
+ - "SERVICENOW_USERNAME"
+ - "SERVICENOW_PASSWORD"
+ - "service-now.com"
+verify:
+ method: GET
+ url: ""
+ headers: {}
+ valid_status: []
+ invalid_status: []
+```
+
+providers/sap-ai-core.yaml:
+
+```yaml
+format_version: 1
+name: sap-ai-core
+display_name: SAP AI Core / Joule
+tier: 9
+last_verified: "2026-04-05"
+keywords:
+ - "sap-ai-core"
+ - "sap-joule"
+ - "SAP_AICORE_CLIENT_ID"
+ - "SAP_AICORE_CLIENT_SECRET"
+ - "SAP_AICORE_AUTH_URL"
+ - "hana.ondemand.com"
+ - "aicore"
+verify:
+ method: GET
+ url: ""
+ headers: {}
+ valid_status: []
+ invalid_status: []
+```
+
+providers/palantir.yaml:
+
+```yaml
+format_version: 1
+name: palantir
+display_name: Palantir AIP
+tier: 9
+last_verified: "2026-04-05"
+keywords:
+ - "palantir"
+ - "foundry"
+ - "PALANTIR_TOKEN"
+ - "FOUNDRY_TOKEN"
+ - "palantirfoundry.com"
+ - "aip-agents"
+verify:
+ method: GET
+ url: ""
+ headers: {}
+ valid_status: []
+ invalid_status: []
+```
+
+Copy all 4 files verbatim to pkg/providers/definitions/.
+
+
+ cd /home/salva/Documents/apikey && for f in salesforce-einstein servicenow sap-ai-core palantir; do diff providers/$f.yaml pkg/providers/definitions/$f.yaml || exit 1; done && go test ./pkg/providers/... -count=1 && go test ./pkg/engine/... -count=1
+
+
+ - All 8 files exist
+ - `grep -q 'einsteinGPT' providers/salesforce-einstein.yaml`
+ - `grep -q 'foundry' providers/palantir.yaml`
+ - `grep -q 'SAP_AICORE_CLIENT_ID' providers/sap-ai-core.yaml`
+ - `go test ./pkg/providers/... -count=1` passes
+
+ 4 enterprise platform providers dual-located.
+
+
+
+ Task 2: Databricks, Snowflake, Oracle GenAI, HPE GreenLake YAMLs
+ providers/databricks.yaml, providers/snowflake.yaml, providers/oracle-genai.yaml, providers/hpe-greenlake.yaml, pkg/providers/definitions/databricks.yaml, pkg/providers/definitions/snowflake.yaml, pkg/providers/definitions/oracle-genai.yaml, pkg/providers/definitions/hpe-greenlake.yaml
+
+ - pkg/providers/schema.go
+
+
+providers/databricks.yaml:
+
+```yaml
+format_version: 1
+name: databricks
+display_name: Databricks (DBRX / Mosaic)
+tier: 9
+last_verified: "2026-04-05"
+keywords:
+ - "databricks"
+ - "DATABRICKS_TOKEN"
+ - "DATABRICKS_HOST"
+ - "dbrx"
+ - "mosaicml"
+ - "dapi"
+ - ".cloud.databricks.com"
+patterns:
+ - regex: 'dapi[a-f0-9]{32}(-[0-9]{1,2})?'
+ entropy_min: 3.5
+ confidence: high
+verify:
+ method: GET
+ url: ""
+ headers: {}
+ valid_status: []
+ invalid_status: []
+```
+
+providers/snowflake.yaml:
+
+```yaml
+format_version: 1
+name: snowflake
+display_name: Snowflake Cortex
+tier: 9
+last_verified: "2026-04-05"
+keywords:
+ - "snowflake"
+ - "SNOWFLAKE_ACCOUNT"
+ - "SNOWFLAKE_USER"
+ - "SNOWFLAKE_PASSWORD"
+ - "SNOWFLAKE_PRIVATE_KEY"
+ - "snowflakecomputing.com"
+ - "cortex"
+verify:
+ method: GET
+ url: ""
+ headers: {}
+ valid_status: []
+ invalid_status: []
+```
+
+providers/oracle-genai.yaml:
+
+```yaml
+format_version: 1
+name: oracle-genai
+display_name: Oracle Cloud Generative AI Service
+tier: 9
+last_verified: "2026-04-05"
+keywords:
+ - "oci-generative-ai"
+ - "OCI_GENAI_COMPARTMENT"
+ - "oracle-cloud-genai"
+ - "inference.generativeai.us-chicago-1"
+ - "oci-cli"
+ - "OCI_CONFIG_FILE"
+verify:
+ method: GET
+ url: ""
+ headers: {}
+ valid_status: []
+ invalid_status: []
+```
+
+providers/hpe-greenlake.yaml:
+
+```yaml
+format_version: 1
+name: hpe-greenlake
+display_name: HPE GreenLake for LLMs
+tier: 9
+last_verified: "2026-04-05"
+keywords:
+ - "hpe-greenlake"
+ - "greenlake"
+ - "HPE_CLIENT_ID"
+ - "HPE_CLIENT_SECRET"
+ - "common.cloud.hpe.com"
+ - "hpe-ai"
+verify:
+ method: GET
+ url: ""
+ headers: {}
+ valid_status: []
+ invalid_status: []
+```
+
+Copy all 4 files verbatim to pkg/providers/definitions/.
+
+
+ cd /home/salva/Documents/apikey && for f in databricks snowflake oracle-genai hpe-greenlake; do diff providers/$f.yaml pkg/providers/definitions/$f.yaml || exit 1; done && go test ./pkg/providers/... -count=1 && go test ./pkg/engine/... -count=1 && test $(grep -l 'tier: 9' providers/*.yaml | wc -l) -eq 8
+
+
+ - All 8 files exist
+ - `grep -q 'dapi' providers/databricks.yaml`
+ - `grep -q 'snowflakecomputing.com' providers/snowflake.yaml`
+ - `grep -q 'greenlake' providers/hpe-greenlake.yaml`
+ - Total Tier 9 count = 8
+ - `go test ./pkg/providers/... -count=1` passes
+
+ All 8 Tier 9 enterprise providers dual-located. PROV-09 satisfied.
+
+
+
+
+
+`grep -l 'tier: 9' providers/*.yaml | wc -l` returns 8.
+
+
+
+- 8 Tier 9 enterprise providers created
+- Databricks uses documented `dapi` high-confidence pattern
+- Strong env var keyword anchors on all
+- No engine regression
+
+
+
diff --git a/.planning/phases/03-tier-3-9-providers/03-07-PLAN.md b/.planning/phases/03-tier-3-9-providers/03-07-PLAN.md
new file mode 100644
index 0000000..751ef5c
--- /dev/null
+++ b/.planning/phases/03-tier-3-9-providers/03-07-PLAN.md
@@ -0,0 +1,504 @@
+---
+phase: 03-tier-3-9-providers
+plan: 07
+type: execute
+wave: 1
+depends_on: []
+files_modified:
+ - providers/reka.yaml
+ - providers/aleph-alpha.yaml
+ - providers/writer.yaml
+ - providers/jasper.yaml
+ - providers/typeface.yaml
+ - providers/comet.yaml
+ - providers/wandb.yaml
+ - providers/langsmith.yaml
+ - providers/pinecone.yaml
+ - providers/weaviate.yaml
+ - providers/qdrant.yaml
+ - providers/chroma.yaml
+ - providers/milvus.yaml
+ - providers/neon.yaml
+ - providers/lamini.yaml
+ - pkg/providers/definitions/reka.yaml
+ - pkg/providers/definitions/aleph-alpha.yaml
+ - pkg/providers/definitions/writer.yaml
+ - pkg/providers/definitions/jasper.yaml
+ - pkg/providers/definitions/typeface.yaml
+ - pkg/providers/definitions/comet.yaml
+ - pkg/providers/definitions/wandb.yaml
+ - pkg/providers/definitions/langsmith.yaml
+ - pkg/providers/definitions/pinecone.yaml
+ - pkg/providers/definitions/weaviate.yaml
+ - pkg/providers/definitions/qdrant.yaml
+ - pkg/providers/definitions/chroma.yaml
+ - pkg/providers/definitions/milvus.yaml
+ - pkg/providers/definitions/neon.yaml
+ - pkg/providers/definitions/lamini.yaml
+autonomous: true
+requirements: [PROV-06]
+must_haves:
+ truths:
+ - "15 Tier 6 Emerging/Niche provider YAMLs load"
+ - "W&B uses documented 40-hex key; LangSmith uses lsv2_ prefix; Pinecone uses pcsk_ prefix"
+ - "Vector DBs and writing tools have strong env var keyword anchors"
+ artifacts:
+ - path: "providers/langsmith.yaml"
+ provides: "LangSmith lsv2_ prefix pattern"
+ contains: "lsv2_"
+ - path: "providers/pinecone.yaml"
+ provides: "Pinecone pcsk_ prefix pattern"
+ contains: "pcsk_"
+ - path: "providers/wandb.yaml"
+ provides: "Weights & Biases 40-hex key pattern"
+ contains: "WANDB_API_KEY"
+ key_links:
+ - from: "provider keywords[]"
+ to: "Registry Aho-Corasick automaton"
+ via: "NewRegistry()"
+ pattern: "keywords"
+---
+
+
+Create 15 Tier 6 Emerging/Niche provider YAMLs — emerging LLM labs (Reka, Aleph Alpha, Lamini), writing tools (Writer, Jasper, Typeface), observability (Comet, W&B, LangSmith), and vector DBs (Pinecone, Weaviate, Qdrant, Chroma, Milvus, Neon).
+
+Purpose: Satisfy PROV-06 (15 Tier 6 Emerging/Niche providers).
+
+Output: 30 YAML files.
+
+Addresses PROV-06.
+
+
+
+@$HOME/.claude/get-shit-done/workflows/execute-plan.md
+@$HOME/.claude/get-shit-done/templates/summary.md
+
+
+
+@.planning/ROADMAP.md
+@.planning/phases/03-tier-3-9-providers/03-CONTEXT.md
+@pkg/providers/schema.go
+
+
+Dual-location required. Several providers in this group have documented prefixes (LangSmith lsv2_, Pinecone pcsk_, W&B 40-hex). Others use keyword-only.
+
+
+
+
+
+
+ Task 1: Emerging labs + writing tools (Reka, Aleph Alpha, Lamini, Writer, Jasper, Typeface, Comet, W&B)
+ providers/reka.yaml, providers/aleph-alpha.yaml, providers/lamini.yaml, providers/writer.yaml, providers/jasper.yaml, providers/typeface.yaml, providers/comet.yaml, providers/wandb.yaml, pkg/providers/definitions/reka.yaml, pkg/providers/definitions/aleph-alpha.yaml, pkg/providers/definitions/lamini.yaml, pkg/providers/definitions/writer.yaml, pkg/providers/definitions/jasper.yaml, pkg/providers/definitions/typeface.yaml, pkg/providers/definitions/comet.yaml, pkg/providers/definitions/wandb.yaml
+
+ - pkg/providers/schema.go
+
+
+providers/reka.yaml:
+
+```yaml
+format_version: 1
+name: reka
+display_name: Reka AI
+tier: 6
+last_verified: "2026-04-05"
+keywords:
+ - "reka"
+ - "REKA_API_KEY"
+ - "api.reka.ai"
+ - "reka-core"
+ - "reka-flash"
+verify:
+ method: GET
+ url: https://api.reka.ai/v1/models
+ headers:
+ X-Api-Key: "{KEY}"
+ valid_status: [200]
+ invalid_status: [401, 403]
+```
+
+providers/aleph-alpha.yaml:
+
+```yaml
+format_version: 1
+name: aleph-alpha
+display_name: Aleph Alpha
+tier: 6
+last_verified: "2026-04-05"
+keywords:
+ - "aleph-alpha"
+ - "aleph_alpha"
+ - "ALEPH_ALPHA_API_KEY"
+ - "AA_TOKEN"
+ - "api.aleph-alpha.com"
+ - "luminous"
+verify:
+ method: GET
+ url: https://api.aleph-alpha.com/models_available
+ headers:
+ Authorization: "Bearer {KEY}"
+ valid_status: [200]
+ invalid_status: [401, 403]
+```
+
+providers/lamini.yaml:
+
+```yaml
+format_version: 1
+name: lamini
+display_name: Lamini
+tier: 6
+last_verified: "2026-04-05"
+keywords:
+ - "lamini"
+ - "LAMINI_API_KEY"
+ - "api.lamini.ai"
+ - "lamini.ai"
+verify:
+ method: GET
+ url: https://api.lamini.ai/v1/models
+ headers:
+ Authorization: "Bearer {KEY}"
+ valid_status: [200]
+ invalid_status: [401, 403]
+```
+
+providers/writer.yaml:
+
+```yaml
+format_version: 1
+name: writer
+display_name: Writer
+tier: 6
+last_verified: "2026-04-05"
+keywords:
+ - "writer.com"
+ - "WRITER_API_KEY"
+ - "api.writer.com"
+ - "palmyra"
+verify:
+ method: GET
+ url: https://api.writer.com/v1/models
+ headers:
+ Authorization: "Bearer {KEY}"
+ valid_status: [200]
+ invalid_status: [401, 403]
+```
+
+providers/jasper.yaml:
+
+```yaml
+format_version: 1
+name: jasper
+display_name: Jasper AI
+tier: 6
+last_verified: "2026-04-05"
+keywords:
+ - "jasper.ai"
+ - "JASPER_API_KEY"
+ - "api.jasper.ai"
+ - "jasper-ai"
+verify:
+ method: GET
+ url: ""
+ headers: {}
+ valid_status: []
+ invalid_status: []
+```
+
+providers/typeface.yaml:
+
+```yaml
+format_version: 1
+name: typeface
+display_name: Typeface
+tier: 6
+last_verified: "2026-04-05"
+keywords:
+ - "typeface"
+ - "typeface.ai"
+ - "TYPEFACE_API_KEY"
+ - "typeface-app"
+verify:
+ method: GET
+ url: ""
+ headers: {}
+ valid_status: []
+ invalid_status: []
+```
+
+providers/comet.yaml:
+
+```yaml
+format_version: 1
+name: comet
+display_name: Comet ML / Opik
+tier: 6
+last_verified: "2026-04-05"
+keywords:
+ - "comet_ml"
+ - "comet-ml"
+ - "COMET_API_KEY"
+ - "COMET_WORKSPACE"
+ - "opik"
+ - "comet.com"
+verify:
+ method: GET
+ url: https://www.comet.com/api/rest/v2/workspaces
+ headers:
+ Authorization: "{KEY}"
+ valid_status: [200]
+ invalid_status: [401, 403]
+```
+
+providers/wandb.yaml:
+
+```yaml
+format_version: 1
+name: wandb
+display_name: Weights & Biases
+tier: 6
+last_verified: "2026-04-05"
+keywords:
+ - "wandb"
+ - "weights_and_biases"
+ - "WANDB_API_KEY"
+ - "api.wandb.ai"
+ - "wandb.ai"
+patterns:
+ - regex: '[a-f0-9]{40}'
+ entropy_min: 3.5
+ confidence: low
+verify:
+ method: GET
+ url: https://api.wandb.ai/graphql
+ headers:
+ Authorization: "Basic {KEY}"
+ valid_status: [200, 400]
+ invalid_status: [401, 403]
+```
+
+Copy all 8 files verbatim to pkg/providers/definitions/.
+
+
+ cd /home/salva/Documents/apikey && for f in reka aleph-alpha lamini writer jasper typeface comet wandb; do diff providers/$f.yaml pkg/providers/definitions/$f.yaml || exit 1; done && go test ./pkg/providers/... -count=1 && go test ./pkg/engine/... -count=1
+
+
+ - All 16 files exist
+ - `grep -q 'luminous' providers/aleph-alpha.yaml`
+ - `grep -q 'palmyra' providers/writer.yaml`
+ - `grep -q 'WANDB_API_KEY' providers/wandb.yaml`
+ - `go test ./pkg/providers/... -count=1` passes
+
+ 8 emerging/writing/observability providers dual-located.
+
+
+
+ Task 2: LangSmith + vector DBs (LangSmith, Pinecone, Weaviate, Qdrant, Chroma, Milvus, Neon)
+ providers/langsmith.yaml, providers/pinecone.yaml, providers/weaviate.yaml, providers/qdrant.yaml, providers/chroma.yaml, providers/milvus.yaml, providers/neon.yaml, pkg/providers/definitions/langsmith.yaml, pkg/providers/definitions/pinecone.yaml, pkg/providers/definitions/weaviate.yaml, pkg/providers/definitions/qdrant.yaml, pkg/providers/definitions/chroma.yaml, pkg/providers/definitions/milvus.yaml, pkg/providers/definitions/neon.yaml
+
+ - pkg/providers/schema.go
+
+
+providers/langsmith.yaml:
+
+```yaml
+format_version: 1
+name: langsmith
+display_name: LangSmith (LangChain)
+tier: 6
+last_verified: "2026-04-05"
+keywords:
+ - "langsmith"
+ - "langchain"
+ - "LANGCHAIN_API_KEY"
+ - "LANGSMITH_API_KEY"
+ - "LANGCHAIN_TRACING_V2"
+ - "api.smith.langchain.com"
+ - "lsv2_"
+patterns:
+ - regex: 'lsv2_(pt|sk)_[a-f0-9]{32}_[a-f0-9]{10}'
+ entropy_min: 4.0
+ confidence: high
+verify:
+ method: GET
+ url: https://api.smith.langchain.com/info
+ headers:
+ X-API-Key: "{KEY}"
+ valid_status: [200]
+ invalid_status: [401, 403]
+```
+
+providers/pinecone.yaml:
+
+```yaml
+format_version: 1
+name: pinecone
+display_name: Pinecone
+tier: 6
+last_verified: "2026-04-05"
+keywords:
+ - "pinecone"
+ - "PINECONE_API_KEY"
+ - "PINECONE_ENVIRONMENT"
+ - "api.pinecone.io"
+ - "pinecone.io"
+ - "pcsk_"
+patterns:
+ - regex: 'pcsk_[A-Za-z0-9]{40,}'
+ entropy_min: 4.0
+ confidence: high
+verify:
+ method: GET
+ url: https://api.pinecone.io/indexes
+ headers:
+ Api-Key: "{KEY}"
+ valid_status: [200]
+ invalid_status: [401, 403]
+```
+
+providers/weaviate.yaml:
+
+```yaml
+format_version: 1
+name: weaviate
+display_name: Weaviate
+tier: 6
+last_verified: "2026-04-05"
+keywords:
+ - "weaviate"
+ - "WEAVIATE_API_KEY"
+ - "WEAVIATE_URL"
+ - "weaviate.io"
+ - "wcs.api"
+verify:
+ method: GET
+ url: ""
+ headers: {}
+ valid_status: []
+ invalid_status: []
+```
+
+providers/qdrant.yaml:
+
+```yaml
+format_version: 1
+name: qdrant
+display_name: Qdrant
+tier: 6
+last_verified: "2026-04-05"
+keywords:
+ - "qdrant"
+ - "QDRANT_API_KEY"
+ - "QDRANT_URL"
+ - "qdrant.tech"
+ - "cloud.qdrant.io"
+verify:
+ method: GET
+ url: ""
+ headers: {}
+ valid_status: []
+ invalid_status: []
+```
+
+providers/chroma.yaml:
+
+```yaml
+format_version: 1
+name: chroma
+display_name: Chroma
+tier: 6
+last_verified: "2026-04-05"
+keywords:
+ - "chromadb"
+ - "chroma-client"
+ - "CHROMA_API_KEY"
+ - "CHROMA_HOST"
+ - "trychroma.com"
+verify:
+ method: GET
+ url: ""
+ headers: {}
+ valid_status: []
+ invalid_status: []
+```
+
+providers/milvus.yaml:
+
+```yaml
+format_version: 1
+name: milvus
+display_name: Milvus / Zilliz
+tier: 6
+last_verified: "2026-04-05"
+keywords:
+ - "milvus"
+ - "zilliz"
+ - "ZILLIZ_API_KEY"
+ - "MILVUS_TOKEN"
+ - "zilliz.com"
+ - "api.cloud.zilliz.com"
+verify:
+ method: GET
+ url: ""
+ headers: {}
+ valid_status: []
+ invalid_status: []
+```
+
+providers/neon.yaml:
+
+```yaml
+format_version: 1
+name: neon
+display_name: Neon (Serverless Postgres + pgvector)
+tier: 6
+last_verified: "2026-04-05"
+keywords:
+ - "neon-db"
+ - "neondb"
+ - "NEON_API_KEY"
+ - "NEON_CONNECTION_STRING"
+ - "console.neon.tech"
+ - "pg.neon.tech"
+verify:
+ method: GET
+ url: https://console.neon.tech/api/v2/projects
+ headers:
+ Authorization: "Bearer {KEY}"
+ valid_status: [200]
+ invalid_status: [401, 403]
+```
+
+Copy all 7 files verbatim to pkg/providers/definitions/.
+
+
+ cd /home/salva/Documents/apikey && for f in langsmith pinecone weaviate qdrant chroma milvus neon; do diff providers/$f.yaml pkg/providers/definitions/$f.yaml || exit 1; done && go test ./pkg/providers/... -count=1 && go test ./pkg/engine/... -count=1 && test $(grep -l 'tier: 6' providers/*.yaml | wc -l) -eq 15
+
+
+ - All 14 files exist
+ - `grep -q 'lsv2_' providers/langsmith.yaml`
+ - `grep -q 'pcsk_' providers/pinecone.yaml`
+ - `grep -q 'zilliz' providers/milvus.yaml`
+ - Total Tier 6 count = 15
+ - `go test ./pkg/providers/... -count=1` passes
+ - `go test ./pkg/engine/... -count=1` passes
+
+ All 15 Tier 6 emerging/niche providers dual-located. PROV-06 satisfied.
+
+
+
+
+
+`grep -l 'tier: 6' providers/*.yaml | wc -l` returns 15.
+
+
+
+- 15 Tier 6 providers created
+- LangSmith lsv2_ and Pinecone pcsk_ use high-confidence regex
+- Vector DB env vars captured
+- No engine regression
+
+
+
diff --git a/.planning/phases/03-tier-3-9-providers/03-08-PLAN.md b/.planning/phases/03-tier-3-9-providers/03-08-PLAN.md
new file mode 100644
index 0000000..5c66c94
--- /dev/null
+++ b/.planning/phases/03-tier-3-9-providers/03-08-PLAN.md
@@ -0,0 +1,284 @@
+---
+phase: 03-tier-3-9-providers
+plan: 08
+type: execute
+wave: 2
+depends_on: ["03-01", "03-02", "03-03", "03-04", "03-05", "03-06", "03-07"]
+files_modified:
+ - pkg/providers/tier39_test.go
+autonomous: true
+requirements: [PROV-03, PROV-04, PROV-05, PROV-06, PROV-07, PROV-08, PROV-09]
+must_haves:
+ truths:
+ - "Registry loads 108 total providers (26 Tier 1-2 + 82 Tier 3-9)"
+ - "Per-tier counts enforced: T3=12, T4=16, T5=11, T6=15, T7=10, T8=10, T9=8"
+ - "All 82 Tier 3-9 provider names are known (lock set against drift)"
+ - "All regex patterns compile under RE2"
+ - "Every provider has ≥1 keyword (Aho-Corasick pre-filter requirement)"
+ - "Phase 2 Tier 1-2 guardrails still pass (no regression)"
+ artifacts:
+ - path: "pkg/providers/tier39_test.go"
+ provides: "Tier 3-9 guardrail tests"
+ contains: "TestTier39"
+ key_links:
+ - from: "pkg/providers/tier39_test.go"
+ to: "registry.NewRegistry() Stats() Get() All()"
+ via: "go test ./pkg/providers/..."
+ pattern: "NewRegistry"
+---
+
+
+Create the Tier 3-9 guardrail test file `pkg/providers/tier39_test.go` that locks in exact provider counts, names, regex compilation, and keyword presence across all 82 new Tier 3-9 providers. Replicates the `tier12_test.go` pattern and serves as the regression net for all future phases.
+
+Purpose: Satisfy all 7 Phase 3 requirements (PROV-03..PROV-09) with a single enforceable test. Any future change that drops a provider, renames one, or introduces a non-compiling regex will break this test in CI.
+
+Output: 1 test file with 10+ test functions. Total registry provider count locked at 108.
+
+Addresses PROV-03, PROV-04, PROV-05, PROV-06, PROV-07, PROV-08, PROV-09.
+
+
+
+@$HOME/.claude/get-shit-done/workflows/execute-plan.md
+@$HOME/.claude/get-shit-done/templates/summary.md
+
+
+
+@.planning/ROADMAP.md
+@.planning/phases/03-tier-3-9-providers/03-CONTEXT.md
+@pkg/providers/tier12_test.go
+@pkg/providers/schema.go
+
+
+Replicate the `tier12_test.go` pattern exactly. Registry API: `NewRegistry()`, `Stats()`, `Get(name)`, `List()`.
+
+Expected provider name sets (must match plans 03-01..03-07 exactly):
+- Tier 3 (12): perplexity, you, voyage, jina, unstructured, assemblyai, deepgram, elevenlabs, stability, runway, midjourney, huggingface
+- Tier 4 (16): deepseek, zhipu, moonshot, qwen, baidu, bytedance, 01ai, minimax, baichuan, stepfun, sensetime, iflytek, tencent, siliconflow, 360ai, kuaishou
+- Tier 5 (11): openrouter, litellm, cloudflare-ai, vercel-ai, portkey, helicone, martian, kong, bricksai, aether, notdiamond
+- Tier 6 (15): reka, aleph-alpha, lamini, writer, jasper, typeface, comet, wandb, langsmith, pinecone, weaviate, qdrant, chroma, milvus, neon
+- Tier 7 (10): github-copilot, cursor, tabnine, codeium, sourcegraph, codewhisperer, replit-ai, codestral, watsonx, oracle-ai
+- Tier 8 (10): ollama, vllm, localai, lmstudio, llamacpp, gpt4all, text-gen-webui, tensorrt-llm, triton, jan
+- Tier 9 (8): salesforce-einstein, servicenow, sap-ai-core, palantir, databricks, snowflake, oracle-genai, hpe-greenlake
+
+Total Tier 3-9: 82. Combined with Tier 1-2 (26): 108 total.
+
+
+
+
+
+
+ Task 1: Create tier39_test.go guardrail test file
+ pkg/providers/tier39_test.go
+
+ - pkg/providers/tier12_test.go (pattern to replicate)
+ - pkg/providers/schema.go (Registry API)
+
+
+Create `pkg/providers/tier39_test.go` with the following contents. The expected name slices MUST match the names in each plan's files exactly.
+
+```go
+package providers
+
+import (
+ "testing"
+)
+
+// expectedTier3 lists all 12 Tier 3 Specialized provider names (PROV-03).
+var expectedTier3 = []string{
+ "perplexity", "you", "voyage", "jina", "unstructured", "assemblyai",
+ "deepgram", "elevenlabs", "stability", "runway", "midjourney", "huggingface",
+}
+
+// expectedTier4 lists all 16 Tier 4 Chinese/Regional provider names (PROV-04).
+var expectedTier4 = []string{
+ "deepseek", "zhipu", "moonshot", "qwen", "baidu", "bytedance",
+ "01ai", "minimax", "baichuan", "stepfun", "sensetime", "iflytek",
+ "tencent", "siliconflow", "360ai", "kuaishou",
+}
+
+// expectedTier5 lists all 11 Tier 5 Infrastructure/Gateway provider names (PROV-05).
+var expectedTier5 = []string{
+ "openrouter", "litellm", "cloudflare-ai", "vercel-ai", "portkey",
+ "helicone", "martian", "kong", "bricksai", "aether", "notdiamond",
+}
+
+// expectedTier6 lists all 15 Tier 6 Emerging/Niche provider names (PROV-06).
+var expectedTier6 = []string{
+ "reka", "aleph-alpha", "lamini", "writer", "jasper", "typeface",
+ "comet", "wandb", "langsmith", "pinecone", "weaviate", "qdrant",
+ "chroma", "milvus", "neon",
+}
+
+// expectedTier7 lists all 10 Tier 7 Code/Dev Tools provider names (PROV-07).
+var expectedTier7 = []string{
+ "github-copilot", "cursor", "tabnine", "codeium", "sourcegraph",
+ "codewhisperer", "replit-ai", "codestral", "watsonx", "oracle-ai",
+}
+
+// expectedTier8 lists all 10 Tier 8 Self-Hosted provider names (PROV-08).
+var expectedTier8 = []string{
+ "ollama", "vllm", "localai", "lmstudio", "llamacpp",
+ "gpt4all", "text-gen-webui", "tensorrt-llm", "triton", "jan",
+}
+
+// expectedTier9 lists all 8 Tier 9 Enterprise provider names (PROV-09).
+var expectedTier9 = []string{
+ "salesforce-einstein", "servicenow", "sap-ai-core", "palantir",
+ "databricks", "snowflake", "oracle-genai", "hpe-greenlake",
+}
+
+func TestTier3Count(t *testing.T) {
+ reg, err := NewRegistry()
+ if err != nil {
+ t.Fatalf("NewRegistry failed: %v", err)
+ }
+ if got := reg.Stats().ByTier[3]; got != 12 {
+ t.Errorf("Tier 3 count = %d, want 12", got)
+ }
+}
+
+func TestTier4Count(t *testing.T) {
+ reg, err := NewRegistry()
+ if err != nil {
+ t.Fatalf("NewRegistry failed: %v", err)
+ }
+ if got := reg.Stats().ByTier[4]; got != 16 {
+ t.Errorf("Tier 4 count = %d, want 16", got)
+ }
+}
+
+func TestTier5Count(t *testing.T) {
+ reg, err := NewRegistry()
+ if err != nil {
+ t.Fatalf("NewRegistry failed: %v", err)
+ }
+ if got := reg.Stats().ByTier[5]; got != 11 {
+ t.Errorf("Tier 5 count = %d, want 11", got)
+ }
+}
+
+func TestTier6Count(t *testing.T) {
+ reg, err := NewRegistry()
+ if err != nil {
+ t.Fatalf("NewRegistry failed: %v", err)
+ }
+ if got := reg.Stats().ByTier[6]; got != 15 {
+ t.Errorf("Tier 6 count = %d, want 15", got)
+ }
+}
+
+func TestTier7Count(t *testing.T) {
+ reg, err := NewRegistry()
+ if err != nil {
+ t.Fatalf("NewRegistry failed: %v", err)
+ }
+ if got := reg.Stats().ByTier[7]; got != 10 {
+ t.Errorf("Tier 7 count = %d, want 10", got)
+ }
+}
+
+func TestTier8Count(t *testing.T) {
+ reg, err := NewRegistry()
+ if err != nil {
+ t.Fatalf("NewRegistry failed: %v", err)
+ }
+ if got := reg.Stats().ByTier[8]; got != 10 {
+ t.Errorf("Tier 8 count = %d, want 10", got)
+ }
+}
+
+func TestTier9Count(t *testing.T) {
+ reg, err := NewRegistry()
+ if err != nil {
+ t.Fatalf("NewRegistry failed: %v", err)
+ }
+ if got := reg.Stats().ByTier[9]; got != 8 {
+ t.Errorf("Tier 9 count = %d, want 8", got)
+ }
+}
+
+func TestTotalProviderCount(t *testing.T) {
+ reg, err := NewRegistry()
+ if err != nil {
+ t.Fatalf("NewRegistry failed: %v", err)
+ }
+ if got := reg.Stats().Total; got != 108 {
+ t.Errorf("Total provider count = %d, want 108", got)
+ }
+}
+
+func TestTier39ProviderNames(t *testing.T) {
+ reg, err := NewRegistry()
+ if err != nil {
+ t.Fatalf("NewRegistry failed: %v", err)
+ }
+ checks := []struct {
+ tier int
+ names []string
+ }{
+ {3, expectedTier3},
+ {4, expectedTier4},
+ {5, expectedTier5},
+ {6, expectedTier6},
+ {7, expectedTier7},
+ {8, expectedTier8},
+ {9, expectedTier9},
+ }
+ for _, c := range checks {
+ for _, name := range c.names {
+ p, ok := reg.Get(name)
+ if !ok {
+ t.Errorf("Tier %d provider %q not found in registry", c.tier, name)
+ continue
+ }
+ if p.Tier != c.tier {
+ t.Errorf("provider %q tier = %d, want %d", name, p.Tier, c.tier)
+ }
+ }
+ }
+}
+```
+
+Note: Do NOT add package-level imports for `regexp` — `TestAllPatternsCompile` and `TestAllProvidersHaveKeywords` already exist in `tier12_test.go` and will exercise every provider (including Tier 3-9) once the registry loads them.
+
+
+ cd /home/salva/Documents/apikey && go test ./pkg/providers/... -count=1 -v -run 'TestTier[3-9]|TestTotalProviderCount|TestTier39ProviderNames|TestAllPatternsCompile|TestAllProvidersHaveKeywords' && go test ./... -count=1
+
+
+ - `pkg/providers/tier39_test.go` exists
+ - `grep -c "^func Test" pkg/providers/tier39_test.go` returns ≥ 9
+ - `go test ./pkg/providers/... -run TestTotalProviderCount -v` passes with Total == 108
+ - `go test ./pkg/providers/... -run TestTier3Count -v` passes
+ - `go test ./pkg/providers/... -run TestTier4Count -v` passes
+ - `go test ./pkg/providers/... -run TestTier5Count -v` passes
+ - `go test ./pkg/providers/... -run TestTier6Count -v` passes
+ - `go test ./pkg/providers/... -run TestTier7Count -v` passes
+ - `go test ./pkg/providers/... -run TestTier8Count -v` passes
+ - `go test ./pkg/providers/... -run TestTier9Count -v` passes
+ - `go test ./pkg/providers/... -run TestTier39ProviderNames -v` passes (all 82 names resolve)
+ - `go test ./pkg/providers/... -run TestAllPatternsCompile -v` passes (inherited from tier12_test.go — all Tier 3-9 regexes compile under RE2)
+ - `go test ./pkg/providers/... -run TestAllProvidersHaveKeywords -v` passes (every provider ≥1 keyword)
+ - Phase 2 guardrails still pass: `go test ./pkg/providers/... -run 'TestTier1|TestTier2'` green
+ - Full repo regression: `go test ./... -count=1` green (engine, storage, providers)
+
+ Tier 3-9 guardrail test file exists, 9+ test functions pass, total provider count locked at 108, all 82 Tier 3-9 provider names verified, no regression in Phase 1/2 tests.
+
+
+
+
+
+`go test ./... -count=1` passes. `go run . providers stats` shows Total 108, with Tier 1: 12, Tier 2: 14, Tier 3: 12, Tier 4: 16, Tier 5: 11, Tier 6: 15, Tier 7: 10, Tier 8: 10, Tier 9: 8.
+
+
+
+- tier39_test.go created with ≥9 test functions
+- Total provider count locked at 108
+- All 82 Tier 3-9 provider names locked against drift
+- All regex patterns compile under RE2 (via existing TestAllPatternsCompile)
+- Every provider has ≥1 keyword (via existing TestAllProvidersHaveKeywords)
+- Full repo `go test ./...` green
+
+
+