---
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"
---

<objective>
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.
</objective>

<execution_context>
@$HOME/.claude/get-shit-done/workflows/execute-plan.md
@$HOME/.claude/get-shit-done/templates/summary.md
</execution_context>

<context>
@.planning/ROADMAP.md
@.planning/phases/03-tier-3-9-providers/03-CONTEXT.md
@pkg/providers/schema.go

<interfaces>
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.
</interfaces>
</context>

<tasks>

<task type="auto">
  <name>Task 1: Ollama, vLLM, LocalAI, LM Studio, llama.cpp YAMLs</name>
  <files>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</files>
  <read_first>
    - pkg/providers/schema.go
  </read_first>
  <action>
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/.
  </action>
  <verify>
    <automated>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</automated>
  </verify>
  <acceptance_criteria>
    - 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
  </acceptance_criteria>
  <done>5 self-hosted runtimes dual-located, keyword-only.</done>
</task>

<task type="auto">
  <name>Task 2: GPT4All, text-gen-webui, TensorRT-LLM, Triton, Jan AI YAMLs</name>
  <files>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</files>
  <read_first>
    - pkg/providers/schema.go
  </read_first>
  <action>
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/.
  </action>
  <verify>
    <automated>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</automated>
  </verify>
  <acceptance_criteria>
    - 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
  </acceptance_criteria>
  <done>All 10 Tier 8 self-hosted runtimes dual-located. PROV-08 satisfied.</done>
</task>

</tasks>

<verification>
`grep -l 'tier: 8' providers/*.yaml | wc -l` returns 10.
</verification>

<success_criteria>
- 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
</success_criteria>

<output>
After completion, create `.planning/phases/03-tier-3-9-providers/03-05-SUMMARY.md`
</output>
