diff --git a/AGENTS.md b/AGENTS.md index e3f55599..5ab19e82 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -91,6 +91,17 @@ ui/desktop/ Wails v2 desktop app (React frontend + embedded ga - **Telegram formatting:** LLM output → `SanitizeAssistantContent()` → `markdownToTelegramHTML()` → `chunkHTML()` → `sendHTML()`. Tables rendered as ASCII in `
` tags
- **i18n:** Web UI uses `i18next` with namespace-split locale files in `ui/web/src/i18n/locales/{lang}/`. Backend uses `internal/i18n` message catalog with `i18n.T(locale, key, args...)`. Locale propagated via `store.WithLocale(ctx)` — WS `connect` param `locale`, HTTP `Accept-Language` header. Supported: en (default), vi, zh. New user-facing strings: add key to `internal/i18n/keys.go`, add translations to all 3 catalog files. New UI strings: add key to all 3 locale dirs. Bootstrap templates (SOUL.md, etc.) stay English-only (LLM consumption).
+## Cross-Surface Feature/Fix Parity
+
+Every feature implementation or bug fix must audit and update all affected product surfaces before it is marked complete:
+
+- **Gateway server:** handlers, WebSocket methods, stores, migrations, provider/runtime behavior, background jobs.
+- **API contract:** request/response structs, `pkg/protocol`, OpenAPI/docs, compatibility shims, tests built from real response shapes.
+- **Web UI:** `ui/web` screens, hooks, i18n, validation, loading/error states, and contract consumers.
+- **CLI/runtime package:** `cmd` commands, operator/runtime package commands, installers/manifests, response parsers, and runtime package docs.
+
+Do not ship a backend-only change when the web UI, CLI/runtime package, or API contract must also change. If a surface is not affected, state `Surface parity: N/A because ...` in the plan, PR, or final report. For cross-repo CLI work, verify the current CLI/runtime package repo and release channel before claiming parity.
+
## Running
```bash
diff --git a/CLAUDE.md b/CLAUDE.md
index c7a1e0d5..db9f9cca 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -91,6 +91,17 @@ ui/desktop/ Wails v2 desktop app (React frontend + embedded ga
- **Telegram formatting:** LLM output → `SanitizeAssistantContent()` → `markdownToTelegramHTML()` → `chunkHTML()` → `sendHTML()`. Tables rendered as ASCII in `` tags
- **i18n:** Web UI uses `i18next` with namespace-split locale files in `ui/web/src/i18n/locales/{lang}/`. Backend uses `internal/i18n` message catalog with `i18n.T(locale, key, args...)`. Locale propagated via `store.WithLocale(ctx)` — WS `connect` param `locale`, HTTP `Accept-Language` header. Supported: en (default), vi, zh. New user-facing strings: add key to `internal/i18n/keys.go`, add translations to all 3 catalog files. New UI strings: add key to all 3 locale dirs. Bootstrap templates (SOUL.md, etc.) stay English-only (LLM consumption).
+## Cross-Surface Feature/Fix Parity
+
+Every feature implementation or bug fix must audit and update all affected product surfaces before it is marked complete:
+
+- **Gateway server:** handlers, WebSocket methods, stores, migrations, provider/runtime behavior, background jobs.
+- **API contract:** request/response structs, `pkg/protocol`, OpenAPI/docs, compatibility shims, tests built from real response shapes.
+- **Web UI:** `ui/web` screens, hooks, i18n, validation, loading/error states, and contract consumers.
+- **CLI/runtime package:** `cmd` commands, operator/runtime package commands, installers/manifests, response parsers, and runtime package docs.
+
+Do not ship a backend-only change when the web UI, CLI/runtime package, or API contract must also change. If a surface is not affected, state `Surface parity: N/A because ...` in the plan, PR, or final report. For cross-repo CLI work, verify the current CLI/runtime package repo and release channel before claiming parity.
+
## Running
```bash
diff --git a/docs/02-providers.md b/docs/02-providers.md
index 7475fad5..1a1885a9 100644
--- a/docs/02-providers.md
+++ b/docs/02-providers.md
@@ -351,6 +351,11 @@ Standard OpenAI-compatible provider targeting the Alibaba Coding API.
- **Default model**: `qwen3.5-plus`
- **Base URL**: `https://coding-intl.dashscope.aliyuncs.com/v1`
+- **Catalog source**: hardcoded because the Coding API does not expose a standard `/v1/models` endpoint
+
+| Model | Display name | Capabilities |
+|-------|--------------|--------------|
+| `qwen3.7-plus` | Qwen 3.7 Plus | Text Generation, Deep Thinking, Visual Understanding |
---
diff --git a/docs/12-extended-thinking.md b/docs/12-extended-thinking.md
index bde6623d..ac18067a 100644
--- a/docs/12-extended-thinking.md
+++ b/docs/12-extended-thinking.md
@@ -139,6 +139,12 @@ Enables thinking via `enable_thinking: true` plus a `thinking_budget` parameter.
Other models (e.g., `qwen3-plus`, `qwen3-turbo`) silently skip thinking injection to avoid API errors.
+**Bailian Coding note**: Bailian is a separate OpenAI-compatible Coding
+endpoint. Its model catalog includes `qwen3.7-plus` with Deep Thinking and
+Visual Understanding listed for selection, but this DashScope `enable_thinking`
+/ `thinking_budget` injection path does not apply to Bailian unless the Coding
+endpoint's explicit request controls are verified separately.
+
**Important limitation**: DashScope does not support streaming when tools are present. When an agent has tools enabled and thinking is active, the provider automatically falls back to non-streaming mode (single `Chat()` call) and synthesizes chunk callbacks to maintain the event flow.
### Codex (ChatGPT OAuth Responses API)
diff --git a/docs/project-changelog.md b/docs/project-changelog.md
index 0a626218..2279ce37 100644
--- a/docs/project-changelog.md
+++ b/docs/project-changelog.md
@@ -6,6 +6,21 @@ Significant changes, features, and fixes in reverse chronological order.
## 2026-06-12
+### Bailian Coding qwen3.7-plus catalog (issue #169)
+
+**Changes**
+
+- Added `qwen3.7-plus` / `Qwen 3.7 Plus` to the hardcoded Bailian
+ Coding provider model catalog.
+- Documented the model's advertised Text Generation, Deep Thinking, and Visual
+ Understanding capabilities while keeping Bailian on the existing
+ OpenAI-compatible provider wrapper.
+
+**Tests**
+
+- Added provider model endpoint coverage to verify Bailian exposes
+ `qwen3.7-plus` without adding unsupported OpenAI reasoning metadata.
+
### Multi-attachment outbound delivery (issue #172)
**Changes**
diff --git a/internal/http/provider_models_catalog.go b/internal/http/provider_models_catalog.go
index 60a252f9..e62c103d 100644
--- a/internal/http/provider_models_catalog.go
+++ b/internal/http/provider_models_catalog.go
@@ -7,6 +7,8 @@ import "github.com/nextlevelbuilder/goclaw/internal/providers"
// The platform does not expose a /v1/models endpoint.
func bailianModels() []ModelInfo {
return []ModelInfo{
+ // qwen3.7-plus: Text Generation + Deep Thinking + Visual Understanding.
+ {ID: "qwen3.7-plus", Name: "Qwen 3.7 Plus"},
{ID: "qwen3.6-plus", Name: "Qwen 3.6 Plus"},
{ID: "qwen3.5-plus", Name: "Qwen 3.5 Plus"},
{ID: "kimi-k2.5", Name: "Kimi K2.5"},
diff --git a/internal/http/provider_models_test.go b/internal/http/provider_models_test.go
index c6f6a202..f55dfb9f 100644
--- a/internal/http/provider_models_test.go
+++ b/internal/http/provider_models_test.go
@@ -116,6 +116,54 @@ func TestProvidersHandlerListProviderModelsChatGPTOAuthIncludesReasoningMetadata
}
}
+func TestProvidersHandlerListProviderModelsBailianIncludesQwen37Plus(t *testing.T) {
+ token := setupProvidersAdminToken(t)
+ providerStore := newMockProviderStore()
+ provider := &store.LLMProviderData{
+ BaseModel: store.BaseModel{ID: uuid.New()},
+ Name: "bailian-coding",
+ ProviderType: store.ProviderBailian,
+ APIKey: "token",
+ Enabled: true,
+ }
+ if err := providerStore.CreateProvider(t.Context(), provider); err != nil {
+ t.Fatalf("CreateProvider() error = %v", err)
+ }
+
+ handler := NewProvidersHandler(providerStore, newMockSecretsStore(), nil, "")
+ mux := http.NewServeMux()
+ handler.RegisterRoutes(mux)
+
+ req := httptest.NewRequest(http.MethodGet, "/v1/providers/"+provider.ID.String()+"/models", nil)
+ req.Header.Set("Authorization", "Bearer "+token)
+ w := httptest.NewRecorder()
+ mux.ServeHTTP(w, req)
+
+ if w.Code != http.StatusOK {
+ t.Fatalf("status code = %d, want %d, body=%s", w.Code, http.StatusOK, w.Body.String())
+ }
+
+ var result ProviderModelsResponse
+ if err := json.NewDecoder(w.Body).Decode(&result); err != nil {
+ t.Fatalf("Decode() error = %v", err)
+ }
+
+ for _, model := range result.Models {
+ if model.ID != "qwen3.7-plus" {
+ continue
+ }
+ if model.Name != "Qwen 3.7 Plus" {
+ t.Fatalf("model name = %q, want Qwen 3.7 Plus", model.Name)
+ }
+ if model.Reasoning != nil {
+ t.Fatalf("model reasoning = %#v, want nil for Bailian OpenAI-compatible catalog entry", model.Reasoning)
+ }
+ return
+ }
+
+ t.Fatalf("qwen3.7-plus not found in Bailian model list: %#v", result.Models)
+}
+
func TestProvidersHandlerListProviderModelsOpenAICompatAnnotatesKnownModels(t *testing.T) {
token := setupProvidersAdminToken(t)
upstream := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
diff --git a/plans/260612-1709-qwen37-bailian-model/phase-01-catalog-and-capability-docs.md b/plans/260612-1709-qwen37-bailian-model/phase-01-catalog-and-capability-docs.md
new file mode 100644
index 00000000..32bf06f8
--- /dev/null
+++ b/plans/260612-1709-qwen37-bailian-model/phase-01-catalog-and-capability-docs.md
@@ -0,0 +1,56 @@
+---
+phase: 1
+title: Catalog and capability docs
+status: completed
+priority: P2
+effort: 30m
+dependencies: []
+---
+
+# Phase 1: Catalog and capability docs
+
+## Overview
+
+Add the new Bailian model to the backend catalog and document its advertised capabilities without changing runtime request-body semantics.
+
+## Requirements
+
+- Functional: `bailianModels()` returns `{ID: "qwen3.7-plus", Name: "Qwen 3.7 Plus"}`.
+- Functional: docs state the model capabilities from issue #169: Text Generation, Deep Thinking, Visual Understanding.
+- Non-functional: no new API schema fields unless already supported by `ModelInfo`.
+- Non-functional: no runtime behavior change for existing Bailian models.
+
+## Architecture
+
+`GET /v1/providers/{id}/models` loads a provider from the store, dispatches `provider_type == "bailian"` to `bailianModels()`, and returns the list. Web and desktop provider model pickers already consume this endpoint, so the backend catalog update is the UI propagation path.
+
+Do not add `qwen3.7-plus` to `internal/providers/reasoning_capability.go`: `OpenAIProvider.buildRequestBody()` uses that registry to decide whether to send OpenAI `reasoning_effort`. Bailian is registered as `NewOpenAIProvider(...)`, not `NewDashScopeProvider(...)`, so Qwen Deep Thinking docs should not imply a wire-level parameter implementation here.
+
+## Related Code Files
+
+- Modify: `internal/http/provider_models_catalog.go`
+- Modify: `docs/02-providers.md`
+- Modify: `docs/12-extended-thinking.md`
+- No UI changes: web and desktop use the existing provider models endpoint.
+
+## Implementation Steps
+
+1. Add `qwen3.7-plus` near the current Qwen Plus entries in `bailianModels()`.
+2. Add concise inline catalog grouping that records Bailian capabilities for Qwen Plus models.
+3. Update `docs/02-providers.md` Bailian section with the new model and capability row.
+4. Update `docs/12-extended-thinking.md` to clarify Bailian advertises Deep Thinking for `qwen3.7-plus`, but GoClaw does not inject DashScope `enable_thinking` controls for Bailian in this change.
+
+## Success Criteria
+
+- [ ] Catalog contains `qwen3.7-plus`.
+- [ ] Docs mention Text Generation, Deep Thinking, Visual Understanding.
+- [ ] No new provider request-body controls are introduced.
+
+## Risk Assessment
+
+Risk: adding reasoning metadata could make Bailian receive unsupported OpenAI `reasoning_effort`.
+Mitigation: leave `LookupReasoningCapability()` unchanged and document the distinction.
+
+## Security Considerations
+
+No new secrets, auth paths, or tenant writes.
diff --git a/plans/260612-1709-qwen37-bailian-model/phase-02-tests-and-verification.md b/plans/260612-1709-qwen37-bailian-model/phase-02-tests-and-verification.md
new file mode 100644
index 00000000..57020944
--- /dev/null
+++ b/plans/260612-1709-qwen37-bailian-model/phase-02-tests-and-verification.md
@@ -0,0 +1,47 @@
+---
+phase: 2
+title: Tests and verification
+status: completed
+priority: P2
+effort: 30m
+dependencies:
+ - 1
+---
+
+# Phase 2: Tests and verification
+
+## Overview
+
+Add regression coverage for Bailian model discovery and run focused validation for the touched backend/docs paths.
+
+## Requirements
+
+- Functional: endpoint-level test proves Bailian returns `qwen3.7-plus`.
+- Functional: test verifies no unsupported reasoning metadata is exposed for this OpenAI-compatible Bailian model.
+- Non-functional: targeted Go package tests pass with the installed Go binary.
+
+## Implementation Steps
+
+1. Add a provider models test in `internal/http/provider_models_test.go` for `store.ProviderBailian`.
+2. Use existing mock provider store and auth token helpers.
+3. Assert HTTP 200, model ID/display name, and nil `Reasoning` for `qwen3.7-plus`.
+4. Run focused test:
+ - `PATH=/usr/local/go/bin:$PATH go test ./internal/http -run 'Bailian|ProviderModels' -count=1`
+5. Run compile checks when feasible:
+ - `PATH=/usr/local/go/bin:$PATH go test ./internal/http -count=1`
+ - broader build/test if the focused package uncovers shared changes.
+
+## Success Criteria
+
+- [ ] Focused test fails before catalog change and passes after.
+- [ ] `go test ./internal/http` passes.
+- [ ] No generated or unrelated files changed.
+
+## Risk Assessment
+
+Risk: test helper requires an API key for Bailian before returning catalog.
+Mitigation: set a dummy API key on the mock provider because the handler checks non-empty `APIKey` before dispatch.
+
+## Security Considerations
+
+Use dummy values only; do not read or write env/secrets.
diff --git a/plans/260612-1709-qwen37-bailian-model/phase-03-ship-beta-pr.md b/plans/260612-1709-qwen37-bailian-model/phase-03-ship-beta-pr.md
new file mode 100644
index 00000000..0b2d501e
--- /dev/null
+++ b/plans/260612-1709-qwen37-bailian-model/phase-03-ship-beta-pr.md
@@ -0,0 +1,46 @@
+---
+phase: 3
+title: "Ship beta PR"
+status: pending
+priority: P2
+effort: "30m"
+dependencies: [2]
+---
+
+# Phase 3: Ship beta PR
+
+## Overview
+
+Ship the completed issue #169 work as a beta-targeted PR to `dev`, with labels updated according to `ck:vibe --beta`.
+
+## Requirements
+
+- Functional: GitHub issue gets a plan/update comment and `ready to cook` before implementation.
+- Functional: PR targets `dev` and references issue #169.
+- Functional: after local and PR review gates pass, source issue and PR get `ready to ship beta`.
+- Non-functional: no merge is performed because the user invoked `--beta`, not `--ship --beta`.
+
+## Implementation Steps
+
+1. Ensure GitHub labels exist: `ready to cook`, `ready to ship stable`, `ready to ship beta`.
+2. Comment on issue #169 with branch, relative plan path, beta mode, and acceptance criteria.
+3. After implementation/tests/review, commit with a focused conventional message.
+4. Push `codex/issue-169-qwen37-bailian-model`.
+5. Create beta PR against `dev`.
+6. Review/fix/reply PR feedback and wait for terminal checks when available.
+7. Add `ready to ship beta` to both issue and PR; remove `ready to cook`.
+
+## Success Criteria
+
+- [ ] PR exists and targets `dev`.
+- [ ] PR/issue labels reflect ready-to-ship-beta state after review.
+- [ ] Merge is skipped.
+
+## Risk Assessment
+
+Risk: GitHub auth lacks label/PR permissions.
+Mitigation: stop with exact `gh` error if label or PR creation fails.
+
+## Security Considerations
+
+Do not include secrets or private env output in GitHub comments/PR body.
diff --git a/plans/260612-1709-qwen37-bailian-model/plan.md b/plans/260612-1709-qwen37-bailian-model/plan.md
new file mode 100644
index 00000000..48c3eeec
--- /dev/null
+++ b/plans/260612-1709-qwen37-bailian-model/plan.md
@@ -0,0 +1,50 @@
+---
+title: Add qwen3.7-plus to Bailian Coding provider
+description: ''
+status: pending
+priority: P2
+issue: 169
+branch: codex/issue-169-qwen37-bailian-model
+tags: []
+blockedBy: []
+blocks: []
+created: '2026-06-12T10:09:09.353Z'
+createdBy: 'ck:plan'
+source: skill
+---
+
+# Add qwen3.7-plus to Bailian Coding provider
+
+## Overview
+
+Add `qwen3.7-plus` to GoClaw's hardcoded Bailian Coding model catalog so the shared `/v1/providers/{id}/models` endpoint exposes it to both web and desktop model pickers. Keep runtime request behavior backward-compatible: Bailian remains an OpenAI-compatible provider, and no GPT/Codex `reasoning_effort` metadata is added for this Qwen model.
+
+## Phases
+
+| Phase | Name | Status |
+|-------|------|--------|
+| 1 | [Catalog and capability docs](./phase-01-catalog-and-capability-docs.md) | Completed |
+| 2 | [Tests and verification](./phase-02-tests-and-verification.md) | Completed |
+| 3 | [Ship beta PR](./phase-03-ship-beta-pr.md) | Pending |
+
+## Dependencies
+
+- Source issue:
+- Verified code paths:
+ - `internal/http/provider_models_catalog.go`: `bailianModels()` hardcoded catalog.
+ - `internal/http/provider_models.go`: Bailian dispatch uses `bailianModels()` then `withReasoningCapabilities()`.
+ - `internal/http/providers.go`: Bailian runtime registration uses `providers.NewOpenAIProvider(...)`.
+ - `internal/providers/openai_request.go`: `reasoning_effort` is gated by `LookupReasoningCapability()`, so do not add `qwen3.7-plus` there.
+
+## Acceptance Criteria
+
+- [x] `qwen3.7-plus` appears in the Bailian Coding model catalog.
+- [x] Display name is `Qwen 3.7 Plus`.
+- [x] Capabilities are documented as Text Generation, Deep Thinking, Visual Understanding.
+- [x] Web/Desktop provider model pickers inherit the model through the existing `/v1/providers/{id}/models` API.
+- [x] Existing Bailian provider registration remains backward-compatible.
+- [x] Tests cover the Bailian model list.
+
+## Unresolved Questions
+
+- Does Bailian expose explicit request parameters for Deep Thinking on `qwen3.7-plus`? Out of scope for this catalog update unless verified separately.
diff --git a/plans/260612-1709-qwen37-bailian-model/reports/issue-169-vibe-update.md b/plans/260612-1709-qwen37-bailian-model/reports/issue-169-vibe-update.md
new file mode 100644
index 00000000..a4fd6056
--- /dev/null
+++ b/plans/260612-1709-qwen37-bailian-model/reports/issue-169-vibe-update.md
@@ -0,0 +1,27 @@
+## Outcome
+Add `qwen3.7-plus` to the Bailian Coding provider model catalog so the shared provider model API exposes it to web and desktop model pickers.
+
+## Implementation
+- Branch: `codex/issue-169-qwen37-bailian-model`
+- Plan: `plans/260612-1709-qwen37-bailian-model/plan.md`
+- Mode: `beta`
+- PR: pending
+
+## Acceptance Criteria
+- [ ] `qwen3.7-plus` appears in Bailian Coding model catalog
+- [ ] Display name is `Qwen 3.7 Plus`
+- [ ] Capabilities are documented/represented as Text Generation, Deep Thinking, Visual Understanding
+- [ ] Web provider model picker can select `qwen3.7-plus` through `/v1/providers/{id}/models`
+- [ ] Desktop provider model picker can select `qwen3.7-plus` through the same backend model API
+- [ ] Existing Bailian provider registration remains backward-compatible
+- [ ] Tests cover the Bailian model catalog
+- [ ] Docs updated where provider model support is documented
+
+## Pipeline State
+- [x] Worktree and branch created
+- [x] TDD plan created
+- [x] Plan validated
+- [x] Plan red-teamed
+- [ ] Cook complete
+- [ ] PR reviewed and fixed
+- [ ] Merged and CI green (only when --ship)
diff --git a/plans/260612-1709-qwen37-bailian-model/reports/reviewer-260612-1723-qwen37-bailian-model-catalog.md b/plans/260612-1709-qwen37-bailian-model/reports/reviewer-260612-1723-qwen37-bailian-model-catalog.md
new file mode 100644
index 00000000..27092b6b
--- /dev/null
+++ b/plans/260612-1709-qwen37-bailian-model/reports/reviewer-260612-1723-qwen37-bailian-model-catalog.md
@@ -0,0 +1,69 @@
+## Code Review Summary
+
+### Scope
+
+- Files: `internal/http/provider_models_catalog.go`, `internal/http/provider_models_test.go`, `docs/02-providers.md`, `docs/12-extended-thinking.md`, `docs/project-changelog.md`
+- LOC: +76 / -0 pending diff
+- Focus: pending changes only, issue #169 Bailian Coding `qwen3.7-plus` catalog
+- Scout findings: `/v1/providers/{id}/models` dispatches Bailian to `bailianModels()`; web and desktop picker paths consume this endpoint; Bailian runtime registration remains `providers.NewOpenAIProvider(...)`; OpenAI `reasoning_effort` remains gated by GPT/Codex reasoning metadata and is not added for `qwen3.7-plus`.
+
+### Overall Assessment
+
+Implementation matches acceptance criteria. No blocking production-readiness issues found.
+
+### Critical Issues
+
+None.
+
+### High Priority
+
+None.
+
+### Medium Priority
+
+None.
+
+### Low Priority
+
+None.
+
+### Edge Cases Found by Scout
+
+- Verified Bailian catalog path requires API key before returning hardcoded models; test covers the current contract with a dummy key.
+- Verified UI propagation does not require hardcoded web/desktop model list updates because pickers call `/v1/providers/{id}/models`.
+- Verified `qwen3.7-plus` is not in `LookupReasoningCapability()`, so selecting it will not trigger unsupported OpenAI `reasoning_effort`.
+
+### Positive Observations
+
+- Test covers endpoint-level behavior, display name, and nil reasoning metadata.
+- Docs correctly distinguish advertised Bailian Deep Thinking capability from DashScope `enable_thinking` / `thinking_budget` request injection.
+- Existing Bailian provider default model and registration path are unchanged.
+
+### Recommended Actions
+
+1. No code changes required.
+2. Plan can mark Phase 2 complete; Phase 3 remains pending.
+
+### Verification
+
+- `PATH=/usr/local/go/bin:$PATH go test ./internal/http -run 'TestProvidersHandlerListProviderModels(BailianIncludesQwen37Plus|ChatGPTOAuthIncludesReasoningMetadata|OpenAICompatAnnotatesKnownModels)'` passed.
+- `PATH=/usr/local/go/bin:$PATH go test ./internal/providers -run 'TestLookupReasoningCapability|TestDashScopeModelSupportsThinking|TestDashScopeThinking'` passed.
+- `PATH=/usr/local/go/bin:$PATH go test ./internal/http` passed.
+- `PATH=/usr/local/go/bin:$PATH go test ./internal/providers` passed.
+- `git diff --check -- internal/http/provider_models_catalog.go internal/http/provider_models_test.go docs/02-providers.md docs/12-extended-thinking.md docs/project-changelog.md` passed.
+
+### Metrics
+
+- Type Coverage: N/A for Go; package compile covered by `go test`
+- Test Coverage: coverage percentage not collected
+- Linting Issues: 0 from `git diff --check`; full lint/vet not run
+
+### Plan Status
+
+- Phase 1: complete by diff evidence.
+- Phase 2: appears complete; focused and package tests passed.
+- Phase 3: pending, not reviewed as implementation.
+
+### Unresolved Questions
+
+None for this catalog implementation. Bailian-specific Deep Thinking wire controls remain explicitly out of scope.
diff --git a/plans/260612-1709-qwen37-bailian-model/reports/scout-report.md b/plans/260612-1709-qwen37-bailian-model/reports/scout-report.md
new file mode 100644
index 00000000..aac10a93
--- /dev/null
+++ b/plans/260612-1709-qwen37-bailian-model/reports/scout-report.md
@@ -0,0 +1,19 @@
+# Scout Report
+
+## Findings
+
+- Repo verified: `digitopvn/goclaw`, default branch `dev`.
+- Source issue verified: #169 requests `qwen3.7-plus` for Bailian Coding.
+- Catalog source: `internal/http/provider_models_catalog.go` -> `bailianModels()`.
+- Endpoint dispatch: `internal/http/provider_models.go` uses `bailianModels()` for `provider_type == "bailian"`.
+- UI propagation: web and desktop model pickers call `/v1/providers/{id}/models`; no hardcoded Bailian model list found in UI.
+- Runtime boundary: `internal/http/providers.go` registers Bailian through `providers.NewOpenAIProvider(...)`.
+- Wire guardrail: `internal/providers/openai_request.go` sends OpenAI `reasoning_effort` only when `LookupReasoningCapability()` returns metadata or model is GPT/o-series.
+
+## Decision
+
+Implement catalog entry, endpoint regression test, and docs. Do not add `qwen3.7-plus` to the GPT/Codex reasoning capability registry in this task.
+
+## Unresolved Questions
+
+- Does Bailian expose explicit thinking request parameters for `qwen3.7-plus`? Not needed for the catalog issue.
diff --git a/plans/260612-1709-qwen37-bailian-model/reports/tester-2026-06-12-issue-169-bailian-qwen37-catalog.md b/plans/260612-1709-qwen37-bailian-model/reports/tester-2026-06-12-issue-169-bailian-qwen37-catalog.md
new file mode 100644
index 00000000..67c4a75a
--- /dev/null
+++ b/plans/260612-1709-qwen37-bailian-model/reports/tester-2026-06-12-issue-169-bailian-qwen37-catalog.md
@@ -0,0 +1,19 @@
+# Tester Report - issue #169 Bailian qwen3.7-plus catalog
+
+## Scope
+- Verified the Bailian Coding model catalog addition in `internal/http/provider_models_catalog.go`.
+- Verified handler coverage in `internal/http/provider_models_test.go`.
+- Checked docs updates in `docs/02-providers.md`, `docs/12-extended-thinking.md`, and `docs/project-changelog.md`.
+
+## Results
+- `PATH=/usr/local/go/bin:$PATH go test ./internal/http -run TestProvidersHandlerListProviderModelsBailianIncludesQwen37Plus -count=1`
+ - PASS
+- `git diff --check`
+ - PASS
+
+## Notes
+- `GET /v1/providers/{id}/models` is the contract used by the web and desktop pickers; no UI hardcoded model list change was needed.
+- Bailian registration remains on the existing OpenAI-compatible provider path with the default model still set to `qwen3.5-plus`.
+
+## Coverage gap
+- Catalog is covered by one focused regression only; no additional provider-level or UI-level test was added in this patch.
diff --git a/plans/260612-1709-qwen37-bailian-model/reports/validation-red-team-report.md b/plans/260612-1709-qwen37-bailian-model/reports/validation-red-team-report.md
new file mode 100644
index 00000000..7952b320
--- /dev/null
+++ b/plans/260612-1709-qwen37-bailian-model/reports/validation-red-team-report.md
@@ -0,0 +1,20 @@
+# Validation And Red-Team Report
+
+## Validation
+
+- Acceptance criteria are mapped to concrete files and tests.
+- Web/Desktop selection is covered through the shared backend model endpoint, not separate UI lists.
+- Backward compatibility is explicit: Bailian provider registration remains unchanged.
+
+## Red-Team Findings
+
+- Finding: Adding `qwen3.7-plus` to `LookupReasoningCapability()` would expose advanced reasoning controls and may make Bailian send OpenAI `reasoning_effort`.
+ - Verdict: Reject for this issue scope. Keep runtime controls unchanged.
+- Finding: Vision capability is not a `ModelInfo` field today.
+ - Verdict: Document capability only; avoid schema expansion for a single catalog entry.
+- Finding: Handler rejects providers with empty API keys before model dispatch.
+ - Verdict: Test must create a Bailian provider with a dummy API key.
+
+## Unresolved Questions
+
+- None blocking implementation.