Step 547: add token ceiling and escalation cost guard

This commit is contained in:
Bill
2026-02-17 10:15:53 -07:00
parent 6d4b806849
commit c9e3c1decd
4 changed files with 238 additions and 0 deletions

View File

@@ -3802,4 +3802,13 @@ target_link_libraries(step546_test PRIVATE
tree_sitter_javascript tree_sitter_typescript
tree_sitter_java tree_sitter_rust tree_sitter_go)
add_executable(step547_test tests/step547_test.cpp)
target_include_directories(step547_test PRIVATE src)
target_link_libraries(step547_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,60 @@
#pragma once
// Step 547: Cost Policy Guard
#include <string>
#include <vector>
struct CostPolicyInput {
int stepTokens = 0;
int workflowTokens = 0;
int stepTokenCeiling = 0;
int workflowTokenCeiling = 0;
bool hasRationale = false;
bool hasEscalationApproval = false;
};
struct CostPolicyResult {
bool allowed = false;
bool requiresEscalation = false;
std::vector<std::string> violations;
std::string action = "allow"; // allow/request_rationale/escalate/block
};
class CostPolicyGuard {
public:
static CostPolicyResult evaluate(const CostPolicyInput& input) {
CostPolicyResult out;
const bool stepOver = input.stepTokenCeiling > 0 && input.stepTokens > input.stepTokenCeiling;
const bool workflowOver = input.workflowTokenCeiling > 0 &&
input.workflowTokens > input.workflowTokenCeiling;
if (!stepOver && !workflowOver) {
out.allowed = true;
out.action = "allow";
return out;
}
if (stepOver) out.violations.push_back("step_token_ceiling_exceeded");
if (workflowOver) out.violations.push_back("workflow_token_ceiling_exceeded");
if (!input.hasRationale) {
out.allowed = false;
out.action = "request_rationale";
return out;
}
// With rationale, require explicit escalation approval for overage execution.
if (!input.hasEscalationApproval) {
out.allowed = false;
out.requiresEscalation = true;
out.action = "escalate";
return out;
}
out.allowed = true;
out.requiresEscalation = true;
out.action = "allow";
return out;
}
};

View File

@@ -0,0 +1,132 @@
// Step 547: Cost Policy Guard (12 tests)
#include "CostPolicyGuard.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 bool hasViolation(const CostPolicyResult& r, const std::string& v) {
for (const auto& x : r.violations) if (x == v) return true;
return false;
}
void test_within_limits_allows_execution() {
TEST(within_limits_allows_execution);
auto r = CostPolicyGuard::evaluate({100, 500, 200, 1000, false, false});
CHECK(r.allowed, "within limits should allow");
CHECK(r.action == "allow", "action should be allow");
PASS();
}
void test_step_ceiling_exceeded_without_rationale_requests_rationale() {
TEST(step_ceiling_exceeded_without_rationale_requests_rationale);
auto r = CostPolicyGuard::evaluate({250, 500, 200, 1000, false, false});
CHECK(!r.allowed, "should not allow without rationale");
CHECK(r.action == "request_rationale", "action mismatch");
CHECK(hasViolation(r, "step_token_ceiling_exceeded"), "step violation missing");
PASS();
}
void test_workflow_ceiling_exceeded_without_rationale_requests_rationale() {
TEST(workflow_ceiling_exceeded_without_rationale_requests_rationale);
auto r = CostPolicyGuard::evaluate({150, 1200, 200, 1000, false, false});
CHECK(!r.allowed, "should not allow without rationale");
CHECK(r.action == "request_rationale", "action mismatch");
CHECK(hasViolation(r, "workflow_token_ceiling_exceeded"), "workflow violation missing");
PASS();
}
void test_both_ceilings_exceeded_collects_both_violations() {
TEST(both_ceilings_exceeded_collects_both_violations);
auto r = CostPolicyGuard::evaluate({250, 1200, 200, 1000, false, false});
CHECK(hasViolation(r, "step_token_ceiling_exceeded"), "step violation missing");
CHECK(hasViolation(r, "workflow_token_ceiling_exceeded"), "workflow violation missing");
PASS();
}
void test_with_rationale_but_no_approval_requires_escalation() {
TEST(with_rationale_but_no_approval_requires_escalation);
auto r = CostPolicyGuard::evaluate({250, 500, 200, 1000, true, false});
CHECK(!r.allowed, "should not allow without approval");
CHECK(r.requiresEscalation, "escalation should be required");
CHECK(r.action == "escalate", "action should be escalate");
PASS();
}
void test_with_rationale_and_approval_allows_with_escalation_flag() {
TEST(with_rationale_and_approval_allows_with_escalation_flag);
auto r = CostPolicyGuard::evaluate({250, 500, 200, 1000, true, true});
CHECK(r.allowed, "approved escalation should allow");
CHECK(r.requiresEscalation, "escalation flag should remain true");
PASS();
}
void test_workflow_overage_with_rationale_and_approval_allows() {
TEST(workflow_overage_with_rationale_and_approval_allows);
auto r = CostPolicyGuard::evaluate({150, 1500, 200, 1000, true, true});
CHECK(r.allowed, "approved workflow overage should allow");
CHECK(hasViolation(r, "workflow_token_ceiling_exceeded"), "workflow violation should be tracked");
PASS();
}
void test_equal_to_step_ceiling_is_allowed() {
TEST(equal_to_step_ceiling_is_allowed);
auto r = CostPolicyGuard::evaluate({200, 500, 200, 1000, false, false});
CHECK(r.allowed, "equal to step ceiling should be allowed");
PASS();
}
void test_equal_to_workflow_ceiling_is_allowed() {
TEST(equal_to_workflow_ceiling_is_allowed);
auto r = CostPolicyGuard::evaluate({150, 1000, 200, 1000, false, false});
CHECK(r.allowed, "equal to workflow ceiling should be allowed");
PASS();
}
void test_zero_ceiling_disables_check() {
TEST(zero_ceiling_disables_check);
auto r = CostPolicyGuard::evaluate({10000, 10000, 0, 0, false, false});
CHECK(r.allowed, "zero ceilings should disable checks");
PASS();
}
void test_negative_tokens_do_not_trigger_violations() {
TEST(negative_tokens_do_not_trigger_violations);
auto r = CostPolicyGuard::evaluate({-10, -50, 200, 1000, false, false});
CHECK(r.allowed, "negative token values should not violate ceilings");
PASS();
}
void test_escalation_not_required_when_within_limits_even_with_rationale() {
TEST(escalation_not_required_when_within_limits_even_with_rationale);
auto r = CostPolicyGuard::evaluate({100, 500, 200, 1000, true, true});
CHECK(r.allowed, "within limits should allow");
CHECK(!r.requiresEscalation, "escalation should not be required");
CHECK(r.violations.empty(), "no violations expected");
PASS();
}
int main() {
std::cout << "Step 547: Cost Policy Guard\n";
test_within_limits_allows_execution(); // 1
test_step_ceiling_exceeded_without_rationale_requests_rationale(); // 2
test_workflow_ceiling_exceeded_without_rationale_requests_rationale();// 3
test_both_ceilings_exceeded_collects_both_violations(); // 4
test_with_rationale_but_no_approval_requires_escalation(); // 5
test_with_rationale_and_approval_allows_with_escalation_flag(); // 6
test_workflow_overage_with_rationale_and_approval_allows(); // 7
test_equal_to_step_ceiling_is_allowed(); // 8
test_equal_to_workflow_ceiling_is_allowed(); // 9
test_zero_ceiling_disables_check(); // 10
test_negative_tokens_do_not_trigger_violations(); // 11
test_escalation_not_required_when_within_limits_even_with_rationale();// 12
std::cout << "\nResults: " << passed << "/" << (passed + failed) << " passed\n";
return failed == 0 ? 0 : 1;
}

View File

@@ -9470,3 +9470,40 @@ penalties for repeated post-apply failures.
- `editor/src/ConstrainedConfidenceCalibrator.h` within header-size limit (`97` <= `600`)
- `editor/tests/step546_test.cpp` within test-file size guidance (`143` lines)
- Header-only architecture and naming conventions remain aligned with `ARCHITECTURE.md`
### Step 547: Cost Policy Guard
**Status:** PASS (12/12 tests)
Implements cost policy enforcement for constrained orchestration with per-step
and per-workflow token ceilings, rationale requirements, and escalation approval
controls for overage execution.
**Files added:**
- `editor/src/CostPolicyGuard.h` - cost policy enforcement module:
- step/workflow ceiling checks
- violation capture for exceeded ceilings
- rationale-required flow for policy overages
- escalation-approval gate for over-budget execution
- deterministic action outputs (`allow`/`request_rationale`/`escalate`)
- `editor/tests/step547_test.cpp` - 12 tests covering:
- within-limit allow behavior
- step/workflow/both overage violation behavior
- rationale and escalation approval behavior
- equal-to-ceiling boundary behavior
- zero-ceiling disabled-check behavior
- negative-token edge behavior
- no-escalation behavior when within limits
**Files modified:**
- `editor/CMakeLists.txt` - `step547_test` target
**Verification run:**
- `cmake -S editor -B editor/build-native` - PASS
- `cmake --build editor/build-native --target step547_test step546_test` - PASS
- `./editor/build-native/step547_test` - PASS (12/12)
- `./editor/build-native/step546_test` - PASS (12/12) regression coverage
**Architecture gate check:**
- `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`