From 6f990315962817b1724fffd20077e644c2dca0c0 Mon Sep 17 00:00:00 2001 From: Bill Date: Tue, 17 Feb 2026 10:17:15 -0700 Subject: [PATCH] Step 548: integrate phase 29a routing and cost policy flow --- editor/CMakeLists.txt | 9 +++ editor/src/Phase29aIntegration.h | 69 ++++++++++++++++ editor/tests/step548_test.cpp | 132 +++++++++++++++++++++++++++++++ progress.md | 43 ++++++++++ 4 files changed, 253 insertions(+) create mode 100644 editor/src/Phase29aIntegration.h create mode 100644 editor/tests/step548_test.cpp diff --git a/editor/CMakeLists.txt b/editor/CMakeLists.txt index 453e96c..469e2c2 100644 --- a/editor/CMakeLists.txt +++ b/editor/CMakeLists.txt @@ -3811,4 +3811,13 @@ target_link_libraries(step547_test PRIVATE tree_sitter_javascript tree_sitter_typescript tree_sitter_java tree_sitter_rust tree_sitter_go) +add_executable(step548_test tests/step548_test.cpp) +target_include_directories(step548_test PRIVATE src) +target_link_libraries(step548_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) diff --git a/editor/src/Phase29aIntegration.h b/editor/src/Phase29aIntegration.h new file mode 100644 index 0000000..04da06b --- /dev/null +++ b/editor/src/Phase29aIntegration.h @@ -0,0 +1,69 @@ +#pragma once +// Step 548: Phase 29a Integration + +#include +#include +#include + +#include "ConstrainedRoutingRulesetExtension.h" +#include "ContextBundleMinimizer.h" +#include "ConstrainedConfidenceCalibrator.h" +#include "CostPolicyGuard.h" + +struct Phase29aRequest { + ConstrainedRoutingInput routing; + ContextBundleInput context; + double baseConfidence = 0.0; + std::string preferredRoute; + std::map successes; + std::map attempts; + std::map postApplyFailures; + CostPolicyInput cost; +}; + +struct Phase29aResult { + bool passed = false; + ConstrainedRoutingDecision routingDecision; + ContextBundleOutput minimizedContext; + CalibratedConfidence calibrated; + CostPolicyResult costPolicy; + std::vector errors; +}; + +class Phase29aIntegration { +public: + static Phase29aResult run(const Phase29aRequest& request) { + Phase29aResult out; + out.routingDecision = ConstrainedRoutingRulesetExtension::decide(request.routing); + out.minimizedContext = ContextBundleMinimizer::minimize(request.context); + out.calibrated = ConstrainedConfidenceCalibrator::calibrate( + request.baseConfidence, + request.successes, + request.attempts, + request.postApplyFailures, + request.preferredRoute); + out.costPolicy = CostPolicyGuard::evaluate(request.cost); + + if (!out.costPolicy.allowed) { + out.errors.push_back("cost_policy_blocked"); + } + + if (out.routingDecision.route == "escalate") { + out.errors.push_back("routing_escalated"); + } + + if (request.context.narrowOperation && + out.minimizedContext.minimalContext.size() > + request.context.fileContext.size() + 2) { + out.errors.push_back("context_not_sufficiently_minimized"); + } + + if (out.calibrated.adjustedConfidence < 0.40 && + out.routingDecision.route == "deterministic_template") { + out.errors.push_back("low_calibrated_confidence_for_template_route"); + } + + out.passed = out.errors.empty(); + return out; + } +}; diff --git a/editor/tests/step548_test.cpp b/editor/tests/step548_test.cpp new file mode 100644 index 0000000..de91250 --- /dev/null +++ b/editor/tests/step548_test.cpp @@ -0,0 +1,132 @@ +// Step 548: Phase 29a Integration (8 tests) + +#include "Phase29aIntegration.h" + +#include + +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 Phase29aRequest baseRequest() { + Phase29aRequest r; + r.routing = {"rename", 0.9, true, true, false}; + r.context.taskitemId = "ti-548"; + r.context.contractTargets = {"Function"}; + r.context.contractSymbols = {"cursor"}; + r.context.contractOps = {"rename"}; + r.context.fileContext = {"file:main.cpp", "ast:Function cursor", "diag:none"}; + r.context.projectContext = {"module:cursor helpers", "module:theme"}; + r.context.dependencyContext = {"dep:cursor_utils", "dep:sdl2"}; + r.context.narrowOperation = true; + + r.baseConfidence = 0.8; + r.preferredRoute = "deterministic_template"; + r.successes = {{"deterministic_template", 8}}; + r.attempts = {{"deterministic_template", 10}}; + r.postApplyFailures = {{"deterministic_template", 1}}; + + r.cost = {120, 500, 200, 1000, false, false}; + return r; +} + +static bool hasError(const Phase29aResult& r, const std::string& e) { + for (const auto& x : r.errors) if (x == e) return true; + return false; +} + +void test_pass_path_with_lower_context_and_cost_compliance() { + TEST(pass_path_with_lower_context_and_cost_compliance); + auto r = Phase29aIntegration::run(baseRequest()); + CHECK(r.passed, "expected pass path"); + CHECK(r.costPolicy.allowed, "cost policy should allow"); + PASS(); +} + +void test_cost_policy_block_fails_integration() { + TEST(cost_policy_block_fails_integration); + auto req = baseRequest(); + req.cost = {400, 1500, 200, 1000, false, false}; + auto r = Phase29aIntegration::run(req); + CHECK(!r.passed, "cost-blocked path should fail integration"); + CHECK(hasError(r, "cost_policy_blocked"), "cost error expected"); + PASS(); +} + +void test_routing_escalation_fails_integration() { + TEST(routing_escalation_fails_integration); + auto req = baseRequest(); + req.routing.hasRecentPostApplyFailures = true; + auto r = Phase29aIntegration::run(req); + CHECK(!r.passed, "routing escalation should fail integration"); + CHECK(hasError(r, "routing_escalated"), "routing escalation error expected"); + PASS(); +} + +void test_narrow_context_is_minimized() { + TEST(narrow_context_is_minimized); + auto req = baseRequest(); + auto r = Phase29aIntegration::run(req); + CHECK(r.minimizedContext.removedContext.size() > 0, "narrow mode should remove irrelevant context"); + PASS(); +} + +void test_low_calibrated_confidence_blocks_template_route() { + TEST(low_calibrated_confidence_blocks_template_route); + auto req = baseRequest(); + req.baseConfidence = 0.2; + req.successes = {{"deterministic_template", 0}}; + req.attempts = {{"deterministic_template", 10}}; + req.postApplyFailures = {{"deterministic_template", 8}}; + auto r = Phase29aIntegration::run(req); + CHECK(!r.passed, "low calibrated confidence should block"); + CHECK(hasError(r, "low_calibrated_confidence_for_template_route"), "calibration error expected"); + PASS(); +} + +void test_calibration_can_shift_route_recommendation() { + TEST(calibration_can_shift_route_recommendation); + auto req = baseRequest(); + req.successes = {{"deterministic_template", 1}, {"constrained_worker", 9}}; + req.attempts = {{"deterministic_template", 10}, {"constrained_worker", 10}}; + req.postApplyFailures = {{"deterministic_template", 6}, {"constrained_worker", 0}}; + auto r = Phase29aIntegration::run(req); + CHECK(r.calibrated.recommendedRoute == "constrained_worker", "calibration should prefer stronger route"); + PASS(); +} + +void test_cost_guard_allows_when_rationale_and_approval_present() { + TEST(cost_guard_allows_when_rationale_and_approval_present); + auto req = baseRequest(); + req.cost = {300, 1300, 200, 1000, true, true}; + auto r = Phase29aIntegration::run(req); + CHECK(r.costPolicy.allowed, "approved overage should be allowed"); + PASS(); +} + +void test_phase29a_handles_non_narrow_context_without_minimization_error() { + TEST(phase29a_handles_non_narrow_context_without_minimization_error); + auto req = baseRequest(); + req.context.narrowOperation = false; + auto r = Phase29aIntegration::run(req); + CHECK(!hasError(r, "context_not_sufficiently_minimized"), "non-narrow mode should not trigger strict minimization error"); + PASS(); +} + +int main() { + std::cout << "Step 548: Phase 29a Integration\n"; + + test_pass_path_with_lower_context_and_cost_compliance(); // 1 + test_cost_policy_block_fails_integration(); // 2 + test_routing_escalation_fails_integration(); // 3 + test_narrow_context_is_minimized(); // 4 + test_low_calibrated_confidence_blocks_template_route(); // 5 + test_calibration_can_shift_route_recommendation(); // 6 + test_cost_guard_allows_when_rationale_and_approval_present(); // 7 + test_phase29a_handles_non_narrow_context_without_minimization_error(); // 8 + + std::cout << "\nResults: " << passed << "/" << (passed + failed) << " passed\n"; + return failed == 0 ? 0 : 1; +} diff --git a/progress.md b/progress.md index 9db890f..0ec58b2 100644 --- a/progress.md +++ b/progress.md @@ -9507,3 +9507,46 @@ controls for overage execution. - `editor/src/CostPolicyGuard.h` within header-size limit (`60` <= `600`) - `editor/tests/step547_test.cpp` within test-file size guidance (`132` lines) - Header-only architecture and naming conventions remain aligned with `ARCHITECTURE.md` + +### Step 548: Phase 29a Integration +**Status:** PASS (8/8 tests) + +Integrates Phase 29a routing intelligence, context minimization, confidence +calibration, and cost policy enforcement into a unified constrained orchestration +decision flow. + +**Files added:** +- `editor/src/Phase29aIntegration.h` - Phase 29a integration gate: + - composes Step 544 routing policy, Step 545 context minimizer, + Step 546 confidence calibration, and Step 547 cost guard + - emits integrated pass/fail signal with structured error reasons + - guards template routing when calibrated confidence is too low + - enforces cost-policy and escalation outcomes in final decision +- `editor/tests/step548_test.cpp` - 8 tests covering: + - pass-path with reduced context and cost compliance + - cost-policy block behavior + - routing-escalation block behavior + - narrow-context minimization behavior + - low-calibrated-confidence template block behavior + - calibration route-shift behavior + - approved overage path behavior + - non-narrow context tolerance behavior + +**Files modified:** +- `editor/CMakeLists.txt` - `step548_test` target + +**Verification run:** +- `cmake -S editor -B editor/build-native` - PASS +- `cmake --build editor/build-native --target step548_test step547_test` - PASS +- `./editor/build-native/step548_test` - PASS (8/8) +- `./editor/build-native/step547_test` - PASS (12/12) regression coverage + +**Architecture gate check:** +- `editor/src/Phase29aIntegration.h` within header-size limit (`69` <= `600`) +- `editor/tests/step548_test.cpp` within test-file size guidance (`132` lines) +- Header-only architecture and naming conventions remain aligned with `ARCHITECTURE.md` + +**Phase 29a totals (544-548):** +- **Steps completed:** 5 +- **New tests in phase plan:** 56/56 passing +- **Routing/context/cost optimization integration:** PASS