Skip to content

feat: remote MarkRoleDegraded + task-cancel HIVE endpoints - #94

Merged
hardcoreerik merged 4 commits into
masterfrom
feat/hive-control-plane-endpoints
Jul 29, 2026
Merged

feat: remote MarkRoleDegraded + task-cancel HIVE endpoints#94
hardcoreerik merged 4 commits into
masterfrom
feat/hive-control-plane-endpoints

Conversation

@hardcoreerik

@hardcoreerik hardcoreerik commented Jul 29, 2026

Copy link
Copy Markdown
Owner

Summary

  • Closes two long-deferred HV-3/HV-4 validation gaps: POST /hive/roles/degrade (forced role recycle) and POST /hive/tasks/cancel (single in-flight task cancel), both Warchief-only authenticated, mirroring the existing /hive/update/deploy pattern.
  • HiveWorkerAgent gained a per-task CancellationTokenSource registry so a remote cancel interrupts exactly one task, independent of the worker's own lifetime token.
  • Found and fixed a real pre-existing bug: HiveElectionService.WarchiefNodeId was never wired from static config, so the existing /hive/update/deploy endpoint was silently unusable in this fleet's actual deployment shape the whole time.
  • docs/ROADMAP.md updated to reflect the 2026-07-29 native-runtime default flip.

Test plan

  • Full unit suite: 687/700 passing, 13 skipped (native-GGUF-gated, pre-existing)
  • Live-verified against a real deployed daemon on HardcorePC (not just unit tests): genuine HMAC-signed requests, real 200/400/404 responses, confirmed via the worker's own log
  • docs/NATIVE_RUNTIME_HIVE_VALIDATION_PLAN.md HV-3/HV-4 sections updated with the full live-verification trail

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added secure, Warchief-only controls to remotely degrade native roles and cancel individual in-flight tasks.
    • Connected remote controls to native runtime recovery and worker task cancellation.
    • Configured the designated Warchief during daemon startup when specified.
  • Bug Fixes

    • Unknown task cancellation requests now fail safely without affecting active work.
    • Authorization checks fail closed when election services are unavailable.
  • Documentation

    • Updated validation records for runtime recovery and task cancellation.
    • Documented native main chat and HIVE workers as the default, with Ollama available as a fallback.

hardcoreerik and others added 2 commits July 29, 2026 10:48
Closes two long-deferred HIVE validation gaps: forced role recycle and
single-task cancellation were both only reachable from internal code paths,
never remotely. Adds POST /hive/roles/degrade and POST /hive/tasks/cancel,
Warchief-only authenticated, mirroring the existing /hive/update/deploy
pattern. Task cancel required a new per-task CancellationTokenSource
registry in HiveWorkerAgent, separate from the worker's whole-process
lifetime token, so a remote cancel interrupts exactly one task.

Live-verified against a real deployed daemon (HardcorePC), not just unit
tests. That verification surfaced a genuine pre-existing bug: HiveElectionService.WarchiefNodeId
was never wired from static config, meaning the pre-existing
/hive/update/deploy endpoint was silently unusable in this fleet's actual
deployment shape. Fixed alongside the new endpoints.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Replaces every stale "Ollama stays default" / "not the default yet" line
with dated status notes reflecting the 2026-07-29 §6 decision, following
the doc's own established pattern of layering status updates rather than
rewriting history.

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

coderabbitai Bot commented Jul 29, 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: 61a7fa6c-82ce-4875-89ea-4e155353ca29

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 daemon now wires authenticated Warchief-only Hive endpoints for native role degradation and per-task cancellation. Native runtime and worker cancellation APIs implement these actions, with tests and validation documentation covering authorization, unknown tasks, and live endpoint behavior. The roadmap records native defaults.

Changes

Hive control operations

Layer / File(s) Summary
Authenticated control endpoints
OrchestratorIDE/Services/Hive/HiveNodeServer.cs, OrchestratorIDE.UnitTests/HiveNodeServerAuthorizationTests.cs
Adds Warchief-only POST /hive/roles/degrade and POST /hive/tasks/cancel routes with payload validation, handler availability responses, and shared authority checks.
Runtime degradation and task cancellation
OrchestratorIDE/Core/Runtime/IRoleRuntime.cs, OrchestratorIDE/Services/Hive/HiveWorkerAgent.cs, OrchestratorIDE.UnitTests/HiveWorkerAgentTests.cs
Adds native degradation forwarding and per-task cancellation token tracking, cleanup, and unknown-task coverage.
Daemon startup and handler wiring
OrchestratorIDE.Daemon/HiveService.cs
Sets the configured Warchief identifier and connects Hive endpoint handlers to the native runtime and worker agent.
Validation and roadmap updates
docs/NATIVE_RUNTIME_HIVE_VALIDATION_PLAN.md, docs/ROADMAP.md
Records live endpoint verification and updates native runtime default status.

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

Sequence Diagram(s)

sequenceDiagram
  participant Warchief
  participant HiveNodeServer
  participant NativeRoleRuntime
  participant HiveWorkerAgent
  Warchief->>HiveNodeServer: POST /hive/roles/degrade
  HiveNodeServer->>NativeRoleRuntime: MarkRoleDegraded(role)
  NativeRoleRuntime-->>HiveNodeServer: Return success response
  Warchief->>HiveNodeServer: POST /hive/tasks/cancel
  HiveNodeServer->>HiveWorkerAgent: TryCancelTask(taskId)
  HiveWorkerAgent-->>HiveNodeServer: Return cancellation result
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 75.00% 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 captures the main change: adding remote role-degrade and task-cancel HIVE endpoints.
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/hive-control-plane-endpoints

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

🧹 Nitpick comments (1)
OrchestratorIDE/Services/Hive/HiveNodeServer.cs (1)

1026-1036: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Fire-and-forget failure bypasses this class's own diagnostics channel.

The catch inside the background Task.Run logs via Console.Error.WriteLine instead of OnLog?.Invoke(...), which is what every other diagnostic path in this class uses (per the doc comment at line 171-173, OnLog is what "UI subscribes and surfaces ... in the HIVE Activity panel"). In the WPF-hosted case this class also serves (per this file's own doc comments elsewhere), a MarkRoleDegraded failure written to stderr is invisible to the operator, whereas routing it through OnLog would surface it the same way pairing/re-sync/dev-approve diagnostics already do.

♻️ Proposed fix
-            catch (Exception ex) { /* best-effort: the next mint will still recycle on its own detection paths */ Console.Error.WriteLine($"[HiveNodeServer] MarkRoleDegraded({role}) failed: {ex.Message}"); }
+            catch (Exception ex)
+            {
+                // best-effort: the next mint will still recycle on its own detection paths
+                OnLog?.Invoke($"⚠ MarkRoleDegraded({role}) failed: {ex.Message}");
+            }
🤖 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/Services/Hive/HiveNodeServer.cs` around lines 1026 - 1036,
Update the exception handler in the background task around
MarkRoleDegradedHandler to report failures through this class’s OnLog?.Invoke
diagnostic channel instead of Console.Error.WriteLine, preserving the existing
failure context and best-effort fire-and-forget behavior.
🤖 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 `@docs/NATIVE_RUNTIME_HIVE_VALIDATION_PLAN.md`:
- Line 765: Add language identifiers to both fenced request examples in the
validation plan, using http for HTTP requests or text where appropriate. Update
both referenced examples consistently without changing their contents.
- Around line 895-899: Update the HV-4 Item 1 coverage status in the plan so it
is not marked fully covered unless Tools/Hv4RecoveryRunner actively starts a
task, invokes the worker-side cancellation endpoint during generation, and
verifies OperationCanceledException or the resulting failure; otherwise retain
the partial-coverage status.

In `@docs/ROADMAP.md`:
- Around line 663-676: Update the Phase 3 roadmap row and the section preface to
remove stale “live opt-in” and “not the default” wording, while preserving
qualifiers about prototype or production readiness. Ensure the text consistently
states that native runtime selection is now the default and Ollama remains an
opt-out alternative, referencing the status note and Phase 3 entry.

In `@OrchestratorIDE/Services/Hive/HiveNodeServer.cs`:
- Around line 1015-1024: Update the role validation in the MarkRoleDegraded
request handling before invoking MarkRoleDegradedHandler to reject parsed
RuntimeRole values that are not defined enum members. Preserve the existing
case-insensitive name parsing and documented 400 response, including the
expected-role message, for undefined numeric or other invalid values.

---

Nitpick comments:
In `@OrchestratorIDE/Services/Hive/HiveNodeServer.cs`:
- Around line 1026-1036: Update the exception handler in the background task
around MarkRoleDegradedHandler to report failures through this class’s
OnLog?.Invoke diagnostic channel instead of Console.Error.WriteLine, preserving
the existing failure context and best-effort fire-and-forget behavior.
🪄 Autofix (Beta)

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: ef73da05-e612-4bd2-a36d-e17014816031

📥 Commits

Reviewing files that changed from the base of the PR and between f8635f9 and ab127f6.

📒 Files selected for processing (8)
  • OrchestratorIDE.Daemon/HiveService.cs
  • OrchestratorIDE.UnitTests/HiveNodeServerAuthorizationTests.cs
  • OrchestratorIDE.UnitTests/HiveWorkerAgentTests.cs
  • OrchestratorIDE/Core/Runtime/IRoleRuntime.cs
  • OrchestratorIDE/Services/Hive/HiveNodeServer.cs
  • OrchestratorIDE/Services/Hive/HiveWorkerAgent.cs
  • docs/NATIVE_RUNTIME_HIVE_VALIDATION_PLAN.md
  • docs/ROADMAP.md

signed-request harness (deleted after use, matching this session's earlier spike/probe
convention) hit the real endpoint over the network with a genuine HMAC-signed, Warchief-identity
request:
```

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.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Add language identifiers to the fenced request examples.

Use an appropriate fence such as ```http or ```text for both examples.

Also applies to: 884-884

🧰 Tools
🪛 markdownlint-cli2 (0.23.1)

[warning] 765-765: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 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 `@docs/NATIVE_RUNTIME_HIVE_VALIDATION_PLAN.md` at line 765, Add language
identifiers to both fenced request examples in the validation plan, using http
for HTTP requests or text where appropriate. Update both referenced examples
consistently without changing their contents.

Source: Linters/SAST tools

Comment on lines +895 to +899
**Item 1 is now fully covered.** The plan's original ask — cancellation surfacing mid-generation
as an `OperationCanceledException` on the worker via a real remote trigger — has that trigger.
`Tools/Hv4RecoveryRunner`'s `cancel` phase still exercises only the Warchief-side campaign-cancel
path (a different, already-covered mechanism); wiring the harness to also exercise this new
worker-side endpoint is a natural follow-up, not yet done.

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 | 🏗️ Heavy lift

Do not mark HV-4 item 1 fully covered without exercising cancellation of an active task.

Lines [888-893] explicitly state that no in-flight task was available and that the successful cancellation path rests only on code review. Either add a live test that starts a task and verifies OperationCanceledException/failure, or keep item 1 partially covered until the harness exercises that path.

🤖 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 `@docs/NATIVE_RUNTIME_HIVE_VALIDATION_PLAN.md` around lines 895 - 899, Update
the HV-4 Item 1 coverage status in the plan so it is not marked fully covered
unless Tools/Hv4RecoveryRunner actively starts a task, invokes the worker-side
cancellation endpoint during generation, and verifies OperationCanceledException
or the resulting failure; otherwise retain the partial-coverage status.

Comment thread docs/ROADMAP.md
Comment on lines +663 to 676
> evidence artifact (PR #81) has landed too, verified on real hardware.
>
> **Status changed 2026-07-29 — native IS now the default, superseding every "not the default
> yet" line in this section below.** `NATIVE_RUNTIME_V2_SPEC.md` §6's gated milestone (live
> multi-machine HIVE validation, `docs/NATIVE_RUNTIME_HIVE_VALIDATION_PLAN.md` HV-1 through
> HV-6) completed with HV-6 at genuine 3×-repeated, 9/9-lane evidence, and the explicit product
> decision that milestone requires was recorded the same day.
> `AppSettings.ExperimentalNativeHiveWorkerEnabled`/`ExperimentalNativeMainChatEnabled` now
> default to `true`. Ollama remains fully implemented and available as `IModelRuntime`'s other
> backend — installs can still opt back out — it is simply no longer the default construction
> path in `MainWindow`'s HIVE-worker and main-chat runtime builders. The "until the ModelDepot +
> installer first-run story is bulletproof..." criterion further down this section is superseded
> by that decision, made against the HV-6 evidence instead.

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.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Reconcile the new native-default claim with the remaining opt-in wording.

The updated status says native is the default, but the phase-3 row still calls it a “live opt-in proof path,” while the section preface retains “not the default” language. Update these qualifiers so the roadmap clearly distinguishes default runtime selection from prototype/production readiness.

Also applies to: 687-687

🤖 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 `@docs/ROADMAP.md` around lines 663 - 676, Update the Phase 3 roadmap row and
the section preface to remove stale “live opt-in” and “not the default” wording,
while preserving qualifiers about prototype or production readiness. Ensure the
text consistently states that native runtime selection is now the default and
Ollama remains an opt-out alternative, referencing the status note and Phase 3
entry.

Comment on lines +1015 to +1024
MarkRoleDegradedRequest? payload;
try { payload = JsonSerializer.Deserialize<MarkRoleDegradedRequest>(body, _jsonIn); }
catch { resp.StatusCode = 400; Error(resp, "bad request"); return; }

if (payload is null || !Enum.TryParse<RuntimeRole>(payload.Role, ignoreCase: true, out var role))
{
resp.StatusCode = 400;
Error(resp, $"invalid or missing role (expected one of: {string.Join(", ", Enum.GetNames<RuntimeRole>())})");
return;
}

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 | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

echo "Repository files containing HiveNodeServer.cs:"
git ls-files | grep -F 'HiveNodeServer.cs' || true

echo
echo "Relevant source excerpt:"
if [ -f "OrchestratorIDE/Services/Hive/HiveNodeServer.cs" ]; then
  sed -n '980,1080p' "OrchestratorIDE/Services/Hive/HiveNodeServer.cs" | nl -ba -v980
fi

echo
echo "Search RuntimeRole and MarkRoleDegradedHandler:"
rg -n "enum RuntimeRole|RuntimeRole|MarkRoleDegradedHandler|MarkRoleDegradedRequest" -S .
echo
echo ".NET Enum.TryParse behavior probe:"
python3 - <<'PY'
# Python enum TryParse has different behavior; this block exists only to satisfy framework if present.
PY

Repository: hardcoreerik/TheOrc

Length of output: 319


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

# Behavioral probe outside repository code: compile and run a small .cs file if dotnet is available.
cat > /tmp/EnumTryParseProbe.cs <<'CS'
using System;
using System.Reflection;

enum RuntimeRole { None = 0, Leader = 1, Follower = 2 }

class Program
{
    static int Main()
    {
        string[] testCases = new[] { "Leader", "999", "leader", "1", "0", "abc" };
        foreach (var role in testCases)
        {
            if (Enum.TryParse<RuntimeRole>(role, ignoreCase: true, out var parsed))
                Console.WriteLine($"{role,-6} -> parsed={parsed} (undefined={(!Enum.IsDefined<RuntimeRole>(parsed)).ToString().ToLower()})");
            else
                Console.WriteLine($"{role,-6} -> parsed_null");
        }
        return 0;
    }
}
CS

if command -v dotnet >/dev/null 2>&1; then
  tmpdir="$(mktemp -d)"
  cp /tmp/EnumTryParseProbe.cs "$tmpdir/Program.cs"
  (
    cd "$tmpdir"
    dotnet new console --force --no-restore >/dev/null 2>&1 || true
    dotnet build >/dev/null 2>&1 || exit 1
    dotnet run
  )
else
  echo "dotnet not available; cannot run behavioral probe"
fi

rm -f /tmp/EnumTryParseProbe.cs
rm -rf "${tmpdir:-}"

Repository: hardcoreerik/TheOrc

Length of output: 207


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

# Behavioral probe outside repository code: compile and run a small .cs file if dotnet is available.
cat > /tmp/EnumTryParseProbe.cs <<'CS'
using System;
using System.Reflection;

enum RuntimeRole { None = 0, Leader = 1, Follower = 2 }

class Program
{
    static int Main()
    {
        string[] testCases = new[] { "Leader", "999", "leader", "1", "0", "abc" };
        foreach (var role in testCases)
        {
            if (Enum.TryParse<RuntimeRole>(role, ignoreCase: true, out var parsed))
                Console.WriteLine($"{role,-6} -> parsed={parsed} (undefined={(!Enum.IsDefined<RuntimeRole>(parsed)).ToString().ToLower()})");
            else
                Console.WriteLine($"{role,-6} -> parsed_null");
        }
        return 0;
    }
}
CS

if command -v dotnet >/dev/null 2>&1; then
  tmpdir="$(mktemp -d)"
  cp /tmp/EnumTryParseProbe.cs "$tmpdir/Program.cs"
  (
    cd "$tmpdir"
    dotnet new console --force --no-restore >/dev/null 2>&1 || true
    dotnet build >/dev/null 2>&1 || exit 1
    dotnet run
  )
else
  echo "dotnet not available; cannot run behavioral probe"
fi

2> /tmp/enum_probe_err.txt; true
rm -f /tmp/EnumTryParseProbe.cs /tmp/enum_probe_err.txt
rm -rf "${tmpdir:-}"

Repository: hardcoreerik/TheOrc

Length of output: 207


🌐 Web query:

Microsoft .NET Enum.TryParse numeric string undefined enum value IsDefined behavior

💡 Result:

In.NET, the Enum.TryParse method is designed to parse both the names and the underlying numeric values of an enumeration [1][2][3]. When a numeric string is provided, Enum.TryParse will successfully parse it into the target enum type even if that numeric value is not explicitly defined in the enumeration [1][4][5]. This behavior occurs because Enum.TryParse treats any string representation of an integer as a valid attempt to convert to the enum's underlying integral type [1][2][5]. Consequently, the method will return true and output the corresponding enum value, regardless of whether that value corresponds to a named member [4][6]. If this behavior is undesirable and you need to ensure that the parsed value is a valid, defined member of the enumeration, you must explicitly call Enum.IsDefined after a successful parse [1][2][5]. Example of the safe usage pattern: string input = "99"; // An undefined value if (Enum.TryParse(input, out MyEnum result) && Enum.IsDefined(typeof(MyEnum), result)) { // Result is a valid, defined member of the enum } else { // Handle invalid or undefined value } Note that Enum.IsDefined evaluates whether the specific value (or name) exists within the enumeration [7][5]. In cases where you are dealing with enumerations marked with the [Flags] attribute, keep in mind that Enum.IsDefined may return false for composite values (e.g., bitwise combinations) even if they are logically valid for your use case, and you should use Enum.HasFlag instead [7].

Citations:


🌐 Web query:

Microsoft .NET Enum.TryParse numeric string undefined enum value IsDefined behavior

💡 Result:

In.NET, the Enum.TryParse method is designed to succeed even when the input numeric string does not correspond to a defined constant within the enumeration [1][2][3]. If the input string is a valid representation of the underlying integral type of the enum, Enum.TryParse will parse it and return true, assigning the resulting value to the output parameter [1][4]. This behavior is intentional, as it allows the method to support the parsing of underlying integral values that may not be explicitly named constants [1][5]. Because Enum.TryParse returns true for these undefined values, it does not implicitly validate that the result is a defined member of the enumeration [6][3]. To ensure that a parsed value is an actual defined member of the enum, you must explicitly call Enum.IsDefined [1][6]. When using Enum.IsDefined for this purpose, it is critical to pass the enum value itself, not the original string [6][7]. Enum.IsDefined(typeof(TEnum), "some_string") looks for a member named "some_string" and will return false if the string is numeric, even if that number corresponds to a valid enum constant [7]. Instead, you should perform the following sequence [6][8][7]: 1. Use Enum.TryParse to convert the string to the enum type [1][8]. 2. Pass the resulting enum value to Enum.IsDefined to verify it is a defined constant [6][8]. Example: string input = "99"; // Undefined value if (Enum.TryParse(input, out MyEnum result)) { if (Enum.IsDefined(typeof(MyEnum), result)) { // Value is defined } else { // Value is parsed but not defined in the enum } }

Citations:


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

echo "Relevant HiveNodeServer excerpt:"
sed -n '980,1090p' "OrchestratorIDE/Services/Hive/HiveNodeServer.cs" | awk '{printf "%6d\t%s\n", NR+979, $0}'

echo
echo "RuntimeRole definition and handler usages:"
rg -n "enum RuntimeRole|RuntimeRole|MarkRoleDegradedHandler|MarkRoleDegradedRequest|IsDefined" -S "OrchestratorIDE/Services/Hive"

Repository: hardcoreerik/TheOrc

Length of output: 7935


Reject undefined RuntimeRole values before invoking the handler.

.NET enum parsing accepts valid integer strings for undefined values, so {"role":"999"} currently returns success and calls MarkRoleDegradedHandler(999) instead of returning the documented 400 role validation error.

🛡️ Proposed fix
-        if (payload is null || !Enum.TryParse<RuntimeRole>(payload.Role, ignoreCase: true, out var role))
+        if (payload is null
+            || !Enum.TryParse<RuntimeRole>(payload.Role, ignoreCase: true, out var role)
+            || !Enum.IsDefined(role))
         {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
MarkRoleDegradedRequest? payload;
try { payload = JsonSerializer.Deserialize<MarkRoleDegradedRequest>(body, _jsonIn); }
catch { resp.StatusCode = 400; Error(resp, "bad request"); return; }
if (payload is null || !Enum.TryParse<RuntimeRole>(payload.Role, ignoreCase: true, out var role))
{
resp.StatusCode = 400;
Error(resp, $"invalid or missing role (expected one of: {string.Join(", ", Enum.GetNames<RuntimeRole>())})");
return;
}
MarkRoleDegradedRequest? payload;
try { payload = JsonSerializer.Deserialize<MarkRoleDegradedRequest>(body, _jsonIn); }
catch { resp.StatusCode = 400; Error(resp, "bad request"); return; }
if (payload is null
|| !Enum.TryParse<RuntimeRole>(payload.Role, ignoreCase: true, out var role)
|| !Enum.IsDefined(role))
{
resp.StatusCode = 400;
Error(resp, $"invalid or missing role (expected one of: {string.Join(", ", Enum.GetNames<RuntimeRole>())})");
return;
}
🤖 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/Services/Hive/HiveNodeServer.cs` around lines 1015 - 1024,
Update the role validation in the MarkRoleDegraded request handling before
invoking MarkRoleDegradedHandler to reject parsed RuntimeRole values that are
not defined enum members. Preserve the existing case-insensitive name parsing
and documented 400 response, including the expected-role message, for undefined
numeric or other invalid values.

hardcoreerik and others added 2 commits July 29, 2026 10:59
grok-review (PR #94, full mode) caught it before merge: a remote
/hive/tasks/cancel reported status "failed" back to the Warchief, and
HiveTaskQueue.HandleFailAsync requeues campaign work whenever attempts
remain -- so cancelling a task would have quietly resurrected it on
another attempt instead of stopping it.

Fixed by giving remote cancellation its own terminal status. ClaimAndExecuteAsync
distinguishes a taskCts-triggered OperationCanceledException from a genuine
failure and reports "cancelled" instead of "failed"; HandleFailAsync now checks
that field first and skips its requeue branch when set, reusing the "cancelled"
status that already exists for Warchief-initiated campaign cancellation rather
than inventing a second vocabulary.

Also from the same review pass: HandleMarkRoleDegraded now awaits its handler
and reports real failures instead of responding 200 before a fire-and-forget
call that could silently fail (this exact endpoint hit a real
MissingMethodException during its own deployment verification); and
/hive/update/deploy uses the shared IsWarchief helper instead of a duplicate
inline check.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Reject undefined RuntimeRole values: Enum.TryParse alone accepts any
integer string as a "successfully parsed" undefined value, so
{"role":"999"} would have called MarkRoleDegradedHandler((RuntimeRole)999)
instead of the documented 400. Added Enum.IsDefined.

Softened the HV-4 item 1 "fully covered" claim to accurately reflect what
was actually live-verified (routing/auth/validation, via 404/400 responses)
versus what still rests on code review (the actual mid-generation cancel
path, since no task was in flight during verification).

Reconciled ROADMAP.md's Phase 2/3 rows, which still read "not
production/default" and "opt-in" right below the new "native is now
default" status note -- clarified that those rows are about prototype
completeness, a different axis from runtime-selection default status.

Fixed two markdownlint fenced-code-language warnings.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@hardcoreerik
hardcoreerik merged commit 01ad297 into master Jul 29, 2026
2 checks passed
@hardcoreerik
hardcoreerik deleted the feat/hive-control-plane-endpoints branch July 29, 2026 18:10
hardcoreerik added a commit that referenced this pull request Jul 30, 2026
The last real gap flagged in this session's HIVE-testing work: TryCancelTask's
"found and actually cancels" path had no coverage, only the "unknown
taskId" negative case. This needed a task genuinely claimed in flight,
not just a constructed HiveWorkerAgent.

TryCancelTask_OnATaskActuallyInFlight_ReportsCancelledNotFailed starts
a real HiveWorkerAgent against a fake Warchief (bare HttpListener --
only needs to hand out one lease and accept one fail-POST, not
validate HMAC auth like the real HiveNodeServer) leasing a task backed
by a Runtime whose StreamCompletionAsync blocks on the cancellation
token indefinitely. A TaskCompletionSource signals the instant
generation actually starts, so the cancel is synchronized against
genuinely in-flight work rather than a fixed sleep guess. Asserts the
terminal report is "Cancellation reported to Warchief," never "Failure
reported" -- the exact distinction PR #94's grok-review fix exists to
preserve (a plain "failed" status would let HiveTaskQueue.HandleFailAsync
silently requeue the same work, the opposite of what cancelling means).

Verified stable across 5 repeated runs (~585ms each) before landing.
Full suite: 693/706 (13 skipped, native-GGUF-gated as always).

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