---
name: lvkit-resolve-vilib
description: Resolve a single unknown vilib VI by looking up its terminal layout in the LabVIEW documentation. Called when VILibResolutionNeeded fires during lvkit generate.
allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebSearch, WebFetch
---

# Resolve Unknown vilib VI

When `VILibResolutionNeeded` fires during `lvkit generate`, this skill resolves it. vilib VIs have KNOWN names (they're filenames), so we can look them up directly. Follow ALL steps IN ORDER.

## Step 0: Detect mode

This skill runs in two contexts. The destination directory and the source-of-truth differ. Decide which one applies BEFORE you do anything else.

Read `pyproject.toml` from the current directory (walk up if needed). If it contains `name = "lvkit"`, you are working **inside lvkit itself**:

- Destination: `data/vilib/<category>.json` (lvkit's shipped, cleanroom data)
- Source of truth: NI's online documentation (via WebSearch/WebFetch)
- The mapping must be cleanroom — derived from public documentation, NOT from the actual vi.lib block diagram

Otherwise, you are working **inside a downstream user's project**:

- Destination: `.lvkit/vilib/<category>.json` (project-local store; run `lvkit init` first if `.lvkit/` doesn't exist)
- Source of truth: the actual file at the **qualified path** the diagnostic provides (e.g. `<vilib>/Utility/error.llb/Error Cluster From Error Code.vi`). The user's own LabVIEW install resolves `<vilib>` to the on-disk `vi.lib` directory. Read the real connector pane and terminals. Web search NI's docs as a backup if you can't open the file.
- The mapping you write may be derived from the actual vi.lib source; that's the user's call. lvkit itself never reads `.lvkit/`.

## Step 1: Record the diagnostic

Write down the EXACT diagnostic output:
- VI name (filename)
- Qualified path (the `<vilib>/...` line — if absent, the parser didn't capture it; ask the user to point you at the source file)
- Every terminal listed: name, index, direction, type
- The caller VI name

## Step 2: Look up the function

The VI name IS the function name. Pick the lookup path that matches your detected mode.

### lvkit mode: web search NI's documentation

Use the WebSearch tool. Good queries:

- `LabVIEW <EXACT VI NAME>` — broad lookup
- `site:ni.com/docs <EXACT VI NAME>` — restrict to NI docs

When you find a candidate page, use WebFetch to read the full Inputs/Outputs section. NI's docs give:

- Every terminal name and its purpose
- Direction (input/output)
- Data type
- Default values for optional inputs

### User-project mode: read the real source file

Use the qualified path from the diagnostic to find the file on disk. Resolve `<vilib>` to the user's LabVIEW vi.lib directory (commonly `C:\Program Files\National Instruments\LabVIEW <version>\vi.lib\` on Windows or `/Applications/LabVIEW <version>/vi.lib/` on macOS).

If `lvkit describe` works on the file (it doesn't require resolution), use it for a quick terminal layout:

```bash
lvkit describe "<full-vilib-path>"
```

If the file isn't accessible, fall back to web search (same as lvkit mode above) or ask the user to open the VI in LabVIEW and read off the connector pane terminal positions. The connector pane index is what lvkit needs.

## Step 3: Match documentation/source terminals to wire types

The diagnostic shows "Wire types from dataflow" with actual indices from the caller. Match each wire index to the terminal list you found in Step 2:

- idx_0 (input) → which terminal?
- idx_1 (output) → which terminal?

The connector pane layout determines the index mapping. Use the actual wire types (from the diagnostic) to disambiguate when multiple terminals have similar types.

## Step 4: Check existing entries

This step is mode-dependent.

### lvkit mode

```bash
grep -r "VI NAME" data/vilib/
```

### User-project mode

```bash
grep -r "VI NAME" .lvkit/vilib/ 2>/dev/null
grep -r "VI NAME" data/vilib/ 2>/dev/null  # also check shipped data — may already be there
```

If a partial entry exists with missing indices, update it. If no entry exists, create one in the appropriate category file.

## Step 5: Add the JSON entry

The destination depends on the mode you detected in Step 0:

- **lvkit mode** → `data/vilib/<category>.json`
- **user-project mode** → `.lvkit/vilib/<category>.json` (and add the category to `.lvkit/vilib/_index.json` if it's not there yet)

Add the entry:

```json
{
  "VI Name.vi": {
    "name": "VI Name",
    "terminals": [
      {
        "name": "terminal_name",
        "index": N,
        "direction": "input",
        "type": "actual_type",
        "python_param": "python_parameter_name"
      }
    ],
    "python_code": "python_equivalent_expression",
    "inline": true
  }
}
```

Rules:
- Terminal names come from the DOCUMENTATION (lvkit mode) or SOURCE FILE (user mode), not guesses
- `python_param` must be a valid Python identifier
- Include ALL terminals including error clusters
- `index` values come from the wire types in the diagnostic (actual connector pane positions)
- If you can't determine an index from the diagnostic, leave it out — the codegen will raise again with more info on the next call site

## Step 6: Re-run generation

```bash
lvkit generate "<vi-path>" -o "<output-dir>" --search-path "<library-path>"
```

If the same VI fails again, the terminal matching is wrong — go back to Step 1.
If a NEW VI fails, start this process again for that one.

**Alternative: soft codegen mode.** Instead of authoring a mapping up front, you can re-run `lvkit generate --placeholder-on-unresolved`. The generated Python contains an inline `raise VILibResolutionNeeded(...)` statement with the same diagnostic context. You can fix the gap contextually in the Python (or come back and write a real mapping later).

## NEVER do these things

- NEVER guess terminal indices — they come from the caller's dataflow diagnostic
- NEVER invent terminal names — they come from the documentation or real source file
- NEVER skip the documentation/source lookup — the VI name IS searchable
- NEVER assume terminal order from the documentation matches connector pane order — use the wire types from the diagnostic to determine actual indices
- NEVER write user-mode mappings into lvkit's `data/` (cleanroom contamination)
- NEVER write lvkit-mode mappings into a user project's `.lvkit/` (wrong destination)
