CF-6 HIVE acceptance JSON used as the frozen B4 run (cf7-gate suite)");
+ Console.WriteLine(" --heldout-questions Path to held-out question JSON (required for cf7-gate-expanded)");
+ Console.WriteLine(" --max-questions Cap questions processed (useful for smoke tests; default: all)");
Console.WriteLine(" --segments Scale-suite segment count (default 640)");
Console.WriteLine(" --background-lines Scale-suite background lines per segment (default 60; 640x60 is ~1M source tokens)");
}
@@ -362,5 +546,9 @@ private sealed record CliOptions(
BenchmarkSuite Suite,
string? B4ArtifactPath,
int ScaleSegments,
- int ScaleBackgroundLines);
+ int ScaleBackgroundLines,
+ string? GrokAuthoredPath,
+ string? CodexAuthoredPath,
+ string? HeldOutQuestionsPath,
+ int? MaxQuestions);
}
diff --git a/Tools/ContextFabricBench/Run-CF7GateExpanded.ps1 b/Tools/ContextFabricBench/Run-CF7GateExpanded.ps1
new file mode 100644
index 00000000..e811227c
--- /dev/null
+++ b/Tools/ContextFabricBench/Run-CF7GateExpanded.ps1
@@ -0,0 +1,288 @@
+<#
+.SYNOPSIS
+ Run the CF-7 gate (expanded corpus, 120 held-out questions) on this machine.
+
+.DESCRIPTION
+ Builds the context-fabric-bench tool, then runs the full cf7-gate-expanded suite
+ against the 128-segment expanded corpus and the frozen 120-question held-out set.
+
+ This script is the canonical re-run recipe for the NEWCOREPC CF-7 benchmark.
+ Hand it to Codex, Grok, or another agent as the starting point for a fresh run.
+
+ PREREQUISITES
+ -------------
+ - .NET 8 SDK (dotnet build)
+ - Gemma 4 12B QAT Q4_0 model installed in the OrchestratorIDE model directory
+ (gemma-4-12B-it-qat-q4_0.gguf or equivalent admitted model; 7B+ Admitted is required)
+ - Windows with CUDA-capable GPU is recommended. CPU-only is possible but very slow
+ (~10-20x longer per inference call).
+
+ VERDICT GUIDANCE
+ ----------------
+ The gate criteria are defined in the suite itself. Look for these lines in stdout:
+
+ B3 verdict: PASS/FAIL, segments X/128, questions Y/120
+ Verdict (expanded corpus, real held-out suite): GO / NO-GO
+
+ A GO result means:
+ - segment_terminal_coverage above threshold
+ - question_pass_rate above threshold
+ - citation_precision above threshold
+ - boundary_stitch_pass_rate above threshold
+ - B0/B1/B2 baselines all ran to completion (Succeeded=true for every question)
+
+ EXPECTED DURATION
+ -----------------
+ NEWCOREPC (RTX 5070 Ti 16GB, Gemma 12B): ~4-6 hours for 120 questions
+ Lower-VRAM machines or smaller models: longer or may hit KV-slot limits
+
+.PARAMETER RepoRoot
+ Path to the OrchestratorIDE-dev repository root.
+ Defaults to the parent of this script's directory (Tools/ContextFabricBench -> repo root).
+
+.PARAMETER ModelRoot
+ Path to the local model directory.
+ Defaults to %APPDATA%\OrchestratorIDE\Models (standard install location).
+
+.PARAMETER OutputDir
+ Directory to write JSON/Markdown results into.
+ Defaults to .orc/adversarial under the repo root.
+ Each run writes its own timestamped files and does NOT overwrite prior results.
+
+.PARAMETER MaxQuestions
+ Cap the question count for a smoke test. Default 0 = run all 120.
+ Example: -MaxQuestions 3 for a quick sanity check.
+
+.PARAMETER Context
+ KV context length in tokens. Default 8192.
+ Lower values (4096) reduce VRAM pressure but may hurt recall.
+
+.PARAMETER GpuLayers
+ GPU layers to offload. Default -1 (auto: offload as many as VRAM allows).
+ Set to 0 to force CPU-only.
+
+.PARAMETER SkipBuild
+ Skip dotnet build and use whatever exe is already in publish/.
+ Use this when you know the last build matches the current source.
+
+.PARAMETER LogFile
+ Path to write a copy of stdout. Defaults to OutputDir/cf7_expanded__console.log.
+ Set to empty string to disable log capture.
+
+.EXAMPLE
+ # Full 120-question run (the standard closure run)
+ .\Run-CF7GateExpanded.ps1
+
+.EXAMPLE
+ # Quick 3-question smoke test to verify setup before committing GPU time
+ .\Run-CF7GateExpanded.ps1 -MaxQuestions 3
+
+.EXAMPLE
+ # Skip rebuild (source unchanged) and target a different model directory
+ .\Run-CF7GateExpanded.ps1 -SkipBuild -ModelRoot "D:\Models\CF"
+
+.EXAMPLE
+ # Force CPU, useful for checking tool logic without a GPU
+ .\Run-CF7GateExpanded.ps1 -MaxQuestions 3 -GpuLayers 0
+
+.NOTES
+ Branch: feat/cf-benchmark-remediation (or any branch that includes the
+ JSON recovery fix and Cf7GateExpanded suite in Program.cs).
+
+ Key artifacts produced:
+ /cf0__.json (B3 single-node CF report)
+ /cf7_baseline_b0_.json (B0 closed-book baseline)
+ /cf7_baseline_b1_.json (B1 truncated-prompt baseline)
+ /cf7_baseline_b2_.json (B2 top-k RAG baseline)
+ /cf7_gate__.json (composite gate report)
+ /cf7_gate__.md (human-readable summary)
+
+ B4 is loaded from the frozen CF-6 HIVE acceptance artifact; it is not re-run.
+ The artifact path is .orc/cf6-acceptance/cf6-acceptance-*.json (auto-detected).
+#>
+
+[CmdletBinding()]
+param(
+ [string]$RepoRoot = (Resolve-Path "$PSScriptRoot/../..").Path,
+ [string]$ModelRoot = (Join-Path $env:APPDATA "OrchestratorIDE\Models"),
+ [string]$OutputDir = "",
+ [int] $MaxQuestions = 0,
+ [int] $Context = 8192,
+ [int] $GpuLayers = -1,
+ [switch]$SkipBuild,
+ [string]$LogFile = ""
+)
+
+Set-StrictMode -Version Latest
+$ErrorActionPreference = "Stop"
+
+# ---------------------------------------------------------------------------
+# Resolve paths
+# ---------------------------------------------------------------------------
+$RepoRoot = Resolve-Path $RepoRoot | Select-Object -ExpandProperty Path
+$BenchDir = Join-Path $RepoRoot "Tools\ContextFabricBench"
+$PublishDir = Join-Path $BenchDir "publish"
+$BenchExe = Join-Path $PublishDir "context-fabric-bench.exe"
+
+if (-not $OutputDir) {
+ $OutputDir = Join-Path $RepoRoot ".orc\adversarial"
+}
+
+$HeldOutPath = Join-Path $RepoRoot ".orc\adversarial\expanded-question-suite-heldout.json"
+
+# Locate the frozen B4 artifact (CF-6 acceptance JSON).
+$B4ArtifactDir = Join-Path $RepoRoot ".orc\cf6-acceptance"
+$B4Artifact = Get-ChildItem $B4ArtifactDir -Filter "cf6-acceptance-*.json" -ErrorAction SilentlyContinue |
+ Sort-Object LastWriteTime -Descending |
+ Select-Object -First 1 -ExpandProperty FullName
+
+# ---------------------------------------------------------------------------
+# Pre-flight checks
+# ---------------------------------------------------------------------------
+Write-Host ""
+Write-Host "=== CF-7 Gate Expanded — Re-run Script ===" -ForegroundColor Cyan
+Write-Host "Repo root : $RepoRoot"
+Write-Host "Model root : $ModelRoot"
+Write-Host "Output dir : $OutputDir"
+Write-Host "Questions : $(if ($MaxQuestions -gt 0) { $MaxQuestions } else { '120 (all)' })"
+Write-Host "Context : $Context tokens"
+Write-Host "GPU layers : $(if ($GpuLayers -eq -1) { 'auto' } else { $GpuLayers })"
+Write-Host ""
+
+# Held-out questions
+if (-not (Test-Path $HeldOutPath)) {
+ Write-Error "Held-out question file not found: $HeldOutPath`n" +
+ "Expected at .orc/adversarial/expanded-question-suite-heldout.json in the repo root.`n" +
+ "This file is generated by the question-suite build process and must be present."
+ exit 1
+}
+
+# B4 artifact
+if (-not $B4Artifact) {
+ Write-Error "No CF-6 acceptance artifact found in: $B4ArtifactDir`n" +
+ "Expected a file matching cf6-acceptance-*.json.`n" +
+ "Ensure the CF-6 HIVE acceptance run has been completed and its artifact is checked in."
+ exit 1
+}
+Write-Host "B4 artifact: $B4Artifact"
+
+# Model directory
+if (-not (Test-Path $ModelRoot)) {
+ Write-Error "Model root not found: $ModelRoot`n" +
+ "Install a qualifying model (7B+ Admitted for CF) and ensure the directory exists."
+ exit 1
+}
+
+$GgufCount = (Get-ChildItem $ModelRoot -Filter "*.gguf" -Recurse -ErrorAction SilentlyContinue).Count
+if ($GgufCount -eq 0) {
+ Write-Error "No .gguf files found under: $ModelRoot`n" +
+ "The CF gate requires at least one 7B+ Admitted model (e.g. gemma-4-12B-it-qat-q4_0.gguf)."
+ exit 1
+}
+Write-Host "GGUF models found: $GgufCount"
+
+# Output directory
+New-Item -ItemType Directory -Force -Path $OutputDir | Out-Null
+
+# ---------------------------------------------------------------------------
+# Build
+# ---------------------------------------------------------------------------
+if ($SkipBuild) {
+ Write-Host ""
+ Write-Host "Skipping build (--SkipBuild)." -ForegroundColor Yellow
+ if (-not (Test-Path $BenchExe)) {
+ Write-Error "Bench exe not found at $BenchExe and -SkipBuild was specified. Run without -SkipBuild first."
+ exit 1
+ }
+} else {
+ Write-Host ""
+ Write-Host "Building context-fabric-bench..." -ForegroundColor Cyan
+ Push-Location $BenchDir
+ try {
+ dotnet publish ContextFabricBench.csproj -c Release -r win-x64 --self-contained false -o publish /p:DebugType=none
+ if ($LASTEXITCODE -ne 0) {
+ Write-Error "dotnet publish failed (exit $LASTEXITCODE). Fix build errors before re-running."
+ exit $LASTEXITCODE
+ }
+ } finally {
+ Pop-Location
+ }
+ Write-Host "Build succeeded." -ForegroundColor Green
+}
+
+# ---------------------------------------------------------------------------
+# Assemble command arguments
+# ---------------------------------------------------------------------------
+$Timestamp = Get-Date -Format "yyyyMMdd_HHmmss"
+
+if (-not $LogFile) {
+ $label = if ($MaxQuestions -gt 0) { "smoke${MaxQuestions}" } else { "full" }
+ $LogFile = Join-Path $OutputDir "cf7_expanded_${label}_${Timestamp}_console.log"
+}
+
+$Args = @(
+ "--suite", "cf7-gate-expanded",
+ "--model-root", $ModelRoot,
+ "--heldout-questions",$HeldOutPath,
+ "--b4-artifact", $B4Artifact,
+ "--output", $OutputDir,
+ "--context", $Context
+)
+
+if ($MaxQuestions -gt 0) {
+ $Args += @("--max-questions", $MaxQuestions)
+}
+
+if ($GpuLayers -ne -1) {
+ $Args += @("--gpu-layers", $GpuLayers)
+}
+
+# ---------------------------------------------------------------------------
+# Run
+# ---------------------------------------------------------------------------
+Write-Host ""
+Write-Host "Starting benchmark..." -ForegroundColor Cyan
+Write-Host "Command: $BenchExe $($Args -join ' ')"
+if ($LogFile) {
+ Write-Host "Log : $LogFile"
+}
+Write-Host ""
+
+$StartTime = Get-Date
+
+if ($LogFile) {
+ # Tee stdout to both console and log file so you can tail the log separately.
+ & $BenchExe @Args 2>&1 | Tee-Object -FilePath $LogFile
+} else {
+ & $BenchExe @Args
+}
+
+$ExitCode = $LASTEXITCODE
+$Elapsed = (Get-Date) - $StartTime
+
+# ---------------------------------------------------------------------------
+# Result summary
+# ---------------------------------------------------------------------------
+Write-Host ""
+Write-Host "=== Run complete ===" -ForegroundColor Cyan
+Write-Host ("Elapsed : {0:hh\:mm\:ss}" -f $Elapsed)
+Write-Host "Exit : $ExitCode"
+
+if ($ExitCode -eq 0) {
+ Write-Host "Verdict : GO -- all gate thresholds met." -ForegroundColor Green
+} elseif ($ExitCode -eq 2) {
+ Write-Host "Verdict : NO-GO -- one or more thresholds were not met." -ForegroundColor Red
+ Write-Host " Review the gate JSON and markdown in: $OutputDir"
+} else {
+ Write-Host "Verdict : ERROR -- the tool exited with code $ExitCode." -ForegroundColor Red
+ Write-Host " Check the log for crash details: $LogFile"
+}
+
+Write-Host ""
+Write-Host "Output artifacts:" -ForegroundColor Cyan
+Get-ChildItem $OutputDir -Filter "cf7_*" |
+ Sort-Object LastWriteTime -Descending |
+ Select-Object -First 8 |
+ ForEach-Object { Write-Host " $($_.Name) ($([math]::Round($_.Length / 1024, 1)) KB)" }
+
+exit $ExitCode
diff --git a/Tools/ToolcallerBench/Program.cs b/Tools/ToolcallerBench/Program.cs
new file mode 100644
index 00000000..97ed9c34
--- /dev/null
+++ b/Tools/ToolcallerBench/Program.cs
@@ -0,0 +1,133 @@
+// Copyright (C) 2025-present hardcoreerik / TheOrc contributors
+// SPDX-License-Identifier: AGPL-3.0-or-later
+using System.Security.Cryptography;
+using System.Text.Json;
+using ToolcallerBench;
+
+if (args.Contains("--help", StringComparer.OrdinalIgnoreCase) || args.Contains("-h", StringComparer.OrdinalIgnoreCase))
+{
+ PrintUsage();
+ return 0;
+}
+
+try
+{
+ var options = ParseArgs(args);
+
+ if (options.Suite != "validate")
+ throw new ArgumentException($"Unknown suite '{options.Suite}'. Only 'validate' is implemented today.");
+
+ if (string.IsNullOrWhiteSpace(options.CapturesDir) || !Directory.Exists(options.CapturesDir))
+ {
+ Console.Error.WriteLine("validate requires --captures pointing at a directory of toolcaller capture JSON files.");
+ return 64;
+ }
+
+ var toolsPath = options.ToolsPath ?? Path.Combine(AppContext.BaseDirectory, "Schemas", "toolcaller_v0_frozen_tools.json");
+ if (!File.Exists(toolsPath))
+ {
+ Console.Error.WriteLine($"Frozen tool inventory not found: {toolsPath}");
+ return 64;
+ }
+
+ var toolsBytes = await File.ReadAllBytesAsync(toolsPath);
+ var toolsHash = Convert.ToHexString(SHA256.HashData(toolsBytes)).ToLowerInvariant();
+
+ var jsonOptions = new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower };
+ var frozenTools = JsonSerializer.Deserialize>(toolsBytes, jsonOptions)
+ ?? throw new InvalidOperationException("Frozen tool inventory parsed to null.");
+
+ Console.WriteLine($"Frozen tool inventory: {frozenTools.Count} tools, sha256 {toolsHash}");
+
+ var captureFiles = Directory.GetFiles(options.CapturesDir, "*.json", SearchOption.TopDirectoryOnly);
+ if (captureFiles.Length == 0)
+ {
+ Console.Error.WriteLine($"No .json capture files found under: {options.CapturesDir}");
+ return 64;
+ }
+
+ var captures = new List();
+ foreach (var file in captureFiles)
+ {
+ try
+ {
+ var capture = JsonSerializer.Deserialize(await File.ReadAllBytesAsync(file), jsonOptions)
+ ?? throw new InvalidOperationException("parsed to null");
+ captures.Add(capture);
+ }
+ catch (Exception ex)
+ {
+ Console.Error.WriteLine($"[ERROR] Failed to parse {Path.GetFileName(file)}: {ex.Message}");
+ return 65;
+ }
+ }
+
+ Console.WriteLine($"Loaded {captures.Count} capture(s) from {options.CapturesDir}");
+
+ var report = ToolcallerCaptureValidator.Validate(captures, frozenTools, toolsHash);
+ var output = options.OutputDir ?? Path.Combine(Environment.CurrentDirectory, ".orc", "toolcaller-bench");
+ var (jsonPath, markdownPath) = await ToolcallerReportWriter.WriteAsync(report, output);
+
+ Console.WriteLine($"Verdict: {(report.Passed ? "PASS" : "FAIL")}, {report.PassedExamples}/{report.TotalExamples} examples passed");
+ Console.WriteLine($"JSON: {jsonPath}");
+ Console.WriteLine($"Markdown: {markdownPath}");
+
+ if (!report.Passed)
+ {
+ foreach (var finding in report.Findings.Where(f => f.Severity == FindingSeverity.Error))
+ Console.Error.WriteLine($" [{finding.Gate}] {finding.ExampleId}: {finding.Detail}");
+ }
+
+ return report.Passed ? 0 : 2;
+}
+catch (Exception ex)
+{
+ Console.Error.WriteLine($"[ERROR] {ex.Message}");
+ return 1;
+}
+
+static void PrintUsage()
+{
+ Console.WriteLine("Usage: toolcaller-bench --suite validate --captures [options]");
+ Console.WriteLine(" --suite Only 'validate' is implemented today.");
+ Console.WriteLine(" --captures Directory of toolcaller capture JSON files to validate.");
+ Console.WriteLine(" --tools Override path to the frozen tool inventory JSON.");
+ Console.WriteLine(" Default: Schemas/toolcaller_v0_frozen_tools.json next to the exe.");
+ Console.WriteLine(" --output Report directory (default .orc/toolcaller-bench).");
+ Console.WriteLine();
+ Console.WriteLine("This tool implements mechanical dataset admission-gate validation only");
+ Console.WriteLine("(training_pit/TOOLCALLER_CAPTURE_SCHEMA.md). It does not generate examples,");
+ Console.WriteLine("run baselines, or call any model. See docs/THEORC_TOOLCALLER_V0.md for the");
+ Console.WriteLine("full F-1 deliverable list this tool partially satisfies.");
+}
+
+static CliOptions ParseArgs(string[] args)
+{
+ string suite = "validate";
+ string? capturesDir = null;
+ string? toolsPath = null;
+ string? outputDir = null;
+
+ for (var i = 0; i < args.Length; i++)
+ {
+ switch (args[i])
+ {
+ case "--suite": suite = Next(args, ref i); break;
+ case "--captures": capturesDir = Next(args, ref i); break;
+ case "--tools": toolsPath = Next(args, ref i); break;
+ case "--output": outputDir = Next(args, ref i); break;
+ default: throw new ArgumentException($"Unknown option '{args[i]}'.");
+ }
+ }
+
+ return new CliOptions(suite, capturesDir, toolsPath, outputDir);
+}
+
+static string Next(string[] args, ref int i)
+{
+ if (i + 1 >= args.Length)
+ throw new ArgumentException($"Option '{args[i]}' requires a value.");
+ return args[++i];
+}
+
+internal sealed record CliOptions(string Suite, string? CapturesDir, string? ToolsPath, string? OutputDir);
diff --git a/Tools/ToolcallerBench/ToolcallerBench.csproj b/Tools/ToolcallerBench/ToolcallerBench.csproj
new file mode 100644
index 00000000..19e6177c
--- /dev/null
+++ b/Tools/ToolcallerBench/ToolcallerBench.csproj
@@ -0,0 +1,16 @@
+
+
+
+ Exe
+ net10.0
+ enable
+ enable
+ toolcaller-bench
+ ToolcallerBench
+
+
+
+
+
+
+
diff --git a/Tools/ToolcallerBench/ToolcallerCaptureValidator.cs b/Tools/ToolcallerBench/ToolcallerCaptureValidator.cs
new file mode 100644
index 00000000..9dc2b4c9
--- /dev/null
+++ b/Tools/ToolcallerBench/ToolcallerCaptureValidator.cs
@@ -0,0 +1,171 @@
+// Copyright (C) 2025-present hardcoreerik / TheOrc contributors
+// SPDX-License-Identifier: AGPL-3.0-or-later
+namespace ToolcallerBench;
+
+///
+/// Implements the mechanical dataset admission gates from
+/// training_pit/TOOLCALLER_CAPTURE_SCHEMA.md. This runs before any model-based judge,
+/// per FOUNDRY_ARENA.md's general policy.
+///
+/// One gate from the schema doc — "approval_state implying the call already executed
+/// or was already approved by the model itself" — is NOT mechanically checked here.
+/// It requires semantic judgment about free-text request/notes content that a keyword
+/// heuristic would either miss or false-positive on; building a fragile approximation
+/// and reporting it as "checked" would misrepresent this validator's real coverage.
+/// It remains a reviewer-only gate until a real approach is chosen (see the "Reviewer
+/// Coverage" note in ToolcallerValidationReport output).
+///
+/// The other schema-doc gate this validator does NOT check — live cross-verification
+/// of policy_outcome against a fresh OrchestratorIDE.Trust.ToolPolicyEngine.Evaluate()
+/// call — is intentionally out of scope for this skeleton. ToolPolicyEngine.cs is only
+/// compiled into OrchestratorIDE.Avalonia.csproj today; referencing it from this bench
+/// tool would pull in the full Avalonia UI stack for a validator that doesn't need it.
+/// This validator instead checks policy_outcome for internal self-consistency (e.g.
+/// "evaluated" must be true whenever decision is "call") and leaves live cross-checking
+/// as an explicit open decision for whoever builds the baseline-generation phase: either
+/// extract ToolPolicyEngine into a shared library, or run the cross-check from inside
+/// the main app instead of this standalone tool.
+///
+public static class ToolcallerCaptureValidator
+{
+ public static ToolcallerValidationReport Validate(
+ IReadOnlyList captures,
+ IReadOnlyList frozenTools,
+ string frozenToolSchemaHash)
+ {
+ ArgumentNullException.ThrowIfNull(captures);
+ ArgumentNullException.ThrowIfNull(frozenTools);
+ ArgumentException.ThrowIfNullOrWhiteSpace(frozenToolSchemaHash);
+
+ var toolsByName = frozenTools.ToDictionary(t => t.Name, StringComparer.Ordinal);
+ var findings = new List();
+ var failedIds = new HashSet(StringComparer.Ordinal);
+
+ void Fail(ToolcallerCapture capture, string gate, string detail)
+ {
+ findings.Add(new ValidationFinding(capture.ExampleId, gate, FindingSeverity.Error, detail));
+ failedIds.Add(capture.ExampleId);
+ }
+
+ void Info(ToolcallerCapture capture, string gate, string detail) =>
+ findings.Add(new ValidationFinding(capture.ExampleId, gate, FindingSeverity.Info, detail));
+
+ foreach (var capture in captures)
+ {
+ // Gate: stale schema hash — example was generated against a since-changed
+ // tool inventory and must be regenerated or explicitly re-validated.
+ if (!string.Equals(capture.ToolSchemaHash, frozenToolSchemaHash, StringComparison.Ordinal))
+ {
+ Fail(capture, "stale_tool_schema_hash",
+ $"Capture references hash '{capture.ToolSchemaHash}' but the frozen inventory is " +
+ $"'{frozenToolSchemaHash}'.");
+ }
+
+ // Gate: reason_code required for clarify/unsupported.
+ var needsReasonCode = capture.Expected.Decision is "clarify" or "unsupported";
+ if (needsReasonCode && string.IsNullOrWhiteSpace(capture.Expected.ReasonCode))
+ {
+ Fail(capture, "missing_reason_code",
+ $"Decision '{capture.Expected.Decision}' requires a non-null reason_code.");
+ }
+
+ if (capture.Expected.Decision == "call")
+ {
+ // Gate: call examples must name a tool.
+ if (string.IsNullOrWhiteSpace(capture.Expected.Tool))
+ {
+ Fail(capture, "call_missing_tool", "Decision 'call' requires expected.tool.");
+ }
+ else
+ {
+ // Gate: target tool must exist in the frozen universe.
+ if (!toolsByName.TryGetValue(capture.Expected.Tool, out var tool))
+ {
+ Fail(capture, "tool_outside_frozen_universe",
+ $"expected.tool '{capture.Expected.Tool}' is not in the frozen v0 tool set.");
+ }
+ else
+ {
+ // Gate: target tool must be in this example's own available_tools.
+ if (!capture.AvailableTools.Contains(capture.Expected.Tool, StringComparer.Ordinal))
+ {
+ Fail(capture, "tool_outside_available_tools",
+ $"expected.tool '{capture.Expected.Tool}' is not in this example's available_tools.");
+ }
+
+ // Gate: no invented arguments, no missing required arguments.
+ var arguments = capture.Expected.Arguments ?? new Dictionary();
+ var invented = arguments.Keys.Where(k => !tool.Parameters.ContainsKey(k)).ToArray();
+ if (invented.Length > 0)
+ {
+ Fail(capture, "invented_argument",
+ $"Argument(s) not in {tool.Name}'s frozen schema: {string.Join(", ", invented)}.");
+ }
+
+ var missingRequired = tool.Required.Where(r => !arguments.ContainsKey(r)).ToArray();
+ if (missingRequired.Length > 0)
+ {
+ Fail(capture, "missing_required_argument",
+ $"{tool.Name} requires argument(s) not present: {string.Join(", ", missingRequired)}.");
+ }
+ }
+ }
+
+ // Gate: a proposed call must have policy_outcome evaluated.
+ if (capture.PolicyOutcome is null || !capture.PolicyOutcome.Evaluated)
+ {
+ Fail(capture, "call_missing_policy_outcome",
+ "Decision 'call' requires policy_outcome.evaluated == true.");
+ }
+ }
+ else
+ {
+ // Non-call decisions should not carry an evaluated policy outcome —
+ // there is no proposed call to evaluate against ToolPolicyEngine.
+ if (capture.PolicyOutcome is { Evaluated: true })
+ {
+ Info(capture, "policy_outcome_evaluated_without_call",
+ $"Decision '{capture.Expected.Decision}' has policy_outcome.evaluated == true; " +
+ "expected only for 'call' decisions.");
+ }
+ }
+
+ // Note (not a failure): flag examples touching the two tools ToolPolicyEngine
+ // does not actively evaluate, per docs/TOOLCALLER_V0_FROZEN_INVENTORY.md.
+ if (capture.Expected.Tool is "grep_code" or "ask_user")
+ {
+ if (capture.PolicyOutcome is { PolicyGapTool: false })
+ {
+ Info(capture, "policy_gap_tool_flag_mismatch",
+ $"expected.tool '{capture.Expected.Tool}' has no dedicated ToolPolicyEngine case; " +
+ "policy_outcome.policy_gap_tool should be true.");
+ }
+ }
+ }
+
+ // Gate: every member of a lineage_group_id must share the same split.
+ foreach (var group in captures.GroupBy(c => c.LineageGroupId))
+ {
+ var splits = group.Select(c => c.Split).Distinct(StringComparer.Ordinal).ToArray();
+ if (splits.Length > 1)
+ {
+ foreach (var capture in group)
+ {
+ Fail(capture, "lineage_group_split_conflict",
+ $"lineage_group_id '{group.Key}' spans splits: {string.Join(", ", splits)}.");
+ }
+ }
+ }
+
+ var total = captures.Count;
+ var failed = failedIds.Count;
+ return new ToolcallerValidationReport(
+ SchemaVersion: "toolcaller-v0",
+ GeneratedUtc: DateTimeOffset.UtcNow,
+ FrozenToolSchemaHash: frozenToolSchemaHash,
+ TotalExamples: total,
+ PassedExamples: total - failed,
+ FailedExamples: failed,
+ Findings: findings);
+ }
+}
diff --git a/Tools/ToolcallerBench/ToolcallerContracts.cs b/Tools/ToolcallerBench/ToolcallerContracts.cs
new file mode 100644
index 00000000..6ef80016
--- /dev/null
+++ b/Tools/ToolcallerBench/ToolcallerContracts.cs
@@ -0,0 +1,90 @@
+// Copyright (C) 2025-present hardcoreerik / TheOrc contributors
+// SPDX-License-Identifier: AGPL-3.0-or-later
+using System.Text.Json;
+using System.Text.Json.Serialization;
+
+namespace ToolcallerBench;
+
+///
+/// A single tool's frozen schema, as recorded in
+/// training_pit/schemas/toolcaller_v0_frozen_tools.json. This is a data mirror of the
+/// live ToolDefinition registrations in OrchestratorIDE/Tools/*.cs — see
+/// docs/TOOLCALLER_V0_FROZEN_INVENTORY.md for the verification trail and the hash
+/// this file's canonical form must reproduce.
+///
+public sealed record FrozenTool(
+ string Name,
+ string Description,
+ IReadOnlyDictionary Parameters,
+ IReadOnlyList Required);
+
+public sealed record FrozenToolParameter(string Type, string Description);
+
+///
+/// One toolcaller-v0 dataset example, per training_pit/TOOLCALLER_CAPTURE_SCHEMA.md.
+///
+public sealed record ToolcallerCapture(
+ [property: JsonPropertyName("schema_version")] string SchemaVersion,
+ [property: JsonPropertyName("tool_schema_hash")] string ToolSchemaHash,
+ [property: JsonPropertyName("example_id")] string ExampleId,
+ [property: JsonPropertyName("lineage_group_id")] string LineageGroupId,
+ [property: JsonPropertyName("captured_at")] DateTimeOffset? CapturedAt,
+ [property: JsonPropertyName("provenance")] ToolcallerProvenance Provenance,
+ [property: JsonPropertyName("role")] string Role,
+ [property: JsonPropertyName("request")] string Request,
+ [property: JsonPropertyName("available_tools")] IReadOnlyList AvailableTools,
+ [property: JsonPropertyName("approval_state")] string ApprovalState,
+ [property: JsonPropertyName("expected")] ToolcallerExpected Expected,
+ [property: JsonPropertyName("policy_outcome")] ToolcallerPolicyOutcome? PolicyOutcome,
+ [property: JsonPropertyName("review_status")] string ReviewStatus,
+ [property: JsonPropertyName("reviewer")] string? Reviewer,
+ [property: JsonPropertyName("split")] string Split,
+ [property: JsonPropertyName("notes")] string? Notes,
+ [property: JsonPropertyName("tags")] IReadOnlyList? Tags);
+
+public sealed record ToolcallerProvenance(
+ [property: JsonPropertyName("source_type")] string SourceType,
+ [property: JsonPropertyName("producing_model")] string? ProducingModel,
+ [property: JsonPropertyName("teacher_model")] string? TeacherModel,
+ [property: JsonPropertyName("prompt_or_recipe_id")] string? PromptOrRecipeId,
+ [property: JsonPropertyName("derived_from_example_id")] string? DerivedFromExampleId);
+
+public sealed record ToolcallerExpected(
+ [property: JsonPropertyName("decision")] string Decision,
+ [property: JsonPropertyName("tool")] string? Tool,
+ [property: JsonPropertyName("arguments")] IReadOnlyDictionary? Arguments,
+ [property: JsonPropertyName("reason_code")] string? ReasonCode);
+
+public sealed record ToolcallerPolicyOutcome(
+ [property: JsonPropertyName("evaluated")] bool Evaluated,
+ [property: JsonPropertyName("risk_level")] string? RiskLevel,
+ [property: JsonPropertyName("is_destructive")] bool IsDestructive,
+ [property: JsonPropertyName("touches_outside_workspace")] bool TouchesOutsideWorkspace,
+ [property: JsonPropertyName("network_access")] bool NetworkAccess,
+ [property: JsonPropertyName("block_reason")] string? BlockReason,
+ [property: JsonPropertyName("policy_gap_tool")] bool PolicyGapTool);
+
+public enum FindingSeverity { Error, Info }
+
+/// One admission-gate violation or informational note found in a single capture.
+public sealed record ValidationFinding(
+ string ExampleId,
+ string Gate,
+ FindingSeverity Severity,
+ string Detail);
+
+///
+/// Result of mechanically validating a set of toolcaller captures against the frozen
+/// tool inventory and the admission gates in TOOLCALLER_CAPTURE_SCHEMA.md.
+///
+public sealed record ToolcallerValidationReport(
+ string SchemaVersion,
+ DateTimeOffset GeneratedUtc,
+ string FrozenToolSchemaHash,
+ int TotalExamples,
+ int PassedExamples,
+ int FailedExamples,
+ IReadOnlyList Findings)
+{
+ public bool Passed => FailedExamples == 0 && TotalExamples > 0;
+}
diff --git a/Tools/ToolcallerBench/ToolcallerReportWriter.cs b/Tools/ToolcallerBench/ToolcallerReportWriter.cs
new file mode 100644
index 00000000..75f0f211
--- /dev/null
+++ b/Tools/ToolcallerBench/ToolcallerReportWriter.cs
@@ -0,0 +1,90 @@
+// Copyright (C) 2025-present hardcoreerik / TheOrc contributors
+// SPDX-License-Identifier: AGPL-3.0-or-later
+using System.Text;
+using System.Text.Json;
+
+namespace ToolcallerBench;
+
+public static class ToolcallerReportWriter
+{
+ private static readonly JsonSerializerOptions _json = new()
+ {
+ WriteIndented = true,
+ PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower,
+ };
+
+ public static async Task<(string JsonPath, string MarkdownPath)> WriteAsync(
+ ToolcallerValidationReport report,
+ string outputDirectory,
+ CancellationToken ct = default)
+ {
+ ArgumentNullException.ThrowIfNull(report);
+ if (string.IsNullOrWhiteSpace(outputDirectory))
+ throw new ArgumentException("Output directory is required.", nameof(outputDirectory));
+
+ var root = Path.GetFullPath(outputDirectory);
+ Directory.CreateDirectory(root);
+ var stamp = $"{DateTime.UtcNow:yyyyMMdd_HHmmss_fff}_{Guid.NewGuid():N}";
+ var jsonPath = Path.Combine(root, $"toolcaller_validate_{stamp}.json");
+ var markdownPath = Path.Combine(root, $"toolcaller_validate_{stamp}.md");
+
+ await File.WriteAllTextAsync(jsonPath, JsonSerializer.Serialize(report, _json), ct).ConfigureAwait(false);
+ await File.WriteAllTextAsync(markdownPath, BuildMarkdown(report), ct).ConfigureAwait(false);
+ return (jsonPath, markdownPath);
+ }
+
+ public static string BuildMarkdown(ToolcallerValidationReport report)
+ {
+ ArgumentNullException.ThrowIfNull(report);
+ var sb = new StringBuilder();
+ sb.AppendLine("# Toolcaller v0 — Mechanical Validation Report");
+ sb.AppendLine();
+ sb.AppendLine($"> Verdict: **{(report.Passed ? "PASS" : "FAIL")}**");
+ sb.AppendLine($"> Schema version: `{report.SchemaVersion}`");
+ sb.AppendLine($"> Frozen tool schema hash: `{report.FrozenToolSchemaHash}`");
+ sb.AppendLine($"> Generated: {report.GeneratedUtc:O}");
+ sb.AppendLine();
+ sb.AppendLine("## Summary");
+ sb.AppendLine();
+ sb.AppendLine("| Metric | Result |");
+ sb.AppendLine("|---|---:|");
+ sb.AppendLine($"| Total examples | {report.TotalExamples} |");
+ sb.AppendLine($"| Passed | {report.PassedExamples} |");
+ sb.AppendLine($"| Failed | {report.FailedExamples} |");
+ sb.AppendLine();
+
+ sb.AppendLine("## Coverage Note");
+ sb.AppendLine();
+ sb.AppendLine("This validator does not mechanically check two gates from " +
+ "`training_pit/TOOLCALLER_CAPTURE_SCHEMA.md`: (1) whether `approval_state` " +
+ "implies a call was already executed/approved by the model — this needs " +
+ "reviewer judgment, not a keyword heuristic; (2) live cross-verification of " +
+ "`policy_outcome` against a fresh `ToolPolicyEngine.Evaluate()` call — " +
+ "`ToolPolicyEngine.cs` is only compiled into `OrchestratorIDE.Avalonia.csproj` " +
+ "today, and this tool intentionally does not pull in that dependency. Only " +
+ "self-consistency of `policy_outcome` (e.g. `evaluated` must be true for " +
+ "`call` decisions) is checked here.");
+ sb.AppendLine();
+
+ if (report.Findings.Count > 0)
+ {
+ sb.AppendLine("## Findings");
+ sb.AppendLine();
+ sb.AppendLine("| Example | Gate | Severity | Detail |");
+ sb.AppendLine("|---|---|---|---|");
+ foreach (var finding in report.Findings)
+ {
+ sb.AppendLine($"| `{Escape(finding.ExampleId)}` | `{Escape(finding.Gate)}` | " +
+ $"{finding.Severity} | {Escape(finding.Detail)} |");
+ }
+ sb.AppendLine();
+ }
+
+ return sb.ToString();
+ }
+
+ private static string Escape(string value) => value
+ .Replace("|", "\\|", StringComparison.Ordinal)
+ .Replace("\r", " ", StringComparison.Ordinal)
+ .Replace("\n", " ", StringComparison.Ordinal);
+}
diff --git a/docs/CONTEXT_FABRIC_BENCHMARK_MANIFEST.md b/docs/CONTEXT_FABRIC_BENCHMARK_MANIFEST.md
index d56a62ff..8a899c41 100644
--- a/docs/CONTEXT_FABRIC_BENCHMARK_MANIFEST.md
+++ b/docs/CONTEXT_FABRIC_BENCHMARK_MANIFEST.md
@@ -100,3 +100,11 @@ Required top-level fields:
The `systems` array must include B0 through B4. Missing artifacts are explicit `Missing` entries, not omitted rows. This keeps the evaluator fail-closed until closed-book, truncated-prompt, top-k RAG, single-node Context Fabric, and HIVE Context Fabric runs are all present.
The initial CF-7 slice may emit a `NO-GO` report with only B3 plus diagnostics populated. That is valid progress: it freezes the report shape and prevents partial benchmark evidence from being mistaken for an architecture pass.
+
+### Re-Running The Expanded 120-Question Gate
+
+[`Tools/ContextFabricBench/Run-CF7GateExpanded.ps1`](../Tools/ContextFabricBench/Run-CF7GateExpanded.ps1)
+is the canonical recipe for re-running the `cf7-gate-expanded` suite (128-segment
+un-marked corpus, 120 held-out questions) on any machine. It auto-locates the frozen B4
+artifact, validates prerequisites, builds from source, and prints a GO/NO-GO summary.
+Use `-MaxQuestions 3` for a quick smoke test before committing GPU time to a full run.
diff --git a/docs/README.md b/docs/README.md
index 61e67867..e1fe8f4c 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -72,6 +72,10 @@ adversarial-review context and may contain deeper implementation notes.
quarantine, and rollback policy
- [THEORC_TOOLCALLER_V0.md](THEORC_TOOLCALLER_V0.md) — documentation-only contract for the first
proposed Foundry proof model
+- [TOOLCALLER_V0_FROZEN_INVENTORY.md](TOOLCALLER_V0_FROZEN_INVENTORY.md) — F-1: the toolcaller-v0
+ tool universe, verified against live code and frozen with a checked-in schema hash
+- [`../training_pit/TOOLCALLER_CAPTURE_SCHEMA.md`](../training_pit/TOOLCALLER_CAPTURE_SCHEMA.md) —
+ F-1: the dataset capture schema and mechanical admission gates for toolcaller-v0 examples
---
diff --git a/docs/THEORC_WARPATH_GAMIFICATION_WHITEPAPER.md b/docs/THEORC_WARPATH_GAMIFICATION_WHITEPAPER.md
new file mode 100644
index 00000000..773b80f1
--- /dev/null
+++ b/docs/THEORC_WARPATH_GAMIFICATION_WHITEPAPER.md
@@ -0,0 +1,1751 @@
+# TheOrc Warpath — Gamification, Scoring, Badges, and Bragging Rights White Paper
+
+> **Status:** Proposed product/design specification.
+> **Target project:** `hardcoreerik/TheOrc`
+> **Target implementation style:** Small, safe, event-driven, local-first, SQLite-backed, no cloud dependency.
+> **Audience:** TheOrc maintainer, AI coding agents, implementation reviewers, product/design contributors.
+> **Primary goal:** Add a meaningful gamification layer that rewards real engineering discipline: clean runs, safe approvals, useful reviews, strong datasets, local-first execution, HIVE/Warband reliability, Context Fabric evidence quality, and measurable model improvement.
+
+---
+
+## 0. Executive Summary
+
+TheOrc already has the bones of a game system: a boss, goblin worker lanes, HIVE nodes, Warbands, Warchief leadership, approval gates, reviewer verdicts, Training Pit captures, ORC ACADEMY adapters, Context Fabric evidence runs, model capability probing, and long-running local infrastructure. The proposed **Warpath** system turns those real product behaviors into scores, badges, trophies, ranks, streaks, and shareable bragging-rights artifacts.
+
+This must not become fake dopamine pasted over a coding tool. The Warpath is not about rewarding raw activity, token spam, shell command count, line count, or fastest approval clicking. It is about making the operator visibly better at the behaviors TheOrc already values:
+
+- safe execution
+- inspectable local automation
+- clean swarm role discipline
+- useful testing and review
+- dataset hygiene
+- source-grounded evidence
+- local model capability discovery
+- HIVE and Warband reliability
+- successful rollback-ready improvements
+- measurable model and workflow wins
+
+The product fantasy is simple:
+
+> **Run the Warband. Improve the Tribe. Prove it locally.**
+
+The user should be able to say:
+
+> **My local AI warband passed 100 clean gated runs, trained its own boss, ran across 3 machines, and processed a million-token source corpus without sending my code to the cloud.**
+
+That is real bragging-rights energy. It is also aligned with TheOrc's product truth.
+
+---
+
+## 1. Repository-Grounded Product Context
+
+This design is grounded in the current public project shape of TheOrc, not in a generic gamification template.
+
+The live repository positions TheOrc as a local-first AI orchestration shell with an Avalonia desktop operator surface, local chat and swarm execution, native-runtime and Ollama-backed model paths, HIVE MIND for distributed local work, ORC ACADEMY for training a better boss model, and Context Fabric for source-grounded memory across corpora larger than a model context window.
+
+The README also emphasizes that TheOrc is built around inspectability, approval gates, local ownership, and source reopening instead of magic-context marketing. The Warpath system must reinforce those values instead of diluting them.
+
+The current roadmap establishes several shipped and partially shipped foundations relevant to Warpath:
+
+- Swarm runtime has RESEARCHER, CODER, UIDEVELOPER, and TESTER lanes.
+- TESTER is intentionally read-only.
+- Swarm Board already has capability badges and per-configuration metrics history.
+- Tool calls already flow through approval-aware handlers.
+- Training Pit already captures, reviews, validates, sanitizes, and exports training data.
+- ORC ACADEMY already produced a production boss adapter and has recorded cases where lower eval loss did not mean better behavior.
+- HIVE MIND and Warbands already provide distributed local execution concepts.
+- Reviewer Quality Gate already has Clean, Minor, and Blocker verdict concepts, but true blocking still needs hardening.
+- Context Fabric has become a major product surface centered on source-grounded evidence and citation/reopening behavior.
+
+The Warpath should therefore be implemented as a **thin event and scoring layer over existing product truth**, not as a separate fantasy system that invents its own reality.
+
+---
+
+## 2. Core Principle
+
+### 2.1 The One Rule
+
+> **Reward quality, safety, learning, and capability. Do not reward spam.**
+
+> **Warpath rewards proof, not activity. It observes verified outcomes only and must not create incentives to train, promote, approve, override, or merge prematurely.**
+
+Warpath scoring must prefer fewer, safer, cleaner, more useful actions over noisy activity. TheOrc is already an automation product. A bad scoring system would accidentally train users and agents to maximize junk output. That would actively harm the project.
+
+### 2.2 Reward These Behaviors
+
+Warpath should reward:
+
+- valid structured plans
+- correct role assignment
+- no role-permission violations
+- TESTER staying read-only
+- useful researcher output
+- tests that actually run
+- reviewer findings that prevent bad output
+- BLOCKER rework that later passes
+- user approvals that happen through proper approval surfaces
+- verified dataset admission
+- valid candidate rejection under a frozen evaluation
+- model probes that improve routing knowledge
+- HIVE node recovery
+- Warband task completion
+- source-grounded answers with verified citations
+- local-only successful runs
+- adapters or candidates that beat baselines under declared evaluation
+- rollbacks handled cleanly
+
+### 2.3 Do Not Reward These Behaviors
+
+Warpath must not reward:
+
+- raw line count
+- raw file count
+- raw shell command count
+- raw model call count
+- raw token usage
+- fastest approval clicking
+- number of unreviewed captures
+- number of generated synthetic examples without independent gates
+- overriding BLOCKERs
+- using a bigger model when a smaller one works
+- bypassing deterministic safety policy
+- noisy chat verbosity
+- repeatedly probing the same model just to farm points
+
+### 2.4 Negative Score Is Allowed, But Should Be Used Carefully
+
+A scoring system that only adds points becomes fake. A scoring system that punishes experimentation becomes oppressive. The balance:
+
+- Unsafe or quality-corrupting behavior can subtract points.
+- Honest failed experiments should not be heavily punished.
+- Rejected bad captures can be recorded as audit milestones, but positive score
+ begins only when the resulting dataset passes admission.
+- BLOCKER findings should be treated as useful if they prevent unsafe apply.
+- BLOCKER overrides should be recorded, visible, and lightly penalized, but not treated as moral failure. Sometimes the operator knows more than the reviewer.
+
+---
+
+## 3. Naming and Product Surface
+
+### 3.1 Recommended Names
+
+| Concept | Recommended Name | Purpose |
+|---|---|---|
+| Overall gamification system | **The Warpath** | The full progression/scoring layer |
+| Profile/stat page | **Tribe Ledger** | Persistent operator/project stats |
+| Achievement wall | **Hall of Skulls** | Badges and trophies |
+| Run scorecard | **Battle Report** | Per-run scoring summary |
+| Project dashboard | **Campaign Map** | Per-workspace progress |
+| Model capability collection | **Bestiary** | Model mastery and probe history |
+| Training Pit achievements | **Forge Marks** | Dataset/training accomplishments |
+| HIVE/Warband achievements | **Crown Deeds** | Distributed execution accomplishments |
+| Reviewer achievements | **Trial Marks** | Gate/reviewer accomplishments |
+| Safety score | **Honor Guard** | Approval and safety-discipline score |
+| Rare trophies | **War Trophies** | High-value bragging rights |
+
+### 3.2 Tone Guidance
+
+The tone should be fun but still professional enough for a serious development tool.
+
+Good tone:
+
+- “The Gate Holds”
+- “No Poison in the Pit”
+- “Clean Bloodline”
+- “Many Hands, One Axe”
+- “Loss Is A Liar”
+- “Local Legend”
+
+Avoid tone that implies unsafe behavior is cool:
+
+- Do not glamorize bypassing approvals.
+- Do not celebrate ignoring BLOCKERs.
+- Do not use language that makes security review feel optional.
+
+### 3.3 Product Promise
+
+Warpath is not a game mode. It is a visible mastery system for TheOrc operators.
+
+Suggested product copy:
+
+> **The Warpath tracks how your local AI tribe improves: clean runs, safer gates, sharper goblins, stronger datasets, better model evidence, and bigger HIVE capability. It rewards proof, not noise.**
+
+---
+
+## 4. User Stories
+
+### 4.1 New User
+
+As a new user, I want to see simple early achievements so I understand the safe workflow.
+
+Examples:
+
+- Open first workspace.
+- Run first read-only task.
+- Approve first safe command.
+- Complete first Swarm run.
+- Open first Battle Report.
+
+Acceptance criteria:
+
+- The user learns correct workflow from badges.
+- No badge encourages bypassing approval.
+- No badge requires cloud services.
+
+### 4.2 Power User
+
+As a power user, I want bragging rights for disciplined local automation.
+
+Examples:
+
+- 100 local-only runs.
+- 25 clean Reviewer Gate results in a row.
+- All active models probed and current.
+- HIVE node recovery works after worker loss.
+- Training dataset passes sanitizer and preflight.
+
+Acceptance criteria:
+
+- Achievements map to real product events.
+- Share exports do not leak private code.
+- Streaks survive app restart.
+
+### 4.3 Maintainer
+
+As the maintainer, I want Warpath to expose quality trends and weak spots.
+
+Examples:
+
+- Which goblin lane causes most penalties?
+- How often does TESTER provide meaningful verification?
+- How often are BLOCKERs overridden?
+- Which models produce the cleanest run scores?
+- Which workspaces have the highest/lowest safety score?
+
+Acceptance criteria:
+
+- Scoring data is local.
+- Metrics can be exported.
+- A bad score helps diagnose the system instead of just shaming the user.
+
+### 4.4 AI Coding Agent
+
+As an AI coding agent implementing this feature, I need explicit rules, schema, triggers, and phased tasks so I do not invent unsafe behavior.
+
+Acceptance criteria:
+
+- Implementation instructions are deterministic.
+- Event names are defined.
+- Point values are defined.
+- Data storage is defined.
+- UI surface is defined.
+- Non-goals are defined.
+
+---
+
+## 5. System Overview
+
+### 5.1 Architecture Summary
+
+Warpath should be implemented as an event-driven scoring layer.
+
+Recommended core pieces:
+
+```text
+Existing TheOrc feature emits event
+ │
+ ▼
+WarpathEventService records event
+ │
+ ▼
+WarpathScoringService updates score projections
+ │
+ ▼
+WarpathBadgeService evaluates badge unlocks
+ │
+ ▼
+WarpathProfileRepository persists profile, badges, trophies, streaks
+ │
+ ▼
+UI surfaces show Battle Report, Tribe Ledger, Hall of Skulls, Campaign Map
+```
+
+### 5.2 Implementation Rules
+
+1. Warpath must not directly execute tools.
+2. Warpath must not modify approval policy.
+3. Warpath must not replace Reviewer Gate, ToolPolicyEngine, Training Pit validators, or Foundry/Arena policies.
+4. Warpath only records and scores events that other systems already produce.
+5. Warpath must be local-first.
+6. Warpath must not upload score data anywhere by default.
+7. Share cards must be explicit user-generated exports.
+8. Share exports must avoid private paths, prompts, code snippets, secrets, or source content.
+9. Warpath scoring must be reproducible from recorded events.
+10. All badge unlocks must be auditable by event history.
+11. Warpath may consume verified events from Foundry, Arena, Training Pit,
+ Reviewer Gate, HIVE, Swarm, and Context Fabric, but Warpath events, scores,
+ ranks, badges, streaks, and trophies must never become inputs to promotion,
+ approval, evaluation, dataset admission, rollback, override, or merge decisions.
+
+### 5.3 Recommended Storage
+
+Use existing SQLite infrastructure if available. If SQLite integration is too expensive for the first pass, use local JSON files as an MVP, but design names so a SQLite migration is straightforward.
+
+Recommended local paths:
+
+```text
+.orc/warpath/profile.json
+.orc/warpath/events.jsonl
+.orc/warpath/badges.json
+.orc/warpath/trophies.md
+.orc/warpath/share-card.json
+.orc/warpath/share-card.md
+```
+
+Recommended later SQLite tables:
+
+```sql
+warpath_events
+warpath_profile
+warpath_badges
+warpath_badge_unlocks
+warpath_trophies
+warpath_run_scores
+warpath_streaks
+warpath_exports
+```
+
+---
+
+## 6. Data Model
+
+### 6.1 Warpath Event
+
+A Warpath event is an immutable record of something that happened.
+
+```json
+{
+ "event_id": "wp_evt_20260703_183012_0001",
+ "schema_version": "warpath-event-v1",
+ "occurred_at": "2026-07-03T18:30:12-07:00",
+ "workspace_id": "sha256-of-normalized-workspace-root-or-null",
+ "run_id": "optional-swarm-or-chat-run-id",
+ "event_type": "swarm.run.completed",
+ "source_system": "SwarmSession",
+ "actor": "system",
+ "role": "CODER",
+ "model": "qwen2.5-coder:14b",
+ "node_id": "optional-hive-node-id",
+ "payload": {
+ "success": true,
+ "files_changed": 3,
+ "tests_passed": true,
+ "review_verdict": "CLEAN"
+ },
+ "privacy": {
+ "contains_user_content": false,
+ "safe_for_share_card": true
+ }
+}
+```
+
+### 6.2 Required Event Fields
+
+| Field | Required | Meaning |
+|---|---:|---|
+| `event_id` | yes | Stable unique event id |
+| `schema_version` | yes | Must be `warpath-event-v1` for first release |
+| `occurred_at` | yes | Local timestamp with timezone or UTC |
+| `workspace_id` | no | Stable hash, not raw local path |
+| `run_id` | no | Existing run/session id if available |
+| `event_type` | yes | Namespaced event type |
+| `source_system` | yes | System that emitted event |
+| `actor` | yes | `system`, `user`, `agent`, `hive-node`, etc. |
+| `role` | no | Swarm role if applicable |
+| `model` | no | Model id if applicable |
+| `node_id` | no | HIVE node id if applicable |
+| `payload` | yes | Event-specific JSON |
+| `privacy` | yes | Share/export safety hints |
+
+### 6.3 Event Type Naming Convention
+
+Use dotted namespaces.
+
+Examples:
+
+```text
+app.workspace.opened
+agent.plan.generated
+agent.tool_call.proposed
+approval.shell.approved
+approval.file_write.approved
+approval.blocked
+swarm.run.started
+swarm.run.completed
+swarm.role.violation
+swarm.tester.write_attempt
+review.verdict.clean
+review.verdict.minor
+review.verdict.blocker
+review.blocker.override
+review.blocker.reworked_clean
+training.capture.staged
+training.capture.accepted
+training.capture.rejected
+training.preflight.passed
+training.preflight.failed
+academy.training.started
+academy.training.completed
+academy.adapter.evaluated
+academy.adapter.promoted
+academy.adapter.rejected
+model.probe.started
+model.probe.completed
+model.capability.changed
+hive.enabled
+hive.node.paired
+hive.node.offline
+hive.node.recovered
+hive.warchief.elected
+warband.connected
+warband.task.completed
+fabric.corpus.attached
+fabric.answer.cited
+fabric.answer.verified
+fabric.exhaustive.passed
+foundry.baseline.reported
+foundry.candidate.evaluated
+foundry.candidate.promoted
+foundry.candidate.quarantined
+```
+
+### 6.4 Warpath Profile
+
+```json
+{
+ "schema_version": "warpath-profile-v1",
+ "operator_name": "local-user-or-null",
+ "rank": "Swarm Tamer",
+ "total_score": 1840,
+ "category_scores": {
+ "swarm_discipline": 320,
+ "quality_gate": 210,
+ "forge_progress": 140,
+ "hive_power": 100,
+ "model_mastery": 260,
+ "campaign_wins": 310,
+ "safety_honor": 420,
+ "fabric_evidence": 80,
+ "foundry_proof": 0
+ },
+ "streaks": {
+ "clean_gate": 4,
+ "local_only": 12,
+ "safe_approval": 22,
+ "forge_purity": 2
+ },
+ "badges_unlocked": [
+ "first_blood",
+ "trial_passed",
+ "beastmaster"
+ ],
+ "trophies_unlocked": [],
+ "last_updated": "2026-07-03T18:30:12-07:00"
+}
+```
+
+---
+
+## 7. Score Categories
+
+### 7.1 Category Summary
+
+| Category | Recommended Max for Initial Display | Meaning |
+|---|---:|---|
+| Swarm Discipline | 1,500 | Role correctness, useful lane output, no permission violations |
+| Quality Gate | 1,500 | Reviewer Gate outcomes and rework discipline |
+| Forge Progress | 1,500 | Verified dataset admission and candidate evaluation outcomes |
+| HIVE Power | 1,000 | Node pairing, Warband task completion, recovery, authenticated mesh behavior |
+| Model Mastery | 1,000 | Model probes, capability freshness, correct model-role fit |
+| Campaign Wins | 1,000 | Completed project runs and applied outputs |
+| Safety Honor | 1,000 | Approval flow discipline, blocked risky operations, no bypasses |
+| Fabric Evidence | 1,000 | Context Fabric citation precision, verified answers, exhaustive evidence tasks |
+| Foundry Proof | 1,000 | Baselines, candidate evaluation, promotion, quarantine/rollback discipline |
+
+Initial visible total: **10,500** soft cap. The profile can continue beyond the cap, but the category cap gives users a readable mastery map.
+
+### 7.2 Why Include Fabric Evidence
+
+Current TheOrc heavily emphasizes Context Fabric as a source-grounded memory layer. Warpath would be incomplete if it ignored evidence quality. Context Fabric achievements should reward verified citations, source reopening, exhaustive recall, correct abstention, and source-to-working-context leverage.
+
+### 7.3 Why Include Foundry Proof
+
+Foundry should not become “I trained a thing, give me points.” Foundry scoring must reward baseline reports, sealed evals, reproducible manifests, no safety regression, successful deployed-artifact verification, rollback readiness, and honest rejection when the candidate fails.
+
+---
+
+## 8. Rank Ladder
+
+Ranks are profile-level titles. They should be fun, but not so goofy that they cheapen the product.
+
+| Rank | Requirement |
+|---|---|
+| Mud Goblin | App launched and Warpath profile created |
+| Camp Hand | First workspace opened |
+| Tool Grunt | First approved tool call |
+| Blooded Coder | First successful file write approved through diff flow |
+| Swarm Tamer | First successful Swarm run |
+| Pit Keeper | First dataset package passes declared admission gates |
+| Gatebreaker | First BLOCKER resolved and rerun CLEAN |
+| Warchief | First HIVE node paired or local node elected Warchief |
+| Warband Captain | First headless Warband task completed |
+| Forge Master | First candidate receives a valid baseline comparison decision |
+| Iron Warchief | 50 clean gated runs |
+| Mythic Warchief | Foundry candidate beats baseline under frozen evaluation |
+| Local Legend | 100 successful local-only runs |
+
+### 8.1 Rank Evaluation Rule
+
+Ranks are not bought with points alone. Each rank has explicit event requirements. This prevents users from farming low-value actions to obtain high-value titles.
+
+### 8.2 Rank Downgrade Rule
+
+Do not downgrade rank automatically. Once earned, ranks remain. However, active profile panels may show warnings such as:
+
+```text
+Iron Warchief — current safety streak broken by recent BLOCKER override.
+```
+
+---
+
+## 9. Run-Level Battle Report
+
+Every completed meaningful run should produce a Battle Report.
+
+### 9.1 Battle Report Example
+
+```text
+Battle Report — Swarm Run 2026-07-03 18:30
+
+Run Score: 87 / 100
+Verdict: CLEAN
+Rank Progress: +42 Warpath XP
+
+Positive:
++10 valid boss plan
++10 correct role assignments
++10 expected files named
++10 no role permission violations
++10 useful researcher output
++15 coder/UI produced expected files
++10 tester ran meaningful verification
++10 tests passed
++15 reviewer CLEAN
++10 all risky actions approved through proper gates
++10 dataset admission passed
+
+Negative:
+-3 stale model probe on UIDEVELOPER model
+-10 tester verification was shallow
+
+Badges unlocked:
+- Trial Passed
+- Hammer Goblin
+```
+
+### 9.2 Run Score Formula
+
+| Component | Points |
+|---|---:|
+| Boss produced valid structured plan | +10 |
+| Correct roles assigned | +10 |
+| Expected files named | +10 |
+| No role permission violations | +10 |
+| Researcher output useful | +10 |
+| Coder/UI produced expected files | +15 |
+| Tester ran meaningful verification | +10 |
+| Tests pass | +10 |
+| Reviewer CLEAN | +15 |
+| Reviewer MINOR | +7 |
+| Reviewer BLOCKER found before apply | +5 |
+| Rework resolves BLOCKER | +15 |
+| Dataset admission passed | +10 |
+| All risky actions approved properly | +10 |
+| Context Fabric citations verified, when applicable | +10 |
+| Local-only stack used successfully | +5 |
+
+### 9.3 Run Penalties
+
+| Problem | Points |
+|---|---:|
+| TESTER tries to write | -25 |
+| Boss assigns wrong lane | -15 |
+| Invented file path/API | -15 |
+| Tool call malformed beyond repair | -10 |
+| BLOCKER overridden | -20 |
+| Risky action bypass attempted | -30 |
+| Unreviewed synthetic data admitted | -50 |
+| Train/eval leakage discovered | -100 and quarantine flag |
+| Source citation cannot be reopened/verified | -15 |
+
+### 9.4 Score Bounds
+
+- Minimum run score: 0.
+- Maximum displayed run score: 100.
+- Bonus points beyond 100 may feed long-term Warpath Score, but the Battle Report should cap at 100 for readability.
+
+---
+
+## 10. Badge System
+
+### 10.1 Badge Definition Schema
+
+```json
+{
+ "badge_id": "trial_passed",
+ "schema_version": "warpath-badge-v1",
+ "name": "Trial Passed",
+ "family": "reviewer_gate",
+ "tier": "common",
+ "description": "A run received a CLEAN Reviewer Gate verdict.",
+ "unlock_rule": {
+ "type": "event_count",
+ "event_type": "review.verdict.clean",
+ "count": 1
+ },
+ "score_award": 25,
+ "share_safe": true
+}
+```
+
+### 10.2 Badge Families
+
+| Family | Purpose |
+|---|---|
+| Swarm Badges | Role discipline and successful multi-lane work |
+| Reviewer Gate Badges | Clean review, BLOCKER handling, rework |
+| Forge Badges | Training Pit, ORC ACADEMY, dataset safety |
+| HIVE/Warband Badges | Distributed local execution and node health |
+| Model Mastery Badges | Capability probing and model-role fit |
+| Context Fabric Badges | Source-grounded evidence and citation quality |
+| Foundry Badges | Baselines, candidate eval, promotion/quarantine |
+| Safety Badges | Approval discipline and blocked risky behavior |
+
+### 10.3 Badge Rarity Tiers
+
+| Tier | Meaning | Suggested Visual |
+|---|---|---|
+| Bone | Common first steps | gray/white |
+| Iron | Uncommon competency | steel |
+| Blood | Rare hard-won achievement | red |
+| Warpaint | Epic system mastery | purple |
+| Gold Crown | Legendary proof | gold |
+| Black Anvil | Mythic evidence-backed milestone | black/neon green |
+
+### 10.4 Starter Badge List
+
+#### Swarm Badges
+
+| Badge | Tier | Trigger |
+|---|---|---|
+| First Blood | Bone | First successful Swarm run |
+| Boss Brain | Iron | Boss produces valid plan with correct roles and expected files |
+| Many Hands, One Axe | Blood | Boss, Researcher, Coder, UI, and Tester all complete useful work in one run |
+| Stay In Your Lane | Blood | 25 runs with no role-permission violations |
+| No Tester With A Crayon | Gold Crown | 100 runs with TESTER never attempting write behavior |
+| Hammer Goblin | Iron | Coder produces files that pass tests on first try |
+| Pixel Shaman | Iron | UIDEVELOPER completes UI task with no layout/test issue |
+| Truth Goblin | Blood | Tester catches a real issue before apply |
+| Perfect Warpath | Gold Crown | Valid plan, useful lanes, tests pass, reviewer CLEAN |
+
+#### Reviewer Gate Badges
+
+| Badge | Tier | Trigger |
+|---|---|---|
+| Trial Passed | Bone | Reviewer verdict CLEAN |
+| Scarred But Worthy | Bone | Reviewer verdict MINOR accepted |
+| The Gate Holds | Iron | BLOCKER prevents apply |
+| Back To The Pit | Iron | BLOCKER result sent back for rework |
+| Redeemed In Battle | Blood | Previously BLOCKED run reruns CLEAN |
+| No Cowardly Merge | Blood | 25 runs without overriding BLOCKER |
+| Blood Oath Override | Iron, audit-flavored | User explicitly overrides BLOCKER |
+| The Judge Nods | Blood | 10 CLEAN reviews in a row |
+| Tribunal Standard | Gold Crown | 100 reviewed diffs with recorded verdicts |
+
+Important: **Blood Oath Override must not award positive score.** It is a visible audit badge, not a reward. It should be shown differently from positive badges.
+
+#### Forge Badges
+
+Capture counts and training lifecycle badges are audit milestones only. They may
+be displayed, but they award zero score. Positive Forge/Foundry score begins only
+with verified evidence: baseline completion, dataset admission, valid candidate
+rejection, deployed-artifact proof, rollback-ready promotion, or Arena-confirmed
+improvement.
+
+| Badge | Tier | Trigger |
+|---|---|---|
+| Ore Collector | Audit | 25 captures staged; 0 points |
+| Ore Sorter | Audit | 25 captures reviewed; 0 points |
+| Cursed Ore Rejected | Audit | 50 bad captures rejected; 0 points |
+| No Poison In The Pit | Blood | Dataset passes its declared admission gates |
+| Gold Tooth Goblin | Audit | 100 gold-quality examples approved; 0 points |
+| Forge Lit | Audit | First training run started; 0 points |
+| Blade Tempered | Audit | First training run completed; 0 points |
+| Sharper Than Base | Gold Crown | Arena confirms candidate improvement over declared baseline |
+| Loss Is A Liar | Gold Crown | Lower eval loss rejected because rubric/eval failed |
+| Clean Bloodline | Gold Crown | No train/eval leakage detected in a full candidate package |
+| Not Worth The Hammer | Blood | Training loses to deterministic baseline and is correctly rejected |
+
+#### HIVE and Warband Badges
+
+| Badge | Tier | Trigger |
+|---|---|---|
+| Campfire Lit | Bone | HIVE enabled |
+| First Ally | Bone | First node paired |
+| Crowned | Iron | Local machine elected Warchief |
+| Crown Transfer | Blood | Warchief election succeeds after node loss |
+| Three Fires Burning | Blood | 3 nodes online |
+| Warband Deployed | Blood | First headless Warband connected |
+| Cloud Raider | Blood | First cloud Warband completes a task |
+| Fleet Commander | Gold Crown | 5+ nodes paired |
+| Dead Node Recovery | Gold Crown | Task requeued after worker loss and completed |
+| Signed And Sealed | Iron | Authenticated HIVE traffic confirmed |
+| No Rogue Goblins | Gold Crown | 100 signed HIVE requests accepted, 0 unsigned accepted |
+
+#### Model Mastery Badges
+
+| Badge | Tier | Trigger |
+|---|---|---|
+| Beastmaster | Bone | First model probed |
+| Know Your Goblin | Iron | All active models probed |
+| Fresh Maps | Iron | All active models probed within 7 days |
+| Right Tool, Right Goblin | Blood | Model selected matches role capability requirements |
+| Tiny But Mean | Blood | Smaller model beats larger model on bounded task |
+| JSON Whisperer | Iron | Model passes structured-output probe |
+| Schema Crusher | Blood | Model passes complex schema probe |
+| Hallucination Hunter | Blood | Model flagged for bad tool behavior and avoided |
+| Local Legend | Gold Crown | Full successful run with local-only model stack |
+
+#### Context Fabric Badges
+
+| Badge | Tier | Trigger |
+|---|---|---|
+| Library Goblin | Bone | First corpus attached |
+| Citation Fang | Iron | First answer with verified citation |
+| Source Reopened | Iron | Citation opens original source successfully |
+| No Bluffing | Blood | Answer abstains correctly when evidence is insufficient |
+| Thread Finder | Blood | Multi-hop answer verified from multiple source ranges |
+| Exhaustive Hunter | Gold Crown | Exhaustive evidence enumeration passes declared gate |
+| Million Token Marauder | Gold Crown | Large deterministic corpus processed unattended with verified results |
+| Fabric Warchief | Black Anvil | HIVE Context Fabric run passes worker-loss/recovery acceptance |
+
+#### Foundry Badges
+
+| Badge | Tier | Trigger |
+|---|---|---|
+| Baseline Before Blade | Iron | Baseline report completed before training |
+| Arena Entered | Iron | Candidate enters declared evaluation |
+| Arena Champion | Black Anvil | Candidate beats production baseline under frozen eval |
+| Quarantine Keeper | Blood | Unsafe/corrupt candidate quarantined correctly |
+| Rollback Ready | Blood | Promotion includes valid rollback target |
+| No False Crown | Gold Crown | Candidate rejected because it failed to beat baseline |
+
+---
+
+## 11. Trophy System
+
+Badges are frequent. Trophies are rare.
+
+### 11.1 Trophy Examples
+
+| Trophy | Requirement |
+|---|---|
+| The Golden Axe | 25 CLEAN gated runs in a row |
+| The Iron Crown | 5 HIVE nodes online and healthy |
+| The Black Anvil | Adapter/candidate beats baseline and passes deployed-artifact eval |
+| The Bone Ledger | 1,000 reviewed captures |
+| The No-Cloud Banner | 100 successful local-only runs |
+| The Perfect Warpath | Swarm run: valid plan, all lanes useful, tests pass, reviewer CLEAN |
+| The Dragon Skull | Major multi-file feature completed with zero BLOCKERs |
+| The Anti-Spam Totem | High success rate with low token/tool-call waste |
+| The Arena Champion | Foundry candidate beats production baseline under frozen eval |
+| The Goblin HR Award | 100 role-safe runs with no permission violations |
+
+### 11.2 Trophy Definition Schema
+
+```json
+{
+ "trophy_id": "the_black_anvil",
+ "schema_version": "warpath-trophy-v1",
+ "name": "The Black Anvil",
+ "tier": "mythic",
+ "description": "A candidate beat the current baseline under frozen evaluation and passed deployed-artifact verification.",
+ "requirements": [
+ { "event_type": "foundry.candidate.evaluated", "payload_match": { "beats_baseline": true } },
+ { "event_type": "foundry.candidate.deployed_artifact_verified", "payload_match": { "passed": true } }
+ ],
+ "share_safe": true
+}
+```
+
+---
+
+## 12. Streaks
+
+Streaks should be visible and motivating, but should not punish experimentation too harshly.
+
+| Streak | Meaning | Break Condition |
+|---|---|---|
+| Clean Gate Streak | Consecutive CLEAN reviewer results | MINOR or BLOCKER |
+| Local-Only Streak | Consecutive successful runs using local models only | Cloud/API model used |
+| Safe Approval Streak | Consecutive risky actions handled through approval gates | Bypass attempt or blocked unsafe action |
+| Tester Truth Streak | Consecutive runs with meaningful TESTER verification | Tester absent or shallow/no verification |
+| Forge Purity Streak | Consecutive dataset preflight/sanitizer passes | Preflight/sanitizer failure |
+| HIVE Uptime Streak | All paired nodes reachable during scheduled checks | Node offline beyond grace window |
+| No Poison Streak | Bad captures rejected before training | Poison/contamination admitted |
+| Citation Precision Streak | Context Fabric answers have verified citations | Citation fails verification |
+
+### 12.1 Streak Reset Policy
+
+- Reset streaks only on relevant failures.
+- Do not reset Local-Only Streak for reading docs or using no model.
+- Do not reset Clean Gate Streak for runs that do not invoke Reviewer Gate.
+- Do not reset Forge Purity Streak for unrelated swarm runs.
+
+---
+
+## 13. Share Cards and Bragging Rights
+
+### 13.1 Privacy Requirements
+
+Share cards must never include:
+
+- raw workspace paths
+- source code snippets
+- prompts containing private content
+- secrets
+- email addresses
+- private IPs
+- file names unless explicitly marked public/share-safe
+- model outputs that contain user content
+
+Share cards may include:
+
+- rank
+- score
+- counts
+- badge names
+- trophy names
+- local-only run count
+- HIVE node count
+- Warband count
+- model names if user allows
+- public repo name if user allows
+- benchmark names if public
+
+### 13.2 Markdown Share Card
+
+```md
+# TheOrc Warpath Card
+
+**Operator:** Erik / hardcoreerik
+**Rank:** Iron Warchief
+**Warpath Score:** 8,740
+**Clean Gate Streak:** 12
+**Local-Only Runs:** 100
+**HIVE Nodes:** 3
+**Warbands:** 1
+**Best Goblin:** TESTER Lv. 14
+
+## Trophies
+
+- The Golden Axe
+- The No-Cloud Banner
+- Truth Goblin
+- No Poison In The Pit
+
+Generated locally by TheOrc. No source code included.
+```
+
+### 13.3 JSON Share Card
+
+```json
+{
+ "schema_version": "warpath-share-card-v1",
+ "generated_at": "2026-07-03T18:30:12-07:00",
+ "rank": "Iron Warchief",
+ "warpath_score": 8740,
+ "clean_gate_streak": 12,
+ "local_only_runs": 100,
+ "hive_nodes": 3,
+ "warbands": 1,
+ "badges": ["Trial Passed", "Truth Goblin", "No Poison In The Pit"],
+ "trophies": ["The Golden Axe", "The No-Cloud Banner"],
+ "privacy_statement": "No source code, prompts, file paths, secrets, or private content included."
+}
+```
+
+### 13.4 GitHub Badge Export
+
+Optional future export:
+
+```md
+
+
+
+```
+
+Do not auto-publish these. Generate local markdown only.
+
+---
+
+## 14. UI Design
+
+### 14.1 New Main Surfaces
+
+| Surface | Description |
+|---|---|
+| Tribe Ledger | Main profile/stat page |
+| Hall of Skulls | Badge/trophy collection page |
+| Battle Report | Per-run scorecard shown after relevant runs |
+| Campaign Map | Per-workspace progress and suggestions |
+| Bestiary | Model mastery view; may integrate with model catalogue/capability data |
+
+### 14.2 MVP UI
+
+MVP should be simple:
+
+- Add a Warpath/Tribe Ledger panel.
+- Show total score, rank, category bars, current streaks.
+- Show latest badges.
+- Show recent Battle Reports.
+- Add a button to export share card.
+
+### 14.3 Battle Report UX
+
+After a run completes:
+
+- Do not interrupt the operator with a huge modal.
+- Show a compact “Battle Report Ready” card.
+- Allow click to expand.
+- If badges unlocked, show a small toast.
+- If penalties occurred, show direct explanation.
+
+### 14.4 Badge Unlock UX
+
+Badge unlock toast should contain:
+
+```text
+Badge Unlocked: Trial Passed
+Reviewer Gate returned CLEAN.
++25 Warpath Score
+```
+
+For audit/flavored badges like Blood Oath Override:
+
+```text
+Audit Mark Recorded: Blood Oath Override
+You overrode a BLOCKER finding with explicit acknowledgement.
+Score impact: -20
+```
+
+### 14.5 Lite Mode
+
+Warpath visuals should respect any Lite Mode or reduced-motion settings. Badges and cards can be visually fun without animation spam.
+
+---
+
+## 15. Integration Points
+
+### 15.1 Swarm Runtime
+
+Emit events for:
+
+- run started
+- run completed
+- boss plan valid/invalid
+- role assigned
+- role violation
+- tester write attempt
+- files staged
+- tests pass/fail
+- worker output empty/useful
+- model fallback used
+
+### 15.2 Approval Flow
+
+Emit events for:
+
+- shell command proposed
+- shell command approved
+- shell command rejected
+- file write proposed
+- file write approved
+- file write rejected
+- unknown tool blocked
+- policy block
+- bypass attempt, if detectable
+
+### 15.3 Reviewer Gate
+
+Emit events for:
+
+- review started
+- review completed
+- verdict CLEAN/MINOR/BLOCKER
+- BLOCKER held apply
+- BLOCKER override acknowledged
+- rework requested
+- rework later passes CLEAN
+
+### 15.4 Training Pit / ORC ACADEMY
+
+Emit events for:
+
+- capture staged
+- capture accepted
+- capture rejected
+- sanitizer passed/failed
+- preflight passed/failed
+- training started
+- training checkpoint
+- training completed
+- adapter evaluated
+- adapter promoted/rejected
+- train/eval leakage found
+- candidate quarantined
+
+### 15.5 Model Wiki / Capability Probing
+
+Emit events for:
+
+- probe started
+- probe completed
+- structured output passed/failed
+- category capability changed
+- model-role mismatch warning
+- smaller model beats larger model on bounded eval
+
+### 15.6 HIVE / Warbands
+
+Emit events for:
+
+- HIVE enabled
+- node discovered
+- node paired
+- node authenticated
+- node offline
+- node recovered
+- Warchief elected
+- Warband connected
+- Warband task completed
+- worker loss detected
+- task requeued
+- stale completion rejected
+
+### 15.7 Context Fabric
+
+Emit events for:
+
+- corpus attached
+- source ingested
+- citation produced
+- citation verified
+- citation failed verification
+- source reopened
+- answer abstained correctly
+- exhaustive task passed
+- distributed fabric task recovered from worker loss
+
+### 15.8 Foundry / Arena
+
+Emit events for:
+
+- baseline report completed
+- candidate trained
+- candidate evaluated
+- candidate beats baseline
+- candidate fails baseline
+- candidate promoted
+- candidate quarantined
+- rollback executed
+
+---
+
+## 16. AI Implementation Guidance for Smaller Models
+
+This section is intentionally direct. It is written so a smaller coding model can follow it without inventing behavior.
+
+### 16.1 Do This
+
+1. Create a Warpath event model.
+2. Create a local repository for storing events.
+3. Create a scoring service that reads events and computes a profile.
+4. Create a badge service that unlocks badges based on event history.
+5. Create a simple UI panel that shows score, rank, categories, streaks, badges, and trophies.
+6. Add event emissions at safe existing boundaries.
+7. Add share-card export that excludes private content.
+8. Add tests for scoring and badge unlock rules.
+
+### 16.2 Do Not Do This
+
+1. Do not execute tools from Warpath code.
+2. Do not change approval behavior.
+3. Do not make any model more trusted because of a badge.
+4. Do not automatically upload score data.
+5. Do not include raw code or private paths in share cards.
+6. Do not reward BLOCKER overrides.
+7. Do not reward raw lines written.
+8. Do not add cloud services.
+9. Do not make Warpath required for normal app operation.
+10. Do not block user work if Warpath storage fails.
+
+### 16.3 Failure Behavior
+
+If Warpath fails:
+
+- Log the error.
+- Do not crash the app.
+- Do not block the swarm.
+- Do not block approvals.
+- Do not block training.
+- Continue the primary workflow.
+
+Warpath is a scoring/visibility layer. It is not mission-critical execution infrastructure.
+
+---
+
+## 17. Phased Implementation Plan
+
+### Phase W-0 — Documentation and Event Inventory
+
+Status: proposed.
+
+Deliverables:
+
+- Accept this white paper.
+- Identify existing code points that can emit events.
+- Create a small event inventory table.
+- Choose JSON or SQLite MVP storage.
+
+Exit criteria:
+
+- Maintainer approves event names and MVP scope.
+- No code behavior changes yet.
+
+### Phase W-1 — Event Logging Foundation
+
+Deliverables:
+
+- `WarpathEvent` model.
+- `IWarpathEventSink` interface.
+- `WarpathEventService` implementation.
+- JSONL or SQLite event storage.
+- Unit tests.
+
+Acceptance criteria:
+
+- Can record event.
+- Can list events.
+- Invalid event schema is rejected.
+- Storage failure does not crash primary workflow.
+
+### Phase W-2 — Profile and Score Projection
+
+Deliverables:
+
+- `WarpathProfile` model.
+- `WarpathScoringService`.
+- Category score calculation.
+- Rank calculation.
+- Streak calculation.
+- Unit tests with fake events.
+
+Acceptance criteria:
+
+- Given a deterministic event list, service returns deterministic score.
+- Penalties are applied correctly.
+- Streaks reset only on relevant events.
+
+### Phase W-3 — Badge and Trophy Engine
+
+Deliverables:
+
+- Badge definitions.
+- Trophy definitions.
+- `WarpathBadgeService`.
+- Unlock persistence.
+- Unit tests for first 25 badges.
+
+Acceptance criteria:
+
+- Badge unlocks once.
+- Badge remains unlocked after restart.
+- Audit mark badges can have negative/no score.
+- Badge unlocks are traceable to event ids.
+
+### Phase W-4 — UI MVP
+
+Deliverables:
+
+- Tribe Ledger panel.
+- Recent badges list.
+- Category bars.
+- Streak list.
+- Recent Battle Reports.
+- Export share card button.
+
+Acceptance criteria:
+
+- UI loads with no events.
+- UI updates after new events.
+- UI does not require network.
+- UI does not show private paths.
+
+### Phase W-5 — Run Battle Reports
+
+Deliverables:
+
+- Battle Report model.
+- Per-run score calculation.
+- Compact completion card.
+- Expanded report view.
+
+Acceptance criteria:
+
+- Swarm run produces report.
+- Reviewer verdict affects report.
+- Penalties are visible and explained.
+
+### Phase W-6 — Integration Expansion
+
+Deliverables:
+
+- Training Pit events.
+- HIVE/Warband events.
+- Model probe events.
+- Context Fabric events.
+- Foundry/Arena events when those systems exist.
+
+Acceptance criteria:
+
+- Each integration emits only share-safe metadata by default.
+- Existing workflows are not blocked by Warpath.
+
+---
+
+## 18. Test Plan
+
+### 18.1 Unit Tests
+
+Required tests:
+
+- `WarpathEventService_RecordEvent_WritesEvent`
+- `WarpathEventService_InvalidEvent_Rejects`
+- `WarpathScoringService_CleanRun_AwardsExpectedPoints`
+- `WarpathScoringService_TesterWriteAttempt_AppliesPenalty`
+- `WarpathScoringService_BlockerOverride_DeductsPoints`
+- `WarpathBadgeService_FirstSwarmRun_UnlocksFirstBlood`
+- `WarpathBadgeService_CleanReview_UnlocksTrialPassed`
+- `WarpathBadgeService_BadgeDoesNotUnlockTwice`
+- `WarpathStreakService_CleanGateStreak_ResetsOnMinor`
+- `WarpathShareCard_DoesNotIncludeWorkspacePath`
+
+### 18.2 Integration Tests
+
+Recommended tests:
+
+- Swarm run completed event creates Battle Report.
+- Reviewer CLEAN event unlocks Trial Passed.
+- BLOCKER override records audit mark and penalty.
+- Dataset admission passed updates Forge Progress.
+- HIVE node paired unlocks First Ally.
+- Model probe completed unlocks Beastmaster.
+
+### 18.3 Privacy Tests
+
+Required tests:
+
+- Share card does not include raw workspace path.
+- Share card does not include prompt text.
+- Share card does not include file contents.
+- Share card does not include private IP unless explicitly allowed and sanitized.
+- Share card does not include email address.
+
+### 18.4 Regression Tests
+
+Warpath must not break:
+
+- normal app launch
+- workspace open
+- swarm run
+- approval flow
+- Training Pit panel
+- HIVE panel
+- Context Fabric workflows
+
+---
+
+## 19. Security and Privacy
+
+### 19.1 Local-First Storage
+
+Warpath data stays local by default.
+
+### 19.2 No Automatic Publishing
+
+Do not automatically publish Warpath profile, score, badge, trophy, or share-card data.
+
+### 19.3 Safe Workspace Identifier
+
+Use a hash for workspace identity, not a raw path.
+
+Bad:
+
+```json
+"workspace": "C:\\Users\\hardc\\source\\repos\\SecretProject"
+```
+
+Good:
+
+```json
+"workspace_id": "sha256:0af1..."
+```
+
+### 19.4 Event Payload Privacy
+
+Events should store facts, not source content.
+
+Good:
+
+```json
+{
+ "event_type": "review.verdict.blocker",
+ "payload": {
+ "blocker_count": 2,
+ "minor_count": 1
+ }
+}
+```
+
+Bad:
+
+```json
+{
+ "event_type": "review.verdict.blocker",
+ "payload": {
+ "full_diff": "...private code..."
+ }
+}
+```
+
+### 19.5 Share Card Redaction
+
+All share exports must include a privacy statement and should be generated from a share-safe projection, not raw events.
+
+---
+
+## 20. Anti-Gaming Controls
+
+### 20.1 Cooldowns
+
+Some badges/events should have cooldowns or uniqueness rules.
+
+Examples:
+
+- Model probe points only count once per model per version or per cooldown window.
+- Repeated failed/identical runs do not farm run completion points.
+- Same capture cannot count as reviewed multiple times.
+
+### 20.2 Quality Gates
+
+Award significant points only after quality evidence.
+
+Training and capture lifecycle events remain visible audit history but award zero
+points. Positive Forge/Foundry score is limited to verified outcomes:
+
+- baseline report completed
+- dataset admission passed
+- candidate correctly rejected under the frozen evaluation
+- deployed artifact passed its declared proof
+- promotion includes a verified rollback target
+- Arena confirmed improvement over the declared baseline
+
+### 20.3 Penalty on Unsafe Shortcuts
+
+Unsafe shortcuts must reduce score.
+
+Examples:
+
+- BLOCKER override: penalty.
+- TESTER write attempt: penalty.
+- train/eval leakage: major penalty and quarantine flag.
+
+### 20.4 No Score for Noise
+
+Do not score:
+
+- repeated tool calls with no success
+- verbose output
+- model chatter
+- huge diffs without tests
+- synthetic data volume without review
+
+---
+
+## 21. Example Warpath Scenarios
+
+### 21.1 Clean Swarm Run
+
+Events:
+
+```text
+swarm.run.started
+agent.plan.generated(valid=true)
+swarm.role.assignment(valid=true)
+approval.file_write.approved
+swarm.tests.passed
+review.verdict.clean
+swarm.run.completed(success=true)
+```
+
+Result:
+
+- Run Score: high.
+- Badge: Trial Passed if first CLEAN.
+- Possible badge: First Blood if first successful Swarm run.
+
+### 21.2 BLOCKER Found and Reworked
+
+Events:
+
+```text
+review.verdict.blocker
+review.blocker.held_apply
+swarm.rework.requested
+review.verdict.clean
+review.blocker.reworked_clean
+```
+
+Result:
+
+- Award The Gate Holds.
+- Award Redeemed In Battle.
+- Positive score for catching and fixing issue.
+
+### 21.3 BLOCKER Overridden
+
+Events:
+
+```text
+review.verdict.blocker
+review.blocker.override
+```
+
+Result:
+
+- Record Blood Oath Override audit mark.
+- Apply score penalty.
+- Do not unlock “No Cowardly Merge.”
+
+### 21.4 Training Loss Trap
+
+Events:
+
+```text
+academy.training.completed
+academy.adapter.evaluated(eval_loss_improved=true, rubric_regressed=true)
+academy.adapter.rejected
+```
+
+Result:
+
+- Unlock Loss Is A Liar.
+- Award discipline points for rejecting bad candidate.
+
+### 21.5 HIVE Worker Loss Recovery
+
+Events:
+
+```text
+hive.node.offline
+hive.task.requeued
+hive.task.reclaimed_by_different_node
+hive.stale_completion.rejected
+hive.task.completed
+```
+
+Result:
+
+- Unlock Dead Node Recovery.
+- Increase HIVE Power.
+
+### 21.6 Context Fabric Verified Answer
+
+Events:
+
+```text
+fabric.corpus.attached
+fabric.answer.cited
+fabric.citation.verified
+fabric.source.reopened
+```
+
+Result:
+
+- Unlock Library Goblin.
+- Unlock Citation Fang.
+- Increase Fabric Evidence.
+
+---
+
+## 22. Development Backlog
+
+### 22.1 MVP Backlog
+
+1. Add `WarpathEvent` model.
+2. Add `IWarpathEventSink`.
+3. Add local JSONL event sink.
+4. Add `WarpathScoringService`.
+5. Add first 25 badge definitions.
+6. Add `WarpathBadgeService`.
+7. Add `WarpathProfile` projection.
+8. Add Tribe Ledger panel.
+9. Add share-card markdown export.
+10. Emit events for Swarm run completed and Reviewer verdict.
+
+### 22.2 Second Backlog
+
+1. Add Training Pit events.
+2. Add HIVE/Warband events.
+3. Add Model probe events.
+4. Add Battle Report view.
+5. Add badge unlock toasts.
+6. Add privacy tests.
+7. Add SQLite migration.
+
+### 22.3 Later Backlog
+
+1. Context Fabric badge integration.
+2. Foundry/Arena badge integration.
+3. PNG share-card generation.
+4. GitHub badge markdown export.
+5. Campaign Map per workspace.
+6. Bestiary/model mastery UI.
+7. Trophy wall visuals.
+
+---
+
+## 23. Suggested File Layout
+
+Actual project paths may vary. Do not force this layout if the repository already has a better convention.
+
+```text
+OrchestratorIDE/Services/Warpath/
+ WarpathEvent.cs
+ WarpathProfile.cs
+ WarpathBadge.cs
+ WarpathTrophy.cs
+ IWarpathEventSink.cs
+ WarpathEventService.cs
+ WarpathScoringService.cs
+ WarpathBadgeService.cs
+ WarpathShareCardService.cs
+ WarpathBattleReportService.cs
+ WarpathRepository.cs
+
+OrchestratorIDE.Avalonia/UI/Panels/Warpath/
+ TribeLedgerPanel.axaml
+ TribeLedgerPanel.axaml.cs
+ HallOfSkullsPanel.axaml
+ HallOfSkullsPanel.axaml.cs
+ BattleReportView.axaml
+ BattleReportView.axaml.cs
+
+OrchestratorIDE.UnitTests/Warpath/
+ WarpathEventServiceTests.cs
+ WarpathScoringServiceTests.cs
+ WarpathBadgeServiceTests.cs
+ WarpathShareCardServiceTests.cs
+```
+
+If TheOrc has moved shared logic into a cross-platform runtime/shared project, place non-UI services there instead.
+
+---
+
+## 24. Open Questions
+
+1. Should Warpath use SQLite immediately or start with JSONL?
+2. Should Warpath be visible by default or opt-in under Settings?
+3. Should operator name be user-provided, GitHub-derived, or omitted?
+4. Should share cards include model names by default?
+5. Should HIVE node names be share-safe by default?
+6. Should Warpath support per-workspace profiles or one global profile plus workspace campaigns?
+7. Should Warpath events be retained forever or compacted into projections after N days?
+8. Should deleted/archived workspaces retain Campaign Map history?
+9. Should badge definitions be code-only, JSON-driven, or hybrid?
+10. Should community-shared badge packs ever be allowed? If yes, only after a safe plugin/config system exists.
+
+Recommended defaults:
+
+- Start global profile plus per-workspace campaign summaries.
+- Use JSONL for MVP if SQLite migration cost is high; otherwise use SQLite immediately.
+- Do not include model names or node names in share cards unless user enables advanced sharing.
+- Keep badge definitions in code for first release to avoid dynamic badge security/quality problems.
+
+---
+
+## 25. Acceptance Criteria for First Merge
+
+The first merge should be small and safe.
+
+Minimum acceptance criteria:
+
+1. Warpath docs accepted.
+2. Event model exists.
+3. Event sink writes local event records.
+4. Scoring service can compute profile from events.
+5. Badge service unlocks at least 10 badges.
+6. Basic Tribe Ledger panel displays rank and score.
+7. Share-card markdown export exists.
+8. Tests cover scoring, badge unlock, and privacy.
+9. No primary workflow depends on Warpath.
+10. No network upload exists.
+
+---
+
+## 26. Final Product Positioning
+
+Warpath should make TheOrc feel more alive without making it less serious.
+
+TheOrc is not just “AI writes code.” It is an operator-controlled local AI system that plans, executes, reviews, learns, routes, cites, and distributes work. Warpath makes that growth visible.
+
+The correct flex is not:
+
+> “I generated a lot of code.”
+
+The correct flex is:
+
+> “My local AI warband runs clean, stays in its lanes, passes review, rejects poisoned data, proves claims from source, and gets better on my hardware.”
+
+That is the heart of TheOrc Warpath.
+
+---
+
+## 27. Appendix A — First 25 MVP Badges
+
+| Badge ID | Name | Family | Tier | Trigger | Score |
+|---|---|---|---|---|---:|
+| `first_blood` | First Blood | Swarm | Bone | First successful Swarm run | 25 |
+| `boss_brain` | Boss Brain | Swarm | Iron | Valid boss plan with correct roles | 25 |
+| `stay_in_your_lane` | Stay In Your Lane | Swarm | Blood | 10 clean role-safe runs | 50 |
+| `truth_goblin` | Truth Goblin | Swarm | Blood | Tester catches issue | 50 |
+| `perfect_warpath` | Perfect Warpath | Swarm | Gold Crown | Valid plan + tests pass + reviewer CLEAN | 100 |
+| `trial_passed` | Trial Passed | Reviewer | Bone | Reviewer CLEAN | 25 |
+| `the_gate_holds` | The Gate Holds | Reviewer | Iron | BLOCKER prevents apply | 25 |
+| `redeemed_in_battle` | Redeemed In Battle | Reviewer | Blood | BLOCKER fixed and rerun CLEAN | 75 |
+| `scarred_but_worthy` | Scarred But Worthy | Reviewer | Bone | MINOR accepted | 15 |
+| `no_cowardly_merge` | No Cowardly Merge | Reviewer | Blood | 10 runs with no BLOCKER override | 50 |
+| `ore_collector` | Ore Collector | Forge | Audit | 25 captures staged | 0 |
+| `ore_sorter` | Ore Sorter | Forge | Audit | 25 captures reviewed | 0 |
+| `no_poison_in_the_pit` | No Poison In The Pit | Forge | Blood | Dataset admission gates pass | 75 |
+| `forge_lit` | Forge Lit | Forge | Audit | First training run started | 0 |
+| `loss_is_a_liar` | Loss Is A Liar | Forge | Gold Crown | Lower loss rejected because rubric failed | 100 |
+| `campfire_lit` | Campfire Lit | HIVE | Bone | HIVE enabled | 20 |
+| `first_ally` | First Ally | HIVE | Bone | First node paired | 30 |
+| `crowned` | Crowned | HIVE | Iron | Machine elected Warchief | 50 |
+| `warband_deployed` | Warband Deployed | HIVE | Blood | First headless Warband connected | 75 |
+| `dead_node_recovery` | Dead Node Recovery | HIVE | Gold Crown | Requeued task completes after worker loss | 100 |
+| `beastmaster` | Beastmaster | Model | Bone | First model probed | 20 |
+| `know_your_goblin` | Know Your Goblin | Model | Iron | All active models probed | 50 |
+| `json_whisperer` | JSON Whisperer | Model | Iron | Structured-output probe passes | 40 |
+| `tiny_but_mean` | Tiny But Mean | Model | Blood | Smaller model beats larger model on bounded eval | 75 |
+| `local_legend` | Local Legend | Model/Safety | Gold Crown | Full successful local-only project run | 100 |
+
+---
+
+## 28. Appendix B — Example Developer Prompt
+
+Use this prompt for Codex/Grok/Qwen when starting implementation:
+
+```text
+Implement Phase W-1 of TheOrc Warpath exactly as specified in docs/THEORC_WARPATH_GAMIFICATION_WHITEPAPER.md.
+
+Scope:
+- Add a WarpathEvent model.
+- Add IWarpathEventSink.
+- Add a local JSONL-backed WarpathEventService.
+- Add validation for required fields.
+- Add unit tests.
+
+Hard rules:
+- Do not change approval behavior.
+- Do not execute tools from Warpath code.
+- Do not upload anything.
+- Do not include workspace raw paths in event records; use a hash or null.
+- Warpath failure must not crash or block primary workflows.
+- Do not implement badges, UI, scoring, or SQLite yet unless explicitly requested.
+
+Acceptance:
+- dotnet build passes.
+- Warpath event tests pass.
+- Existing tests are not broken.
+- Provide a short implementation report with files changed and how to test.
+```
+
+---
+
+## 29. Appendix C — Example Battle Report Payload
+
+```json
+{
+ "schema_version": "warpath-battle-report-v1",
+ "run_id": "swarm_20260703_183012",
+ "created_at": "2026-07-03T18:30:12-07:00",
+ "score": 87,
+ "verdict": "CLEAN",
+ "positive_items": [
+ { "label": "valid boss plan", "points": 10 },
+ { "label": "correct role assignments", "points": 10 },
+ { "label": "tests passed", "points": 10 },
+ { "label": "reviewer CLEAN", "points": 15 }
+ ],
+ "negative_items": [
+ { "label": "stale model probe", "points": -3 }
+ ],
+ "badges_unlocked": ["trial_passed"],
+ "privacy": {
+ "contains_user_content": false,
+ "safe_for_share_card": true
+ }
+}
+```
+
+---
+
+## 30. Appendix D — Glossary
+
+| Term | Meaning |
+|---|---|
+| Warpath | Overall gamification and mastery system |
+| Tribe Ledger | User/operator profile and stats page |
+| Hall of Skulls | Badge and trophy display |
+| Battle Report | Per-run scorecard |
+| Campaign Map | Workspace/project progress view |
+| Bestiary | Model capability/probe mastery view |
+| Forge Marks | Training Pit/ORC ACADEMY achievements |
+| Crown Deeds | HIVE/Warband achievements |
+| Trial Marks | Reviewer Gate achievements |
+| Honor Guard | Safety and approval-discipline score |
+| War Trophy | Rare high-value achievement |
+| Audit Mark | Visible record of risky/exception action, not necessarily positive |
+
+---
+
+## 31. Closing
+
+Warpath is a natural fit for TheOrc because TheOrc is already a system of roles, gates, evidence, training loops, distributed workers, and local ownership. The implementation must stay honest: no fake claims, no cloud scoreboard, no unsafe incentives, no noise farming.
+
+Build it as a local evidence-backed mastery layer. Make the user proud of clean engineering behavior. Make the goblins funny. Keep the gates serious.
+
+That is the winning version.
diff --git a/docs/TOOLCALLER_V0_FROZEN_INVENTORY.md b/docs/TOOLCALLER_V0_FROZEN_INVENTORY.md
new file mode 100644
index 00000000..2b8cc9ca
--- /dev/null
+++ b/docs/TOOLCALLER_V0_FROZEN_INVENTORY.md
@@ -0,0 +1,135 @@
+# TheOrc Foundry — Toolcaller v0 Frozen Tool Inventory
+
+> **Status: 🔲 F-1 deliverable.** This document freezes the tool universe and schema
+> version for the `theorc-toolcaller` v0 proof defined in
+> [THEORC_TOOLCALLER_V0.md](THEORC_TOOLCALLER_V0.md). It does not authorize training.
+>
+> **Schema version:** `toolcaller-v0-tools-1.0`
+> **Frozen tool set SHA-256:** `c456ca416882788664b14ea332aa968de76735171a2e53a76eac7c4c6e2bfefd`
+> **Canonical artifact:** [training_pit/schemas/toolcaller_v0_frozen_tools.json](../training_pit/schemas/toolcaller_v0_frozen_tools.json)
+>
+> The hash is a plain SHA-256 over the checked-in file's raw bytes (not a re-serialized
+> canonical form) so it is trivially reproducible from any language or tool —
+> `sha256sum training_pit/schemas/toolcaller_v0_frozen_tools.json` reproduces it directly.
+> Any edit to this file (including whitespace) changes the hash and invalidates every
+> dataset example generated against the prior version — bump the schema version and
+> regenerate rather than silently reusing stale examples.
+
+---
+
+## Decision
+
+The frozen v0 tool universe is the **same 6 tools F-0 proposed**: `read_file`,
+`list_files`, `grep_code`, `write_file`, `run_shell`, `ask_user`. This F-1 pass verified
+each one against the live tool registrations rather than accepting the proposal on faith
+(see [Verification](#verification) below), and found no reason to add or remove a tool
+for the v0 proof. Scope stays at F-0's minimum because the smallest reproducible proof
+answers the training-vs-baseline question fastest; expanding scope now would be solving
+a problem the v0 proof does not yet need solved.
+
+That said, verification surfaced two things the v0 dataset and evaluation design must
+account for honestly rather than paper over:
+
+1. **`ToolPolicyEngine` only actively risk-evaluates 4 of these 6 tools.** `read_file`,
+ `list_files`, `write_file`, and `run_shell` each have a dedicated `Evaluate` case;
+ `grep_code` and `ask_user` fall through to the engine's default
+ `ToolRiskLevel.ReadWorkspace` assessment with no destructive/out-of-workspace/network
+ checks of their own (`OrchestratorIDE/Trust/ToolPolicyEngine.cs`, `Evaluate()` switch).
+ Dataset examples that need a real deterministic-policy outcome for `grep_code` or
+ `ask_user` will get the default assessment, not a tool-specific one. This is a fact
+ about the current policy layer, not a v0 dataset bug — it should be recorded as a
+ known limitation in every baseline/eval report that touches those two tools.
+2. **Swarm worker roles are `Researcher` / `Coder` / `UIDeveloper` / `Tester`,** not the
+ "boss/coder/reviewer/worker" framing implied elsewhere. Each role has its own tool
+ subset (below); `available_tools` in every dataset example must reflect the subset the
+ originating role actually had, not the full frozen 6.
+
+## Excluded From v0 (Verified, Not Assumed)
+
+The live registry exposes far more than 6 tools: `get_outline`, `run_tests`, `fetch_url`,
+four codegraph tools (`graph_search`, `trace_path`, `get_architecture`, `detect_changes`,
+`graph_adr`), four Context Fabric library tools (`library_list`, `library_search`,
+`library_open`, `library_graph`), and a chat-only research pack
+(`web_search`, `fetch_page`, `save_markdown_document`) that deliberately excludes
+`run_shell`. None of these are in the v0 universe. If a later Foundry phase wants
+toolcaller coverage for any of them, treat that as a new frozen-inventory revision with
+its own hash, not a silent addition to v0.
+
+## Per-Role Available-Tool Subsets (Verified)
+
+Source: `SwarmSession.GetWorkerTools()`, `OrchestratorIDE/Agents/SwarmSession.cs:1645-1667`.
+`ask_user` is appended to every role (handled in-process, never dispatched through the
+tool registry).
+
+| Role | Tools available (within the v0 frozen 6) |
+|---|---|
+| `Researcher` | `grep_code`, `read_file`, `list_files`, `ask_user` (role also gets `fetch_url`, `get_outline`, both outside v0) |
+| `Coder` | `write_file`, `read_file`, `run_shell`, `list_files`, `grep_code`, `ask_user` |
+| `UIDeveloper` | `write_file`, `read_file`, `run_shell`, `list_files`, `ask_user` (no `grep_code`) |
+| `Tester` | `run_shell`, `read_file`, `list_files`, `ask_user` (deliberately **no** `write_file` — prevents self-patching) |
+
+A `theorc-toolcaller` v0 example's `available_tools` field must be the intersection of
+this table's row with the frozen 6, not the full frozen set, whenever the example is
+derived from or intended to represent a specific role.
+
+## Verification
+
+Each frozen tool was checked against its live `ToolDefinition` registration, not taken
+from the F-0 proposal text:
+
+| Tool | Registration | Required args |
+|---|---|---|
+| `read_file` | `OrchestratorIDE/Tools/FileTools.cs:33-62` | `path` |
+| `write_file` | `OrchestratorIDE/Tools/FileTools.cs:65-114` | `path`, `content` |
+| `list_files` | `OrchestratorIDE/Tools/FileTools.cs:117-...` | none |
+| `grep_code` | `OrchestratorIDE/Tools/SearchTools.cs:14-...` | `pattern` |
+| `run_shell` | `OrchestratorIDE/Tools/ShellTools.cs:22-...` | `command` |
+| `ask_user` | `OrchestratorIDE/Agents/SwarmSession.cs` (`AskUserTool`, virtual — never dispatched through `_toolRegistry`) | `question` |
+
+The exact `name` / `description` / `parameters` / `required` fields for all 6 are in
+[training_pit/schemas/toolcaller_v0_frozen_tools.json](../training_pit/schemas/toolcaller_v0_frozen_tools.json).
+Any future edit to these tool registrations must be reflected there and the hash above
+recomputed before generating or accepting new dataset examples.
+
+## Coverage Strategy: Organic Capture First
+
+F-1 data generation for `theorc-toolcaller` uses TheOrc's own swarm as the primary source —
+real tool-call decisions from real swarm runs, captured as they happen, rather than
+synthetic-only authoring. `OrchestratorIDE/Services/Swarm/ToolcallerDatasetCapture.cs`
+stages two organic signals from `RunWorkerLoopAsync`'s real tool-execution loop:
+
+- **`call`** — every tool a worker actually proposes and dispatches, including `ask_user`
+ (a correct `ask_user` call is a `call` decision under this schema, not a separate
+ `clarify` type, since `ask_user` is itself one of the six frozen tools).
+- **`no_tool`** — a worker turn that produces a substantive answer with no tool call at all.
+
+This was a deliberate choice over scripting adversarial/near-match/unsupported-tool swarm
+tasks to bootstrap full category coverage faster. The tradeoff, recorded here rather than
+discovered later: organic capture alone will under-cover `clarify` (beyond `ask_user`) and
+`unsupported` — the current worker loop has no natural signal for either. Real usage may
+close that gap slowly, or a scripted bootstrap pass may be added later; that decision is
+open, not resolved by this document.
+
+Every organic capture still needs mechanical validation
+([Tools/ToolcallerBench](../Tools/ToolcallerBench)), the existing sanitizer
+(`training_pit/scripts/sanitize_dataset.py` — captures will contain real file paths and
+real repo content from whatever workspace the swarm ran in), and human review before any
+example is assigned a train/eval split. The capture hook stages pending/unreviewed
+examples only; it does not promote, split, or train anything.
+
+## Relationship to Other F-1 Deliverables
+
+This document satisfies F-1 deliverable #1 ("frozen v0 tool/schema inventory") from
+[THEORC_TOOLCALLER_V0.md](THEORC_TOOLCALLER_V0.md). It feeds directly into:
+
+- [TOOLCALLER_CAPTURE_SCHEMA.md](../training_pit/TOOLCALLER_CAPTURE_SCHEMA.md) — the
+ dataset schema that references this frozen tool set and its hash.
+- `Tools/ToolcallerBench` — the eval harness skeleton, which loads
+ `toolcaller_v0_frozen_tools.json` as its fixture source of truth rather than
+ hand-duplicating tool definitions.
+- `OrchestratorIDE/Services/Swarm/ToolcallerDatasetCapture.cs` — the live capture hook
+ described above, which stages examples against this frozen tool set and hash.
+
+Remaining F-1 deliverables (baseline report, development/sealed-test manifests,
+promotion margin, `run_manifest.json` contract, chat-template round-trip fixture) are not
+addressed by this document and remain open F-1 work.
diff --git a/training_pit/PLAN_CAPTURE_SCHEMA.md b/training_pit/PLAN_CAPTURE_SCHEMA.md
index 47a3916e..ac3dbf85 100644
--- a/training_pit/PLAN_CAPTURE_SCHEMA.md
+++ b/training_pit/PLAN_CAPTURE_SCHEMA.md
@@ -6,7 +6,9 @@
> corpus to Avalonia is a separate, deliberate decision.
> **Schema version:** 1.0
-> **Status:** Defined. Not yet auto-populated (DatasetCapture.cs not built).
+> **Status:** Defined and auto-populated. `OrchestratorIDE/Services/Swarm/DatasetCapture.cs`
+> stages qualifying boss plans to `.orc/swarm/dataset-staging/`, called from
+> `SwarmSession.RunInternalAsync()` after every swarm run.
>
> This is a **specialized** format for capturing boss/swarm planning outputs, plan quality
> scores, failure modes, and DPO/ORPO contrastive pairs.
@@ -110,21 +112,24 @@ They serve three purposes:
---
-## Auto-Capture Hook (Phase 2)
+## Auto-Capture Hook (Built)
-When Phase 2 starts, add to `SwarmSession.RunBossDecomposeAsync`:
+Wired into `SwarmSession.RunInternalAsync()`, called after `Tasks` is populated:
```csharp
-// After ParseBossPlan() succeeds:
-// File: OrchestratorIDE/Services/Swarm/DatasetCapture.cs (NOT BUILT YET)
-var score = EvalRubric.Score(tasks, userGoal).Composite;
-if (score >= AutoCaptureThreshold || score <= NegativeCaptureThreshold)
- await DatasetCapture.StageExampleAsync(runId, userGoal, raw, tasks, score);
+// File: OrchestratorIDE/Services/Swarm/DatasetCapture.cs
+await DatasetCapture.StageAsync(runId, userGoal, bossRaw, tasks, bossModel, stagingDir);
```
-Constants (planned, not enforced yet):
-- `AutoCaptureThreshold = 70` — stages as positive example
-- `NegativeCaptureThreshold = 39` — stages as negative example
+`StageAsync` scores the plan with `EvalRubric.Score`, then stages only if the composite
+score clears a threshold (marginal 40–69 is silently skipped — see `EvalRubric.PositiveThreshold`
+/ `EvalRubric.NegativeThreshold` for current values):
+- `Composite >= PositiveThreshold` — stages as `plan_capture_good_{runId}_{score:D3}.json`
+- `Composite <= NegativeThreshold` — stages as `plan_capture_bad_{runId}_{score:D3}.json`
+
+Capture is best-effort: parse or write failures are swallowed so a capture problem never
+disrupts the swarm run. A Phase 1 SQL dual-write also indexes the capture in
+`CaptureRepository` when configured; the JSON file remains the canonical record.
---
diff --git a/training_pit/TOOLCALLER_CAPTURE_SCHEMA.md b/training_pit/TOOLCALLER_CAPTURE_SCHEMA.md
new file mode 100644
index 00000000..b6974d94
--- /dev/null
+++ b/training_pit/TOOLCALLER_CAPTURE_SCHEMA.md
@@ -0,0 +1,217 @@
+# The Training Pit — Toolcaller Capture Schema
+
+> **Schema version:** toolcaller-v0
+> **Status:** Defined and auto-populated. `OrchestratorIDE/Services/Swarm/ToolcallerDatasetCapture.cs`
+> stages real, organic "call" and "no_tool" examples from live swarm tool-call decisions to
+> `.orc/swarm/dataset-staging/toolcaller/`, called from `RunWorkerLoopAsync`'s tool-execution
+> loop. This is TheOrc generating its own F-1 training data from real usage rather than
+> synthetic-only authoring — see the coverage-strategy note in
+> [TOOLCALLER_V0_FROZEN_INVENTORY.md](../docs/TOOLCALLER_V0_FROZEN_INVENTORY.md).
+> Captures remain pending/unreviewed until mechanical validation
+> ([Tools/ToolcallerBench](../Tools/ToolcallerBench)), sanitization, and human review are
+> complete — no split is assigned at capture time.
+>
+> Neither `DATASET_SCHEMA.md` (chat-JSONL SFT format) nor `PLAN_CAPTURE_SCHEMA.md`
+> (boss plan-decomposition format) can hold a tool-call example: neither has
+> `available_tools`, a call/no_tool/clarify/unsupported decision enum, or a
+> `tool` + `arguments` output shape. This is a new sibling format, not a
+> replacement for either existing schema.
+>
+> This schema exists to satisfy F-1 deliverable #3 ("mapping to existing Training
+> Pit dataset formats") from
+> [THEORC_TOOLCALLER_V0.md](../docs/THEORC_TOOLCALLER_V0.md). Defining the schema
+> does not authorize dataset generation or training — F-1's other deliverables
+> (baseline report, frozen manifests, promotion margin) remain open work.
+
+---
+
+## What Toolcaller Captures Are For
+
+A toolcaller capture records a single bounded tool-proposal decision:
+`role + available tools + request → expected decision (+ tool/arguments) → policy outcome`
+
+Unlike a plan capture (which records an open-ended multi-task decomposition), a
+toolcaller capture's target output is small and enumerable: one of `call`, `no_tool`,
+`clarify`, or `unsupported`, plus an exact tool/argument pair when the decision is `call`.
+This is what makes `theorc-toolcaller` a bounded v0 proof rather than a general
+planning or coding task.
+
+The frozen tool universe, per-role tool subsets, and schema hash this format depends on
+are defined in
+[docs/TOOLCALLER_V0_FROZEN_INVENTORY.md](../docs/TOOLCALLER_V0_FROZEN_INVENTORY.md).
+Every capture must reference that hash so a later change to a tool's registered
+schema is detectable against examples generated under the old one.
+
+---
+
+## Schema
+
+```jsonc
+{
+ // ── Identity ─────────────────────────────────────────────────────────────
+ "schema_version": "toolcaller-v0",
+ "tool_schema_hash": "c456ca416882788664b14ea332aa968de76735171a2e53a76eac7c4c6e2bfefd",
+ "example_id": "tc_20260703_001", // tc_YYYYMMDD_NNN
+ "lineage_group_id": "tc_lg_00042", // shared by every paraphrase/repair/synthetic
+ // sibling derived from the same source case;
+ // train/eval split must not divide a group
+ "captured_at": "2026-07-03T19:04:01Z",
+
+ // ── Source and transformation provenance ────────────────────────────────
+ "provenance": {
+ "source_type": "human-authored", // "human-authored" | "swarm_capture" |
+ // "corrected_model_output" | "synthetic" |
+ // "repair" | "paraphrase"
+ "producing_model": null, // model id if source_type implies model output
+ "teacher_model": null, // teacher id if synthetic (proposed data, not gold)
+ "prompt_or_recipe_id": null, // authoring prompt/recipe version, if applicable
+ "derived_from_example_id": null // example_id this was paraphrased/repaired from,
+ // if any (must share lineage_group_id)
+ },
+
+ // ── Input context ────────────────────────────────────────────────────────
+ "role": "coder", // "researcher" | "coder" | "ui_developer" |
+ // "tester" (SwarmWorkerRole, lowercase)
+ "request": "Create the approved config file with the given contents.",
+ "available_tools": ["write_file", "read_file", "run_shell", "list_files", "grep_code"],
+ // must equal the frozen per-role subset from
+ // TOOLCALLER_V0_FROZEN_INVENTORY.md, not an
+ // arbitrary list
+ "approval_state": "approved", // "approved" | "pending" | "denied" | "n/a" —
+ // upstream approval context the request carries
+ // in, NOT the model's own decision
+
+ // ── Expected output ──────────────────────────────────────────────────────
+ "expected": {
+ "decision": "call", // "call" | "no_tool" | "clarify" | "unsupported"
+ "tool": "write_file", // required when decision == "call"; must be a
+ // member of available_tools
+ "arguments": { // required when decision == "call"; must match
+ "path": "config/example.json", // the tool's frozen parameter schema exactly —
+ "content": "{\"key\": \"value\"}" // no invented or obsolete fields
+ },
+ "reason_code": null // required when decision is "clarify" or
+ // "unsupported" (see Reason Codes below);
+ // null when decision is "call" or "no_tool"
+ },
+
+ // ── Deterministic policy cross-check ────────────────────────────────────
+ "policy_outcome": {
+ "evaluated": true, // false only for "no_tool"/"clarify"/"unsupported"
+ // examples where no call was proposed to evaluate
+ "risk_level": "read_workspace", // ToolRiskEngine.ToolRiskLevel value, lowercase
+ "is_destructive": false,
+ "touches_outside_workspace": false,
+ "network_access": false,
+ "block_reason": null, // non-null string means ToolPolicyEngine hard-blocks
+ "policy_gap_tool": false // true when this example's tool is grep_code or
+ // ask_user, i.e. ToolPolicyEngine.Evaluate() has no
+ // dedicated case for it and fell through to the
+ // default ReadWorkspace assessment — see
+ // TOOLCALLER_V0_FROZEN_INVENTORY.md's known gap
+ },
+
+ // ── Review and split ─────────────────────────────────────────────────────
+ "review_status": "accepted", // "pending" | "accepted" | "rejected"
+ "reviewer": "human:hce", // "auto" | "human:"
+ "split": "train", // "train" | "eval" — assigned before any candidate
+ // training; every member of a lineage_group_id
+ // must share the same split
+ "notes": "",
+ "tags": []
+}
+```
+
+---
+
+## Decision Taxonomy
+
+| Value | Meaning |
+|---|---|
+| `call` | Exactly one tool call is the correct proposal; `tool` and `arguments` are required and must be exact |
+| `no_tool` | The request is answerable without invoking any tool in the frozen v0 universe |
+| `clarify` | Required information is missing or the request is ambiguous; a `reason_code` is required |
+| `unsupported` | The request cannot be represented by any tool in the frozen v0 universe; a `reason_code` is required |
+
+`policy_outcome` is evaluation context recorded alongside the example, never the model's
+target decision. A `call` example's proposed tool/arguments are separately run through
+the real `ToolPolicyEngine.Evaluate()` to confirm the recorded `policy_outcome` matches —
+disagreement between the two is a hard dataset-admission failure (see below), not
+something to silently reconcile by editing the expected decision.
+
+## Reason Codes (`clarify` / `unsupported`)
+
+| Value | Applies to | Meaning |
+|---|---|---|
+| `missing_required_argument` | `clarify` | The tool is clear but a required argument value is absent from the request |
+| `ambiguous_target` | `clarify` | Multiple plausible tools or targets exist and the request doesn't disambiguate |
+| `ambiguous_intent` | `clarify` | The request's goal itself is unclear, independent of tool/argument choice |
+| `no_matching_tool` | `unsupported` | No tool in the frozen v0 universe can represent the request at all |
+| `tool_outside_role` | `unsupported` | A matching tool exists in the frozen 6 but not in the originating role's available subset |
+
+## Role Taxonomy
+
+Matches `SwarmWorkerRole` (`OrchestratorIDE/Agents/SwarmSession.cs`), lowercased:
+`researcher`, `coder`, `ui_developer`, `tester`. Do not use "boss/reviewer/worker" —
+those are not current `SwarmWorkerRole` values (see
+[TOOLCALLER_V0_FROZEN_INVENTORY.md](../docs/TOOLCALLER_V0_FROZEN_INVENTORY.md)).
+
+---
+
+## Dataset Admission Gates
+
+In addition to [FOUNDRY_ARENA.md](../docs/FOUNDRY_ARENA.md)'s general dataset admission
+gate, a toolcaller capture hard-fails mechanical validation on:
+
+- `expected.tool` absent from the frozen tool universe (`toolcaller_v0_frozen_tools.json`)
+- `expected.tool` present but absent from the example's own `available_tools`
+- `expected.arguments` containing a key not in the tool's frozen parameter schema
+ (invented argument), or missing a required parameter
+- `decision == "call"` with `expected.arguments` absent or incomplete
+- `decision` in `{"clarify", "unsupported"}` with `reason_code` null
+- `policy_outcome.evaluated == true` but the recorded outcome disagrees with a fresh
+ `ToolPolicyEngine.Evaluate()` run against `expected.tool`/`expected.arguments`
+- `approval_state` implying the call already executed or was already approved by the
+ model itself, rather than being upstream context the request carries in
+- any two examples sharing a `lineage_group_id` assigned to different `split` values
+- `tool_schema_hash` not matching the currently frozen inventory hash (stale example,
+ must be regenerated or explicitly re-validated before use)
+
+Mechanical validation runs before any model-based judge, matching the general Foundry
+Arena admission gate.
+
+---
+
+## File Naming
+
+```
+training_pit/datasets/toolcaller/
+ toolcaller_capture_{split}_{example_id}.json
+```
+
+One JSON object per file, mirroring the plan-capture convention
+(`PLAN_CAPTURE_SCHEMA.md`) rather than JSONL — captures are reviewed and admitted
+individually before any export/conversion step produces a training-ready JSONL.
+
+---
+
+## Relationship To Existing Formats
+
+| Format | Captures | Toolcaller-v0 reuses |
+|---|---|---|
+| `DATASET_SCHEMA.md` (chat JSONL) | Final SFT training format (`messages[]` + flat metadata) | File-per-example → reviewed-manifest → JSONL export pipeline shape; not the field layout |
+| `PLAN_CAPTURE_SCHEMA.md` (plan capture) | Boss plan decomposition + quality rubric | Identity/versioning conventions (`schema_version`, `example_id` date-stamped ID), one-JSON-per-file staging, `annotator`/review fields |
+| `TOOLCALLER_CAPTURE_SCHEMA.md` (this doc) | Bounded tool-proposal decision + policy cross-check | — |
+
+`ToolcallerDatasetCapture` (`OrchestratorIDE/Services/Swarm/ToolcallerDatasetCapture.cs`)
+targets this schema, mirroring `DatasetCapture.cs`'s conventions. Building the hook was
+scoped as F-1 tooling to generate real F-1 data, not as F-2 training work — no model is
+trained or promoted by this capture pipeline alone.
+
+---
+
+## Version History
+
+| Version | Date | Changes |
+|---|---|---|
+| toolcaller-v0 | 2026-07-03 | Initial schema, derived from THEORC_TOOLCALLER_V0.md's canonical example shape and dataset requirements |
diff --git a/training_pit/schemas/toolcaller_v0_frozen_tools.json b/training_pit/schemas/toolcaller_v0_frozen_tools.json
new file mode 100644
index 00000000..3f8f20a7
--- /dev/null
+++ b/training_pit/schemas/toolcaller_v0_frozen_tools.json
@@ -0,0 +1,115 @@
+[
+ {
+ "description": "Read the contents of a file.",
+ "name": "read_file",
+ "parameters": {
+ "path": {
+ "description": "File path relative to workspace root, or absolute.",
+ "type": "string"
+ }
+ },
+ "required": [
+ "path"
+ ]
+ },
+ {
+ "description": "List files in a directory (recursive, respects .gitignore-style skips).",
+ "name": "list_files",
+ "parameters": {
+ "depth": {
+ "description": "Max recursion depth (default 3).",
+ "type": "integer"
+ },
+ "path": {
+ "description": "Directory path. Defaults to workspace root.",
+ "type": "string"
+ }
+ },
+ "required": []
+ },
+ {
+ "description": "Search code for a pattern. Uses ripgrep if available, falls back to built-in.",
+ "name": "grep_code",
+ "parameters": {
+ "glob": {
+ "description": "File glob filter (e.g. '*.cs', '*.py'). Optional.",
+ "type": "string"
+ },
+ "path": {
+ "description": "Directory to search. Defaults to workspace root.",
+ "type": "string"
+ },
+ "pattern": {
+ "description": "Regex pattern to search for.",
+ "type": "string"
+ }
+ },
+ "required": [
+ "pattern"
+ ]
+ },
+ {
+ "description": "Write content to a file. Shows a diff preview before writing.",
+ "name": "write_file",
+ "parameters": {
+ "content": {
+ "description": "Complete new file content.",
+ "type": "string"
+ },
+ "path": {
+ "description": "File path relative to workspace root.",
+ "type": "string"
+ },
+ "reason": {
+ "description": "Why this change is being made.",
+ "type": "string"
+ }
+ },
+ "required": [
+ "path",
+ "content"
+ ]
+ },
+ {
+ "description": "Run a PowerShell command in the workspace. Use env_setup to source an environment script BEFORE the command -- both run in the same process so variables like IDF_PATH survive. Example: env_setup=\". C:\\esp-idf\\export.ps1\", command=\"idf.py build\". Blocked: destructive commands.",
+ "name": "run_shell",
+ "parameters": {
+ "command": {
+ "description": "The PowerShell command to run.",
+ "type": "string"
+ },
+ "cwd": {
+ "description": "Working directory (default: workspace root).",
+ "type": "string"
+ },
+ "env_setup": {
+ "description": "Optional. A PowerShell snippet run BEFORE command in the same process. Use this to source environment scripts (e.g. \". C:\\esp-idf\\export.ps1\"). The environment it sets is visible to command.",
+ "type": "string"
+ },
+ "reason": {
+ "description": "Why this command needs to run.",
+ "type": "string"
+ }
+ },
+ "required": [
+ "command"
+ ]
+ },
+ {
+ "description": "Pause your task and ask the user a question. Use when you genuinely need user input to proceed -- e.g. ambiguous requirements, a critical design choice, or needing credentials/paths you can't infer. Keep it rare: ask at most once per task.",
+ "name": "ask_user",
+ "parameters": {
+ "options": {
+ "description": "Optional JSON array of suggested answer strings, e.g. [\"Option A\",\"Option B\"]. Omit if open-ended.",
+ "type": "string"
+ },
+ "question": {
+ "description": "Clear, specific question to ask the user.",
+ "type": "string"
+ }
+ },
+ "required": [
+ "question"
+ ]
+ }
+]