Deterministic library dispatch layer. Five new headers: - LibrarySelection: result struct with avoidedLibraries + justification - OperationClassifier: wraps taxonomy with ClassificationResult - PerTaskLibrarySelector: sort by score, pick max, build avoided list - SelectionJustificationLog: append-only auditable selection log - Sprint287IntegrationSummary: 8-task spec, all selections verified 25/25 tests passing. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
100 lines
3.7 KiB
C++
100 lines
3.7 KiB
C++
// Step 1966: SelectionJustificationLog
|
|
//
|
|
// t1: append and size
|
|
// t2: findByDomain returns matching entries only
|
|
// t3: findByLibrary filters correctly
|
|
// t4: findByTask returns correct entries
|
|
// t5: clear resets the log; entries() ordering preserved
|
|
|
|
#include "SelectionJustificationLog.h"
|
|
#include <iostream>
|
|
|
|
namespace ws = whetstone;
|
|
static int p = 0, f = 0;
|
|
#define T(n) { std::cout << " " << #n << "... "; }
|
|
#define P() { std::cout << "PASS\n"; ++p; }
|
|
#define F(m) { std::cout << "FAIL: " << m << "\n"; ++f; }
|
|
#define C(c, m) if (!(c)) { F(m); return; }
|
|
|
|
static ws::SelectionJustificationLog makeLog() {
|
|
ws::SelectionJustificationLog log;
|
|
log.append({"t1", "serialization.json", "nlohmann_json", 0.92f,
|
|
"nlohmann_json scores 0.92 vs protobuf at 0.60", "2026-03-02"});
|
|
log.append({"t2", "compute.matrix", "cublas", 0.99f,
|
|
"cublas scores 0.99 vs numpy at 0.95", "2026-03-02"});
|
|
log.append({"t3", "serialization.json", "serde_json", 0.98f,
|
|
"serde_json scores 0.98 (only qualified)", "2026-03-02"});
|
|
log.append({"t4", "compute.statistics", "numpy", 0.93f,
|
|
"numpy scores 0.93 (only qualified library)", "2026-03-02"});
|
|
return log;
|
|
}
|
|
|
|
void t1() {
|
|
T(append_and_size);
|
|
ws::SelectionJustificationLog log;
|
|
C(log.size() == 0, "empty initially");
|
|
log.append({"t1", "serialization.json", "nlohmann_json", 0.92f, "j", "2026-03-02"});
|
|
C(log.size() == 1, "size 1 after append");
|
|
log.append({"t2", "compute.matrix", "cublas", 0.99f, "j", "2026-03-02"});
|
|
C(log.size() == 2, "size 2 after second append");
|
|
C(log.entries().size() == 2, "entries() matches size");
|
|
P();
|
|
}
|
|
|
|
void t2() {
|
|
T(findByDomain_filters_correctly);
|
|
auto log = makeLog();
|
|
auto json_entries = log.findByDomain("serialization.json");
|
|
C(json_entries.size() == 2, "2 serialization.json entries");
|
|
C(json_entries[0].taskId == "t1", "first is t1");
|
|
C(json_entries[1].taskId == "t3", "second is t3");
|
|
auto none = log.findByDomain("network.async");
|
|
C(none.empty(), "no entries for network.async");
|
|
P();
|
|
}
|
|
|
|
void t3() {
|
|
T(findByLibrary_filters_correctly);
|
|
auto log = makeLog();
|
|
auto cublas = log.findByLibrary("cublas");
|
|
C(cublas.size() == 1, "1 cublas entry");
|
|
C(cublas[0].operationDomain == "compute.matrix", "correct domain");
|
|
auto numpy = log.findByLibrary("numpy");
|
|
C(numpy.size() == 1, "1 numpy entry");
|
|
C(numpy[0].capabilityScore == 0.93f, "correct score");
|
|
P();
|
|
}
|
|
|
|
void t4() {
|
|
T(findByTask_returns_correct_entry);
|
|
auto log = makeLog();
|
|
auto t2 = log.findByTask("t2");
|
|
C(t2.size() == 1, "1 t2 entry");
|
|
C(t2[0].selectedLibrary == "cublas", "cublas for t2");
|
|
auto missing = log.findByTask("t99");
|
|
C(missing.empty(), "no t99 entry");
|
|
P();
|
|
}
|
|
|
|
void t5() {
|
|
T(clear_resets_and_ordering_preserved);
|
|
auto log = makeLog();
|
|
C(log.size() == 4, "4 entries before clear");
|
|
log.clear();
|
|
C(log.size() == 0, "empty after clear");
|
|
C(log.entries().empty(), "entries() empty after clear");
|
|
// Re-append and verify ordering preserved
|
|
log.append({"a", "serialization.json", "nlohmann_json", 0.92f, "j", "2026-03-02"});
|
|
log.append({"b", "compute.matrix", "cublas", 0.99f, "j", "2026-03-02"});
|
|
C(log.entries()[0].taskId == "a", "first entry preserved");
|
|
C(log.entries()[1].taskId == "b", "second entry preserved");
|
|
P();
|
|
}
|
|
|
|
int main() {
|
|
std::cout << "Step 1966: SelectionJustificationLog\n";
|
|
t1(); t2(); t3(); t4(); t5();
|
|
std::cout << "\n" << p << "/" << (p + f) << " passed\n";
|
|
return f > 0 ? 1 : 0;
|
|
}
|