Step 635: capability declaration generator

This commit is contained in:
Bill
2026-02-17 21:38:39 -07:00
parent 9130277713
commit 6b067c6800
4 changed files with 224 additions and 0 deletions

View File

@@ -4594,4 +4594,13 @@ target_link_libraries(step634_test PRIVATE
tree_sitter_javascript tree_sitter_typescript
tree_sitter_java tree_sitter_rust tree_sitter_go)
add_executable(step635_test tests/step635_test.cpp)
target_include_directories(step635_test PRIVATE src)
target_link_libraries(step635_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,68 @@
#pragma once
// Step 635: Capability declaration struct generator
#include <algorithm>
#include <string>
#include <vector>
struct CapabilityDeclarationOutput {
bool success = false;
std::string headerCode;
std::vector<std::string> typeNames;
};
class CapabilityDeclarationGenerator {
public:
static CapabilityDeclarationOutput generate(const std::string& namespaceName = "whetstone") {
CapabilityDeclarationOutput out;
if (namespaceName.empty()) return out;
out.typeNames = {
"NodeCapability",
"CapabilitySet",
"EnergyContext",
"JobRequirements"
};
std::string code;
code += "#pragma once\n";
code += "#include <string>\n";
code += "#include <vector>\n\n";
code += "namespace " + namespaceName + " {\n\n";
code += "struct NodeCapability {\n";
code += " std::string name;\n";
code += " int level = 0;\n";
code += "};\n\n";
code += "struct CapabilitySet {\n";
code += " std::vector<NodeCapability> items;\n";
code += "};\n\n";
code += "struct EnergyContext {\n";
code += " std::string mode = \"Normal\";\n";
code += " int wattsAvailable = 0;\n";
code += "};\n\n";
code += "struct JobRequirements {\n";
code += " std::vector<std::string> requiredCaps;\n";
code += " int minLevel = 0;\n";
code += "};\n\n";
code += "inline bool supports(const CapabilitySet& caps, const JobRequirements& req) {\n";
code += " if (req.requiredCaps.empty()) return true;\n";
code += " for (const auto& needed : req.requiredCaps) {\n";
code += " bool found = false;\n";
code += " for (const auto& have : caps.items) {\n";
code += " if (have.name == needed && have.level >= req.minLevel) { found = true; break; }\n";
code += " }\n";
code += " if (!found) return false;\n";
code += " }\n";
code += " return true;\n";
code += "}\n\n";
code += "} // namespace " + namespaceName + "\n";
out.success = true;
out.headerCode = code;
return out;
}
static bool containsType(const CapabilityDeclarationOutput& out, const std::string& typeName) {
return std::find(out.typeNames.begin(), out.typeNames.end(), typeName) != out.typeNames.end();
}
};

View File

@@ -0,0 +1,116 @@
// Step 635: Capability declaration struct generator (12 tests)
#include "CapabilityDeclarationGenerator.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_generate_requires_non_empty_namespace() {
TEST(generate_requires_non_empty_namespace);
auto out = CapabilityDeclarationGenerator::generate("");
CHECK(!out.success, "empty namespace should fail");
PASS();
}
void test_generate_succeeds_with_default_namespace() {
TEST(generate_succeeds_with_default_namespace);
auto out = CapabilityDeclarationGenerator::generate();
CHECK(out.success, "generate should succeed");
PASS();
}
void test_output_contains_node_capability_struct() {
TEST(output_contains_node_capability_struct);
auto out = CapabilityDeclarationGenerator::generate();
CHECK(out.headerCode.find("struct NodeCapability") != std::string::npos, "NodeCapability missing");
PASS();
}
void test_output_contains_capability_set_struct() {
TEST(output_contains_capability_set_struct);
auto out = CapabilityDeclarationGenerator::generate();
CHECK(out.headerCode.find("struct CapabilitySet") != std::string::npos, "CapabilitySet missing");
PASS();
}
void test_output_contains_energy_context_struct() {
TEST(output_contains_energy_context_struct);
auto out = CapabilityDeclarationGenerator::generate();
CHECK(out.headerCode.find("struct EnergyContext") != std::string::npos, "EnergyContext missing");
PASS();
}
void test_output_contains_job_requirements_struct() {
TEST(output_contains_job_requirements_struct);
auto out = CapabilityDeclarationGenerator::generate();
CHECK(out.headerCode.find("struct JobRequirements") != std::string::npos, "JobRequirements missing");
PASS();
}
void test_output_contains_supports_helper() {
TEST(output_contains_supports_helper);
auto out = CapabilityDeclarationGenerator::generate();
CHECK(out.headerCode.find("inline bool supports") != std::string::npos, "supports helper missing");
PASS();
}
void test_contains_type_detects_known_types() {
TEST(contains_type_detects_known_types);
auto out = CapabilityDeclarationGenerator::generate();
CHECK(CapabilityDeclarationGenerator::containsType(out, "NodeCapability"), "type should exist");
CHECK(CapabilityDeclarationGenerator::containsType(out, "JobRequirements"), "type should exist");
PASS();
}
void test_contains_type_rejects_unknown_type() {
TEST(contains_type_rejects_unknown_type);
auto out = CapabilityDeclarationGenerator::generate();
CHECK(!CapabilityDeclarationGenerator::containsType(out, "UnknownType"), "unknown type should not exist");
PASS();
}
void test_header_uses_header_only_pattern() {
TEST(header_uses_header_only_pattern);
auto out = CapabilityDeclarationGenerator::generate();
CHECK(out.headerCode.find("#pragma once") != std::string::npos, "pragma once missing");
PASS();
}
void test_custom_namespace_is_applied() {
TEST(custom_namespace_is_applied);
auto out = CapabilityDeclarationGenerator::generate("hivemind");
CHECK(out.headerCode.find("namespace hivemind") != std::string::npos, "custom namespace missing");
PASS();
}
void test_type_count_matches_expected_set() {
TEST(type_count_matches_expected_set);
auto out = CapabilityDeclarationGenerator::generate();
CHECK(out.typeNames.size() == 4, "expected 4 generated types");
PASS();
}
int main() {
std::cout << "Step 635: Capability declaration struct generator\n";
test_generate_requires_non_empty_namespace();
test_generate_succeeds_with_default_namespace();
test_output_contains_node_capability_struct();
test_output_contains_capability_set_struct();
test_output_contains_energy_context_struct();
test_output_contains_job_requirements_struct();
test_output_contains_supports_helper();
test_contains_type_detects_known_types();
test_contains_type_rejects_unknown_type();
test_header_uses_header_only_pattern();
test_custom_namespace_is_applied();
test_type_count_matches_expected_set();
std::cout << "\nResults: " << passed << "/" << (passed + failed) << " passed\n";
return failed == 0 ? 0 : 1;
}

View File

@@ -12857,3 +12857,34 @@ INTERFACE target text.
- `editor/src/SchemaToCppGenerator.h` (`116` <= `600`)
- `editor/tests/step634_test.cpp` within test-file size guidance (`128` lines)
- Header-only architecture and naming conventions remain aligned with `ARCHITECTURE.md`
### Step 635: Capability declaration struct generator
**Status:** PASS (12/12 tests)
Adds a capability declaration generator for shared drone/orchestrator types:
`NodeCapability`, `CapabilitySet`, `EnergyContext`, and `JobRequirements`, plus
a header-only `supports(...)` helper.
**Files added:**
- `editor/src/CapabilityDeclarationGenerator.h` - capability type generator:
- emits shared capability structs and helper logic
- supports namespace customization for generated header text
- exposes generated type set metadata for validation/tests
- `editor/tests/step635_test.cpp` - 12 tests covering:
- namespace validation and default generation
- generated type presence and helper emission
- header-only pattern checks and type set integrity
**Files modified:**
- `editor/CMakeLists.txt` - `step635_test` target
**Verification run:**
- `cmake -S editor -B editor/build-native` - PASS
- `cmake --build editor/build-native --target step635_test step634_test` - PASS
- `./editor/build-native/step635_test` - PASS (12/12)
- `./editor/build-native/step634_test` - PASS (12/12) regression coverage
**Architecture gate check:**
- `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`