Files
whetstone_DSL/editor/tests/step1993_test.cpp
Bill 410bb2d78c Steps 1991-1993: AST sidecar lifecycle + schema stub fixes + IR chain
Step 1991: Wire AST sidecar lifecycle hooks
- openFile (DispatchPart2.h): auto-calls loadSidecarAST() after parse,
  returns annotationsRestored + staleAnnotations
- saveBuffer (DispatchPart3.h): auto-calls saveSidecarAST() +
  saveSemannoSidecar() after write, returns annotationsSaved +
  sidecarPath + semannoPath

Step 1992: Fix 9 schema stubs in Sprint 142/143/144 tool registrations
- All 9 text/AST sync and merge tools now have proper inputSchema with
  required id and documented optional parameters (language, text, mode)

Step 1993: Fix ingest_legacy_to_ir → generate_cpp_from_ir chain
- ingest_legacy_to_ir now emits ir field (SemanticCoreIR format)
  alongside existing graph/api_intent/assumption/readiness fields
- RecoveryNode → IRNode mapping: intent→kind, confidence in metadata
- Neighbor lists become inferred edges; moduleId = "legacy:" + slug
- generate_cpp_from_ir now accepts result["ir"] directly

15/15 tests passing across all three steps.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-24 02:38:43 -06:00

139 lines
5.5 KiB
C++

// Step 1993: ingest_legacy_to_ir → generate_cpp_from_ir chain fix
// Verifies that ingest_legacy_to_ir emits a valid SemanticCoreIR "ir" field
// that can be passed directly to generate_cpp_from_ir without transformation.
#include "MCPServer.h"
#include "SemanticCoreIR.h"
#include <cassert>
#include <iostream>
#include <string>
static json callTool(MCPServer& srv, const std::string& name, json params = json::object()) {
json req = {{"jsonrpc", "2.0"}, {"id", 1},
{"method", "tools/call"},
{"params", {{"name", name}, {"arguments", std::move(params)}}}};
return srv.handleRequest(req);
}
static bool isSuccess(const json& resp) {
return resp.contains("result") &&
resp["result"].contains("isError") &&
resp["result"]["isError"] == false;
}
// Parse the content text back to json for deeper inspection.
static json resultJson(const json& resp) {
if (!resp.contains("result") || !resp["result"].contains("content")) return json::object();
const auto& content = resp["result"]["content"];
if (!content.is_array() || content.empty()) return json::object();
const std::string text = content[0].value("text", "{}");
return json::parse(text, nullptr, false);
}
int main() {
int passed = 0;
MCPServer srv;
// ----------------------------------------------------------------
// Test 1: ingest_legacy_to_ir returns an "ir" field
// ----------------------------------------------------------------
{
auto resp = callTool(srv, "whetstone_ingest_legacy_to_ir",
{{"source", "MyLegacyModule"}, {"language", "cpp"}});
assert(isSuccess(resp));
json r = resultJson(resp);
assert(r["success"] == true);
assert(r.contains("ir"));
assert(r["ir"].is_object());
std::cout << "Test 1 PASSED: ingest_legacy_to_ir emits ir field\n";
++passed;
}
// ----------------------------------------------------------------
// Test 2: ir field is a valid SemanticCoreIR (parses + validates)
// ----------------------------------------------------------------
{
auto resp = callTool(srv, "whetstone_ingest_legacy_to_ir",
{{"source", "MyLegacyModule"}, {"language", "cpp"}});
json r = resultJson(resp);
const json& irJson = r["ir"];
SemanticCoreIR ir;
std::string err;
bool parsed = SemanticCoreIRModel::fromJson(irJson, &ir, &err);
assert(parsed && "SemanticCoreIRModel::fromJson failed");
bool valid = SemanticCoreIRModel::validate(ir, &err);
assert(valid && "SemanticCoreIRModel::validate failed");
assert(!ir.moduleId.empty());
assert(!ir.nodes.empty());
std::cout << "Test 2 PASSED: ir field parses and validates as SemanticCoreIR\n";
++passed;
}
// ----------------------------------------------------------------
// Test 3: ir nodes have unique ids and known kinds
// ----------------------------------------------------------------
{
auto resp = callTool(srv, "whetstone_ingest_legacy_to_ir",
{{"source", "SomeSource"}, {"language", "cpp"}});
json r = resultJson(resp);
SemanticCoreIR ir;
std::string err;
SemanticCoreIRModel::fromJson(r["ir"], &ir, &err);
std::set<std::string> ids;
for (const auto& n : ir.nodes) {
assert(!n.id.empty());
assert(ids.insert(n.id).second && "duplicate node id");
assert(n.language == "cpp");
}
for (const auto& e : ir.edges) {
assert(!e.fromId.empty() && !e.toId.empty());
assert(e.relation == "inferred");
}
std::cout << "Test 3 PASSED: IR nodes have unique ids and valid edges\n";
++passed;
}
// ----------------------------------------------------------------
// Test 4: ir field passes directly to generate_cpp_from_ir
// ----------------------------------------------------------------
{
auto ingestResp = callTool(srv, "whetstone_ingest_legacy_to_ir",
{{"source", "MyLegacyModule"}, {"language", "cpp"}});
assert(isSuccess(ingestResp));
json ingestResult = resultJson(ingestResp);
auto genResp = callTool(srv, "whetstone_generate_cpp_from_ir",
{{"ir", ingestResult["ir"]}, {"profile", "safe-first"}});
assert(isSuccess(genResp));
json genResult = resultJson(genResp);
assert(genResult["success"] == true);
assert(genResult.contains("files"));
std::cout << "Test 4 PASSED: generate_cpp_from_ir accepts ir from ingest\n";
++passed;
}
// ----------------------------------------------------------------
// Test 5: existing ingest output fields are preserved
// ----------------------------------------------------------------
{
auto resp = callTool(srv, "whetstone_ingest_legacy_to_ir",
{{"source", "LegacyTodoModule TODO fix me"}, {"language", "cpp"}});
json r = resultJson(resp);
assert(r.contains("graph"));
assert(r.contains("api_intent"));
assert(r.contains("assumption"));
assert(r.contains("ambiguity"));
assert(r.contains("readiness"));
assert(r.contains("ir")); // new field alongside existing
std::cout << "Test 5 PASSED: existing fields preserved alongside ir\n";
++passed;
}
std::cout << "\n" << passed << "/5 passed\n";
return passed == 5 ? 0 : 1;
}