Step 636: drone error synthesis

This commit is contained in:
Bill
2026-02-17 21:39:37 -07:00
parent 6b067c6800
commit 748a173b0f
4 changed files with 212 additions and 0 deletions

View File

@@ -4603,4 +4603,13 @@ target_link_libraries(step635_test PRIVATE
tree_sitter_javascript tree_sitter_typescript
tree_sitter_java tree_sitter_rust tree_sitter_go)
add_executable(step636_test tests/step636_test.cpp)
target_include_directories(step636_test PRIVATE src)
target_link_libraries(step636_test PRIVATE
nlohmann_json::nlohmann_json
unofficial::tree-sitter::tree-sitter
tree_sitter_python tree_sitter_cpp tree_sitter_elisp
tree_sitter_javascript tree_sitter_typescript
tree_sitter_java tree_sitter_rust tree_sitter_go)
# Step 12: Dear ImGui shell scaffolding created (main.cpp exists but not built due to dependencies)

View File

@@ -0,0 +1,62 @@
#pragma once
// Step 636: Error type synthesis for drone
#include <string>
#include <vector>
enum class DroneErrorKind {
MqttError,
NexusError,
ExecutionError,
CapabilityMismatch
};
struct DroneErrorSpec {
DroneErrorKind kind = DroneErrorKind::ExecutionError;
std::string message;
int code = 0;
bool retryable = false;
};
class DroneErrorSynthesis {
public:
static std::string className(DroneErrorKind kind) {
if (kind == DroneErrorKind::MqttError) return "MqttError";
if (kind == DroneErrorKind::NexusError) return "NexusError";
if (kind == DroneErrorKind::ExecutionError) return "ExecutionError";
return "CapabilityMismatch";
}
static std::string toErrorCodeCategory(DroneErrorKind kind) {
if (kind == DroneErrorKind::MqttError) return "mqtt";
if (kind == DroneErrorKind::NexusError) return "nexus";
if (kind == DroneErrorKind::ExecutionError) return "execution";
return "capability";
}
static std::string expectedAlias(DroneErrorKind kind,
const std::string& valueType = "void") {
return "std::expected<" + valueType + ", " + className(kind) + ">";
}
static bool isRetryable(const DroneErrorSpec& spec) {
if (spec.kind == DroneErrorKind::CapabilityMismatch) return false;
if (spec.code < 0) return false;
return spec.retryable;
}
static std::string synthesizeHeader(const std::string& ns = "whetstone") {
if (ns.empty()) return "";
std::string code;
code += "#pragma once\n";
code += "#include <expected>\n";
code += "#include <string>\n\n";
code += "namespace " + ns + " {\n";
code += "struct MqttError { int code = 0; std::string message; };\n";
code += "struct NexusError { int code = 0; std::string message; };\n";
code += "struct ExecutionError { int code = 0; std::string message; };\n";
code += "struct CapabilityMismatch { int code = 0; std::string message; };\n";
code += "} // namespace " + ns + "\n";
return code;
}
};

View File

@@ -0,0 +1,109 @@
// Step 636: Error type synthesis for drone (12 tests)
#include "DroneErrorSynthesis.h"
#include <iostream>
static int passed = 0, failed = 0;
#define TEST(name) { std::cout << " " << #name << "... "; }
#define PASS() { std::cout << "PASS\n"; ++passed; }
#define FAIL(msg) { std::cout << "FAIL: " << msg << "\n"; ++failed; }
#define CHECK(cond, msg) if (!(cond)) { FAIL(msg); return; }
void test_class_name_for_mqtt_error() {
TEST(class_name_for_mqtt_error);
CHECK(DroneErrorSynthesis::className(DroneErrorKind::MqttError) == "MqttError", "name mismatch");
PASS();
}
void test_class_name_for_nexus_error() {
TEST(class_name_for_nexus_error);
CHECK(DroneErrorSynthesis::className(DroneErrorKind::NexusError) == "NexusError", "name mismatch");
PASS();
}
void test_category_for_execution_error() {
TEST(category_for_execution_error);
CHECK(DroneErrorSynthesis::toErrorCodeCategory(DroneErrorKind::ExecutionError) == "execution", "category mismatch");
PASS();
}
void test_category_for_capability_mismatch() {
TEST(category_for_capability_mismatch);
CHECK(DroneErrorSynthesis::toErrorCodeCategory(DroneErrorKind::CapabilityMismatch) == "capability", "category mismatch");
PASS();
}
void test_expected_alias_default_value_type() {
TEST(expected_alias_default_value_type);
CHECK(DroneErrorSynthesis::expectedAlias(DroneErrorKind::MqttError) == "std::expected<void, MqttError>", "alias mismatch");
PASS();
}
void test_expected_alias_custom_value_type() {
TEST(expected_alias_custom_value_type);
CHECK(DroneErrorSynthesis::expectedAlias(DroneErrorKind::NexusError, "int") == "std::expected<int, NexusError>", "alias mismatch");
PASS();
}
void test_retryable_true_for_mqtt_positive_code() {
TEST(retryable_true_for_mqtt_positive_code);
DroneErrorSpec spec{DroneErrorKind::MqttError, "timeout", 1, true};
CHECK(DroneErrorSynthesis::isRetryable(spec), "expected retryable");
PASS();
}
void test_retryable_false_for_capability_mismatch() {
TEST(retryable_false_for_capability_mismatch);
DroneErrorSpec spec{DroneErrorKind::CapabilityMismatch, "missing cap", 1, true};
CHECK(!DroneErrorSynthesis::isRetryable(spec), "capability mismatch should not retry");
PASS();
}
void test_retryable_false_for_negative_code() {
TEST(retryable_false_for_negative_code);
DroneErrorSpec spec{DroneErrorKind::NexusError, "fatal", -1, true};
CHECK(!DroneErrorSynthesis::isRetryable(spec), "negative code should not retry");
PASS();
}
void test_synthesize_header_contains_mqtt_error() {
TEST(synthesize_header_contains_mqtt_error);
auto code = DroneErrorSynthesis::synthesizeHeader();
CHECK(code.find("struct MqttError") != std::string::npos, "mqtt struct missing");
PASS();
}
void test_synthesize_header_contains_expected_include() {
TEST(synthesize_header_contains_expected_include);
auto code = DroneErrorSynthesis::synthesizeHeader();
CHECK(code.find("#include <expected>") != std::string::npos, "expected include missing");
PASS();
}
void test_synthesize_header_rejects_empty_namespace() {
TEST(synthesize_header_rejects_empty_namespace);
auto code = DroneErrorSynthesis::synthesizeHeader("");
CHECK(code.empty(), "empty namespace should produce empty output");
PASS();
}
int main() {
std::cout << "Step 636: Error type synthesis for drone\n";
test_class_name_for_mqtt_error();
test_class_name_for_nexus_error();
test_category_for_execution_error();
test_category_for_capability_mismatch();
test_expected_alias_default_value_type();
test_expected_alias_custom_value_type();
test_retryable_true_for_mqtt_positive_code();
test_retryable_false_for_capability_mismatch();
test_retryable_false_for_negative_code();
test_synthesize_header_contains_mqtt_error();
test_synthesize_header_contains_expected_include();
test_synthesize_header_rejects_empty_namespace();
std::cout << "\nResults: " << passed << "/" << (passed + failed) << " passed\n";
return failed == 0 ? 0 : 1;
}

View File

@@ -12888,3 +12888,35 @@ a header-only `supports(...)` helper.
- `editor/src/CapabilityDeclarationGenerator.h` (`68` <= `600`)
- `editor/tests/step635_test.cpp` within test-file size guidance (`116` lines)
- Header-only architecture and naming conventions remain aligned with `ARCHITECTURE.md`
### Step 636: Error type synthesis for drone
**Status:** PASS (12/12 tests)
Adds a drone error synthesis module covering `MqttError`, `NexusError`,
`ExecutionError`, and `CapabilityMismatch` with category mapping, retryability
rules, and `std::expected` alias generation helpers.
**Files added:**
- `editor/src/DroneErrorSynthesis.h` - error synthesis model:
- error kind and spec modeling
- category and expected-alias helpers
- header text synthesis for generated drone error types
- `editor/tests/step636_test.cpp` - 12 tests covering:
- class/category mapping correctness
- expected-alias generation behavior
- retryability edge cases
- synthesized-header content and empty-namespace handling
**Files modified:**
- `editor/CMakeLists.txt` - `step636_test` target
**Verification run:**
- `cmake -S editor -B editor/build-native` - PASS
- `cmake --build editor/build-native --target step636_test step635_test` - PASS
- `./editor/build-native/step636_test` - PASS (12/12)
- `./editor/build-native/step635_test` - PASS (12/12) regression coverage
**Architecture gate check:**
- `editor/src/DroneErrorSynthesis.h` (`62` <= `600`)
- `editor/tests/step636_test.cpp` within test-file size guidance (`109` lines)
- Header-only architecture and naming conventions remain aligned with `ARCHITECTURE.md`