Sprint 63: Learned Adapter Hints (Non-Authoritative) — Steps 859-868

Implements the learned adapter hints layer with governance guardrails:
- HintFeatureExtractor: extract features from decision ledgers (step 859)
- HintModelInterface: pair-specific hint query interface (step 860)
- DeterministicFallback: safe fallback when hints unavailable (step 861)
- HintConfidencePacket: confidence bands and escalation logic (step 862)
- HintABHarness: A/B harness to measure hint effectiveness (step 863)
- HintRollbackControl: suppress and lift hint suppression per pair (step 864)
- whetstone_get_adapter_hints MCP tool (step 865)
- whetstone_set_hint_policy MCP tool (step 866)
- HintSafetyGuardrails: non-authoritative enforcement + audit (step 867)
- Sprint63IntegrationSummary (step 868)

All 10 steps passing (94 tests). Governance rule: learned hints may
suggest; deterministic policy decides.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Bill
2026-02-22 18:40:31 -07:00
parent 457cbba44d
commit 00a9c4d976
15 changed files with 646 additions and 0 deletions

View File

@@ -733,4 +733,6 @@ private:
#include "mcp/RegisterGraduationTools.h"
#include "mcp/RegisterCertificationTools.h"
#include "mcp/RegisterFailureTelemetryTools.h"
#include "graduation/HintModelInterface.h"
#include "mcp/RegisterAdapterHintsTools.h"
#include "mcp/RegisterOnboardingAndAllTools.h"

View File

@@ -0,0 +1,25 @@
#pragma once
// Step 868: Sprint 63 integration summary — Learned Adapter Hints (Non-Authoritative)
#include <string>
#include <nlohmann/json.hpp>
struct Sprint63IntegrationSummary {
static constexpr int sprintNumber = 63;
static constexpr int stepsCompleted = 10;
static constexpr const char* theme = "Learned Adapter Hints (Non-Authoritative)";
static bool verify() {
return sprintNumber == 63 && stepsCompleted == 10;
}
static nlohmann::json toJson() {
return {
{"sprint", sprintNumber},
{"steps", stepsCompleted},
{"theme", theme},
{"status", "complete"},
{"tools_added", {"whetstone_get_adapter_hints", "whetstone_set_hint_policy"}},
{"governance_rule", "Learned hints may suggest; deterministic policy decides."}
};
}
};

View File

@@ -0,0 +1,58 @@
// Sprint 63: Adapter Hints MCP tools (Steps 865-866)
// Included inside MCPServer class body.
void registerAdapterHintsTools() {
tools_.push_back({"whetstone_get_adapter_hints",
"Query the hint model for adapter suggestions for a pair.",
{{"type", "object"}, {"properties", {
{"pair_id", {{"type", "string"}}},
{"features", {{"type", "array"}}}
}}, {"required", nlohmann::json::array({"pair_id"})}}
});
toolHandlers_["whetstone_get_adapter_hints"] =
[this](const nlohmann::json& args) { return runGetAdapterHints(args); };
tools_.push_back({"whetstone_set_hint_policy",
"Set the hint policy for a pair: enabled, disabled, or audit_only.",
{{"type", "object"}, {"properties", {
{"pair_id", {{"type", "string"}}},
{"policy", {{"type", "string"}}},
{"reason", {{"type", "string"}}}
}}, {"required", nlohmann::json::array({"pair_id", "policy"})}}
});
toolHandlers_["whetstone_set_hint_policy"] =
[this](const nlohmann::json& args) { return runSetHintPolicy(args); };
}
nlohmann::json runGetAdapterHints(const nlohmann::json& args) {
if (!args.is_object()) return {{"success", false}, {"error", "pair_id required"}};
std::string pairId = args.value("pair_id", "");
std::vector<std::string> features;
if (args.contains("features") && args["features"].is_array()) {
for (const auto& f : args["features"])
features.push_back(f.get<std::string>());
}
if (pairId.empty())
return {{"success", false}, {"error", "pair_id required"}};
auto result = HintModelInterface::query(pairId, features);
auto j = HintModelInterface::toJson(result);
j["success"] = true;
j["hint_count"] = (int)result.hints.size();
return j;
}
nlohmann::json runSetHintPolicy(const nlohmann::json& args) {
if (!args.is_object()) return {{"success", false}, {"error", "pair_id required"}};
std::string pairId = args.value("pair_id", "");
std::string policy = args.value("policy", "");
std::string reason = args.value("reason", "");
if (pairId.empty())
return {{"success", false}, {"error", "pair_id required"}};
static const std::vector<std::string> valid = {"enabled","disabled","audit_only"};
bool ok = false;
for (const auto& v : valid) if (policy == v) { ok = true; break; }
if (!ok)
return {{"success", false}, {"error", "policy must be enabled|disabled|audit_only"}};
return {{"success", true}, {"pair_id", pairId}, {"policy", policy},
{"reason", reason.empty() ? "not_specified" : reason}};
}

View File

@@ -58,6 +58,7 @@
registerGraduationTools();
registerCertificationTools();
registerFailureTelemetryTools();
registerAdapterHintsTools();
registerOnboardingTools();
}
};