Add step 618 sprint 36a integration
This commit is contained in:
@@ -4441,4 +4441,13 @@ target_link_libraries(step617_test PRIVATE
|
||||
tree_sitter_javascript tree_sitter_typescript
|
||||
tree_sitter_java tree_sitter_rust tree_sitter_go)
|
||||
|
||||
add_executable(step618_test tests/step618_test.cpp)
|
||||
target_include_directories(step618_test PRIVATE src)
|
||||
target_link_libraries(step618_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)
|
||||
|
||||
71
editor/src/Sprint36aIntegration.h
Normal file
71
editor/src/Sprint36aIntegration.h
Normal file
@@ -0,0 +1,71 @@
|
||||
#pragma once
|
||||
// Step 618: Sprint 36a MCP Intake Integration
|
||||
|
||||
#include "MCPServer.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
struct Sprint36aIntegrationResult {
|
||||
bool success = false;
|
||||
std::string stage;
|
||||
int taskCount = 0;
|
||||
int readyCount = 0;
|
||||
int escalateCount = 0;
|
||||
std::vector<std::string> blockers;
|
||||
};
|
||||
|
||||
class Sprint36aIntegration {
|
||||
public:
|
||||
static Sprint36aIntegrationResult run(const std::string& markdown) {
|
||||
Sprint36aIntegrationResult out;
|
||||
MCPServer mcp;
|
||||
|
||||
json intake = callTool(mcp, "whetstone_architect_intake", {{"markdown", markdown}});
|
||||
if (!intake.value("success", false)) {
|
||||
out.stage = "intake";
|
||||
return out;
|
||||
}
|
||||
|
||||
json generated = callTool(mcp, "whetstone_generate_taskitems", {
|
||||
{"normalizedRequirements", intake["normalizedRequirements"]},
|
||||
{"conflicts", intake["conflicts"]}
|
||||
});
|
||||
if (!generated.value("success", false)) {
|
||||
out.stage = "generate";
|
||||
return out;
|
||||
}
|
||||
|
||||
json queue = callTool(mcp, "whetstone_queue_ready", {
|
||||
{"tasks", generated["tasks"]},
|
||||
{"normalizedRequirements", intake["normalizedRequirements"]}
|
||||
});
|
||||
if (!queue.value("success", false)) {
|
||||
out.stage = "queue";
|
||||
return out;
|
||||
}
|
||||
|
||||
out.stage = "done";
|
||||
out.taskCount = (int)generated["tasks"].size();
|
||||
out.readyCount = queue.value("readyCount", 0);
|
||||
out.escalateCount = queue.value("escalateCount", 0);
|
||||
for (const auto& blocker : queue["blockers"]) {
|
||||
out.blockers.push_back(blocker.get<std::string>());
|
||||
}
|
||||
out.success = queue.value("ready", false);
|
||||
return out;
|
||||
}
|
||||
|
||||
private:
|
||||
static json callTool(MCPServer& mcp, const std::string& name, const json& args) {
|
||||
json req = {
|
||||
{"jsonrpc", "2.0"},
|
||||
{"id", 1},
|
||||
{"method", "tools/call"},
|
||||
{"params", {{"name", name}, {"arguments", args}}}
|
||||
};
|
||||
json resp = mcp.handleRequest(req);
|
||||
std::string text = resp["result"]["content"][0].value("text", "{}");
|
||||
return json::parse(text);
|
||||
}
|
||||
};
|
||||
121
editor/tests/step618_test.cpp
Normal file
121
editor/tests/step618_test.cpp
Normal file
@@ -0,0 +1,121 @@
|
||||
// Step 618: Sprint 36a Integration (8 tests)
|
||||
|
||||
#include "Sprint36aIntegration.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; } else {}
|
||||
|
||||
static std::string clearSpec() {
|
||||
return
|
||||
"## Goals\n"
|
||||
"- Ship architect intake MCP tools\n"
|
||||
"\n"
|
||||
"## Constraints\n"
|
||||
"- Keep code header only\n"
|
||||
"\n"
|
||||
"## Dependencies\n"
|
||||
"- nlohmann json\n"
|
||||
"\n"
|
||||
"## Acceptance Criteria\n"
|
||||
"- queue includes acceptance checks\n";
|
||||
}
|
||||
|
||||
static std::string riskySpec() {
|
||||
return
|
||||
"## Goals\n"
|
||||
"- maybe improve intake maybe maybe\n"
|
||||
"\n"
|
||||
"## Constraints\n"
|
||||
"- Do not use dynamic allocation in hot path\n"
|
||||
"- Use dynamic allocation in hot path for warmup\n"
|
||||
"\n"
|
||||
"## Dependencies\n"
|
||||
"- maybe add extra libs\n"
|
||||
"\n"
|
||||
"## Acceptance Criteria\n"
|
||||
"- maybe all tests pass\n";
|
||||
}
|
||||
|
||||
static bool hasBlocker(const Sprint36aIntegrationResult& r, const std::string& blocker) {
|
||||
for (const auto& b : r.blockers) if (b == blocker) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void test_clear_spec_reaches_done_stage() {
|
||||
TEST(clear_spec_reaches_done_stage);
|
||||
auto result = Sprint36aIntegration::run(clearSpec());
|
||||
CHECK(result.stage == "done", "expected done stage");
|
||||
PASS();
|
||||
}
|
||||
|
||||
void test_clear_spec_integration_success() {
|
||||
TEST(clear_spec_integration_success);
|
||||
auto result = Sprint36aIntegration::run(clearSpec());
|
||||
CHECK(result.success, "clear spec should be queue ready");
|
||||
PASS();
|
||||
}
|
||||
|
||||
void test_clear_spec_produces_tasks() {
|
||||
TEST(clear_spec_produces_tasks);
|
||||
auto result = Sprint36aIntegration::run(clearSpec());
|
||||
CHECK(result.taskCount >= 1, "taskCount should be >= 1");
|
||||
PASS();
|
||||
}
|
||||
|
||||
void test_clear_spec_has_ready_items() {
|
||||
TEST(clear_spec_has_ready_items);
|
||||
auto result = Sprint36aIntegration::run(clearSpec());
|
||||
CHECK(result.readyCount >= 1, "readyCount should be >= 1");
|
||||
PASS();
|
||||
}
|
||||
|
||||
void test_clear_spec_has_no_escalations() {
|
||||
TEST(clear_spec_has_no_escalations);
|
||||
auto result = Sprint36aIntegration::run(clearSpec());
|
||||
CHECK(result.escalateCount == 0, "escalateCount should be zero");
|
||||
PASS();
|
||||
}
|
||||
|
||||
void test_empty_markdown_fails_at_intake_stage() {
|
||||
TEST(empty_markdown_fails_at_intake_stage);
|
||||
auto result = Sprint36aIntegration::run("");
|
||||
CHECK(!result.success, "empty markdown should fail");
|
||||
CHECK(result.stage == "intake", "should fail at intake");
|
||||
PASS();
|
||||
}
|
||||
|
||||
void test_risky_spec_not_queue_ready() {
|
||||
TEST(risky_spec_not_queue_ready);
|
||||
auto result = Sprint36aIntegration::run(riskySpec());
|
||||
CHECK(!result.success, "risky spec should not be queue ready");
|
||||
CHECK(result.escalateCount >= 1, "should produce escalations");
|
||||
PASS();
|
||||
}
|
||||
|
||||
void test_risky_spec_has_escalation_blocker() {
|
||||
TEST(risky_spec_has_escalation_blocker);
|
||||
auto result = Sprint36aIntegration::run(riskySpec());
|
||||
CHECK(hasBlocker(result, "escalations_present"), "expected escalations_present blocker");
|
||||
PASS();
|
||||
}
|
||||
|
||||
int main() {
|
||||
std::cout << "Step 618: Sprint 36a Integration\n";
|
||||
|
||||
test_clear_spec_reaches_done_stage(); // 1
|
||||
test_clear_spec_integration_success(); // 2
|
||||
test_clear_spec_produces_tasks(); // 3
|
||||
test_clear_spec_has_ready_items(); // 4
|
||||
test_clear_spec_has_no_escalations(); // 5
|
||||
test_empty_markdown_fails_at_intake_stage(); // 6
|
||||
test_risky_spec_not_queue_ready(); // 7
|
||||
test_risky_spec_has_escalation_blocker(); // 8
|
||||
|
||||
std::cout << "\nResults: " << passed << "/" << (passed + failed) << " passed\n";
|
||||
return failed == 0 ? 0 : 1;
|
||||
}
|
||||
30
progress.md
30
progress.md
@@ -12186,3 +12186,33 @@ Adds an `instructions` string field to MCP `initialize` responses, populated fro
|
||||
- `editor/src/MCPServer.h` within header-size limit (`551` <= `600`)
|
||||
- `editor/tests/step617_test.cpp` within test-file size guidance (`165` lines)
|
||||
- Header-only architecture and naming conventions remain aligned with `ARCHITECTURE.md`
|
||||
|
||||
### Step 618: Phase 36a Integration
|
||||
**Status:** PASS (8/8 tests)
|
||||
|
||||
Adds a Sprint 36a end-to-end integration harness that executes the full MCP
|
||||
intake flow: spec markdown → intake tool → taskitem generation tool → queue
|
||||
readiness tool.
|
||||
|
||||
**Files added:**
|
||||
- `editor/src/Sprint36aIntegration.h` - integration runner:
|
||||
- sequential MCP tool orchestration across steps 614-616
|
||||
- stage-aware result reporting and queue summary extraction
|
||||
- `editor/tests/step618_test.cpp` - 8 integration tests covering:
|
||||
- happy-path end-to-end readiness
|
||||
- risky-spec escalation/blocker behavior
|
||||
- intake-stage failure propagation for invalid markdown
|
||||
|
||||
**Files modified:**
|
||||
- `editor/CMakeLists.txt` - `step618_test` target
|
||||
|
||||
**Verification run:**
|
||||
- `cmake -S editor -B editor/build-native` - PASS
|
||||
- `cmake --build editor/build-native --target step618_test step617_test` - PASS
|
||||
- `./editor/build-native/step618_test` - PASS (8/8)
|
||||
- `./editor/build-native/step617_test` - PASS (12/12) regression coverage
|
||||
|
||||
**Architecture gate check:**
|
||||
- `editor/src/Sprint36aIntegration.h` within header-size limit (`71` <= `600`)
|
||||
- `editor/tests/step618_test.cpp` within test-file size guidance (`121` lines)
|
||||
- Header-only architecture and naming conventions remain aligned with `ARCHITECTURE.md`
|
||||
|
||||
Reference in New Issue
Block a user