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:
- Selects the best vision-capable model from
AICapabilityRegistry (selectModel private, lines 110-160)
- Builds the describe prompt from
DescribeOptions flags (buildPrompt private, lines 161-168)
- Calls
AIProviderDaemon.generateText directly with the assembled message
- 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
-
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
-
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.)
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:AICapabilityRegistry(selectModelprivate, lines 110-160)DescribeOptionsflags (buildPromptprivate, lines 161-168)AIProviderDaemon.generateTextdirectly with the assembled messageVisionDescription(parseResponseprivate, 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
Rust side — new
continuum-core/src/cognition/vision_describe.rs:VisionDescribeRequeststruct (image bytes + DescribeOptions equivalent) with ts-rs exportVisionDescriptionstruct (description + objects + colors + text + responseTimeMs) with ts-rs exportdescribe_image(req: VisionDescribeRequest) -> Result<VisionDescription, VisionDescribeError>function that:cognition/vision-describeTS side — rewrite
VisionInferenceProvider.tsas a thin shim:Commands.execute('cognition/vision-describe', opts)selectModel,buildPrompt,parseResponseprivate methods (all Rust-side now)VisionDescriptionServiceSHA-256 dedup) since that's TS-platform-side caching, not AI logicVisionDescriptionService.tsto call the new shimAIProviderDaemonimport (replaced by Commands.execute)Acceptance
grep -rln "AIProviderDaemon" system/vision/returns zero hitsVisionDescriptionServiceSHA-256 cache still works (verify the Vision AI persona seed reply unchanged)Why this is the outlier-validation candidate
Per CLAUDE.md outlier-validation strategy: pick LOCAL-AND-SIMPLE first to prove the migration pattern.
VisionInferenceProvideris 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.)