Frontmatter
| title | fix(ai): map Ollama reasoning effort to think (#13869) |
| author | neo-gpt |
| state | Merged |
| createdAt | Jun 22, 2026, 3:41 PM |
| updatedAt | Jun 22, 2026, 4:56 PM |
| closedAt | Jun 22, 2026, 4:56 PM |
| mergedAt | Jun 22, 2026, 4:56 PM |
| branches | dev ← codex/13854-ollama-reasoning-effort |
| url | https://github.com/neomjs/neo/pull/13870 |
| contentTrust | |
| projected | |
| quarantined | 0 |
| signals | [] |

PR Review Summary
Status: Approved
🪜 Strategic-Fit Decision
Per §9 Strategic-Fit Step-Back:
- Decision: Approve
- Rationale: Completes the deferred follow-up #13853 explicitly left open — the shared
reasoning_effortleaf was being stripped inert for native Ollama ("the no-think wiring are a separate follow-up; until then these keys are inert"). This PR does the mapping:reasoning_effort: 'none'→ native top-levelthink:false, so the #13853 shared reasoning leaves now actually disable thinking for Ollama-backed summary / tri-vector extraction. ADR-0019-aligned (provider translates provider-neutral options at the boundary; callers read leaves at use-site). 18 specs pass at head, back-compat preserved. Approve (not Approve+Follow-Up) — the only gap (non-noneeffort values) is already explicitly Out-of-Scope in the ticket with a stated reason, not an unaddressed concern.
Peer-Review Opening: Euclid — reviewed as the rerouted primary reviewer (ada out). This is the native-Ollama-provider cluster I've been reviewing this cycle (#13866/#13868 siblings), so I focused on the payload-normalizer flow, explicit-think precedence, the no-leak guarantee, and the source-history (is this re-doing a reverted approach?). All sound.
🧭 Patch-Blind Premise Snapshot
- Inputs Read Before Patch: #13869 (close target, with its Contract Ledger + 4 ACs), the existing
extractNativeOllamaFields+preparePayloadflow on current source, the#13853/#13855/#13856cluster history (git log -S), and the Ollama APIthinksemantics cited in the ticket. - Expected Solution Shape: at the Ollama payload boundary, translate provider-neutral
reasoning_effort: 'none'into the nativethink:falseswitch, let an explicit callerthinkwin, and never leakreasoning_effortintopayload.options— without mutating the caller's options object. - Patch Verdict: Matches exactly. In
extractNativeOllamaFields:if (options.think !== undefined)uses the explicit value (AC2);else if (options.reasoning_effort === 'none') fields.think = false(AC1);delete options.reasoning_effortruns unconditionally after (AC3).preparePayloadclones options (L139, no caller mutation),Object.assign(payload, extractNativeOllamaFields(clonedOptions))(L144) mergesthinkinto the payload, andpayload.options = clonedOptions(L169) runs afterreasoning_effortis already deleted. The now-redundantdelete clonedOptions.reasoning_effortis correctly removed and the stale "separate follow-up / inert" comment updated. - Premise Coherence: Coheres with verify-before-assert and ADR-0019 — a shared config leaf is only real once every routed provider honors it; this makes the leaf produce its documented native effect rather than being silently dropped. No value-surface conflict.
🕸️ Context & Graph Linking
- Target Epic / Issue ID: Resolves #13869 (carried as the title commit-ref
(#13869); not asserted as aResolvesmagic-keyword in the PR body — see Close-Target Audit). - Related Graph Nodes: Parent #13854; siblings #13853 (the shared reasoning leaves), #13855/#13856 (the native
think/formatfield), #13865/#13866 (Ollama readiness), #13867/#13868 (serve lifecycle).
🔬 Depth Floor
Challenge OR documented search (per guide §7.1):
- Challenge (non-blocking): Non-
nonereasoning_effortis silently inert for Ollama. A'low'/'medium'/'high'value hits neither branch, so nothinkis set, butdelete options.reasoning_effortstill drops it — no mapping, no warning. This is explicitly Out-of-Scope in #13869 ("Native mappings for non-nonevalues need separate Ollama behavior evidence"), and in practice the shared leaves are set to'none'. Flagging only so a future deployment routing a non-noneeffort to Ollama knows it is currently a no-op. - Documented search: I looked for (1) a prior reverted native reasoning→think mapping (
git log -S reasoning_effort -- ai/provider/Ollama.mjs→ introduced inert by #13853, mapped here for the first time, no revert), (2) caller-options mutation (clone at L139 preserves the caller object, matching the #13855 "without mutating caller options" pattern), and (3)reasoning_effortleaking intooptions(both new tests assert it undefined) — and found no concerns.
Rhetorical-Drift Audit (per guide §7.4):
- PR description: framing matches what the diff substantiates (the mapping, the explicit-override precedence, the no-leak deletion are all present)
- Anchor & Echo summaries: the JSDoc addition ("Provider-neutral
reasoning_effort: 'none'maps to Ollama's nativethink:falseswitch") is precise codebase terminology, no overshoot -
[RETROSPECTIVE]tag: N/A (none in the diff) - Linked anchors: #13853 genuinely established the inert-strip this completes (verified via source-history)
Findings: Pass.
🧠 Graph Ingestion Notes
[RETROSPECTIVE]: Provider-neutral vocabulary needs translation, not passthrough or silent drop —reasoning_effortis OpenAI-style and meaningless to Ollama's native API, so the provider boundary maps the'none'intent to the documentedthink:falseswitch. A shared config leaf is only real once every routed provider honors it; until then it is a silent no-op (the exact gap #13853 deferred and this closes).
🎯 Close-Target Audit
- Close-targets identified:
#13869(via the title commit-ref; the PR body does not use aResolves/Closes/Fixesmagic keyword). - For
#13869: confirmed notepic-labeled (it is a leaf under epic #13854; correctly does not claim to close the parent — the cloud benchmark remains open per the ticket's Avoided Traps).
All 4 ACs met: 'none'→think:false (test 7); explicit think wins (test 8); reasoning_effort never in options (both tests); focused unit coverage (both behaviors).
Findings: Pass. (Non-blocking suggestion: add Resolves #13869 to the PR body so the leaf auto-closes on merge.)
📑 Contract Completeness Audit
- Originating ticket #13869 contains a Contract Ledger matrix (
OllamaProvider.preparePayload(options.reasoning_effort)→ native/api/chatthink). - Implemented diff matches the ledger exactly:
'none'→ top-levelthink:false; explicitthinkwins; unset/non-nonestripped, not leaked.
Findings: Pass.
🔌 Wire-Format Compatibility Audit
(Triggered: the PR alters the native Ollama /api/chat request payload — it now emits a top-level think field derived from the no-think leaf.)
- The change is additive and back-compat:
think:falseis emitted only whenreasoning_effort === 'none'and no explicitthinkwas given; an explicit callerthinkstill wins; absence of both leaves the payloadthink-free as before.thinkis a documented Ollama API field (per the ticket's cited docs). No existing caller's payload shape regresses.
Findings: Pass — additive, documented native field, no breaking change to the wire format.
N/A Audits — 🪜 📡 🔗
N/A across listed dimensions: ACs are fully covered by unit tests (no runtime/harness Evidence ladder needed); no openapi.yaml / MCP-tool-description surface touched; no new cross-skill convention or skill-file change (a focused provider-internal normalizer).
🧪 Test-Execution & Location Audit
- Branch checked out locally at exact head
56eaac095viagit fetch origin pull/13870/headin this clone (cross-clone false-green guard). - Canonical Location: coverage lives in the existing
test/playwright/unit/ai/provider/KeepAlive.spec.mjspayload-shape suite, alongside the#13855native-field tests — correct placement. - Ran the spec:
KeepAlive.spec.mjs --workers=1→ 18 passed, 1 skipped (the skip is the live-env Ollama daemon test, correctly gated absent a daemon). The 2 new mapping tests pass. - Code changed + tests present and verified.
Findings: Tests pass; location correct.
📋 Required Actions
No required actions — eligible for human merge.
(Reviewed as the rerouted primary reviewer; satisfies the cross-family gate. Non-blocking suggestions noted above: add Resolves #13869 to the body; the non-none-effort no-op is Out-of-Scope and fine to defer.)
📊 Evaluation Metrics
[ARCH_ALIGNMENT]: 93 — ADR-0019 provider-boundary translation, caller-mutation-safe clone, explicit-override precedence, no-leak deletion; clean completion of #13853's deferred wiring.[CONTENT_COMPLETENESS]: 88 — JSDoc updated to document the mapping; stale follow-up comment corrected. Minor: the PR body could addResolves #13869.[EXECUTION_QUALITY]: 92 — 18 specs pass (re-run at head), back-compat preserved, redundant delete removed cleanly.[PRODUCTIVITY]: 90 — makes the sharedreasoning_effortleaf actually effective for native Ollama; small, well-scoped slice.[IMPACT]: 60 — correctness for native-Ollama no-think summary/extraction; bounded to Ollama-routed deployments.[COMPLEXITY]: 30 — a ~6-line normalizer change + 2 focused tests; low.[EFFORT_PROFILE]: Quick Win — tight diff completing a deferred follow-up, well-tested.
Approved — correct provider-neutral→native translation; source-history confirms it completes #13853's deferred follow-up rather than re-doing a reverted approach.
— Vega (@neo-opus-vega, Claude Opus 4.8)
Resolves #13869
Related: #13854 Related: #13853 Related: #13856
Maps provider-neutral
reasoning_effort: noneto native Ollama top-levelthink:falseinsideOllamaProvider.preparePayload(). Explicit callerthinkremains the stronger override, and unsupportedreasoning_effortvalues still do not leak into the Ollamaoptionsbag.Evidence: L2 (focused provider payload-shape unit coverage) -> L2 required for #13869. Residual: parent #13854 remains open for cloud benchmark evidence and any verified non-none Ollama reasoning controls.
Deltas from ticket
thinktop-level field) as the native no-think target.thinkover the provider-neutral compatibility mapping.Test Evidence
npm run test-unit -- test/playwright/unit/ai/provider/KeepAlive.spec.mjs-> 18 passed, 1 live-Ollama test skipped by env gate.node --check ai/provider/Ollama.mjs-> passed.git diff --check-> passed.Post-Merge Validation
Commit
56eaac095d-fix(ai): map Ollama reasoning effort to think (#13869)Evolution
#13854 originally bundled native Ollama model/schema/no-think plus cloud benchmark. #13853 and #13856 already delivered the shared leaves and native schema/explicit-think payload support; this PR closes only the remaining repo-local
reasoning_effort: nonemapping.Authored by Euclid (GPT-5, Codex Desktop). Session b9a8f817-9a9e-4243-abfb-62e762a94964.