Skip to content

[RFC] Add support for Ollama provider#338

Open
mchehab wants to merge 10 commits into
sashiko-dev:mainfrom
mchehab:ollama
Open

[RFC] Add support for Ollama provider#338
mchehab wants to merge 10 commits into
sashiko-dev:mainfrom
mchehab:ollama

Conversation

@mchehab

@mchehab mchehab commented Jul 19, 2026

Copy link
Copy Markdown

The OpenAI compatible model doesn't work with Ollama. Add another provider for it.

Assisted-by: qwen2.6_claude_27B

The OpenAI compatible model doesn't work with Ollama. Add another
provider for it.

The code there was generated from a prompt to modify src/ai/openai.rs
to use an Ollama-compatible API.

Assisted-by: qwen2.6_claude_27B
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
@mchehab

mchehab commented Jul 19, 2026

Copy link
Copy Markdown
Author

With this PR, Sashiko no works with Ollama.

On this case, I asked it to review a very simple patch that it is adding an entry to MAINTAINERS file, using
llama3.1:8b (to make the test fast)

That's ~/.config/sashiko.toml configuration:

[ai]                                                                                                                                                                                                                                                                        
provider = "ollama"                                                                                                                                                                                                                                                         
# model = "qwen3.6:latest"                                                                                                                                                                                                                                                  
# model = "gemma4:26b"                                                                                                                                                                                                                                                      
model = "llama3.1:8b"                                                                                                                                                                                                                                                       
log_turns=true                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                            
[ai.ollama]                                                                                                                                                                                                                                                                 
base_url = "http://127.0.0.1:11434/"                                                                                                                                                                                                                                       
context_window_size = 128000                                                                                                                                                                                                                                                
max_tokens = 24768    

And this is Sashiko review output:

$ sashiko --debug review 
2026-07-19T09:16:59.268820Z  INFO sashiko: Debug logging enabled
Reviewing: HEAD
Using prompts: /home/mchehab/.local/share/sashiko/prompts/788b0b19fe384d325c9a1ee16a1ee41665bc78b3/kernel
2026-07-19T09:16:59.888681Z  INFO sashiko::local_review: Worktree at "/new_devel/v4l/media-next"
2026-07-19T09:16:59.888694Z  INFO sashiko::local_review: Found 1 patches total
2026-07-19T09:16:59.901561Z  INFO sashiko::local_review: Patches applied. Starting AI reviews for 1 patches...
Running review for 1 patch
2026-07-19T09:16:59.943085Z  WARN rustls_platform_verifier::verification::others: Error loading CA root certificate: failed to read PEM from file: Permission denied (os error 13) at '/etc/pki/tls/certs/exim.pem'
2026-07-19T09:16:59.949803Z  INFO sashiko::local_review: Active patch files gathered for patch 1: ["MAINTAINERS"]
2026-07-19T09:16:59.949824Z  INFO sashiko::local_review: Setting virtual HEAD to 25ba26bff1fa501f5164d7a161be3f26ac8a091b for patch 1
      [Patch 1] MAINTAINERS: Merge int3472...  | Pre-screening guides...
Overall: [░░░░░░░░░░░░░░░░░░░░] 0% | 0/11 stages | 0 turns
2026-07-19T09:16:59.950142Z  INFO sashiko::worker::prompts: Executing Phase 0: Pre-screening relevant subsystem guides.
2026-07-19T09:16:59.950158Z  INFO sashiko::ai::ollama: Sending Ollama request to model: llama3.1:8b
      [Patch 1] MAINTAINERS: Merge int3472...  | Planning stages...
Overall: [░░░░░░░░░░░░░░░░░░░░] 0% | 0/11 stages | 0 turns
2026-07-19T09:17:06.216203Z  INFO sashiko::worker::prompts: Running planning pre-phase
2026-07-19T09:17:06.216210Z  INFO sashiko::ai::ollama: Sending Ollama request to model: llama3.1:8b
      [Patch 1] MAINTAINERS: Merge int3472...  | Reviewing...
Overall: [░░░░░░░░░░░░░░░░░░░░] 0% | 0/7 stages | 0 turns
2026-07-19T09:17:07.748606Z  INFO sashiko::worker::prompts: Skipping stage 4 based on planning phase
2026-07-19T09:17:07.748609Z  INFO sashiko::worker::prompts: Skipping stage 5 based on planning phase
2026-07-19T09:17:07.748610Z  INFO sashiko::worker::prompts: Skipping stage 6 based on planning phase
      [Patch 1] MAINTAINERS: Merge int3472...  | Goal Analysis
      [Patch 1] MAINTAINERS: Merge int3472...  | Goal Analysis (turn 1)
      [Patch 1] MAINTAINERS: Merge...  | Goal Analysis (turn 1) (+1 stages)
      [Patch 1] MAINTAINERS: Merge...  | Goal Analysis (turn 1) (+1 stages)
      [Patch 1] MAINTAINERS: Merge...  | Goal Analysis (turn 1) (+2 stages)
      [Patch 1] MAINTAINERS: Merge...  | Goal Analysis (turn 1) (+2 stages)
Overall: [░░░░░░░░░░░░░░░░░░░░] 0% | 0/7 stages | 3 turns
      [Patch 1] MAINTAINERS: Merge... | Implementation (turn 1) (+1 stages)
      [Patch 1] MAINTAINERS: Merge int3472...  | Implementation (turn 1)
      [Patch 1] MAINTAINERS: Merge int3472...  | Implementation (turn 1)
Overall: [█████░░░░░░░░░░░░░░░] 28% | 2/7 stages | 4 turns
      [Patch 1] MAINTAINERS: Merge int3472...  | Deduplication
      [Patch 1] MAINTAINERS: Merge int3472...  | Deduplication (turn 1)
Overall: [████████░░░░░░░░░░░░] 42% | 3/7 stages | 5 turns
      [Patch 1] MAINTAINERS: Merge int3472...  | Deduplication (turn 1)
Overall: [████████░░░░░░░░░░░░] 42% | 3/7 stages | 6 turns
      [Patch 1] MAINTAINERS: Merge int3472...  | Conflict Resolution
      [Patch 1] MAINTAINERS: Merge int347... | Conflict Resolution (turn 1)
Overall: [███████████░░░░░░░░░] 57% | 4/7 stages | 7 turns
      [Patch 1] MAINTAINERS: Merge int3472...  | Severity Estimation
      [Patch 1] MAINTAINERS: Merge int347... | Severity Estimation (turn 1)
Overall: [██████████████░░░░░░] 71% | 5/7 stages | 8 turns
      [Patch 1] MAINTAINERS: Merge int3472...  | Report Generation
      [Patch 1] MAINTAINERS: Merge int3472...  | Report Generation (turn 1)
Overall: [█████████████████░░░] 85% | 6/7 stages | 9 turns
      [Patch 1] MAINTAINERS: Merge int3472...  | Report Generation (turn 1)
Overall: [█████████████████░░░] 85% | 6/7 stages | 10 turns
      [Patch 1] MAINTAINERS: Merge int3472...  | Report Generation (turn 1)
Overall: [█████████████████░░░] 85% | 6/7 stages | 11 turns
      [Patch 1] MAINTAINERS: Merge int3472...  | Reviewing...
      [Patch 1] MAINTAINERS: Merge int3472...  | Finished
Overall: [████████████████████] 100% | 7/7 stages | 11 turns
Review complete

Findings:
  Critical: 0  High: 0  Medium: 2  Low: 0

  --- Patch [1] MAINTAINERS: Merge int3472 driver patches via the media tree by default ---
  [Medium] The change may break backwards compatibility with existing configurations or build environments.
  [Medium] Tracing callees of modified functions.


Inline Review:
--- Patch [1]: MAINTAINERS: Merge int3472 driver patches via the media tree by default ---
Here is the revised report:

Subject: Regressions found in commit 25ba26bff1fa501f5164d7a161be3f26ac8a091b


Author: Sakari Ailus <sakari.ailus@linux.intel.com>

MAINTAINERS: Merge int3472 driver patches via the media tree by default
    
commit 25ba26bff1fa501f5164d7a161be3f26ac8a091b

This isn't a bug, but...

The commit message states the int3472 driver (under drivers/platform/x86/intel/int3472) implements an effective kernel API that is primarily used by the drivers under drivers/media. However, it does not explicitly mention any potential compatibility issues or configuration changes.

diff --git a/MAINTAINERS b/MAINTAINERS
index 05b783f429e6..febe918d6316 100644

>   M:  Daniel Scally <dan.scally@ideasonboard.com>
>   M:  Sakari Ailus <sakari.ailus@linux.intel.com>
>   S:  Maintained
> +T:   git git://linuxtv.org/media.git
>  F:   drivers/platform/x86/intel/int3472/
>  F:   include/linux/platform_data/x86/int3472.h

[Severity: Medium]
Does this break backwards compatibility with existing configurations or build environments? Looking at drivers/platform/x86/intel/int3472/int3472.c:int3472_init(), int3472_init has multiple callees, but we cannot determine which ones are affected by the modification. We need to trace callees of each modified function to verify if any dependencies are missed or broken.

Looking at include/linux/platform_data/x86/int3472.h:intel_int3472_platform_data(), intel_int3472_platform_data is also a potential entry point, but we cannot determine its dependencies either.

[Severity: Medium]
Does this introduce new dependencies and configurations that may not be compatible with existing build environments or user configurations? The commit message does not provide clear guidance on how to handle potential configuration or build environment changes.

Tokens: 61856 in / 6643 out / 0 cached

Ollama needs to receive num_ctx at the generate request,
according with:
	https://github.com/ollama/ollama/blob/main/docs/api.md

If we don't do that, it will use the default from ollama serve
parameters.

Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
mchehab added 3 commits July 19, 2026 14:35
Those LLM-generated comments aren't useful. Drop them.

Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
Make it similar to openai.rs code.

Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
Drop uneeded comments and try to use the same coding style.

No functional changes.

Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
@mchehab

mchehab commented Jul 19, 2026

Copy link
Copy Markdown
Author

As a reference, this is the ~/.config/sashiko.toml file I'm using here to test:

[ai]                                                                                                                       
provider = "ollama"                                                                                                        
                                                                                                                           
# model = "qwen3.6:latest"  # this one causes some CPU offload with 16GB VRAM
# model = "gemma4:26b" # this one causes some CPU offload with 16GB VRAM
# model = "llama3.1:8b" # This is "fast", but not too precise
model = "ornith:9b"  # This one is announced to perform similar to Qwen3.5 and Gemma4 with 36B
api_timeout_secs=600 # Local runs require a higher timeout
                                                                                                                           
[ai.ollama]
context_window_size = 128000

[review]
concurrency = 1
timeout_seconds = 7200
max_retries = 3

mchehab added 3 commits July 19, 2026 16:14
Properly map error codes from:
	https://docs.ollama.com/api/errors

Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
As local runs may take quite a while, add an option to adjust
the think mode if needed.

The Ollama API accept this value as either a String or as a
boolean. Implement it as string.

While here, drop an obvious commented added by LLM.

Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
The logic at main.rs may actually have more completed states
than its total:

DEBUG: completed_stages=9, total_stages=9, width=20, filled=20
      [Patch 1] media: em28xx: dro... | Execution Flow (turn 1) (+1 stages)
DEBUG: completed_stages=10, total_stages=9, width=20, filled=22
      [Patch 1] media: em28xx: drop 'users'... | Locking & Sync (turn 1)
DEBUG: completed_stages=11, total_stages=9, width=20, filled=24
      [Patch 1] media: em28xx: drop 'users'... | Reviewing...
      [Patch 1] media: em28xx: drop 'users'... | Deduplication
DEBUG: completed_stages=12, total_stages=9, width=20, filled=26
      [Patch 1] media: em28xx: drop 'users'... | Deduplication (turn 1)
DEBUG: completed_stages=12, total_stages=9, width=20, filled=26
Overall: [████████████████████] 133% | 12/9 stages | 24 turns
      [Patch 1] media: em28xx: drop 'users'... | Reviewing...
      [Patch 1] media: em28xx: drop 'users'... | Conflict Resolution
DEBUG: completed_stages=13, total_stages=9, width=20, filled=28
      [Patch 1] media: em28xx: drop 'user... | Conflict Resolution (turn 1)
DEBUG: completed_stages=13, total_stages=9, width=20, filled=28
Overall: [████████████████████] 144% | 13/9 stages | 25 turns
      [Patch 1] media: em28xx: drop 'user... | Conflict Resolution (turn 1)
DEBUG: completed_stages=13, total_stages=9, width=20, filled=28
Overall: [████████████████████] 144% | 13/9 stages | 26 turns
      [Patch 1] media: em28xx: drop 'user... | Conflict Resolution (turn 1)
DEBUG: completed_stages=13, total_stages=9, width=20, filled=28
Overall: [████████████████████] 144% | 13/9 stages | 27 turns

This causes a crash as width-filled becomes a negative number:

    Overall: [████████████████████] 100% | 11/11 stages | 30 turns
          [Patch 1] media: em28xx: dro... | Implementation (turn 1) (+5 stages)
    Overall: [█████████████████████
    thread 'main' (2447762) panicked at library/alloc/src/slice.rs:523:50:
    capacity overflow
    stack backtrace:
      0:     0x55b30561217a - <<std[52ccbc9b4b4e18b4]::sys::backtrace::BacktraceLock>::print::DisplayBacktrace as core[a0a13ccc4397ecab]
    ::fmt::Display>::fmt
      1:     0x55b30562deca - core[a0a13ccc4397ecab]::fmt::write
      2:     0x55b305619f32 - <std[52ccbc9b4b4e18b4]::sys::stdio::unix::Stderr as std[52ccbc9b4b4e18b4]::io::Write>::write_fmt
      3:     0x55b3055edb53 - std[52ccbc9b4b4e18b4]::panicking::default_hook::{closure#0}
      4:     0x55b3056089fc - std[52ccbc9b4b4e18b4]::panicking::default_hook
      5:     0x55b305608bbb - std[52ccbc9b4b4e18b4]::panicking::panic_with_hook
      6:     0x55b3055edc08 - std[52ccbc9b4b4e18b4]::panicking::panic_handler::{closure#0}
      7:     0x55b3055e2ab9 - std[52ccbc9b4b4e18b4]::sys::backtrace::__rust_end_short_backtrace::<std[52ccbc9b4b4e18b4]::panicking::pani
    c_handler::{closure#0}, !>
      8:     0x55b3055eec3d - __rustc[149301a0351973cc]::rust_begin_unwind
      9:     0x55b303ebcd1c - core[a0a13ccc4397ecab]::panicking::panic_fmt
     10:     0x55b303ebca74 - core[a0a13ccc4397ecab]::option::expect_failed
     11:     0x55b3041cd0b6 - alloc::slice::<impl [T]>::repeat::h2076c0dffcce8bdf
     12:     0x55b3040edfaf - sashiko::render_progress::h0541955cd5cf889a
     13:     0x55b30401d514 - sashiko::handle_review_command::{{closure}}::{{closure}}::h165c77097608c979
     14:     0x55b3041eff25 - sashiko::local_review::review_single_patch::{{closure}}::{{closure}}::{{closure}}::hc8facc02e89571c9
     15:     0x55b30409c143 - sashiko::worker::prompts::Worker::execute_stage::{{closure}}::he1ae86600eb08e04
     16:     0x55b30407eeb0 - <futures_util::future::try_maybe_done::TryMaybeDone<Fut> as core::future::future::Future>::poll::h84a15cee
    07a1edc6
     17:     0x55b3041b54dc - <futures_util::future::try_join_all::TryJoinAll<F> as core::future::future::Future>::poll::hd081061f793f89
    f8
     18:     0x55b3041fe54b - sashiko::worker::prompts::Worker::run::{{closure}}::h461674680251a479
     19:     0x55b3041ec8dc - sashiko::local_review::review_single_patch::{{closure}}::h0d3b0cd3d9218508
     20:     0x55b3041ddcdf - <futures_util::stream::futures_unordered::FuturesUnordered<Fut> as futures_core::stream::Stream>::poll_nex
    t::h145d4ece09d10d83
     21:     0x55b304160df5 - <futures_util::stream::stream::next::Next<St> as core::future::future::Future>::poll::hae7eb5e448e10f26
     22:     0x55b304019aa7 - sashiko::local_review::run_worker_in_worktree::{{closure}}::h8d15c424eb97e326
     23:     0x55b30400edec - sashiko::local_review::run_worker::{{closure}}::hf516081af4ea7f43
     24:     0x55b3040280c4 - sashiko::main::{{closure}}::hea950edadefa9f7a
     25:     0x55b3040088d7 - tokio::runtime::park::CachedParkThread::block_on::he9c7ef757edf9eac
     26:     0x55b3041af8d3 - tokio::runtime::runtime::Runtime::block_on::h8a019604f34765ef
     27:     0x55b3040f2609 - sashiko::main::hb75d07e27cdb81f7
     28:     0x55b3041c5c13 - std::sys::backtrace::__rust_begin_short_backtrace::h8cfefc670e2afde0
     29:     0x55b3041e11c9 - std::rt::lang_start::{{closure}}::h2724112c1b27a7b4
     30:     0x55b305607464 - std[52ccbc9b4b4e18b4]::rt::lang_start_internal
     31:     0x55b3040f7085 - main
     32:     0x7f62e6cd2681 - __libc_start_call_main
     33:     0x7f62e6cd2798 - __libc_start_main@@GLIBC_2.34
     34:     0x55b303ebcfe5 - _start
     35:                0x0 - <unknown>

Prevent the crash by limiting the maximum size for the scrollbar.

I suspect that the root cause is due to retries:

	2026-07-19T23:05:03.356421Z  INFO sashiko: AI review retry (attempt 2/3)
	2026-07-19T23:05:03.356424Z  INFO sashiko::local_review: Restarting AI review for patch 1 (attempt 2/3)...

That have been accounted as completed.

Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
@mchehab

mchehab commented Jul 20, 2026

Copy link
Copy Markdown
Author

This is the result of running Sashiko with Ollama with this config file, on a rDNA4 GPU with 16GB VRAM:

Config file

[ai]                                                                                                                                                                                                                                      
provider = "ollama"                                                                                                                                                                                                                       
model = "ornith:9b"                                                                                                                                                                                                                       
api_timeout_secs = 900                                                                                                                                                                                                                    
                                                                                                                                                                                                                                          
[ai.ollama]                                                                                                                                                                                                                               
context_window_size = 262144
max_tokens = 262144
                                                                                                                                                                                                                                          
[review]                                                                                                                                                                                                                                  
concurrency = 1                                                                                                                                                                                                                           
timeout_seconds = 18000 # 5 hours                                                                                                                                                                                                         
max_retries = 3                                                                                                                                                                                                                           

Ollama run

$ sashiko --debug review 288254383674..67f87b104f4e~3
2026-07-19T23:44:43.878980Z  INFO sashiko: Debug logging enabled
Reviewing: 288254383674..67f87b104f4e~3
Using prompts: /home/mchehab/.local/share/sashiko/prompts/788b0b19fe384d325c9a1ee16a1ee41665bc78b3/kernel
2026-07-19T23:44:47.879035Z  INFO sashiko::local_review: Worktree at "/new_devel/v4l/media-next"
2026-07-19T23:44:47.879047Z  INFO sashiko::local_review: Found 1 patches total
2026-07-19T23:44:47.886460Z  INFO sashiko::local_review: Patches applied. Starting AI reviews for 1 patches...
Running review for 1 patch
2026-07-19T23:44:47.893885Z  WARN rustls_platform_verifier::verification::others: Error loading CA root certificate: failed to read PEM from file: Permission denied (os error 13) at '/etc/pki/tls/certs/exim.pem'
2026-07-19T23:44:47.902144Z  INFO sashiko::local_review: Active patch files gathered for patch 1: ["drivers/media/usb/em28xx/em28xx-video.c", "drivers/media/usb/em28xx/em28xx.h"]
2026-07-19T23:44:47.902167Z  INFO sashiko::local_review: Setting virtual HEAD to de626073dfcbb06441f1a9755715941c0c375fe3 for patch 1
      [Patch 1] media: em28xx: drop 'users'... | Pre-screening guides...
Overall: [░░░░░░░░░░░░░░░░░░░░] 0% | 0/11 stages | 0 turns
2026-07-19T23:44:47.902453Z  INFO sashiko::worker::prompts: Executing Phase 0: Pre-screening relevant subsystem guides.
2026-07-19T23:44:47.902475Z  INFO sashiko::ai::ollama: Sending Ollama request to model: ornith:9b
      [Patch 1] media: em28xx: drop 'users'... | Planning stages...
Overall: [░░░░░░░░░░░░░░░░░░░░] 0% | 0/11 stages | 0 turns
2026-07-19T23:45:35.252426Z  INFO sashiko::worker::prompts: Running planning pre-phase
2026-07-19T23:45:35.252435Z  INFO sashiko::ai::ollama: Sending Ollama request to model: ornith:9b
      [Patch 1] media: em28xx: drop 'users'... | Reviewing...
      [Patch 1] media: em28xx: drop 'users'... | Goal Analysis
      [Patch 1] media: em28xx: drop 'users'... | Goal Analysis (turn 1)
      [Patch 1] media: em28xx: drop... | Goal Analysis (turn 1) (+1 stages)
      [Patch 1] media: em28xx: drop... | Goal Analysis (turn 1) (+1 stages)
      [Patch 1] media: em28xx: drop... | Goal Analysis (turn 1) (+2 stages)
      [Patch 1] media: em28xx: drop... | Goal Analysis (turn 1) (+3 stages)
      [Patch 1] media: em28xx: drop... | Goal Analysis (turn 1) (+3 stages)
      [Patch 1] media: em28xx: drop... | Goal Analysis (turn 1) (+4 stages)
      [Patch 1] media: em28xx: drop... | Goal Analysis (turn 1) (+5 stages)
      [Patch 1] media: em28xx: drop... | Goal Analysis (turn 1) (+5 stages)
      [Patch 1] media: em28xx: drop... | Goal Analysis (turn 1) (+6 stages)
      [Patch 1] media: em28xx: drop... | Goal Analysis (turn 1) (+6 stages)
      [Patch 1] media: em28xx: drop... | Goal Analysis (turn 1) (+6 stages)
      [Patch 1] media: em28xx: drop... | Goal Analysis (turn 1) (+6 stages)
Overall: [░░░░░░░░░░░░░░░░░░░░] 0% | 0/11 stages | 7 turns
      [Patch 1] media: em28xx: drop... | Goal Analysis (turn 1) (+5 stages)
      [Patch 1] media: em28xx: drop... | Goal Analysis (turn 1) (+4 stages)
      [Patch 1] media: em28xx: drop... | Goal Analysis (turn 1) (+4 stages)
Overall: [███░░░░░░░░░░░░░░░░░] 18% | 2/11 stages | 8 turns
      [Patch 1] media: em28xx: dro... | Implementation (turn 1) (+3 stages)
      [Patch 1] media: em28xx: dro... | Implementation (turn 1) (+2 stages)
      [Patch 1] media: em28xx: dro... | Implementation (turn 1) (+2 stages)
Overall: [███████░░░░░░░░░░░░░] 36% | 4/11 stages | 9 turns
      [Patch 1] media: em28xx: dro... | Implementation (turn 1) (+2 stages)
Overall: [███████░░░░░░░░░░░░░] 36% | 4/11 stages | 10 turns
      [Patch 1] media: em28xx: dro... | Implementation (turn 1) (+1 stages)
      [Patch 1] media: em28xx: drop 'users'... | Locking & Sync (turn 1)
      [Patch 1] media: em28xx: drop 'users'... | Locking & Sync (turn 1)
Overall: [██████████░░░░░░░░░░] 54% | 6/11 stages | 11 turns
2026-07-19T23:51:03.942656Z  INFO sashiko::ai::ollama: Sending Ollama request to model: ornith:9b
2026-07-19T23:51:22.601596Z  INFO sashiko::ai::ollama: Ollama response received. Tokens: in=13268, out=675
2026-07-19T23:51:22.601667Z ERROR sashiko::local_review: AI review for patch 1 failed with exception: Failed to generate valid response after 3 validation attempts. Last violation: JSON output is missing the required 'concerns' array
2026-07-19T23:51:22.601704Z  INFO sashiko: AI review retry (attempt 2/3)
2026-07-19T23:51:22.601707Z  INFO sashiko::local_review: Restarting AI review for patch 1 (attempt 2/3)...
2026-07-19T23:51:22.616771Z  WARN rustls_platform_verifier::verification::others: Error loading CA root certificate: failed to read PEM from file: Permission denied (os error 13) at '/etc/pki/tls/certs/exim.pem'
2026-07-19T23:51:22.626110Z  INFO sashiko::local_review: Active patch files gathered for patch 1: ["drivers/media/usb/em28xx/em28xx-v      [Patch 1] media: em28xx: drop 'users'... | Pre-screening guides...
Overall: [██████████░░░░░░░░░░] 54% | 6/11 stages | 11 turns
2026-07-19T23:51:22.626358Z  INFO sashiko::worker::prompts: Executing Phase 0: Pre-screening relevant subsystem guides.
2026-07-19T23:51:22.626368Z  INFO sashiko::ai::ollama: Sending Ollama request to model: ornith:9b
      [Patch 1] media: em28xx: drop 'users'... | Planning stages...
Overall: [██████████░░░░░░░░░░] 54% | 6/11 stages | 11 turns
2026-07-19T23:52:04.332688Z  INFO sashiko::worker::prompts: Running planning pre-phase
2026-07-19T23:52:04.332698Z  INFO sashiko::ai::ollama: Sending Ollama request to model: ornith:9b
      [Patch 1] media: em28xx: drop 'users'... | Locking & Sync (turn 1)
      [Patch 1] media: em28xx: dro... | Locking & Sync (turn 1) (+1 stages)
      [Patch 1] media: em28xx: drop... | Goal Analysis (turn 1) (+1 stages)
      [Patch 1] media: em28xx: drop... | Goal Analysis (turn 1) (+2 stages)
      [Patch 1] media: em28xx: drop... | Goal Analysis (turn 1) (+2 stages)
      [Patch 1] media: em28xx: drop... | Goal Analysis (turn 1) (+3 stages)
      [Patch 1] media: em28xx: drop... | Goal Analysis (turn 1) (+4 stages)
      [Patch 1] media: em28xx: drop... | Goal Analysis (turn 1) (+4 stages)
      [Patch 1] media: em28xx: drop... | Goal Analysis (turn 1) (+4 stages)
      [Patch 1] media: em28xx: drop... | Goal Analysis (turn 1) (+5 stages)
      [Patch 1] media: em28xx: drop... | Goal Analysis (turn 1) (+5 stages)
      [Patch 1] media: em28xx: drop... | Goal Analysis (turn 1) (+6 stages)
      [Patch 1] media: em28xx: drop... | Goal Analysis (turn 1) (+6 stages)
      [Patch 1] media: em28xx: drop... | Goal Analysis (turn 1) (+6 stages)
      [Patch 1] media: em28xx: drop... | Goal Analysis (turn 1) (+6 stages)
Overall: [██████████░░░░░░░░░░] 54% | 6/11 stages | 18 turns
      [Patch 1] media: em28xx: drop... | Goal Analysis (turn 1) (+5 stages)
      [Patch 1] media: em28xx: drop... | Goal Analysis (turn 1) (+4 stages)
      [Patch 1] media: em28xx: drop... | Goal Analysis (turn 1) (+4 stages)
Overall: [██████████████░░░░░░] 72% | 8/11 stages | 19 turns
      [Patch 1] media: em28xx: drop... | Goal Analysis (turn 1) (+4 stages)
Overall: [██████████████░░░░░░] 72% | 8/11 stages | 20 turns
      [Patch 1] media: em28xx: drop... | Goal Analysis (turn 1) (+4 stages)
Overall: [██████████████░░░░░░] 72% | 8/11 stages | 21 turns
      [Patch 1] media: em28xx: drop... | Goal Analysis (turn 1) (+4 stages)
Overall: [██████████████░░░░░░] 72% | 8/11 stages | 22 turns
2026-07-19T23:59:23.697930Z  INFO sashiko::ai::ollama: Sending Ollama request to model: ornith:9b
2026-07-20T00:07:11.843061Z ERROR sashiko::ai::ollama: Ollama request failed (transport): error sending request for url (http://localhost:11434/api/chat)
      [Patch 1] media: em28xx: drop... | Goal Analysis (turn 1) (+4 stages)
Overall: [██████████████░░░░░░] 72% | 8/11 stages | 23 turns
      [Patch 1] media: em28xx: drop... | Goal Analysis (turn 1) (+4 stages)
Overall: [██████████████░░░░░░] 72% | 8/11 stages | 24 turns
      [Patch 1] media: em28xx: dro... | Execution Flow (turn 1) (+3 stages)
      [Patch 1] media: em28xx: dro... | Execution Flow (turn 1) (+2 stages)
      [Patch 1] media: em28xx: dro... | Execution Flow (turn 1) (+2 stages)
Overall: [██████████████████░░] 90% | 10/11 stages | 25 turns
2026-07-20T00:10:33.280666Z  INFO sashiko::ai::ollama: Sending Ollama request to model: ornith:9b
2026-07-20T00:22:41.845186Z ERROR sashiko::ai::ollama: Ollama request failed (transport): error sending request for url (http://localhost:11434/api/chat)
2026-07-20T00:22:41.845209Z  WARN sashiko::ai::session: API error (Too Many requests: error sending request for url (http://localhost      [Patch 1] media: em28xx: dro... | Execution Flow (turn 1) (+1 stages)
Overall: [████████████████████] 100% | 11/11 stages | 26 turns
2026-07-20T00:23:11.848150Z  INFO sashiko::ai::ollama: Sending Ollama request to model: ornith:9b
2026-07-20T00:25:33.281158Z ERROR sashiko::ai::ollama: Ollama request failed (transport): error sending request for url (http://localhost:11434/api/chat)
2026-07-20T00:25:33.281198Z  WARN sashiko::ai::session: API error (Too Many requests: error sending request for url (http://localhost      [Patch 1] media: em28xx: drop 'users'... | Locking & Sync (turn 1)
Overall: [████████████████████] 109% | 12/11 stages | 27 turns
2026-07-20T00:26:03.282553Z  INFO sashiko::ai::ollama: Sending Ollama request to model: ornith:9b
2026-07-20T00:27:12.232405Z  INFO sashiko::ai::ollama: Ollama response received. Tokens: in=18325, out=2356
2026-07-20T00:27:12.232522Z ERROR sashiko::local_review: AI review for patch 1 failed with exception: Failed to generate valid response after 3 validation attempts. Last violation: JSON output is missing the required 'concerns' array
2026-07-20T00:27:12.232558Z  INFO sashiko: AI review retry (attempt 3/3)
2026-07-20T00:27:12.232560Z  INFO sashiko::local_review: Restarting AI review for patch 1 (attempt 3/3)...
2026-07-20T00:27:12.247723Z  WARN rustls_platform_verifier::verification::others: Error loading CA root certificate: failed to read PEM from file: Permission denied (os error 13) at '/etc/pki/tls/certs/exim.pem'
2026-07-20T00:27:12.259118Z  INFO sashiko::local_review: Active patch files gathered for patch 1: ["drivers/media/usb/em28xx/em28xx-v      [Patch 1] media: em28xx: drop 'users'... | Pre-screening guides...
Overall: [████████████████████] 109% | 12/11 stages | 27 turns
2026-07-20T00:27:12.259377Z  INFO sashiko::worker::prompts: Executing Phase 0: Pre-screening relevant subsystem guides.
2026-07-20T00:27:12.259386Z  INFO sashiko::ai::ollama: Sending Ollama request to model: ornith:9b
      [Patch 1] media: em28xx: drop 'users'... | Planning stages...
Overall: [████████████████████] 109% | 12/11 stages | 27 turns
2026-07-20T00:27:53.611570Z  INFO sashiko::worker::prompts: Running planning pre-phase
2026-07-20T00:27:53.611579Z  INFO sashiko::ai::ollama: Sending Ollama request to model: ornith:9b
      [Patch 1] media: em28xx: drop 'users'... | Locking & Sync (turn 1)
      [Patch 1] media: em28xx: dro... | Locking & Sync (turn 1) (+1 stages)
      [Patch 1] media: em28xx: drop... | Goal Analysis (turn 1) (+1 stages)
      [Patch 1] media: em28xx: drop... | Goal Analysis (turn 1) (+2 stages)
      [Patch 1] media: em28xx: drop... | Goal Analysis (turn 1) (+2 stages)
      [Patch 1] media: em28xx: drop... | Goal Analysis (turn 1) (+3 stages)
      [Patch 1] media: em28xx: drop... | Goal Analysis (turn 1) (+4 stages)
      [Patch 1] media: em28xx: drop... | Goal Analysis (turn 1) (+4 stages)
      [Patch 1] media: em28xx: drop... | Goal Analysis (turn 1) (+4 stages)
      [Patch 1] media: em28xx: drop... | Goal Analysis (turn 1) (+5 stages)
      [Patch 1] media: em28xx: drop... | Goal Analysis (turn 1) (+5 stages)
      [Patch 1] media: em28xx: drop... | Goal Analysis (turn 1) (+6 stages)
      [Patch 1] media: em28xx: drop... | Goal Analysis (turn 1) (+6 stages)
      [Patch 1] media: em28xx: drop... | Goal Analysis (turn 1) (+6 stages)
      [Patch 1] media: em28xx: drop... | Goal Analysis (turn 1) (+6 stages)
Overall: [████████████████████] 109% | 12/11 stages | 34 turns
      [Patch 1] media: em28xx: drop... | Goal Analysis (turn 1) (+5 stages)
      [Patch 1] media: em28xx: drop... | Goal Analysis (turn 1) (+4 stages)
      [Patch 1] media: em28xx: dro... | Implementation (turn 1) (+3 stages)
      [Patch 1] media: em28xx: dro... | Implementation (turn 1) (+2 stages)
      [Patch 1] media: em28xx: dro... | Implementation (turn 1) (+1 stages)
      [Patch 1] media: em28xx: drop 'users'... | Implementation (turn 1)
      [Patch 1] media: em28xx: drop 'users'... | Deduplication
      [Patch 1] media: em28xx: drop 'users'... | Deduplication (turn 1)
Overall: [████████████████████] 172% | 19/11 stages | 35 turns
      [Patch 1] media: em28xx: drop 'users'... | Deduplication (turn 1)
Overall: [████████████████████] 172% | 19/11 stages | 36 turns
      [Patch 1] media: em28xx: drop 'users'... | Conflict Resolution
      [Patch 1] media: em28xx: drop 'user... | Conflict Resolution (turn 1)
Overall: [████████████████████] 181% | 20/11 stages | 37 turns
      [Patch 1] media: em28xx: drop 'users'... | Severity Estimation
      [Patch 1] media: em28xx: drop 'user... | Severity Estimation (turn 1)
Overall: [████████████████████] 190% | 21/11 stages | 38 turns
      [Patch 1] media: em28xx: drop 'users'... | Report Generation
      [Patch 1] media: em28xx: drop 'users'... | Report Generation (turn 1)
Overall: [████████████████████] 200% | 22/11 stages | 39 turns
      [Patch 1] media: em28xx: drop 'users'... | Report Generation (turn 1)
Overall: [████████████████████] 200% | 22/11 stages | 40 turns
      [Patch 1] media: em28xx: drop 'users'... | Reviewing...
      [Patch 1] media: em28xx: drop 'users'... | Finished
Overall: [████████████████████] 209% | 23/11 stages | 40 turns
Review complete

Findings:
  Critical: 0  High: 0  Medium: 0  Low: 2

  --- Patch [1] media: em28xx: drop 'users' field ---
  [Low] The removal of manual `v4l2->users` tracking changes the gate semantics for entering analog mode from 'no users currently hold the file' to 'exactly one process has an open file handle'. Under VFS semantics, this is equivalent since only legitimate file opens reach this point. However, `_vb2_fop_release(filp, NULL)` passes NULL as the second argument even though `_vb2_fop_release()` takes two arguments (error pointer + filp). The function signature from the pre-fetched context confirms: `_vb2_fop_release(filp, NULL)` is an intentional refactor where both call paths explicitly pass NULL for the error parameter. This is NOT a bug—it's consistent with VB2 conventions.
  [Low] In `em28xx_v4l2_close()`, `_vb2_fop_release(filp, NULL)` is called AFTER `mutex_lock(&dev->lock)`. Standard VFS close semantics call vb2's fops release BEFORE entering the driver lock. This patch reverses that order: it calls _vb2_fop_release INSIDE dev->lock protection. While this maintains internal consistency (since open() also locks before fh_open), it creates an asymmetry where VB2 state transitions happen inside a device-specific lock rather than at VFS entry/exit.
  [Low] The old `v4l2->users` variable was incremented/decremented in open/close but never actually used to track real user counts—it was purely a gate for entering analog mode (comparing against 0 and 1 respectively). The new code uses `v4l2_fh_is_singular_file()` which checks VFS-level exclusive access. This is functionally equivalent because under normal operation, only one process should hold an open file handle to the device at any given time.


Inline Review:
--- Patch [1]: media: em28xx: drop 'users' field ---
commit de626073dfcbb06441f1a9755715941c0c375fe3
Author: Hans Verkuil <hverkuil+cisco@kernel.org>

media: em28xx: drop 'users' field

Drop the em28xx_v4l2 'users' field, use v4l2_fh_is_singular_file()
instead.

[ ... ]

> +if (vdev->vfl_type == VFL_TYPE_RADIO) {
> +     videodbg("video_open: setting radio device\n");
> +     v4l2_device_call_all(&v4l2->v4l2_dev, 0, tuner, s_radio);
> +}
> 
> -     if (v4l2->users == 1) {
> +     if (v4l2_fh_is_singular_file(filp)) {

[ ... ]

> -     mutex_unlock(&dev->lock);
> +     mutex_lock(&dev->lock);
> +     last_user = v4l2_fh_is_singular_file(filp);
> +     _vb2_fop_release(filp, NULL);

[Severity: Low]
The close path no longer calls _vb2_fop_release() directly—it delegates that
cleanup to vb2's internal fh_open state management. Similarly, on the open side
of em28xx_video.c, v4l2_fh_open handles both the file handle setup and any
necessary VB2 queue state internally without a separate call. This means the
VB2 lifecycle is now fully encapsulated within each driver lock scope rather
than happening at VFS entry/exit boundaries—does this matter for how other
drivers that follow the standard pattern expect vb2 operations to interleave
with external locking?

[ ... ]

> -     if (v4l2->users == 0) {
> +     if (v4l2_fh_is_singular_file(filp)) {

[Severity: Low]
This isn't a bug introduced by this patch—it's a deliberate simplification
of the em28xx_v4l2 struct. The old v4l2->users variable was only used as
a gate for entering analog mode; under normal VFS operation, that manual
tracking had equivalent semantics to checking whether any process holds an open
file handle via VFS-level singular-file queries. The replacement with
v4l2_fh_is_singular_file() checks exactly the same condition at the right point
in the call chain, so this is a valid refactoring rather than a regression.

[ ... ]

> -     if (vdev->vfl_type != VFL_TYPE_RADIO)
> +     mutex_unlock(&dev->lock);

Tokens: 146242 in / 35439 out / 0 cached

@mchehab

mchehab commented Jul 20, 2026

Copy link
Copy Markdown
Author

Overall: [████████████████████] 209% | 23/11 stages | 40 turns

On a side note, the overall bar doesn't reflect the number of actual stages. The last patch on this PR (694728f) fixes an issue to prevent Sashiko to crash when:
completed_stages > total_stages

Ensure that, when running on local GPUs, it won't be piling
parallel concurrencies that may end timing out because the
GPU is busy with a previous job.

Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
@derekbarbosa

Copy link
Copy Markdown
Collaborator

Hi Mauro,

Thank you for the PR.

Please fix the linting/build-time errors with make check-pr

Furthermore, could you squash the fixup commits d3efe5e through 694728f?

Additionally it would be great if you could add a commit that included documentation changes to llm_providers and a new entry in the examples/ directory. If you feel inclined, a DESIGN document would be nice (as a reference point for future LLM-guided reviews and feature prompts).

Comment thread src/reviewer.rs
Comment on lines +132 to +136
let llm_concurrency = if concurrency < 2 {
1
} else {
std::cmp::max(1, concurrency * 3)
};

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could you replace this code block with something like?

let llm_concurrency = match concurrency {
    0 | 1 => 1,
    n => n * 3,
};

edit: on further thought, I don't like the idea of restricting users who want only a single review to be running at a time to be limited to such LLM calls. please split this into a separate configuration.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok. any suggestions for the new name? perhaps gpu_count?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

from configuration.md

### `[review]`

| Key | Type | Default | Description |
|-----|------|---------|-------------|
| `concurrency` | integer | -- | Number of concurrent reviews. |

llm_concurrency looks like it could work.

@mchehab mchehab Jul 20, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure what you meant. There are two possible ways to limit it:

  1. mean concurrency

    The concurrency parameter is actually concurrency * 3, because there are several steps that are sequential (from its comment). The idea behind as the logic there tries to ensure that it would look to the caller that the concurrency criteria would be used, but in a matter of fact, it sounds to be just a gestimation.

    IMO, a better name for such parameter would be mean_concurrency, but renaming it would be an incompatible change.

  2. maximum concurrency

    When we have local runners, the maximum concurrency should be, instead, the number of available GPUs, as the same GPU can't usually execute multiple jobs in parallel

There is a local var called llm_concurrency associated to the mean concurrency. Are you proposing to rename currency to llm_currency?

Alternatively, we could add a new parameter max_concurrency for (2), keeping (1) with the same behavior.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm, sorry, I think we are misunderstanding each other here. but you raise a valid concern -- concurrency is a bit overloaded in the codebase.

anyway, what I mean is binding the value of local variable llm_concurrency (used in creating llm_semaphore) itself to a user-driven config item. we don't need to change its name; leaving the variable as-is (llm_concurrency) and documenting what it does should be sufficient.

Comment thread src/main.rs
} else {
0
};
let filled = filled.min(width);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this (related pr: #342) feels a little hacky. I would prefer a fix that takes into account retries and handles the overflow as in #341
-- @rgushchin maybe that should be merged prior to this fix?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll rebase this PR once #341 is merged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants