Deliver NVIM-SPEC-GMWDCMJZ as vertical slices, each observable through Neovim surfaces.
Evidence for transport, tool authority, and concurrency comes from NVIM-RESEARCH-KZYYEFY_.
Placement: pivi is an ordinary configuration module at lua/bugabinga/pivi/, like the other Neovim modules, with its bundled Pi companion extension under lua/bugabinga/pivi/extension/.
Module-level testing rules live in that directory's AGENTS.md.
Publishing state through native variables and User events still holds, so other configuration consumes pivi without depending on its internals.
Queue state-machine spec matching the spec's run states
5
Submissions carry immutable buffer, revision, cursor, range, and selection snapshots; queued items keep their own
bugabinga.pivi.context, bugabinga.pivi.session
Snapshot immutability spec under later buffer edits
6
Pi reads unsaved loaded-buffer content and current core editor state on demand, including arbitrary Lua
companion extension, bugabinga.pivi.rpc
Tool-result spec comparing buffer versus disk content
7
A normal Pi edit lands in a loaded buffer without reload, stays undoable as one change, and is visible to later shell work
bugabinga.pivi.edit, companion extension
Undo and coherence spec covering join failure fallback
8
Edits leave a navigable trail; findings populate quickfix, location lists, and a distinct diagnostic namespace
bugabinga.pivi.activity
Namespace isolation and navigation spec
9
Streaming tool arguments render ghost text that never mutates a buffer before arguments are complete
bugabinga.pivi.activity, bugabinga.pivi.edit
Partial-argument spec asserting zero mutation
10
Follow mode tracks located events in a dedicated window or tab and restores the prior location
bugabinga.pivi.follow
Window ownership and restore spec
11
:Pi command ... runs discovered Pi commands; / opens entry only at the first character of an input buffer
bugabinga.pivi.command
Cursor-position and discovery spec
12
Extension dialogs and fire-and-forget status map to native surfaces and answer with matching identifiers
bugabinga.pivi.dialog
Request and response correlation spec
Slice 1 is the walking skeleton; every later slice keeps just test green before the next begins.
Critical paths
Child output arrives in fast contexts; all editor work defers through scheduling before API calls.
Submission during an active run always chooses steering or follow-up; rejection is never silent.
Help spawns its own session-less child so working-session history, queue, and status remain untouched.
Buffer authority prefers injecting operations into Pi's built-in tools over reimplementing them, because result and detail shapes must match exactly.
Risks
Risk
Slice
Mitigation
Undo join refuses after undo or redo
7
Detect refusal and fall back to separate undo blocks rather than losing the edit
Partial tool arguments are invalid JSON
9
Treat ghost text as presentation only; mutate solely on complete validated arguments
Tool override breaks rendering or session state
6, 7
Keep built-in renderers and detail shapes; override behavior only
Status consumers stall the statusline
3
Read cached state only
Agent shell work reads stale disk content
7
Make agent buffer edits visible to filesystem readers as part of the edit behavior
---
id: NVIM-PLAN-CEJPO_XF
type: plan
title: Deliver pivi native Neovim integration
spec: NVIM-SPEC-GMWDCMJZ
status: approved
---
# Deliver pivi native Neovim integration
## Intent
Deliver [NVIM-SPEC-GMWDCMJZ](../../specs/NVIM-SPEC-GMWDCMJZ-pivi-native-neovim-integration/index.md) as vertical slices, each observable through Neovim surfaces.
Evidence for transport, tool authority, and concurrency comes from [NVIM-RESEARCH-KZYYEFY_](../../research/NVIM-RESEARCH-KZYYEFY_-pi-and-neovim-capabilities-for-pivi/index.md).
Placement: pivi is an ordinary configuration module at `lua/bugabinga/pivi/`, like the other Neovim modules, with its bundled Pi companion extension under `lua/bugabinga/pivi/extension/`.
Module-level testing rules live in that directory's `AGENTS.md`.
Publishing state through native variables and `User` events still holds, so other configuration consumes pivi without depending on its internals.
## Module map
```mermaid
flowchart TB
command["bugabinga.pivi.command"] --> session["bugabinga.pivi.session"]
command --> help["bugabinga.pivi.help"]
session --> rpc["bugabinga.pivi.rpc"]
session --> status["bugabinga.pivi.status"]
status --> publish["bugabinga.pivi.publish"]
session --> transcript["bugabinga.pivi.transcript"]
session --> context["bugabinga.pivi.context"]
session --> dialog["bugabinga.pivi.dialog"]
rpc --> extension["companion Pi extension"]
extension --> edit["bugabinga.pivi.edit"]
edit --> activity["bugabinga.pivi.activity"]
activity --> follow["bugabinga.pivi.follow"]
help --> rpc
```
| Module | Responsibility |
| --- | --- |
| `bugabinga.pivi.rpc` | Child process lifetime, strict LF JSONL framing, request correlation, deferral out of fast contexts |
| `bugabinga.pivi.session` | Session identity, working directory, queue delivery, abort, resume, switch |
| `bugabinga.pivi.status` | Cached semantic state; no RPC during status evaluation |
| `bugabinga.pivi.publish` | `vim.g` state plus `User` autocmd events with payload data |
| `bugabinga.pivi.transcript` | Prompt, transcript, and detail buffers |
| `bugabinga.pivi.context` | Immutable submission snapshots and ambient editor state |
| `bugabinga.pivi.edit` | Buffer-authoritative mutation, undo coherence, disk visibility |
| `bugabinga.pivi.activity` | Extmarks, signs, virtual text, diagnostics, quickfix and location lists |
| `bugabinga.pivi.follow` | Optional viewport following |
| `bugabinga.pivi.dialog` | Extension UI requests mapped to `vim.ui` surfaces |
| `bugabinga.pivi.help` | Ephemeral session-less run |
| `bugabinga.pivi.command` | `:Pi` subcommands, slash-command entry, `<Plug>` mappings |
| companion extension | Editor tools plus buffer-authoritative operations for built-in Pi tools |
## Slice order
```mermaid
flowchart LR
s1["1 Ask and stream"] --> s3["3 Status and events"]
s1 --> s2["2 Ephemeral help"]
s3 --> s4["4 Session control"]
s4 --> s5["5 Submission context"]
s5 --> s6["6 Buffer-authoritative reads"]
s6 --> s7["7 Native edits"]
s7 --> s8["8 Activity and lists"]
s7 --> s9["9 Streaming ghost text"]
s8 --> s10["10 Follow mode"]
s4 --> s11["11 Slash commands"]
s4 --> s12["12 Extension dialogs"]
```
| # | Observable behavior | Modules touched | Verified by |
| --- | --- | --- | --- |
| 1 | `:Pi ask {text}` starts Pi, streams assistant text into a transcript buffer, and survives partial reads | `bugabinga.pivi.rpc`, `bugabinga.pivi.session`, `bugabinga.pivi.transcript`, `bugabinga.pivi.command` | Framing and assembly specs plus a live round trip |
| 2 | `:Pi help {q}` answers from an independent session-less run without touching any working session | `bugabinga.pivi.help`, `bugabinga.pivi.command` | Concurrent-run spec asserting untouched session history, queue, and status |
| 3 | Status changes update cached state, emit semantic `User` events, and never issue RPC during evaluation | `bugabinga.pivi.status`, `bugabinga.pivi.publish` | Event payload spec plus a consumer that degrades when pivi is absent |
| 4 | Create, resume, switch, stop sessions; queue steering or follow-up during a run; list, clear, abort | `bugabinga.pivi.session`, `bugabinga.pivi.command`, `bugabinga.pivi.transcript` | Queue state-machine spec matching the spec's run states |
| 5 | Submissions carry immutable buffer, revision, cursor, range, and selection snapshots; queued items keep their own | `bugabinga.pivi.context`, `bugabinga.pivi.session` | Snapshot immutability spec under later buffer edits |
| 6 | Pi reads unsaved loaded-buffer content and current core editor state on demand, including arbitrary Lua | companion extension, `bugabinga.pivi.rpc` | Tool-result spec comparing buffer versus disk content |
| 7 | A normal Pi edit lands in a loaded buffer without reload, stays undoable as one change, and is visible to later shell work | `bugabinga.pivi.edit`, companion extension | Undo and coherence spec covering join failure fallback |
| 8 | Edits leave a navigable trail; findings populate quickfix, location lists, and a distinct diagnostic namespace | `bugabinga.pivi.activity` | Namespace isolation and navigation spec |
| 9 | Streaming tool arguments render ghost text that never mutates a buffer before arguments are complete | `bugabinga.pivi.activity`, `bugabinga.pivi.edit` | Partial-argument spec asserting zero mutation |
| 10 | Follow mode tracks located events in a dedicated window or tab and restores the prior location | `bugabinga.pivi.follow` | Window ownership and restore spec |
| 11 | `:Pi command ...` runs discovered Pi commands; `/` opens entry only at the first character of an input buffer | `bugabinga.pivi.command` | Cursor-position and discovery spec |
| 12 | Extension dialogs and fire-and-forget status map to native surfaces and answer with matching identifiers | `bugabinga.pivi.dialog` | Request and response correlation spec |
Slice 1 is the walking skeleton; every later slice keeps `just test` green before the next begins.
## Critical paths
- Child output arrives in fast contexts; all editor work defers through scheduling before API calls.
- Submission during an active run always chooses steering or follow-up; rejection is never silent.
- Help spawns its own session-less child so working-session history, queue, and status remain untouched.
- Buffer authority prefers injecting operations into Pi's built-in tools over reimplementing them, because result and detail shapes must match exactly.
## Risks
| Risk | Slice | Mitigation |
| --- | --- | --- |
| Undo join refuses after undo or redo | 7 | Detect refusal and fall back to separate undo blocks rather than losing the edit |
| Partial tool arguments are invalid JSON | 9 | Treat ghost text as presentation only; mutate solely on complete validated arguments |
| Tool override breaks rendering or session state | 6, 7 | Keep built-in renderers and detail shapes; override behavior only |
| Status consumers stall the statusline | 3 | Read cached state only |
| Agent shell work reads stale disk content | 7 | Make agent buffer edits visible to filesystem readers as part of the edit behavior |