// Step 315: Routing Annotation Types — Subject 9: Workflow (12 tests) // 6 annotation types: ContextWidth, Review, Automatability, Priority, // ImplementationStatus, + AmbiguityAnnotation level/description fields. // Wired through Serialization, CompactAST, SidecarPersistence, SemannoFormat. #include "ast/Module.h" #include "ast/Function.h" #include "ast/Annotation.h" #include "ast/Serialization.h" #include "CompactAST.h" #include "SidecarPersistence.h" #include "SemannoFormat.h" #include #include #include #include using json = nlohmann::json; 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 {} // 1. ContextWidthAnnotation construction + properties void test_context_width_construction() { TEST(context_width_construction); auto cw = std::make_unique(); cw->id = "cw1"; cw->width = "project"; CHECK(cw->conceptType == "ContextWidthAnnotation", "conceptType"); CHECK(cw->width == "project", "width"); PASS(); } // 2. ReviewAnnotation construction + properties void test_review_construction() { TEST(review_construction); auto rv = std::make_unique(); rv->id = "rv1"; rv->required = true; rv->reviewer = "human"; rv->reason = "security-critical"; CHECK(rv->conceptType == "ReviewAnnotation", "conceptType"); CHECK(rv->required == true, "required"); CHECK(rv->reviewer == "human", "reviewer"); CHECK(rv->reason == "security-critical", "reason"); PASS(); } // 3. AutomatabilityAnnotation construction void test_automatability_construction() { TEST(automatability_construction); auto aa = std::make_unique(); aa->id = "aa1"; aa->strategy = "llm"; aa->confidence = 0.85; CHECK(aa->conceptType == "AutomatabilityAnnotation", "conceptType"); CHECK(aa->strategy == "llm", "strategy"); CHECK(aa->confidence > 0.8, "confidence"); PASS(); } // 4. PriorityAnnotation with blockedBy void test_priority_construction() { TEST(priority_construction); auto pa = std::make_unique(); pa->id = "pa1"; pa->level = "critical"; pa->blockedBy.push_back("task-1"); pa->blockedBy.push_back("task-2"); CHECK(pa->conceptType == "PriorityAnnotation", "conceptType"); CHECK(pa->level == "critical", "level"); CHECK(pa->blockedBy.size() == 2, "blockedBy count"); CHECK(pa->blockedBy[0] == "task-1", "blockedBy[0]"); PASS(); } // 5. ImplementationStatusAnnotation construction void test_impl_status_construction() { TEST(impl_status_construction); auto is = std::make_unique(); is->id = "is1"; is->status = "skeleton"; is->assignee = "agent-1"; CHECK(is->conceptType == "ImplementationStatusAnnotation", "conceptType"); CHECK(is->status == "skeleton", "status"); CHECK(is->assignee == "agent-1", "assignee"); PASS(); } // 6. JSON roundtrip for all 5 types void test_json_roundtrip() { TEST(json_roundtrip); // Build module with all 5 workflow annotations on a function auto mod = std::make_unique("mod1", "testmod", "python"); auto fn = std::make_unique("fn1", "process"); auto cw = std::make_unique(); cw->id = "cw1"; cw->width = "file"; fn->addChild("annotations", cw.release()); auto rv = std::make_unique(); rv->id = "rv1"; rv->required = true; rv->reviewer = "agent"; rv->reason = "complex"; fn->addChild("annotations", rv.release()); auto aa = std::make_unique(); aa->id = "aa1"; aa->strategy = "template"; aa->confidence = 0.9; fn->addChild("annotations", aa.release()); auto pa = std::make_unique(); pa->id = "pa1"; pa->level = "high"; pa->blockedBy.push_back("dep-1"); fn->addChild("annotations", pa.release()); auto is = std::make_unique(); is->id = "is1"; is->status = "partial"; is->assignee = "claude"; fn->addChild("annotations", is.release()); mod->addChild("functions", fn.release()); // Serialize json j = toJson(mod.get()); std::string serialized = j.dump(); CHECK(serialized.find("ContextWidthAnnotation") != std::string::npos, "CW in JSON"); CHECK(serialized.find("ReviewAnnotation") != std::string::npos, "RV in JSON"); CHECK(serialized.find("AutomatabilityAnnotation") != std::string::npos, "AA in JSON"); CHECK(serialized.find("PriorityAnnotation") != std::string::npos, "PA in JSON"); CHECK(serialized.find("ImplementationStatusAnnotation") != std::string::npos, "IS in JSON"); // Deserialize auto* restored = fromJson(j); CHECK(restored != nullptr, "fromJson returned non-null"); auto fns = restored->getChildren("functions"); CHECK(!fns.empty(), "has functions"); auto annos = fns[0]->getChildren("annotations"); CHECK(annos.size() == 5, "5 annotations restored, got: " + std::to_string(annos.size())); // Verify types bool hasCW = false, hasRV = false, hasAA = false, hasPA = false, hasIS = false; for (auto* a : annos) { if (a->conceptType == "ContextWidthAnnotation") { hasCW = true; auto* cwn = static_cast(a); CHECK(cwn->width == "file", "CW width restored"); } if (a->conceptType == "ReviewAnnotation") { hasRV = true; auto* rvn = static_cast(a); CHECK(rvn->required == true, "RV required restored"); CHECK(rvn->reviewer == "agent", "RV reviewer restored"); } if (a->conceptType == "AutomatabilityAnnotation") { hasAA = true; auto* aan = static_cast(a); CHECK(aan->strategy == "template", "AA strategy restored"); CHECK(aan->confidence > 0.8, "AA confidence restored"); } if (a->conceptType == "PriorityAnnotation") { hasPA = true; auto* pan = static_cast(a); CHECK(pan->level == "high", "PA level restored"); CHECK(pan->blockedBy.size() == 1, "PA blockedBy restored"); } if (a->conceptType == "ImplementationStatusAnnotation") { hasIS = true; auto* isn = static_cast(a); CHECK(isn->status == "partial", "IS status restored"); CHECK(isn->assignee == "claude", "IS assignee restored"); } } CHECK(hasCW && hasRV && hasAA && hasPA && hasIS, "All 5 types roundtripped"); delete restored; PASS(); } // 7. Compact AST semantic summary includes workflow annotations void test_compact_ast_summary() { TEST(compact_ast_summary); auto mod = std::make_unique("mod1", "testmod", "python"); auto fn = std::make_unique("fn1", "process"); auto cw = std::make_unique(); cw->id = "cw1"; cw->width = "project"; fn->addChild("annotations", cw.release()); auto pa = std::make_unique(); pa->id = "pa1"; pa->level = "critical"; fn->addChild("annotations", pa.release()); auto is = std::make_unique(); is->id = "is1"; is->status = "skeleton"; fn->addChild("annotations", is.release()); auto* fnPtr = fn.get(); mod->addChild("functions", fn.release()); // Use toJsonCompactTree which walks the full tree including children json compactTree = toJsonCompactTree(mod.get()); std::string str = compactTree.dump(); CHECK(str.find("contextWidth") != std::string::npos, "contextWidth in compact"); CHECK(str.find("priority") != std::string::npos, "priority in compact"); CHECK(str.find("implStatus") != std::string::npos, "implStatus in compact"); PASS(); } // 8. SidecarPersistence recognizes all 5 as semantic annotations void test_sidecar_recognition() { TEST(sidecar_recognition); CHECK(isSemanticAnnotation("ContextWidthAnnotation"), "CW is semantic"); CHECK(isSemanticAnnotation("ReviewAnnotation"), "RV is semantic"); CHECK(isSemanticAnnotation("AutomatabilityAnnotation"), "AA is semantic"); CHECK(isSemanticAnnotation("PriorityAnnotation"), "PA is semantic"); CHECK(isSemanticAnnotation("ImplementationStatusAnnotation"), "IS is semantic"); PASS(); } // 9. SemannoFormat emits all 5 types void test_semanno_emission() { TEST(semanno_emission); SemannoEmitter emitter; auto cw = std::make_unique(); cw->id = "cw1"; cw->width = "local"; std::string cwOut = emitter.emit(cw.get()); CHECK(cwOut.find("@semanno:contextwidth") != std::string::npos, "CW semanno tag: " + cwOut); CHECK(cwOut.find("local") != std::string::npos, "CW width value"); auto rv = std::make_unique(); rv->id = "rv1"; rv->required = true; rv->reviewer = "human"; std::string rvOut = emitter.emit(rv.get()); CHECK(rvOut.find("@semanno:review") != std::string::npos, "RV semanno tag: " + rvOut); CHECK(rvOut.find("human") != std::string::npos, "RV reviewer value"); auto aa = std::make_unique(); aa->id = "aa1"; aa->strategy = "deterministic"; std::string aaOut = emitter.emit(aa.get()); CHECK(aaOut.find("@semanno:automatability") != std::string::npos, "AA semanno tag: " + aaOut); CHECK(aaOut.find("deterministic") != std::string::npos, "AA strategy value"); auto pa = std::make_unique(); pa->id = "pa1"; pa->level = "medium"; std::string paOut = emitter.emit(pa.get()); CHECK(paOut.find("@semanno:priority") != std::string::npos, "PA semanno tag: " + paOut); CHECK(paOut.find("medium") != std::string::npos, "PA level value"); auto is = std::make_unique(); is->id = "is1"; is->status = "complete"; is->assignee = "alice"; std::string isOut = emitter.emit(is.get()); CHECK(isOut.find("@semanno:implstatus") != std::string::npos, "IS semanno tag: " + isOut); CHECK(isOut.find("complete") != std::string::npos, "IS status value"); PASS(); } // 10. AmbiguityAnnotation extended with level + description void test_ambiguity_extended() { TEST(ambiguity_extended); auto aa = std::make_unique(); aa->id = "amb1"; aa->intent = "original intent"; aa->options.push_back("opt1"); aa->level = "high"; aa->description = "Requirements are unclear"; // JSON roundtrip auto mod = std::make_unique("mod1", "testmod", "python"); auto fn = std::make_unique("fn1", "process"); fn->addChild("annotations", aa.release()); mod->addChild("functions", fn.release()); json j = toJson(mod.get()); auto* restored = fromJson(j); auto annos = restored->getChildren("functions")[0]->getChildren("annotations"); CHECK(!annos.empty(), "has annotations"); auto* amb = static_cast(annos[0]); CHECK(amb->intent == "original intent", "intent preserved"); CHECK(amb->level == "high", "level preserved"); CHECK(amb->description == "Requirements are unclear", "description preserved"); delete restored; PASS(); } // 11. Semanno parse roundtrip for workflow annotations void test_semanno_parse_roundtrip() { TEST(semanno_parse_roundtrip); SemannoEmitter emitter; auto cw = std::make_unique(); cw->id = "cw1"; cw->width = "cross-project"; std::string emitted = "# " + emitter.emit(cw.get()); auto entry = SemannoParser::parse(emitted); CHECK(entry.type == "contextwidth", "Parsed type: " + entry.type); CHECK(entry.properties.count("width"), "has width property"); CHECK(entry.properties["width"] == "cross-project", "width value: " + entry.properties["width"]); PASS(); } // 12. Validation of enum values void test_enum_validation() { TEST(enum_validation); // ContextWidth valid values std::set validWidths = {"local", "file", "project", "cross-project"}; for (const auto& w : validWidths) { auto cw = std::make_unique(); cw->width = w; CHECK(validWidths.count(cw->width), "Valid width: " + w); } // Automatability valid values std::set validStrategies = {"deterministic", "template", "slm", "llm", "human"}; for (const auto& s : validStrategies) { auto aa = std::make_unique(); aa->strategy = s; CHECK(validStrategies.count(aa->strategy), "Valid strategy: " + s); } // Priority valid values std::set validLevels = {"critical", "high", "medium", "low"}; for (const auto& l : validLevels) { auto pa = std::make_unique(); pa->level = l; CHECK(validLevels.count(pa->level), "Valid level: " + l); } // ImplementationStatus valid values std::set validStatuses = {"skeleton", "partial", "complete", "needs-review"}; for (const auto& s : validStatuses) { auto is = std::make_unique(); is->status = s; CHECK(validStatuses.count(is->status), "Valid status: " + s); } PASS(); } int main() { std::cout << "Step 315: Routing Annotation Types (Subject 9: Workflow)\n"; test_context_width_construction(); test_review_construction(); test_automatability_construction(); test_priority_construction(); test_impl_status_construction(); test_json_roundtrip(); test_compact_ast_summary(); test_sidecar_recognition(); test_semanno_emission(); test_ambiguity_extended(); test_semanno_parse_roundtrip(); test_enum_validation(); std::cout << "\nResults: " << passed << "/" << (passed + failed) << " passed\n"; return failed > 0 ? 1 : 0; }