Sprint 289: Integration into generate_taskitems (steps 1973-1977)
EnrichedExecutionContract, TaskitemLibraryAnnotator, AnnotatedTaskitemValidator, DispatchJustificationReport, Sprint289IntegrationSummary. 25/25 tests passing. Full pipeline: spec -> classifier -> selector -> advisor -> enriched contracts. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -11129,3 +11129,18 @@ target_include_directories(step1971_test PRIVATE src)
|
||||
|
||||
add_executable(step1972_test tests/step1972_test.cpp)
|
||||
target_include_directories(step1972_test PRIVATE src)
|
||||
|
||||
add_executable(step1973_test tests/step1973_test.cpp)
|
||||
target_include_directories(step1973_test PRIVATE src)
|
||||
|
||||
add_executable(step1974_test tests/step1974_test.cpp)
|
||||
target_include_directories(step1974_test PRIVATE src)
|
||||
|
||||
add_executable(step1975_test tests/step1975_test.cpp)
|
||||
target_include_directories(step1975_test PRIVATE src)
|
||||
|
||||
add_executable(step1976_test tests/step1976_test.cpp)
|
||||
target_include_directories(step1976_test PRIVATE src)
|
||||
|
||||
add_executable(step1977_test tests/step1977_test.cpp)
|
||||
target_include_directories(step1977_test PRIVATE src)
|
||||
|
||||
59
editor/src/AnnotatedTaskitemValidator.h
Normal file
59
editor/src/AnnotatedTaskitemValidator.h
Normal file
@@ -0,0 +1,59 @@
|
||||
#pragma once
|
||||
// Step 1975: AnnotatedTaskitemValidator
|
||||
// Validates enrichment of EnrichedExecutionContracts.
|
||||
// ValidationReport { passCount, failCount, errors (include taskDescription) }.
|
||||
// If enrichmentRequired=true, any unenriched contract is an error.
|
||||
// Also validates capabilityScore in [0,1] for enriched contracts.
|
||||
|
||||
#include "EnrichedExecutionContract.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace whetstone {
|
||||
|
||||
struct ValidationReport {
|
||||
int passCount = 0;
|
||||
int failCount = 0;
|
||||
std::vector<std::string> errors;
|
||||
|
||||
bool allPassed() const { return failCount == 0; }
|
||||
};
|
||||
|
||||
class AnnotatedTaskitemValidator {
|
||||
public:
|
||||
ValidationReport validate(
|
||||
const std::vector<EnrichedExecutionContract>& contracts,
|
||||
bool enrichmentRequired) const {
|
||||
|
||||
ValidationReport report;
|
||||
|
||||
for (const auto& c : contracts) {
|
||||
const std::string desc = c.taskDescription.empty()
|
||||
? "(unnamed task)" : c.taskDescription;
|
||||
|
||||
bool pass = true;
|
||||
|
||||
// Check enrichment requirement
|
||||
if (enrichmentRequired && !c.isEnriched()) {
|
||||
report.errors.push_back("task not enriched: " + desc);
|
||||
pass = false;
|
||||
}
|
||||
|
||||
// Validate fields on enriched contracts
|
||||
if (c.isEnriched()) {
|
||||
if (c.capabilityScore < 0.0f || c.capabilityScore > 1.0f) {
|
||||
report.errors.push_back(
|
||||
"capabilityScore out of range [0,1] for: " + desc);
|
||||
pass = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (pass) ++report.passCount;
|
||||
else ++report.failCount;
|
||||
}
|
||||
|
||||
return report;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace whetstone
|
||||
78
editor/src/DispatchJustificationReport.h
Normal file
78
editor/src/DispatchJustificationReport.h
Normal file
@@ -0,0 +1,78 @@
|
||||
#pragma once
|
||||
// Step 1976: DispatchJustificationReport
|
||||
// Per-project structured report of every task -> library choice -> score -> why.
|
||||
// finalize() computes averageScore from enriched entries (non-empty selectedLibrary).
|
||||
// serialize() returns JSON string via nlohmann::json.
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace whetstone {
|
||||
|
||||
struct JustificationEntry {
|
||||
std::string taskDescription;
|
||||
std::string selectedLibrary; // empty if unenriched
|
||||
std::string operationDomain;
|
||||
float capabilityScore = 0.0f;
|
||||
std::string justification;
|
||||
std::vector<std::string> avoidedLibraries; // names only
|
||||
};
|
||||
|
||||
class DispatchJustificationReport {
|
||||
public:
|
||||
std::string projectId;
|
||||
std::vector<JustificationEntry> entries;
|
||||
int totalTasks = 0;
|
||||
int enrichedCount = 0;
|
||||
float averageScore = 0.0f;
|
||||
|
||||
void add(JustificationEntry entry) {
|
||||
++totalTasks;
|
||||
if (!entry.selectedLibrary.empty()) ++enrichedCount;
|
||||
entries.push_back(std::move(entry));
|
||||
}
|
||||
|
||||
// Compute averageScore from enriched entries.
|
||||
void finalize() {
|
||||
if (enrichedCount == 0) {
|
||||
averageScore = 0.0f;
|
||||
return;
|
||||
}
|
||||
float sum = 0.0f;
|
||||
int count = 0;
|
||||
for (const auto& e : entries) {
|
||||
if (!e.selectedLibrary.empty()) {
|
||||
sum += e.capabilityScore;
|
||||
++count;
|
||||
}
|
||||
}
|
||||
averageScore = count > 0 ? sum / static_cast<float>(count) : 0.0f;
|
||||
}
|
||||
|
||||
// Serialize to JSON string (2-space indent).
|
||||
std::string serialize() const {
|
||||
nlohmann::json j;
|
||||
j["projectId"] = projectId;
|
||||
j["totalTasks"] = totalTasks;
|
||||
j["enrichedCount"] = enrichedCount;
|
||||
j["averageScore"] = averageScore;
|
||||
|
||||
nlohmann::json jEntries = nlohmann::json::array();
|
||||
for (const auto& e : entries) {
|
||||
nlohmann::json je;
|
||||
je["taskDescription"] = e.taskDescription;
|
||||
je["selectedLibrary"] = e.selectedLibrary;
|
||||
je["operationDomain"] = e.operationDomain;
|
||||
je["capabilityScore"] = e.capabilityScore;
|
||||
je["justification"] = e.justification;
|
||||
je["avoidedLibraries"] = e.avoidedLibraries;
|
||||
jEntries.push_back(je);
|
||||
}
|
||||
j["entries"] = jEntries;
|
||||
|
||||
return j.dump(2);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace whetstone
|
||||
33
editor/src/EnrichedExecutionContract.h
Normal file
33
editor/src/EnrichedExecutionContract.h
Normal file
@@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
// Step 1973: EnrichedExecutionContract
|
||||
// Extends base execution contract with library dispatch fields.
|
||||
// isEnriched() is true only when selectedLibrary and operationDomain are both set.
|
||||
// Default-constructed contracts are not enriched.
|
||||
|
||||
#include "LibrarySelection.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace whetstone {
|
||||
|
||||
struct EnrichedExecutionContract {
|
||||
// Base contract fields
|
||||
std::string language;
|
||||
std::string stepId;
|
||||
std::string taskDescription;
|
||||
|
||||
// Library dispatch fields (empty by default — not enriched)
|
||||
std::string selectedLibrary;
|
||||
std::string operationDomain;
|
||||
float capabilityScore = 0.0f;
|
||||
std::vector<std::string> preferredAPIs;
|
||||
std::vector<AvoidedLibrary> avoidedLibraries;
|
||||
std::string justification;
|
||||
|
||||
// True when selectedLibrary and operationDomain are both non-empty.
|
||||
bool isEnriched() const {
|
||||
return !selectedLibrary.empty() && !operationDomain.empty();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace whetstone
|
||||
99
editor/src/Sprint289IntegrationSummary.h
Normal file
99
editor/src/Sprint289IntegrationSummary.h
Normal file
@@ -0,0 +1,99 @@
|
||||
#pragma once
|
||||
// Step 1977: Sprint 289 Integration Summary
|
||||
// Full pipeline: spec -> classifier -> selector -> advisor -> enriched taskitems.
|
||||
// 4 named tasks annotated using seed ledger (Sprint 286) + seed catalog (Sprint 288).
|
||||
//
|
||||
// Tasks:
|
||||
// 1. "implement JSON serialization" -> serialization.json -> nlohmann_json (0.92)
|
||||
// 2. "perform matrix multiply on GPU" -> compute.matrix -> cublas (0.99)
|
||||
// 3. "serialize binary IPC message" -> serialization.binary -> protobuf (0.95)
|
||||
// 4. "parallel array sort on GPU" -> compute.parallel -> thrust (0.97)
|
||||
|
||||
#include "TaskitemLibraryAnnotator.h"
|
||||
#include "AnnotatedTaskitemValidator.h"
|
||||
#include "DispatchJustificationReport.h"
|
||||
#include "Sprint286IntegrationSummary.h"
|
||||
#include "Sprint288IntegrationSummary.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace whetstone {
|
||||
|
||||
class Sprint289IntegrationSummary {
|
||||
public:
|
||||
int stepsCompleted = 5;
|
||||
bool success = true;
|
||||
|
||||
std::string sprintName() const {
|
||||
return "Sprint 289: generate_taskitems Integration";
|
||||
}
|
||||
|
||||
// Build seed ledger + catalog, annotate 4 tasks, return enriched contracts.
|
||||
static std::vector<EnrichedExecutionContract> buildAnnotatedTaskitems() {
|
||||
auto ledger = Sprint286IntegrationSummary::buildSeedLedger();
|
||||
auto catalog = Sprint288IntegrationSummary::buildSeedCatalog();
|
||||
TaskitemLibraryAnnotator annotator;
|
||||
|
||||
std::vector<EnrichedExecutionContract> result;
|
||||
|
||||
// Task 1: JSON serialization (nlohmann_json vs protobuf)
|
||||
result.push_back(annotator.annotate(
|
||||
"implement JSON serialization",
|
||||
{"nlohmann_json", "protobuf"},
|
||||
ledger, catalog));
|
||||
|
||||
// Task 2: GPU matrix multiply (cublas vs numpy)
|
||||
result.push_back(annotator.annotate(
|
||||
"perform matrix multiply on GPU",
|
||||
{"cublas", "numpy"},
|
||||
ledger, catalog));
|
||||
|
||||
// Task 3: Binary IPC serialization (protobuf dominates)
|
||||
result.push_back(annotator.annotate(
|
||||
"serialize binary IPC message",
|
||||
{"protobuf", "nlohmann_json"},
|
||||
ledger, catalog));
|
||||
|
||||
// Task 4: Parallel GPU sort (thrust dominates)
|
||||
result.push_back(annotator.annotate(
|
||||
"parallel array sort on GPU",
|
||||
{"thrust", "numpy"},
|
||||
ledger, catalog));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Returns true when all 4 contracts are enriched.
|
||||
static bool verifyAllEnriched() {
|
||||
auto contracts = buildAnnotatedTaskitems();
|
||||
if (contracts.size() != 4) return false;
|
||||
for (const auto& c : contracts) {
|
||||
if (!c.isEnriched()) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Build DispatchJustificationReport from the 4 annotated tasks.
|
||||
static DispatchJustificationReport buildJustificationReport() {
|
||||
auto contracts = buildAnnotatedTaskitems();
|
||||
DispatchJustificationReport report;
|
||||
report.projectId = "sprint289-proof";
|
||||
|
||||
for (const auto& c : contracts) {
|
||||
JustificationEntry entry;
|
||||
entry.taskDescription = c.taskDescription;
|
||||
entry.selectedLibrary = c.selectedLibrary;
|
||||
entry.operationDomain = c.operationDomain;
|
||||
entry.capabilityScore = c.capabilityScore;
|
||||
entry.justification = c.justification;
|
||||
for (const auto& a : c.avoidedLibraries) {
|
||||
entry.avoidedLibraries.push_back(a.name);
|
||||
}
|
||||
report.add(entry);
|
||||
}
|
||||
report.finalize();
|
||||
return report;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace whetstone
|
||||
64
editor/src/TaskitemLibraryAnnotator.h
Normal file
64
editor/src/TaskitemLibraryAnnotator.h
Normal file
@@ -0,0 +1,64 @@
|
||||
#pragma once
|
||||
// Step 1974: TaskitemLibraryAnnotator
|
||||
// Runs OperationClassifier -> PerTaskLibrarySelector -> LibrarySymbolAdvisor per taskitem.
|
||||
// Returns EnrichedExecutionContract. Unenriched if domain unknown or no library scores > 0.
|
||||
// Always sets taskDescription on the returned contract.
|
||||
|
||||
#include "EnrichedExecutionContract.h"
|
||||
#include "OperationClassifier.h"
|
||||
#include "PerTaskLibrarySelector.h"
|
||||
#include "LibrarySymbolAdvisor.h"
|
||||
#include "LibraryCapabilityLedger.h"
|
||||
#include "LibrarySymbolCatalog.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace whetstone {
|
||||
|
||||
class TaskitemLibraryAnnotator {
|
||||
public:
|
||||
EnrichedExecutionContract annotate(
|
||||
const std::string& taskDescription,
|
||||
const std::vector<std::string>& availableLibraries,
|
||||
const LibraryCapabilityLedger& ledger,
|
||||
const LibrarySymbolCatalog& catalog) const {
|
||||
|
||||
EnrichedExecutionContract ec;
|
||||
ec.taskDescription = taskDescription;
|
||||
|
||||
// Step 1: classify the task description into an operation domain
|
||||
auto classifier = OperationClassifier::withDefaultTaxonomy();
|
||||
auto cr = classifier.classify(taskDescription);
|
||||
if (!cr.isKnown) {
|
||||
return ec; // domain unknown — unenriched
|
||||
}
|
||||
|
||||
// Step 2: select best library for the domain
|
||||
PerTaskLibrarySelector selector;
|
||||
auto sel = selector.select(cr.domain, availableLibraries, ledger);
|
||||
if (!sel.hasSelection()) {
|
||||
return ec; // no library scores > 0 — unenriched
|
||||
}
|
||||
|
||||
// Step 3: populate enriched fields from selection
|
||||
ec.selectedLibrary = sel.selectedLibrary;
|
||||
ec.operationDomain = sel.operationDomain;
|
||||
ec.capabilityScore = sel.capabilityScore;
|
||||
ec.preferredAPIs = sel.preferredAPIs;
|
||||
ec.avoidedLibraries = sel.avoidedLibraries;
|
||||
ec.justification = sel.justification;
|
||||
|
||||
// Step 4: supplement preferredAPIs from symbol advisor if not already populated
|
||||
if (ec.preferredAPIs.empty()) {
|
||||
LibrarySymbolAdvisor advisor;
|
||||
auto syms = advisor.advise(sel.selectedLibrary, sel.operationDomain, catalog);
|
||||
for (const auto& s : syms) {
|
||||
ec.preferredAPIs.push_back(s.functionName);
|
||||
}
|
||||
}
|
||||
|
||||
return ec;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace whetstone
|
||||
84
editor/tests/step1973_test.cpp
Normal file
84
editor/tests/step1973_test.cpp
Normal file
@@ -0,0 +1,84 @@
|
||||
// Step 1973: EnrichedExecutionContract
|
||||
//
|
||||
// t1: default-constructed contract is not enriched
|
||||
// t2: setting selectedLibrary + operationDomain makes it enriched
|
||||
// t3: only selectedLibrary set -> not enriched
|
||||
// t4: only operationDomain set -> not enriched
|
||||
// t5: all fields set and readable
|
||||
|
||||
#include "EnrichedExecutionContract.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; }
|
||||
|
||||
void t1() {
|
||||
T(default_not_enriched);
|
||||
ws::EnrichedExecutionContract ec;
|
||||
C(!ec.isEnriched(), "default not enriched");
|
||||
C(ec.selectedLibrary.empty(), "selectedLibrary empty");
|
||||
C(ec.operationDomain.empty(), "operationDomain empty");
|
||||
C(ec.capabilityScore == 0.0f, "capabilityScore 0");
|
||||
C(ec.preferredAPIs.empty(), "preferredAPIs empty");
|
||||
C(ec.avoidedLibraries.empty(), "avoidedLibraries empty");
|
||||
P();
|
||||
}
|
||||
|
||||
void t2() {
|
||||
T(enriched_after_both_fields_set);
|
||||
ws::EnrichedExecutionContract ec;
|
||||
ec.selectedLibrary = "nlohmann_json";
|
||||
ec.operationDomain = "serialization.json";
|
||||
C(ec.isEnriched(), "enriched after both set");
|
||||
P();
|
||||
}
|
||||
|
||||
void t3() {
|
||||
T(not_enriched_only_library_set);
|
||||
ws::EnrichedExecutionContract ec;
|
||||
ec.selectedLibrary = "cublas";
|
||||
C(!ec.isEnriched(), "not enriched without operationDomain");
|
||||
P();
|
||||
}
|
||||
|
||||
void t4() {
|
||||
T(not_enriched_only_domain_set);
|
||||
ws::EnrichedExecutionContract ec;
|
||||
ec.operationDomain = "compute.matrix";
|
||||
C(!ec.isEnriched(), "not enriched without selectedLibrary");
|
||||
P();
|
||||
}
|
||||
|
||||
void t5() {
|
||||
T(all_fields_set_and_readable);
|
||||
ws::EnrichedExecutionContract ec;
|
||||
ec.language = "C++";
|
||||
ec.stepId = "serialize";
|
||||
ec.taskDescription = "implement JSON serialization";
|
||||
ec.selectedLibrary = "nlohmann_json";
|
||||
ec.operationDomain = "serialization.json";
|
||||
ec.capabilityScore = 0.92f;
|
||||
ec.preferredAPIs = {"nlohmann::json::dump()", "nlohmann::json::parse()"};
|
||||
ec.avoidedLibraries = {{"protobuf", "score 0.60 < selected 0.92", 0.60f}};
|
||||
ec.justification = "nlohmann_json scores 0.92 vs protobuf at 0.60";
|
||||
C(ec.isEnriched(), "enriched");
|
||||
C(ec.language == "C++", "language");
|
||||
C(ec.stepId == "serialize", "stepId");
|
||||
C(ec.taskDescription == "implement JSON serialization", "taskDescription");
|
||||
C(ec.capabilityScore == 0.92f, "capabilityScore");
|
||||
C(ec.preferredAPIs.size() == 2, "2 preferredAPIs");
|
||||
C(ec.avoidedLibraries.size() == 1, "1 avoidedLibrary");
|
||||
C(ec.avoidedLibraries[0].name == "protobuf","avoidedLibrary name");
|
||||
P();
|
||||
}
|
||||
|
||||
int main() {
|
||||
std::cout << "Step 1973: EnrichedExecutionContract\n";
|
||||
t1(); t2(); t3(); t4(); t5();
|
||||
std::cout << "\n" << p << "/" << (p + f) << " passed\n";
|
||||
return f > 0 ? 1 : 0;
|
||||
}
|
||||
99
editor/tests/step1974_test.cpp
Normal file
99
editor/tests/step1974_test.cpp
Normal file
@@ -0,0 +1,99 @@
|
||||
// Step 1974: TaskitemLibraryAnnotator
|
||||
//
|
||||
// t1: annotates JSON serialization task with nlohmann_json
|
||||
// t2: returns unenriched for unknown domain text
|
||||
// t3: returns unenriched when no library scores > 0 for domain
|
||||
// t4: avoidedLibraries populated when runner-up has score > 0
|
||||
// t5: preferredAPIs populated from ledger record
|
||||
|
||||
#include "TaskitemLibraryAnnotator.h"
|
||||
#include "Sprint286IntegrationSummary.h"
|
||||
#include "Sprint288IntegrationSummary.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::LibraryCapabilityLedger makeLedger() {
|
||||
return ws::Sprint286IntegrationSummary::buildSeedLedger();
|
||||
}
|
||||
static ws::LibrarySymbolCatalog makeCatalog() {
|
||||
return ws::Sprint288IntegrationSummary::buildSeedCatalog();
|
||||
}
|
||||
|
||||
void t1() {
|
||||
T(annotates_json_task_with_nlohmann);
|
||||
auto ledger = makeLedger();
|
||||
auto catalog = makeCatalog();
|
||||
ws::TaskitemLibraryAnnotator ann;
|
||||
auto ec = ann.annotate("implement JSON serialization",
|
||||
{"nlohmann_json", "protobuf"}, ledger, catalog);
|
||||
C(ec.isEnriched(), "enriched");
|
||||
C(ec.selectedLibrary == "nlohmann_json", "nlohmann_json selected");
|
||||
C(ec.operationDomain == "serialization.json", "domain serialization.json");
|
||||
C(ec.capabilityScore > 0.0f, "score > 0");
|
||||
C(ec.taskDescription == "implement JSON serialization", "taskDescription set");
|
||||
P();
|
||||
}
|
||||
|
||||
void t2() {
|
||||
T(unenriched_for_unknown_domain);
|
||||
auto ledger = makeLedger();
|
||||
auto catalog = makeCatalog();
|
||||
ws::TaskitemLibraryAnnotator ann;
|
||||
auto ec = ann.annotate("xyzzy frobnicate quantum entanglement",
|
||||
{"nlohmann_json", "protobuf"}, ledger, catalog);
|
||||
C(!ec.isEnriched(), "not enriched for unknown domain");
|
||||
C(ec.selectedLibrary.empty(), "selectedLibrary empty");
|
||||
C(ec.taskDescription == "xyzzy frobnicate quantum entanglement", "taskDescription still set");
|
||||
P();
|
||||
}
|
||||
|
||||
void t3() {
|
||||
T(unenriched_when_no_library_scores_above_zero);
|
||||
auto ledger = makeLedger();
|
||||
auto catalog = makeCatalog();
|
||||
ws::TaskitemLibraryAnnotator ann;
|
||||
// Use compute.fft domain; neither library has any score in ledger
|
||||
auto ec = ann.annotate("compute FFT transform", {"nlohmann_json", "protobuf"}, ledger, catalog);
|
||||
C(!ec.isEnriched(), "not enriched when no library qualifies");
|
||||
P();
|
||||
}
|
||||
|
||||
void t4() {
|
||||
T(avoided_libraries_populated_for_runner_up);
|
||||
auto ledger = makeLedger();
|
||||
auto catalog = makeCatalog();
|
||||
ws::TaskitemLibraryAnnotator ann;
|
||||
// nlohmann_json (0.92) vs protobuf (0.60) for serialization.json
|
||||
auto ec = ann.annotate("JSON serialization task",
|
||||
{"nlohmann_json", "protobuf"}, ledger, catalog);
|
||||
C(ec.isEnriched(), "enriched");
|
||||
C(!ec.avoidedLibraries.empty(), "avoidedLibraries non-empty");
|
||||
C(ec.avoidedLibraries[0].name == "protobuf", "protobuf avoided");
|
||||
P();
|
||||
}
|
||||
|
||||
void t5() {
|
||||
T(preferred_apis_populated);
|
||||
auto ledger = makeLedger();
|
||||
auto catalog = makeCatalog();
|
||||
ws::TaskitemLibraryAnnotator ann;
|
||||
auto ec = ann.annotate("perform matrix multiply on GPU",
|
||||
{"cublas", "numpy"}, ledger, catalog);
|
||||
C(ec.isEnriched(), "enriched");
|
||||
C(ec.selectedLibrary == "cublas", "cublas selected");
|
||||
C(!ec.preferredAPIs.empty(), "preferredAPIs non-empty");
|
||||
P();
|
||||
}
|
||||
|
||||
int main() {
|
||||
std::cout << "Step 1974: TaskitemLibraryAnnotator\n";
|
||||
t1(); t2(); t3(); t4(); t5();
|
||||
std::cout << "\n" << p << "/" << (p + f) << " passed\n";
|
||||
return f > 0 ? 1 : 0;
|
||||
}
|
||||
116
editor/tests/step1975_test.cpp
Normal file
116
editor/tests/step1975_test.cpp
Normal file
@@ -0,0 +1,116 @@
|
||||
// Step 1975: AnnotatedTaskitemValidator
|
||||
//
|
||||
// t1: all enriched contracts, required=true -> all pass
|
||||
// t2: unenriched contract, required=true -> fails with taskDescription in error
|
||||
// t3: unenriched contract, required=false -> passes
|
||||
// t4: enriched contract with capabilityScore > 1 -> fails
|
||||
// t5: empty contracts vector -> 0 pass, 0 fail
|
||||
|
||||
#include "AnnotatedTaskitemValidator.h"
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
|
||||
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::EnrichedExecutionContract makeEnriched(const std::string& task,
|
||||
const std::string& lib,
|
||||
const std::string& domain,
|
||||
float score) {
|
||||
ws::EnrichedExecutionContract ec;
|
||||
ec.taskDescription = task;
|
||||
ec.selectedLibrary = lib;
|
||||
ec.operationDomain = domain;
|
||||
ec.capabilityScore = score;
|
||||
return ec;
|
||||
}
|
||||
|
||||
static ws::EnrichedExecutionContract makeUnenriched(const std::string& task) {
|
||||
ws::EnrichedExecutionContract ec;
|
||||
ec.taskDescription = task;
|
||||
return ec;
|
||||
}
|
||||
|
||||
void t1() {
|
||||
T(all_enriched_required_true_all_pass);
|
||||
ws::AnnotatedTaskitemValidator v;
|
||||
std::vector<ws::EnrichedExecutionContract> contracts = {
|
||||
makeEnriched("task A", "nlohmann_json", "serialization.json", 0.92f),
|
||||
makeEnriched("task B", "cublas", "compute.matrix", 0.99f),
|
||||
};
|
||||
auto report = v.validate(contracts, true);
|
||||
C(report.passCount == 2, "2 pass");
|
||||
C(report.failCount == 0, "0 fail");
|
||||
C(report.allPassed(), "allPassed");
|
||||
P();
|
||||
}
|
||||
|
||||
void t2() {
|
||||
T(unenriched_required_true_fails_with_taskdesc);
|
||||
ws::AnnotatedTaskitemValidator v;
|
||||
std::vector<ws::EnrichedExecutionContract> contracts = {
|
||||
makeEnriched("enriched task", "cublas", "compute.matrix", 0.99f),
|
||||
makeUnenriched("unenriched task"),
|
||||
};
|
||||
auto report = v.validate(contracts, true);
|
||||
C(report.passCount == 1, "1 pass");
|
||||
C(report.failCount == 1, "1 fail");
|
||||
C(!report.errors.empty(), "errors non-empty");
|
||||
// Error must include taskDescription
|
||||
bool found = false;
|
||||
for (const auto& e : report.errors) {
|
||||
if (e.find("unenriched task") != std::string::npos) found = true;
|
||||
}
|
||||
C(found, "error contains taskDescription");
|
||||
P();
|
||||
}
|
||||
|
||||
void t3() {
|
||||
T(unenriched_required_false_passes);
|
||||
ws::AnnotatedTaskitemValidator v;
|
||||
std::vector<ws::EnrichedExecutionContract> contracts = {
|
||||
makeUnenriched("unnamed work"),
|
||||
makeEnriched("known task", "thrust", "compute.parallel", 0.97f),
|
||||
};
|
||||
auto report = v.validate(contracts, false);
|
||||
C(report.passCount == 2, "2 pass");
|
||||
C(report.failCount == 0, "0 fail");
|
||||
C(report.allPassed(), "allPassed");
|
||||
P();
|
||||
}
|
||||
|
||||
void t4() {
|
||||
T(enriched_bad_capability_score_fails);
|
||||
ws::AnnotatedTaskitemValidator v;
|
||||
ws::EnrichedExecutionContract bad = makeEnriched("bad task", "lib", "domain", 1.5f);
|
||||
auto report = v.validate({bad}, true);
|
||||
C(report.failCount == 1, "1 fail");
|
||||
C(!report.errors.empty(), "errors non-empty");
|
||||
bool found = false;
|
||||
for (const auto& e : report.errors) {
|
||||
if (e.find("bad task") != std::string::npos) found = true;
|
||||
}
|
||||
C(found, "error mentions bad task");
|
||||
P();
|
||||
}
|
||||
|
||||
void t5() {
|
||||
T(empty_contracts_zero_counts);
|
||||
ws::AnnotatedTaskitemValidator v;
|
||||
auto report = v.validate({}, true);
|
||||
C(report.passCount == 0, "0 pass");
|
||||
C(report.failCount == 0, "0 fail");
|
||||
C(report.allPassed(), "allPassed on empty");
|
||||
P();
|
||||
}
|
||||
|
||||
int main() {
|
||||
std::cout << "Step 1975: AnnotatedTaskitemValidator\n";
|
||||
t1(); t2(); t3(); t4(); t5();
|
||||
std::cout << "\n" << p << "/" << (p + f) << " passed\n";
|
||||
return f > 0 ? 1 : 0;
|
||||
}
|
||||
117
editor/tests/step1976_test.cpp
Normal file
117
editor/tests/step1976_test.cpp
Normal file
@@ -0,0 +1,117 @@
|
||||
// Step 1976: DispatchJustificationReport
|
||||
//
|
||||
// t1: add entries, finalize computes averageScore correctly
|
||||
// t2: serialize returns valid JSON string (parseable by nlohmann)
|
||||
// t3: JSON contains all required top-level fields
|
||||
// t4: unenriched entry (empty selectedLibrary) not counted in enrichedCount
|
||||
// t5: projectId present in JSON and entries array present
|
||||
|
||||
#include "DispatchJustificationReport.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::JustificationEntry makeEntry(const std::string& task,
|
||||
const std::string& lib,
|
||||
const std::string& domain,
|
||||
float score) {
|
||||
ws::JustificationEntry e;
|
||||
e.taskDescription = task;
|
||||
e.selectedLibrary = lib;
|
||||
e.operationDomain = domain;
|
||||
e.capabilityScore = score;
|
||||
e.justification = lib + " scores " + std::to_string(score);
|
||||
return e;
|
||||
}
|
||||
|
||||
void t1() {
|
||||
T(finalize_computes_average_score);
|
||||
ws::DispatchJustificationReport r;
|
||||
r.projectId = "test-project";
|
||||
r.add(makeEntry("task A", "nlohmann_json", "serialization.json", 0.92f));
|
||||
r.add(makeEntry("task B", "cublas", "compute.matrix", 0.99f));
|
||||
r.finalize();
|
||||
C(r.totalTasks == 2, "2 total tasks");
|
||||
C(r.enrichedCount == 2, "2 enriched");
|
||||
// averageScore = (0.92 + 0.99) / 2 = 0.955
|
||||
C(r.averageScore > 0.9f && r.averageScore < 1.0f, "averageScore in (0.9, 1.0)");
|
||||
P();
|
||||
}
|
||||
|
||||
void t2() {
|
||||
T(serialize_returns_valid_json);
|
||||
ws::DispatchJustificationReport r;
|
||||
r.projectId = "parse-test";
|
||||
r.add(makeEntry("task X", "thrust", "compute.parallel", 0.97f));
|
||||
r.finalize();
|
||||
std::string json = r.serialize();
|
||||
C(!json.empty(), "JSON non-empty");
|
||||
// Must be parseable
|
||||
bool ok = false;
|
||||
try {
|
||||
auto parsed = nlohmann::json::parse(json);
|
||||
ok = true;
|
||||
} catch (...) {}
|
||||
C(ok, "JSON parseable");
|
||||
P();
|
||||
}
|
||||
|
||||
void t3() {
|
||||
T(json_has_all_required_fields);
|
||||
ws::DispatchJustificationReport r;
|
||||
r.projectId = "fields-test";
|
||||
r.add(makeEntry("task Y", "protobuf", "serialization.binary", 0.95f));
|
||||
r.finalize();
|
||||
auto j = nlohmann::json::parse(r.serialize());
|
||||
C(j.contains("projectId"), "projectId");
|
||||
C(j.contains("totalTasks"), "totalTasks");
|
||||
C(j.contains("enrichedCount"), "enrichedCount");
|
||||
C(j.contains("averageScore"), "averageScore");
|
||||
C(j.contains("entries"), "entries");
|
||||
C(j["entries"].is_array(), "entries is array");
|
||||
P();
|
||||
}
|
||||
|
||||
void t4() {
|
||||
T(unenriched_entry_not_counted_in_enriched_count);
|
||||
ws::DispatchJustificationReport r;
|
||||
r.projectId = "mixed";
|
||||
r.add(makeEntry("enriched task", "thrust", "compute.parallel", 0.97f));
|
||||
// Unenriched entry: empty selectedLibrary
|
||||
ws::JustificationEntry ue;
|
||||
ue.taskDescription = "unenriched task";
|
||||
r.add(ue);
|
||||
r.finalize();
|
||||
C(r.totalTasks == 2, "2 total");
|
||||
C(r.enrichedCount == 1, "1 enriched");
|
||||
// averageScore should be based on enriched entry only
|
||||
C(r.averageScore > 0.9f, "averageScore based on enriched only");
|
||||
P();
|
||||
}
|
||||
|
||||
void t5() {
|
||||
T(project_id_in_json_and_entries_array);
|
||||
ws::DispatchJustificationReport r;
|
||||
r.projectId = "my-special-project";
|
||||
r.add(makeEntry("a", "cublas", "compute.matrix", 0.99f));
|
||||
r.add(makeEntry("b", "nlohmann_json", "serialization.json", 0.92f));
|
||||
r.finalize();
|
||||
auto j = nlohmann::json::parse(r.serialize());
|
||||
C(j["projectId"] == "my-special-project", "projectId value");
|
||||
C(j["entries"].size() == 2, "2 entries");
|
||||
C(j["entries"][0].contains("taskDescription"), "entry has taskDescription");
|
||||
C(j["entries"][0].contains("avoidedLibraries"), "entry has avoidedLibraries");
|
||||
P();
|
||||
}
|
||||
|
||||
int main() {
|
||||
std::cout << "Step 1976: DispatchJustificationReport\n";
|
||||
t1(); t2(); t3(); t4(); t5();
|
||||
std::cout << "\n" << p << "/" << (p + f) << " passed\n";
|
||||
return f > 0 ? 1 : 0;
|
||||
}
|
||||
78
editor/tests/step1977_test.cpp
Normal file
78
editor/tests/step1977_test.cpp
Normal file
@@ -0,0 +1,78 @@
|
||||
// Step 1977: Sprint 289 Integration
|
||||
//
|
||||
// t1: buildAnnotatedTaskitems returns 4 contracts
|
||||
// t2: verifyAllEnriched passes
|
||||
// t3: JSON serialization task selects nlohmann_json
|
||||
// t4: matrix multiply task selects cublas
|
||||
// t5: Sprint289IntegrationSummary metadata correct + report averageScore > 0
|
||||
|
||||
#include "Sprint289IntegrationSummary.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; }
|
||||
|
||||
void t1() {
|
||||
T(build_annotated_returns_4_contracts);
|
||||
auto contracts = ws::Sprint289IntegrationSummary::buildAnnotatedTaskitems();
|
||||
C(contracts.size() == 4, "4 contracts");
|
||||
for (const auto& c : contracts) {
|
||||
C(!c.taskDescription.empty(), "taskDescription set on each contract");
|
||||
}
|
||||
P();
|
||||
}
|
||||
|
||||
void t2() {
|
||||
T(verify_all_enriched_passes);
|
||||
C(ws::Sprint289IntegrationSummary::verifyAllEnriched(), "verifyAllEnriched");
|
||||
P();
|
||||
}
|
||||
|
||||
void t3() {
|
||||
T(json_task_selects_nlohmann_json);
|
||||
auto contracts = ws::Sprint289IntegrationSummary::buildAnnotatedTaskitems();
|
||||
// Contract 0: "implement JSON serialization"
|
||||
const auto& c = contracts[0];
|
||||
C(c.isEnriched(), "enriched");
|
||||
C(c.selectedLibrary == "nlohmann_json", "nlohmann_json selected");
|
||||
C(c.operationDomain == "serialization.json", "domain serialization.json");
|
||||
C(c.capabilityScore > 0.9f, "score > 0.9");
|
||||
P();
|
||||
}
|
||||
|
||||
void t4() {
|
||||
T(matrix_multiply_task_selects_cublas);
|
||||
auto contracts = ws::Sprint289IntegrationSummary::buildAnnotatedTaskitems();
|
||||
// Contract 1: "perform matrix multiply on GPU"
|
||||
const auto& c = contracts[1];
|
||||
C(c.isEnriched(), "enriched");
|
||||
C(c.selectedLibrary == "cublas", "cublas selected");
|
||||
C(c.operationDomain == "compute.matrix", "domain compute.matrix");
|
||||
C(c.capabilityScore > 0.95f, "cublas score > 0.95");
|
||||
P();
|
||||
}
|
||||
|
||||
void t5() {
|
||||
T(metadata_and_report);
|
||||
ws::Sprint289IntegrationSummary s;
|
||||
C(s.stepsCompleted == 5, "5 steps");
|
||||
C(s.success, "success");
|
||||
C(s.sprintName() == "Sprint 289: generate_taskitems Integration", "sprintName");
|
||||
auto report = ws::Sprint289IntegrationSummary::buildJustificationReport();
|
||||
C(report.totalTasks == 4, "4 total tasks in report");
|
||||
C(report.enrichedCount == 4, "4 enriched in report");
|
||||
C(report.averageScore > 0.0f, "averageScore > 0");
|
||||
C(report.projectId == "sprint289-proof", "projectId");
|
||||
P();
|
||||
}
|
||||
|
||||
int main() {
|
||||
std::cout << "Step 1977: Sprint 289 Integration\n";
|
||||
t1(); t2(); t3(); t4(); t5();
|
||||
std::cout << "\n" << p << "/" << (p + f) << " passed\n";
|
||||
return f > 0 ? 1 : 0;
|
||||
}
|
||||
Reference in New Issue
Block a user