Skip to content

Native Runtime v2.0 launch: degraded VRAM admission + live status - #100

Merged
hardcoreerik merged 2 commits into
masterfrom
feat/native-runtime-v2-launch
Aug 4, 2026
Merged

Native Runtime v2.0 launch: degraded VRAM admission + live status#100
hardcoreerik merged 2 commits into
masterfrom
feat/native-runtime-v2-launch

Conversation

@hardcoreerik

@hardcoreerik hardcoreerik commented Aug 4, 2026

Copy link
Copy Markdown
Owner

Summary

The core native-runtime robustness fix for the v2.0 launch: OrcScheduler.TryAdmit no longer hard-denies a role that doesn't fit full GPU residency. It now searches for the largest GPU-layer count that does fit and admits in degraded (partial GPU + CPU) mode instead — a VRAM-tight box still runs, just slower, rather than refusing every native call outright. RuntimeOrchestrator.EnsureAdmitted threads the reduced GpuLayers through to the actual model load so the degraded admission actually takes effect, and tracks a distinct DegradedAdmissionCount/LastDegradedReason (never conflated with real rejections). MainWindow gets an always-on status-bar VRAM badge (nvidia-smi, 5s poll, color-coded by headroom) surfacing this live, independent of opening Settings.

Also included, each a self-contained concern reviewed on its own:

  • Studio-tool auth relaxation — Art Forge/CaseForge/KeyHound bearer tokens become optional (hardcoreerik's own local instances run unauthenticated). LocalIntegrationHost still gates every call on IsLocal (loopback/private-IP/single-label host only), so dropping the token requirement never opens a path to a public host.
  • ChatPanel trust-level wiring — OrcChat's tool-call/file-write approvals now honor the global Plan/Guarded/Standard/Full-Auto trust level (previously only the per-conversation "Always approve" checkbox had any effect), and the status bar's model badge updates when a model is switched from inside OrcChat.
  • Daemon CI + browser automation — CI now builds OrchestratorIDE.Daemon explicitly (it cherry-picks shared source via <Compile Include> rather than a ProjectReference, so it can silently break while the main Avalonia build stays green), and the Daemon project carries the headless browser-automation source set (Playwright, NativeToolCapability, PathSandbox) for Warband nodes.

Deliberately excluded: SkillLoader.cs/SkillLoaderTests.cs and the NATIVE_RUNTIME_V2_SPEC.md §8 "self-authored skills" section. That mechanism's loader half is solid (verified rejecting malformed input safely across 3 distinct real failure modes), but the swarm-authoring half has failed both live attempts so far (documented NOT CLOSED in the spec's own run log) — not launch material yet.

Test plan

  • OrchestratorIDE.Avalonia builds clean (Debug)
  • OrchestratorIDE.Daemon builds clean (Debug)
  • OrchestratorIDE.UnitTests builds clean with SkillLoader fully absent from this branch's scope
  • 41 tests pass: OrcSchedulerTests, OrcChatToolCatalogTests, ArtForgeToolsTests, CaseForgeToolsTests, KeyHoundAtlasToolsTests — including two new OrcScheduler tests (degrade instead of deny; fail closed when even zero GPU layers can't fit the fixed overhead floor)
  • Manual: confirm the VRAM status-bar badge renders and updates live on a real GPU box

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added a live VRAM usage indicator to the status bar, including threshold-based coloring and unavailable-state messaging.
    • Added adaptive GPU scheduling that can reduce GPU layers or fall back to CPU execution when VRAM is limited.
    • Added headless browser automation support.
    • Added global approval modes for tool and file-write actions.
    • Integrations can now be configured without authentication tokens when supported.
  • Bug Fixes

    • Improved reporting of GPU resource degradation and admission failures.

…ol auth relaxation, trust-level wiring, Daemon CI

Native Runtime robustness (the actual v2.0 launch content): OrcScheduler.TryAdmit no
longer hard-denies a role that doesn't fit full GPU residency -- it searches for the
largest GPU-layer count that DOES fit and admits in degraded (partial GPU + CPU)
mode instead, so a VRAM-tight box still runs, just slower, rather than refusing
every native call outright. RuntimeOrchestrator.EnsureAdmitted threads the reduced
GpuLayers through to the actual load so the degraded admission takes effect, and
tracks a distinct DegradedAdmissionCount/LastDegradedReason (never conflated with
real rejections). MainWindow gets an always-on status-bar VRAM badge (nvidia-smi,
5s poll, color-coded by headroom) surfacing this live, independent of opening
Settings.

Also included, each self-contained and reviewed as its own concern:
- Studio-tool bearer tokens (Art Forge/CaseForge/KeyHound) become optional --
  hardcoreerik's own local instances run unauthenticated; LocalIntegrationHost still
  gates every call on IsLocal (loopback/private-IP/single-label only), so dropping
  the token requirement never exposes a public-host path.
- ChatPanel: OrcChat's tool-call/file-write approvals now honor the global
  Plan/Guarded/Standard/Full-Auto trust level (previously only the per-conversation
  "Always approve" checkbox had any effect), and the status bar's model badge
  updates when a model is switched from inside OrcChat.
- CI now builds OrchestratorIDE.Daemon explicitly (it cherry-picks shared source via
  <Compile Include> rather than a ProjectReference, so it can silently break while
  the main Avalonia build stays green) and the Daemon project carries the headless
  browser-automation source set (Playwright, NativeToolCapability, PathSandbox) for
  Warband nodes.

Deliberately excluded: SkillLoader.cs / SkillLoaderTests.cs and the
NATIVE_RUNTIME_V2_SPEC.md §8 "self-authored skills" section. That mechanism's
loader half is solid (verified rejecting malformed input safely across 3 distinct
real failure modes), but the swarm-authoring half has failed both live attempts so
far (documented NOT CLOSED in the spec's own run log) -- not launch material yet.

Verified: OrchestratorIDE.Avalonia, OrchestratorIDE.Daemon, and
OrchestratorIDE.UnitTests all build clean with SkillLoader fully absent from this
branch's scope; the 41 tests covering OrcScheduler/OrcChatToolCatalog/ArtForge/
CaseForge/KeyHoundAtlas all pass (including two new OrcScheduler tests: degrade
instead of deny, and fail closed when even zero GPU layers can't fit the fixed
overhead floor).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: eee4d6fa-fc85-429a-b76b-04a71cdb28e1

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The PR adds progressive GPU-layer degradation with telemetry, live VRAM monitoring, optional authentication for local integrations, global chat approval handling, active-model synchronization, and daemon browser-automation build coverage.

Changes

Runtime admission and VRAM telemetry

Layer / File(s) Summary
Progressive GPU-layer admission
OrchestratorIDE/Core/Runtime/OrcScheduler.cs, OrchestratorIDE.UnitTests/OrcSchedulerTests.cs
The scheduler can reduce GPU layers when full residency exceeds available VRAM. Tests cover degraded admission and CPU-only denial.
Effective runtime reservation and telemetry
OrchestratorIDE/Core/Runtime/RuntimeOrchestrator.cs
Runtime loading uses effective GPU-layer options and records degradation counts and reasons in reservation snapshots.
VRAM status and HIVE telemetry display
OrchestratorIDE.Avalonia/MainWindow.axaml, OrchestratorIDE.Avalonia/MainWindow.axaml.cs
The status bar polls nvidia-smi every five seconds and displays VRAM usage, availability, thresholds, and degradation telemetry.

Local integrations and chat controls

Layer / File(s) Summary
Optional authentication for local integrations
OrchestratorIDE.Avalonia/Tools/*, OrchestratorIDE/Research/OrcChatToolCatalog.cs
ArtForge, CaseForge, and KeyHound accept missing tokens for validated local services. Authorization headers are omitted for blank tokens.
Unauthenticated registration coverage
OrchestratorIDE.UnitTests/*ForgeToolsTests.cs, OrchestratorIDE.UnitTests/KeyHoundAtlasToolsTests.cs, OrchestratorIDE.UnitTests/OrcChatToolCatalogTests.cs
Tests cover tokenless localhost registration, tool creation, and public-target rejection.
Chat approval and active-model wiring
OrchestratorIDE.Avalonia/UI/Panels/ChatPanel.axaml.cs, OrchestratorIDE.Avalonia/MainWindow.axaml.cs
Global trust levels control approval decisions. Active-model changes update the session and status bar through the shared window wiring.

Daemon browser automation build

Layer / File(s) Summary
Daemon compilation and CI build
OrchestratorIDE.Daemon/OrchestratorIDE.Daemon.csproj, .github/workflows/ci.yml
The daemon compiles browser automation sources with Playwright, and CI builds it in Release mode without restore or incremental compilation.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant RuntimeOrchestrator
  participant OrcScheduler
  participant NativeRuntime
  participant MainWindow
  RuntimeOrchestrator->>OrcScheduler: Request VRAM admission
  OrcScheduler-->>RuntimeOrchestrator: Return effective GPU layers
  RuntimeOrchestrator->>NativeRuntime: Load using effective options
  MainWindow->>NativeRuntime: Read reservation telemetry
  NativeRuntime-->>MainWindow: Return VRAM and degradation status
Loading
sequenceDiagram
  participant User
  participant ChatPanel
  participant ApprovalQueue
  participant MainWindow
  User->>ChatPanel: Trigger tool or file-write action
  ChatPanel->>ApprovalQueue: Apply global trust level
  ApprovalQueue-->>ChatPanel: Approve or deny action
  ChatPanel-->>MainWindow: Report active-model change
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 21.88% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main changes: degraded VRAM admission and live VRAM status.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/native-runtime-v2-launch

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@OrchestratorIDE.Avalonia/Tools/LocalIntegrationHost.cs`:
- Around line 24-36: Update LocalIntegrationHost.CreateClient and its callers so
bearer tokens are attached only for HTTPS endpoints; validate the target URI or
enforce the HTTPS check before invoking CreateClient. Preserve unauthenticated
local HTTP support, but never send a nonblank bearerToken over cleartext HTTP.
- Around line 24-36: Update CreateClient and the local-tool registration flow so
tokenless requests are permitted only for loopback endpoints; private-IP and
single-label hosts must require a bearer token or an explicit authentication
opt-in. Preserve the existing IsLocal gating while ensuring image_create and
atlas_start cannot target non-loopback local services without authentication.

In `@OrchestratorIDE/Core/Runtime/OrcScheduler.cs`:
- Around line 164-168: Update the admission calculation around requestedLayers
and requiredBytes to estimate memory using the resolved requested GPU-layer
count rather than full GPU residency. Return normal admission when that estimate
fits, including GpuLayers = 0 and partial requests; only enter the descending
fallback loop when the requested count does not fit, preserving the loop’s
lower-layer search. Add tests covering zero and partial GpuLayers requests.

In `@OrchestratorIDE/Core/Runtime/RuntimeOrchestrator.cs`:
- Around line 399-403: The RecordDegradation call currently executes before
LoadBindingAsync and CreateConversationAsync, so it records a degradation even
if those operations fail and the conversation never loads. Return the
decision.Reason or degradation information from the current location to
GetConversationForBindingAsync, then move the RecordDegradation call to execute
after both LoadBindingAsync and CreateConversationAsync succeed, placing it
alongside the reservation commit.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 736f5e3e-cbd7-486b-a391-5345df6ee314

📥 Commits

Reviewing files that changed from the base of the PR and between f9c41fc and e389757.

📒 Files selected for processing (17)
  • .github/workflows/ci.yml
  • OrchestratorIDE.Avalonia/MainWindow.axaml
  • OrchestratorIDE.Avalonia/MainWindow.axaml.cs
  • OrchestratorIDE.Avalonia/Tools/ArtForgeTools.cs
  • OrchestratorIDE.Avalonia/Tools/CaseForgeTools.cs
  • OrchestratorIDE.Avalonia/Tools/KeyHoundAtlasTools.cs
  • OrchestratorIDE.Avalonia/Tools/LocalIntegrationHost.cs
  • OrchestratorIDE.Avalonia/UI/Panels/ChatPanel.axaml.cs
  • OrchestratorIDE.Daemon/OrchestratorIDE.Daemon.csproj
  • OrchestratorIDE.UnitTests/ArtForgeToolsTests.cs
  • OrchestratorIDE.UnitTests/CaseForgeToolsTests.cs
  • OrchestratorIDE.UnitTests/KeyHoundAtlasToolsTests.cs
  • OrchestratorIDE.UnitTests/OrcChatToolCatalogTests.cs
  • OrchestratorIDE.UnitTests/OrcSchedulerTests.cs
  • OrchestratorIDE/Core/Runtime/OrcScheduler.cs
  • OrchestratorIDE/Core/Runtime/RuntimeOrchestrator.cs
  • OrchestratorIDE/Research/OrcChatToolCatalog.cs
💤 Files with no reviewable changes (1)
  • OrchestratorIDE.Avalonia/Tools/CaseForgeTools.cs

Comment on lines +24 to +36
/// <summary>
/// <paramref name="bearerToken"/> is optional (hardcoreerik, 2026-08-01: his own local
/// Art Forge Studio / ComfyUI / KeyHound instances run with no auth at all — a hobby-project
/// front end for ComfyUI he wrote himself, not a service that issues device tokens). No
/// Authorization header is sent when it's null/blank; this is only safe because every caller
/// already gates on <see cref="IsLocal"/> first, so an unauthenticated request can only ever
/// reach a loopback/private-IP/single-label host, never a public one.
/// </summary>
public static HttpClient CreateClient(string? bearerToken)
{
var http = new HttpClient(SharedHandler, disposeHandler: false) { Timeout = TimeSpan.FromMinutes(2) };
http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", bearerToken);
if (!string.IsNullOrWhiteSpace(bearerToken))
http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", bearerToken);

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.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== files =="
git ls-files | rg 'LocalIntegrationHost\.cs|Integration|Service|Api|Client' | sed -n '1,120p'

echo "== outline LocalIntegrationHost.cs =="
file="OrchestratorIDE.Avalonia/Tools/LocalIntegrationHost.cs"
if [ -f "$file" ]; then
  ast-grep outline "$file" --view expanded || true
  echo "== relevant lines =="
  nl -ba "$file" | sed -n '1,220p'
fi

echo "== CreareClient/IsLocal callers =="
rg -n "CreateClient|IsLocal|Authorization|DefaultRequestHeaders" -S . --glob '!bin/**' --glob '!obj/**' | sed -n '1,240p'

Repository: hardcoreerik/TheOrc

Length of output: 7379


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== LocalIntegrationHost.cs =="
python3 - <<'PY'
from pathlib import Path
p=Path('OrchestratorIDE.Avalonia/Tools/LocalIntegrationHost.cs')
lines=p.read_text().splitlines()
for i,l in enumerate(lines,1):
    print(f'{i:4}: {l}')
PY

echo "== usages =="
rg -n "CreateClient|IsLocal\\(|DefaultRequestHeaders\\.Authorization|Authorization" -S . --glob '!bin/**' --glob '!obj/**' | sed -n '1,240p'

echo "== scheme-related checks in relevant tools/services =="
rg -n "http://|https://|Uri\\(|Scheme|IsLocal|CreateClient" -S OrchestratorIDE.Avalonia OrchestratorIDE --glob '!bin/**' --glob '!obj/**' | sed -n '1,320p'

Repository: hardcoreerik/TheOrc

Length of output: 30587


🏁 Script executed:

#!/bin/bash
set -euo pipefail

for src in \
  OrchestratorIDE.Avalonia/Tools/ArtForgeTools.cs \
  OrchestratorIDE.Avalonia/Tools/KeyHoundAtlasTools.cs \
  OrchestratorIDE.Avalonia/Tools/CaseForgeTools.cs
do
  echo "== $src =="
  python3 - <<'PY' "$src"
from pathlib import Path
import sys
p=Path(sys.argv[1])
lines=p.read_text().splitlines()
for i,l in enumerate(lines,1):
    print(f'{i:4}: {l}')
PY
done

echo "== settings/config field names around local URLs/token storage =="
rg -n "ArtForge|ComfyUI|KeyHound|bearerToken|bearer_token|Bearer|Token|LocalIntegrationHost|WorkerUrl|WarchiefUrl|Url" \
  OrchestratorIDE.Avalonia OrchestratorIDE --glob '!bin/**' --glob '!obj/**' | sed -n '1,320p'

echo "== request URL construction near CreateClient calls =="
rg -n -A30 -B30 "CreateClient\\(|IsLocal\\(" OrchestratorIDE.Avalonia/Tools/ArtForgeTools.cs OrchestratorIDE.Avalonia/Tools/KeyHoundAtlasTools.cs OrchestratorIDE.Avalonia/Tools/CaseForgeTools.cs | sed -n '1,320p'

Repository: hardcoreerik/TheOrc

Length of output: 50375


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== RegisterTool calls / art forge / keyhound / caseforge integration wiring =="
rg -n -A20 -B20 "ArtForgeTools\\.Register|KeyHoundAtlasTools\\.Register|CaseForgeTools\\.Register|Art Forge|KeyHound|CaseForge|Bearer|bearer" \
  OrchestratorIDE.Avalonia --glob '!bin/**' --glob '!obj/**' | sed -n '1,360p'

echo "== focused config/dialog text =="
rg -n -A5 -B5 "Local Studio|Art Forge|KeyHound|CaseForge|bearer|Bearer Token|Token" \
  OrchestratorIDE.Avalonia/OrchestratorIDE.Avalonia.csproj OrchestratorIDE.Avalonia UI Dialog Windows Controls Panels --glob '*.cs' --glob '*.acsl' --glob '*.axaml' --glob '*.md' -S 2>/dev/null | sed -n '1,280p'

Repository: hardcoreerik/TheOrc

Length of output: 50375


Sensitive Data Exposure (CWE-319): Cleartext Transmission of Sensitive Information

Reachability: Internal

Require HTTPS before attaching a bearer token.

These registerers accept http URLs and only call IsLocal, while CreateClient attaches Authorization for any nonblank token. A bearer token can therefore be sent over cleartext HTTP to a loopback/private-IP/single-label endpoint. Enforce https before calling LocalIntegrationHost.CreateClient, or validate the target URI in the helper.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@OrchestratorIDE.Avalonia/Tools/LocalIntegrationHost.cs` around lines 24 - 36,
Update LocalIntegrationHost.CreateClient and its callers so bearer tokens are
attached only for HTTPS endpoints; validate the target URI or enforce the HTTPS
check before invoking CreateClient. Preserve unauthenticated local HTTP support,
but never send a nonblank bearerToken over cleartext HTTP.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Locate file =="
fd -a 'LocalIntegrationHost.cs' . || true

echo "== File outline =="
ast-grep outline OrchestratorIDE.Avalonia/Tools/LocalIntegrationHost.cs --view expanded || true

echo "== Relevant file content =="
cat -n OrchestratorIDE.Avalonia/Tools/LocalIntegrationHost.cs

echo "== Search IsLocal and CreateClient usages =="
rg -n "IsLocal|CreateClient|bearerToken|image_create|atlas_start|LocalIntegrationHost" -S .

Repository: hardcoreerik/TheOrc

Length of output: 12974


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== ArtForgeTools.cs relevant sections =="
cat -n OrchestratorIDE.Avalonia/Tools/ArtForgeTools.cs | sed -n '1,80p'
cat -n OrchestratorIDE.Avalonia/Tools/ArtForgeTools.cs | sed -n '120,230p'

echo "== KeyHoundAtlasTools.cs relevant sections =="
cat -n OrchestratorIDE.Avalonia/Tools/KeyHoundAtlasTools.cs | sed -n '1,80p'
cat -n OrchestratorIDE.Avalonia/Tools/KeyHoundAtlasTools.cs | sed -n '120,230p'

echo "== CaseForgeTools.cs relevant sections =="
cat -n OrchestratorIDE.Avalonia/Tools/CaseForgeTools.cs | sed -n '1,80p'
cat -n OrchestratorIDE.Avalonia/Tools/CaseForgeTools.cs | sed -n '160,230p'

echo "== Configuration references for bearer token/service URLs =="
rg -n "Bearer|bearer|BearerToken|ArtForge|KeyHound|CaseForge|ServiceUrl|WorkerUrl|WorkspaceUrl|RequiresApproval|Approval" OrchestratorIDE.Avalonia OrchestratorIDE -S

echo "== HTTP request methods and URLs in tool implementations =="
rg -n "CreateRequest|PostAsJson|SendAsync|http\.|Image |Atlas |Create|Start|Worker|Service|Workflow|Target" OrchestratorIDE.Avalonia/Tools/*Tools.cs -S

Repository: hardcoreerik/TheOrc

Length of output: 50375


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
from pathlib import Path
src = {
    "art": Path("OrchestratorIDE.Avalonia/Tools/ArtForgeTools.cs").read_text(),
    "keyhound": Path("OrchestratorIDE.Avalonia/Tools/KeyHoundAtlasTools.cs").read_text(),
    "caseforge": Path("OrchestratorIDE.Avalonia/Tools/CaseForgeTools.cs").read_text(),
    "host": Path("OrchestratorIDE.Avalonia/Tools/LocalIntegrationHost.cs").read_text(),
}

checks = {
    "CreateClient sends bearer only when non-blank": 'bearerToken' in src["host"] and 'new AuthenticationHeaderValue("Bearer", bearerToken)' in src["host"],
    "CreateClient never adds Authorization on blank token": src["host"].count('new AuthenticationHeaderValue("Bearer", bearerToken)') == 1 and src["host"].index("bearerToken is optional") < src["host"].index("new AuthenticationHeaderValue") < src["host"].index("return http;"),
    "ArtForge image_create is POST to configured api": 'Name = "image_create"' in src["art"] and 'HttpMethod.Post' in src["art"] and 'api/v1/generations/images' in src["art"],
    "KeyHound atlas_start is POST to configured api": 'Name = "atlas_start"' in src["keyhound"] and 'HttpMethod.Post' in src["keyhound"] and 'api/pepe-core/runs' in src["keyhound"],
    "ArtForge Register accepts blank bearer token": 'string? bearerToken = null' in src["art"] and 'if (!IsLocal(serviceUrl))' in src["art"],
    "KeyHound Register accepts blank bearer token": 'string? bearerToken = null' in src["keyhound"] and 'if (!IsLocal(serviceUrl))' in src["keyhound"],
    "CaseForge Register accepts blank bearer token": 'string? bearerToken = null' in src["caseforge"] and 'if (!IsLocal(workerUrl))' in src["caseforge"],
    "IsLocal includes private IPv4 ranges": 'bytes[0] == 10' in src["host"] and 'bytes[0] == 192 && bytes[1] == 168' in src["host"] and 'bytes[0] == 172 && bytes[1]' in src["host"],
}
for name, ok in checks.items():
    print(f"{name}: {ok}")
PY

Repository: hardcoreerik/TheOrc

Length of output: 263


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
from pathlib import Path
src = {
    "art": Path("OrchestratorIDE.Avalonia/Tools/ArtForgeTools.cs").read_text(),
    "keyhound": Path("OrchestratorIDE.Avalonia/Tools/KeyHoundAtlasTools.cs").read_text(),
    "caseforge": Path("OrchestratorIDE.Avalonia/Tools/CaseForgeTools.cs").read_text(),
    "host": Path("OrchestratorIDE.Avalonia/Tools/LocalIntegrationHost.cs").read_text(),
}

checks = {
    "Host optionality and bearer token behavior": all(x in src["host"] for x in [
        "bearerToken is optional",
        '"Bearer", bearerToken',
        "return http;"
    ]),
    "ArtForge accepts URL plus bearer token and sends POST image_create": all(x in src["art"] for x in [
        "string? bearerToken = null",
        "ImageForgeStudioRegistration? ",
        "Name = \"image_create\"",
        "HttpMethod.Post",
        "api/v1/generations/images"
    ]),
    "KeyHound accepts URL plus bearer token and sends POST atlas_start": all(x in src["keyhound"] for x in [
        "string? bearerToken = null",
        "Name = \"atlas_start\"",
        "HttpMethod.Post",
        "api/pepe-core/runs"
    ]),
    "CaseForge accepts URL plus bearer token": all(x in src["caseforge"] for x in [
        "string? bearerToken = null",
        "Name = \"model3d_create\"",
        "HttpMethod.Post",
        "v1/jobs"
    ]),
    "IsLocal accepts private IPv4 ranges": all(x in src["host"] for x in [
        "bytes[0] == 10",
        "bytes[0] == 192 && bytes[1] == 168",
        "bytes[0] == 172 && bytes[1] is >= 16 and <= 31"
    ]),
    "IsLocal accepts loopback and private IPv6 ranges": all(x in src["host"] for x in [
        "IPAddress.IsLoopback(ip)",
        "bytes[0] == 0xfe" in src["host"],
        "bytes[0] == 0xfc"
    ]),
}
for name, ok in checks.items():
    print(f"{name}: {ok}")
PY

echo "== Tool definition context =="
rg -n "ImageForgeStudioRegistration|KeyHoundAtlasRegistration|caseForgeToken|CaseForgeUri|KeyHound|ArtForgeUri|caseForgeUri|serviceUri" -S .

echo "== Read-only source scan for approval before Register calls =="
rg -n "Register\(.*CaseForge|Register\(.*ArtForge|Register\(.*KeyHound|Token\s*=|BearerToken\s*=|caseForgeToken|artForgeToken|KeyHoundToken" OrchestratorIDE.Avalonia OrchestratorIDE -S

Repository: hardcoreerik/TheOrc

Length of output: 338


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
from pathlib import Path
checks = {}
for name in ("host", "art", "keyhound", "caseforge"):
    src = Path(f"OrchestratorIDE.Avalonia/Tools/{('LocalIntegrationHost' if name=='host' else {'art':'ArtForge','keyhound':'KeyHoundAtlas','caseforge':'CaseForge'}[name]+'Tools').replace('KeyHoundAtlas','KeyHoundAtlas')}.cs").read_text() if name != 'host' else Path("OrchestratorIDE.Avalonia/Tools/LocalIntegrationHost.cs").read_text()
    print(f"-- {name} contains essential terms --")
    for term in ["BearerToken", "bearerToken", "Bearer", "IsLocal"]:
        print(f"{name}.{term}: {term in src}")
    print()

print("Search registration callers:")
for pattern in ["Register(\s*", "Token\s*=", "BearerToken\s*=", "caseForgeToken", "artForgeToken", "KeyHoundToken", "ImageForgeStudioRegistration", "KeyHoundAtlasRegistration"]:
    out = __import__('subprocess').check_output(["rg", "-n", pattern, "-S", "."], text=True)
    if out:
        print(pattern)
        print(out[:1200])
        print("---")
PY

Repository: hardcoreerik/TheOrc

Length of output: 1228


Broken Authentication (CWE-306): Missing Authentication for Critical Function

Require authentication for non-loopback local tools.

IsLocal allows private-IP and single-label LAN hosts, but CreateClient only sends a bearer token when one is configured. For image_create / atlas_start, approval gates the user action but not the endpoint identity. If private-LAN services are not fully trusted, restrict tokenless tool registration to loopback addresses, or require explicit opt-in authentication for private/single-label addresses.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@OrchestratorIDE.Avalonia/Tools/LocalIntegrationHost.cs` around lines 24 - 36,
Update CreateClient and the local-tool registration flow so tokenless requests
are permitted only for loopback endpoints; private-IP and single-label hosts
must require a bearer token or an explicit authentication opt-in. Preserve the
existing IsLocal gating while ensuring image_create and atlas_start cannot
target non-loopback local services without authentication.

Comment on lines +164 to +168
var requestedLayers = options.GpuLayers < 0
? header.BlockCount
: Math.Min(options.GpuLayers, header.BlockCount);

for (var layers = requestedLayers - 1; layers >= 0; layers--)

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.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Evaluate the requested GPU-layer count before degrading it.

The initial requiredBytes estimate uses full GPU residency, regardless of options.GpuLayers. The loop then starts at requestedLayers - 1.

As a result, GpuLayers = 0 skips the loop and can be denied even when CPU-only execution fits. A partial request such as GpuLayers = 10 can also be reduced to 9 even when 10 layers fit.

Calculate the initial estimate with the resolved requested layer count. Return a normal admission if that estimate fits. Search lower counts only if the requested count does not fit. Add explicit tests for zero and partial GpuLayers values.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@OrchestratorIDE/Core/Runtime/OrcScheduler.cs` around lines 164 - 168, Update
the admission calculation around requestedLayers and requiredBytes to estimate
memory using the resolved requested GPU-layer count rather than full GPU
residency. Return normal admission when that estimate fits, including GpuLayers
= 0 and partial requests; only enter the descending fallback loop when the
requested count does not fit, preserving the loop’s lower-layer search. Add
tests covering zero and partial GpuLayers requests.

Comment on lines +399 to +403
requiredBytes = OrcScheduler.EstimateRequiredBytes(
binding, options, reusesBaseWeights, gpuLayerOverride: reducedLayers);
effectiveOptions = options! with { GpuLayers = reducedLayers };
RecordDegradation(decision.Reason);
}

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.

🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

Record degradation only after the admission pipeline succeeds.

RecordDegradation runs before LoadBindingAsync and CreateConversationAsync. If either operation fails, the snapshot reports a degraded admission that never loaded or ran.

Return the degradation reason to GetConversationForBindingAsync. Record it after conversation creation succeeds, beside the reservation commit.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@OrchestratorIDE/Core/Runtime/RuntimeOrchestrator.cs` around lines 399 - 403,
The RecordDegradation call currently executes before LoadBindingAsync and
CreateConversationAsync, so it records a degradation even if those operations
fail and the conversation never loads. Return the decision.Reason or degradation
information from the current location to GetConversationForBindingAsync, then
move the RecordDegradation call to execute after both LoadBindingAsync and
CreateConversationAsync succeed, placing it alongside the reservation commit.

…Ollama-default gaps

CodeRabbit findings fixed, each verified with a real test:

- LocalIntegrationHost.cs (Broken Authentication, CWE-306, Major): the optional-
  bearer-token change let ANY IsLocal host skip auth, not just loopback -- a
  private-IP/single-label LAN host is reachable by another machine on the same
  network. CreateClient now requires a token unless the target is genuinely
  loopback; callers already catch the resulting ArgumentException the same way
  they catch an invalid URL, so this fails safe (tool doesn't register) rather
  than crashing. New test: RejectsNoTokenOnAPrivateLanHost (confirmed it throws).

- OrcScheduler.cs (degraded-admission math, Major): the initial admission check
  always estimated full GPU residency regardless of what GpuLayers was actually
  requested, and the degrade-search loop always started from requestedLayers-1 --
  so an explicit partial request that already fit got needlessly reduced further,
  and GpuLayers=0 (explicit CPU-only) could never be evaluated at all (the loop's
  own bound, -1, was already below its lower bound of 0 before it started). Fixed
  by resolving the requested layer count BEFORE the first estimate, so the first
  check evaluates against what was actually asked. Two new tests added and
  verified red (against the old code, via git stash) before green: a partial
  request that fits no longer degrades further, and GpuLayers=0 that fits is now
  admitted instead of denied.

- RuntimeOrchestrator.cs (degradation recorded too early, Minor): RecordDegradation
  ran inside EnsureAdmitted, before the caller's own load/conversation-create ever
  ran -- a load failure after a degraded admission still left the telemetry
  counter claiming a successful degraded admission that never happened.
  EnsureAdmitted now only REPORTS the degradation (a new DegradedReason return
  value); GetConversationForBindingAsync records it, only after its own load and
  conversation-create succeed, beside the reservation commit. New test proves
  EnsureAdmitted alone leaves DegradedAdmissionCount at 0.

Also closes the two remaining Ollama-default gaps found while auditing "is Ollama
actually optional everywhere" against the 2026-07-29 native-default decision:

- SwarmSession (the local Swarm board's boss/worker/researcher pipeline) was the
  one core surface still hardcoded to Ollama with no native option at all, hard-
  erroring if Ollama wasn't configured. New AppSettings.ExperimentalNativeSwarmEnabled
  (default true) gates a BuildSwarmRuntime() mirroring BuildAgentLoopRuntime()'s
  exact fail-closed pattern (no silent Ollama fallback -- a native failure surfaces
  as an explicit error). One NativeWithFallbackRuntime instance serves boss/coder/
  researcher via NativeRoleRuntime's existing modelNameFilter resolution, the same
  mechanism OrcChat's model switcher already relies on. Settings UI toggle added.

- OrcChat/Research's own Backend setting still defaulted to Ollama for the
  fallback path used when native main chat is explicitly disabled. Flipped to
  LlamaCpp, same "never silently default to Ollama" policy -- an unconfigured
  fallback should surface loudly as something to fix, not be quietly absorbed.

Doc-drift fixes: README.md's two "native runtime becomes default -- not yet
started" blocks were stale (the flip landed 2026-07-29); PROJECT_TRUTH.md's
"SwarmSession genuinely not touched" note was stale after the fix above.

Verified: full test suite 800/800 (13 real-model lanes correctly skipped, no
GGUF configured in this environment), OrchestratorIDE.Avalonia builds clean.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@hardcoreerik
hardcoreerik merged commit caaffeb into master Aug 4, 2026
2 checks passed
@hardcoreerik
hardcoreerik deleted the feat/native-runtime-v2-launch branch August 4, 2026 20:26
hardcoreerik added a commit that referenced this pull request Aug 5, 2026
…ase D)

SkillLoader.cs (declarative HTTP-tool manifests -- {workspace}/.orc/skills/*/tools.json,
the data-driven counterpart to ToolCompiler's compiled-C# tools) existed with a full
test suite but was never actually registered: not in the csproj's explicit compile
list, and never called from MainWindow.AutoLoadWorkspaceToolsAsync despite its own doc
comment claiming it was. Also fixes a stale call site -- LocalIntegrationHost.CreateClient
gained a required serviceUri parameter in PR #100 (the loopback-vs-bearer-token auth
gap fix) after this file was written, which SkillLoader.cs's build was silently never
catching since it wasn't compiled at all.

Now wired for real: added to the compile list, called alongside ToolCompiler's scan on
workspace open, and the CreateClient call site updated to pass the skill's resolved base
URI. Full suite (819 tests) passes.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
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