Block approve_ceo_strategy until hires exist

The CEO prompt carried a plea — "do not submit strategy before hires,
we have observed a loop" — in place of an actual gate. The model
could (and did) ignore it, land back in team_building mode, and
resubmit. Move the invariant into the /approvals POST handler:
reject approve_ceo_strategy with 409 STRATEGY_BEFORE_HIRES when no
hire_agent approval exists for the company, and 409 STRATEGY_ALREADY_FILED
when one is already pending or approved.

Introduce listCompanyApprovalsByType on the database facade to keep
the route stateless. Trim the prompt to describe the gate instead of
begging the model to obey.
This commit is contained in:
ZacharyZhang-NY committed 2026-04-19 19:22:34 -04:00
1 parent 09d1e2bd30
commit 0443b4a197
4 files changed
+43 -6

No files matched your search

+27
View File
@@ -41,6 +41,33 @@ export function registerApprovalRoutes(server: AgentApiServer) {
return;
}
// Team-building strategy approvals must follow their intended hires.
// Accepting an approve_ceo_strategy before any hire_agent requests
// exist was observed to re-enter the empty team-building loop (see
// comment in ceo-modes/team-building.en.md and §5.2 of 问题.md).
// Reject the request at the API boundary so the model cannot
// circumvent the ordering by resubmitting.
if (input.type === "approve_ceo_strategy") {
const companyHireApprovals = db.listCompanyApprovalsByType(companyId, "hire_agent");
if (companyHireApprovals.length === 0) {
server.json(res, 409, {
error: "approve_ceo_strategy requires at least one hire_agent approval to exist first. Submit the intended hires, then file the strategy.",
code: "STRATEGY_BEFORE_HIRES",
});
return;
}
const existingStrategy = db.listCompanyApprovalsByType(companyId, "approve_ceo_strategy")
.find((a) => a.state === "pending" || a.state === "approved");
if (existingStrategy) {
server.json(res, 409, {
error: "approve_ceo_strategy already exists for this company; do not submit another.",
code: "STRATEGY_ALREADY_FILED",
existingApprovalId: existingStrategy.id,
});
return;
}
}
let id: string;
try {
id = db.requestApproval({