Skip to content

feat(vim): add known_human checkpoint plugin#1052

Open
svarlamov wants to merge 6 commits intomainfrom
feat/known-human-vim
Open

feat(vim): add known_human checkpoint plugin#1052
svarlamov wants to merge 6 commits intomainfrom
feat/known-human-vim

Conversation

@svarlamov
Copy link
Copy Markdown
Member

@svarlamov svarlamov commented Apr 11, 2026

Summary

  • New Vimscript plugin (agent-support/vim/) that fires git-ai checkpoint known_human --hook-input stdin on file save with 500ms debounce per git repo root
  • Uses BufWritePost autocmd + timer_start(500, ...) for async debounce
  • Uses Vim 8+ async job API (job_start/ch_sendraw) for non-blocking git-ai calls; falls back to synchronous system() on Vim < 8.0
  • New VimInstaller Rust struct that detects Vim and surfaces manual install instructions

Manual install steps (for docs site)

Native packages (Vim 8+)

mkdir -p ~/.vim/pack/git-ai/start/git-ai
cp -r agent-support/vim/* ~/.vim/pack/git-ai/start/git-ai/

vim-plug (~/.vimrc)

Plug 'git-ai-project/git-ai', {'rtp': 'agent-support/vim'}

Vundle (~/.vimrc)

Plugin 'git-ai-project/git-ai'

Add to .vimrc: set rtp+=~/.vim/bundle/git-ai/agent-support/vim

Test plan

  • cargo clippy -- -D warnings passes
  • cargo test passes

🤖 Generated with Claude Code


Open with Devin

Adds a Vimscript plugin that fires git-ai checkpoint known_human on
file save with 500ms debounce per git repo root. Uses Vim 8+ async
job API (job_start/ch_sendraw) with synchronous fallback for older Vim.
No auto-install; installer surfaces manual steps for native packages,
vim-plug, and Vundle.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
devin-ai-integration[bot]

This comment was marked as resolved.

Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

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

Devin Review found 1 new potential issue.

View 11 additional findings in Devin Review.

Open in Devin Review

Comment thread src/mdm/agents/vim.rs
Comment on lines +53 to +54
message: concat!(
"Vim: Automatic installation is not supported. ",
Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration bot Apr 11, 2026

Choose a reason for hiding this comment

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

🔴 VimInstaller's install_extras message is silently dropped due to missing keyword triggers

The VimInstaller's install_extras returns an InstallResult with changed: false and a message starting with "Vim: Automatic installation is not supported. Install the plugin using one of these methods:...". In the display logic at src/commands/install_hooks.rs:570-588, results are only shown if result.changed is true, or if the message contains "already", "Unable", or "manually". The Vim message contains none of these keywords, so all four display conditions fail and the manual installation instructions are silently swallowed. Users who have Vim installed will see zero output for Vim during git-ai install-hooks, making the plugin integration completely undiscoverable.

Relevant display conditions in install_hooks.rs:570-588

result.changed && !dry_run → false (changed=false)
result.changed && dry_run → false
result.message.contains("already") → false
result.message.contains("Unable") || result.message.contains("manually") → false

Compare with JetBrains' fallback message which includes both "Unable" and "manually": "{}: Unable to automatically install plugin. Please install manually from: {}" at src/mdm/agents/jetbrains.rs:120-123.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

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

Devin Review found 1 new potential issue.

View 10 additional findings in Devin Review.

Open in Devin Review

Comment on lines +113 to +130
if has('job') && has('channel')
" Vim 8+ async job API
let l:opts = {
\ 'in_io': 'pipe',
\ 'out_io': 'null',
\ 'err_io': 'null',
\ }
let l:job = job_start(l:cmd, l:opts)
if job_status(l:job) ==# 'run'
let l:chan = job_getchannel(l:job)
call ch_sendraw(l:chan, l:payload)
call ch_close_in(l:chan)
endif
else
" Fallback: synchronous (Vim < 8.0)
let l:shell_cmd = join(map(copy(l:cmd), 'shellescape(v:val)'), ' ')
call system(l:shell_cmd, l:payload)
endif
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔴 Checkpoint command blocks Neovim UI because Neovim's async job API is not used

The plugin checks has('job') && has('channel') at line 113 to decide whether to use async execution. In Neovim, both has('job') and has('channel') return 0 (Neovim uses jobstart()/chansend() instead of Vim 8's job_start()/ch_sendraw()). This causes the code to fall through to the synchronous system() call at line 128, which blocks the editor for the entire duration of git-ai checkpoint. The plugin already detects Neovim at line 77 for the JSON payload, so this is an oversight in the execution path. For Neovim, the code should use jobstart() + chansend() + chanclose() for non-blocking execution.

Suggested change
if has('job') && has('channel')
" Vim 8+ async job API
let l:opts = {
\ 'in_io': 'pipe',
\ 'out_io': 'null',
\ 'err_io': 'null',
\ }
let l:job = job_start(l:cmd, l:opts)
if job_status(l:job) ==# 'run'
let l:chan = job_getchannel(l:job)
call ch_sendraw(l:chan, l:payload)
call ch_close_in(l:chan)
endif
else
" Fallback: synchronous (Vim < 8.0)
let l:shell_cmd = join(map(copy(l:cmd), 'shellescape(v:val)'), ' ')
call system(l:shell_cmd, l:payload)
endif
if has('nvim')
" Neovim async job API
let l:job = jobstart(l:cmd, {'on_exit': {-> 0}})
if l:job > 0
call chansend(l:job, l:payload)
call chanclose(l:job, 'stdin')
endif
elseif has('job') && has('channel')
" Vim 8+ async job API
let l:opts = {
\ 'in_io': 'pipe',
\ 'out_io': 'null',
\ 'err_io': 'null',
\ }
let l:job = job_start(l:cmd, l:opts)
if job_status(l:job) ==# 'run'
let l:chan = job_getchannel(l:job)
call ch_sendraw(l:chan, l:payload)
call ch_close_in(l:chan)
endif
else
" Fallback: synchronous (Vim < 8.0)
let l:shell_cmd = join(map(copy(l:cmd), 'shellescape(v:val)'), ' ')
call system(l:shell_cmd, l:payload)
endif
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

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.

1 participant