Step 432: add Phase 19a integration suite

This commit is contained in:
Bill
2026-02-16 17:18:27 -07:00
parent 54bb39c69b
commit 2ac44a66f7
3 changed files with 241 additions and 0 deletions

View File

@@ -2767,4 +2767,13 @@ target_link_libraries(step431_test PRIVATE
tree_sitter_javascript tree_sitter_typescript
tree_sitter_java tree_sitter_rust tree_sitter_go)
add_executable(step432_test tests/step432_test.cpp)
target_include_directories(step432_test PRIVATE src)
target_link_libraries(step432_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,182 @@
// Step 432: Phase 19a Integration Tests (8 tests)
#include "WorkflowTaskBoard.h"
#include "WorkflowTaskDetail.h"
#include "WorkflowDependencyView.h"
#include "WorkflowProgressDashboard.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 WorkItem makeItem(const std::string& id, const std::string& status,
const std::string& worker, const std::vector<std::string>& deps = {}) {
WorkItem wi;
wi.id = id;
wi.nodeId = id + "_node";
wi.nodeName = id;
wi.nodeType = "Function";
wi.bufferId = "src/" + id + ".cpp";
wi.status = status;
wi.workerType = worker;
wi.priority = "high";
wi.contextWidth = "file";
wi.reviewRequired = (worker == "llm" || worker == "human");
wi.dependencies = deps;
wi.result.generatedCode = "void " + id + "() {}";
return wi;
}
static WorkflowState makeWorkflow() {
WorkflowState wf("phase19a");
wf.queue.enqueue(makeItem("taskA", WI_READY, "template"));
wf.queue.enqueue(makeItem("taskB", WI_IN_PROGRESS, "llm", {"taskA"}));
wf.queue.enqueue(makeItem("taskC", WI_REVIEW, "llm", {"taskB"}));
wf.queue.enqueue(makeItem("taskD", WI_COMPLETE, "deterministic"));
return wf;
}
static WorkflowProgress makeProgress() {
WorkflowProgress p(4);
p.recordEvent({"routed", "taskA", {{"workerType", "template"}}, "2026-01-01T00:00:00Z"});
p.recordEvent({"completed", "taskA", json::object(), "2026-01-01T00:01:00Z"});
p.recordEvent({"routed", "taskB", {{"workerType", "llm"}}, "2026-01-01T00:02:00Z"});
p.recordEvent({"blocked", "", {{"blockers", json::array({
{{"type", "needs-review"}, {"itemIds", json::array({"taskC"})}, {"description", "review pending"}}
})}}, "2026-01-01T00:03:00Z"});
return p;
}
static int countColumn(const std::vector<TaskBoardColumn>& cols, const std::string& key) {
for (const auto& c : cols) if (c.key == key) return (int)c.cards.size();
return 0;
}
void test_task_board_reflects_workflow_state() {
TEST(task_board_reflects_workflow_state);
auto board = WorkflowTaskBoard::build(makeWorkflow());
CHECK(countColumn(board, "ready") >= 1, "ready column missing cards");
CHECK(countColumn(board, "review") >= 1, "review column missing cards");
PASS();
}
void test_dependency_graph_updates_after_completion() {
TEST(dependency_graph_updates_after_completion);
auto wf = makeWorkflow();
auto g1 = WorkflowDependencyView::build(wf);
auto b1 = g1.getNode("taskB");
CHECK(b1.has_value() && b1->colorHex == "#3498DB", "taskB should start blue");
auto item = wf.queue.getItem("taskB");
item->status = WI_COMPLETE;
wf.queue.updateItem("taskB", *item);
auto g2 = WorkflowDependencyView::build(wf);
auto b2 = g2.getNode("taskB");
CHECK(b2.has_value() && b2->colorHex == "#2ECC71", "taskB should turn green");
PASS();
}
void test_progress_dashboard_reflects_event_stream() {
TEST(progress_dashboard_reflects_event_stream);
auto d = WorkflowProgressDashboard::build(makeWorkflow(), makeProgress(), nullptr);
CHECK(!d.throughputSeries.empty(), "throughput series missing");
CHECK(!d.blockerSummary.empty(), "blocker summary missing");
PASS();
}
void test_review_approve_updates_board_and_detail() {
TEST(review_approve_updates_board_and_detail);
auto wf = makeWorkflow();
CHECK(WorkflowTaskDetail::approve(wf, "taskC"), "approve should succeed");
auto board = WorkflowTaskBoard::build(wf);
CHECK(countColumn(board, "review") == 0, "review column should be cleared");
CHECK(countColumn(board, "complete") >= 2, "complete column should increase");
auto detail = WorkflowTaskDetail::build(wf, "taskC");
CHECK(detail.has_value() && detail->status == WI_COMPLETE, "detail should show complete");
PASS();
}
void test_review_reject_requeues_and_visible_on_board() {
TEST(review_reject_requeues_and_visible_on_board);
auto wf = makeWorkflow();
CHECK(WorkflowTaskDetail::reject(wf, "taskC", "needs changes"), "reject should succeed");
auto board = WorkflowTaskBoard::build(wf);
CHECK(countColumn(board, "ready") >= 2, "rejected item should requeue to ready");
PASS();
}
void test_dependency_click_navigates_to_task_detail() {
TEST(dependency_click_navigates_to_task_detail);
auto wf = makeWorkflow();
auto graph = WorkflowDependencyView::build(wf);
std::string id = WorkflowDependencyView::navigateToTaskId(graph, "taskB");
auto detail = WorkflowTaskDetail::build(wf, id);
CHECK(!id.empty(), "navigation id missing");
CHECK(detail.has_value(), "detail should be openable from graph click");
PASS();
}
void test_board_filter_and_detail_consistency() {
TEST(board_filter_and_detail_consistency);
auto wf = makeWorkflow();
TaskBoardFilter f;
f.workerType = "llm";
auto board = WorkflowTaskBoard::build(wf, f);
int cards = 0;
std::string firstId;
for (const auto& col : board) {
cards += (int)col.cards.size();
if (firstId.empty() && !col.cards.empty()) firstId = col.cards[0].itemId;
}
auto detail = WorkflowTaskDetail::build(wf, firstId);
CHECK(cards >= 2, "llm filter should keep two cards");
CHECK(detail.has_value() && detail->workerType == "llm", "detail worker mismatch");
PASS();
}
void test_end_to_end_visual_workflow_sequence() {
TEST(end_to_end_visual_workflow_sequence);
auto wf = makeWorkflow();
WorkflowProgress prog(4);
prog.recordEvent({"routed", "taskA", {{"workerType", "template"}}, "2026-01-01T00:00:00Z"});
prog.recordEvent({"completed", "taskA", json::object(), "2026-01-01T00:01:00Z"});
auto a = wf.queue.getItem("taskB");
a->status = WI_COMPLETE;
wf.queue.updateItem("taskB", *a);
prog.recordEvent({"completed", "taskB", json::object(), "2026-01-01T00:02:00Z"});
CHECK(WorkflowTaskDetail::approve(wf, "taskC"), "review approval failed");
prog.recordEvent({"completed", "taskC", json::object(), "2026-01-01T00:03:00Z"});
auto board = WorkflowTaskBoard::build(wf);
auto graph = WorkflowDependencyView::build(wf);
auto dash = WorkflowProgressDashboard::build(wf, prog, nullptr);
CHECK(countColumn(board, "review") == 0, "review should be empty");
CHECK(graph.getNode("taskC").has_value() &&
graph.getNode("taskC")->colorHex == "#2ECC71",
"taskC should be green in graph");
CHECK(dash.completedItems >= 3, "dashboard completion should advance");
PASS();
}
int main() {
std::cout << "Step 432: Phase 19a Integration Tests\n";
test_task_board_reflects_workflow_state(); // 1
test_dependency_graph_updates_after_completion(); // 2
test_progress_dashboard_reflects_event_stream(); // 3
test_review_approve_updates_board_and_detail(); // 4
test_review_reject_requeues_and_visible_on_board(); // 5
test_dependency_click_navigates_to_task_detail(); // 6
test_board_filter_and_detail_consistency(); // 7
test_end_to_end_visual_workflow_sequence(); // 8
std::cout << "\nResults: " << passed << "/" << (passed + failed)
<< " passed\n";
return failed == 0 ? 0 : 1;
}

View File

@@ -4944,6 +4944,56 @@ tracking into a panel-ready snapshot.
- `editor/src/MCPServer.h` (`1940` > `600`)
- `editor/src/HeadlessAgentRPCHandler.h` (`2768` > `600`)
### Step 432: Phase 19a Integration
**Status:** PASS (8/8 tests)
Added Phase 19a integration coverage ensuring task board, task detail actions,
dependency view, and progress dashboard stay synchronized across workflow state
changes and review lifecycle transitions.
**Files created:**
- `editor/tests/step432_test.cpp` — 8 integration tests covering:
1. task board state sync
2. dependency graph update after completion
3. progress dashboard timeline/blocker sync
4. review approve flow updates board+detail
5. review reject flow requeues on board
6. dependency-node click to detail navigation
7. board filter/detail consistency
8. end-to-end visible flow (route -> execute -> review -> complete)
**Files modified:**
- `editor/CMakeLists.txt``step432_test` target
**Verification run:**
- `step432_test` — PASS (8/8) new phase-integration coverage
- `step431_test` — PASS (12/12) regression coverage
- `step430_test` — PASS (12/12) regression coverage
**Phase 19a completion snapshot (Steps 428-432):**
- Step 428: task board model (kanban columns, filters, moves)
- Step 429: task detail model (skeleton/result/diff/routing/review actions)
- Step 430: dependency graph visualization adapter
- Step 431: progress dashboard model
- Step 432: integration across board/detail/graph/dashboard
**Architecture gate check (end of Phase 19a):**
- New Phase 19a headers within header-size limit:
- `editor/src/WorkflowTaskBoard.h` (`154` <= `600`)
- `editor/src/WorkflowTaskDetail.h` (`121` <= `600`)
- `editor/src/WorkflowDependencyView.h` (`94` <= `600`)
- `editor/src/WorkflowProgressDashboard.h` (`112` <= `600`)
- New Phase 19a tests within file-size guidance:
- `editor/tests/step428_test.cpp` (`186` lines)
- `editor/tests/step429_test.cpp` (`169` lines)
- `editor/tests/step430_test.cpp` (`155` lines)
- `editor/tests/step431_test.cpp` (`202` lines)
- `editor/tests/step432_test.cpp` (`182` lines)
- Legacy oversized headers persist:
- `editor/src/ast/Serialization.h` (`1427` > `600`)
- `editor/src/MCPServer.h` (`1940` > `600`)
- `editor/src/HeadlessAgentRPCHandler.h` (`2768` > `600`)
# Roadmap Planning — Sprints 12-25+
## Status: Planning Complete (Sprints 12-19 detailed, 20-25 in roadmap.md)