Skip to content

oxidizer: migrate VisionInferenceProvider to Rust cognition/vision_describe #1276

@joelteply

Description

@joelteply

airc-queue card

Coordinates work via the AIRC queue substrate (airc#562). Edit this card by commenting OR by running airc queue claim/airc queue release/airc queue heartbeat (later PRs).

{
  "kind": "airc-queue-card-v1",
  "id": "#1276",
  "status": "in-progress",
  "evidence": "Adopted existing GitHub issue into airc queue.",
  "next_action": "Triage, claim, or close this adopted backlog card.",
  "owner": "claude-tab-1",
  "last_heartbeat": "2026-05-15T19:30Z @ f2f541c52"
}

Close this issue when the work is done (status=merged/abandoned).

Original issue body

Pre-adoption body

First concrete sub-card under #1248 umbrella (TS-side AI logic that violates 'TS is thin glue' directive).

Scope

src/system/vision/VisionInferenceProvider.ts (176 LOC) currently:

  1. Selects the best vision-capable model from AICapabilityRegistry (selectModel private, lines 110-160)
  2. Builds the describe prompt from DescribeOptions flags (buildPrompt private, lines 161-168)
  3. Calls AIProviderDaemon.generateText directly with the assembled message
  4. Parses the response into a VisionDescription (parseResponse private, lines 175-180)

Per airc-8a5e directive 2026-05-14: "Treat TS as thin UI/configurator/browser/JTAG glue only. Any durable logic for ... provider/model selection ... belongs in Rust." All four steps above are durable logic that should run Rust-side.

Migration shape

  1. Rust side — new continuum-core/src/cognition/vision_describe.rs:

    • VisionDescribeRequest struct (image bytes + DescribeOptions equivalent) with ts-rs export
    • VisionDescription struct (description + objects + colors + text + responseTimeMs) with ts-rs export
    • describe_image(req: VisionDescribeRequest) -> Result<VisionDescription, VisionDescribeError> function that:
      • Selects best vision model via the existing Rust model_resolver
      • Builds the prompt
      • Calls inference (Candle / llama.cpp / cloud adapter via existing path)
      • Parses + returns
    • Wire as IPC command cognition/vision-describe
  2. TS side — rewrite VisionInferenceProvider.ts as a thin shim:

    • Single method that calls Commands.execute('cognition/vision-describe', opts)
    • Drop selectModel, buildPrompt, parseResponse private methods (all Rust-side now)
    • Keep cache logic (VisionDescriptionService SHA-256 dedup) since that's TS-platform-side caching, not AI logic
    • Update VisionDescriptionService.ts to call the new shim
    • Drop direct AIProviderDaemon import (replaced by Commands.execute)

Acceptance

  • grep -rln "AIProviderDaemon" system/vision/ returns zero hits
  • VisionDescriptionService SHA-256 cache still works (verify the Vision AI persona seed reply unchanged)
  • TS file shrinks from 176 LOC to <50 LOC (thin shim + types)
  • Cognition Rust tests for new vision_describe path pass
  • ESLint baseline drops by the deletion-line count (or holds; doesn't increase)

Why this is the outlier-validation candidate

Per CLAUDE.md outlier-validation strategy: pick LOCAL-AND-SIMPLE first to prove the migration pattern. VisionInferenceProvider is the smallest #1248 file (176 LOC vs AIDecisionService 709, RecipeGenerateServerCommand 371) AND has the cleanest seam (one external API call, three private methods that move together). Once this lands clean, the pattern (Rust function + IPC command + thin TS shim) is proven for the remaining #1248 files.

Refs #1248 (umbrella).

Status log

  • 2026-05-15T19:30Z — claim by claude-tab-1 -> status=in-progress

  • 2026-05-15T19:00Z — released by claude-tab-2 -> status=blocked (Started + hit prereq gap: cloud-vision Rust adapters don't exist yet; clean migration needs PR-0 to build those first. Comment posted with details.)

  • 2026-05-15T17:36Z — released by claude-tab-2 -> status=claimed (Filed + sized + scoped — releasing for whoever has the cycles to take the implementation. I'm not actively coding it; oxidizer-class work for any peer.)

Metadata

Metadata

Assignees

No one assigned

    Labels

    airc-queueAIRC-backed agent work queue card

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions