fix(automation): surface malformed condition JSON instead of silently returning false

P2-46: Previous bare try/catch hid parse errors, making rules silently
non-firing. Let JSON.parse throw; the caller (evaluateAutomationRules)
already logs and records the failure.
This commit is contained in:
ZacharyZhang-NY committed 2026-04-16 22:51:00 -04:00
1 parent 6b391887c3
commit 4ebd98bb99
1 file changed
+29 -31
+29 -31
View File
@@ -10,39 +10,37 @@ export function matchesEventConfig(
if (sourceDepartment && ctx.department && sourceDepartment !== ctx.department) { if (sourceDepartment && ctx.department && sourceDepartment !== ctx.department) {
return false; return false;
} }
try { // Surface malformed condition JSON to the caller (automation service) so the
const conditions = JSON.parse(configJson) as Record<string, unknown>; // operator sees it in logs instead of silently filtering out the rule.
if (Object.keys(conditions).length === 0) return true; const conditions = JSON.parse(configJson) as Record<string, unknown>;
if (conditions.status && ctx.newStatus && conditions.status !== ctx.newStatus) return false; if (Object.keys(conditions).length === 0) return true;
if (conditions.previousStatus && ctx.previousStatus && conditions.previousStatus !== ctx.previousStatus) return false; if (conditions.status && ctx.newStatus && conditions.status !== ctx.newStatus) return false;
if (conditions.priority) { if (conditions.previousStatus && ctx.previousStatus && conditions.previousStatus !== ctx.previousStatus) return false;
try { if (conditions.priority) {
const task = ctx.taskId ? db.getTask(ctx.taskId) : null; try {
if (task && task.priority !== conditions.priority) return false; const task = ctx.taskId ? db.getTask(ctx.taskId) : null;
// If task was deleted, skip this condition instead of rejecting the rule. if (task && task.priority !== conditions.priority) return false;
} catch { // If task was deleted, skip this condition instead of rejecting the rule.
// Entity missing — treat as condition not applicable, continue matching. } catch {
} // Entity missing — treat as condition not applicable, continue matching.
} }
if (typeof conditions.budgetThresholdPct === "number" && ctx.agentId) {
try {
const agent = db.getAgent(ctx.agentId);
if (agent.budgetMonthlyUsd > 0) {
const utilization = agent.spentMonthlyUsd / agent.budgetMonthlyUsd;
if (utilization < (conditions.budgetThresholdPct as number) / 100) return false;
}
// If budget is 0 (unlimited), skip budget condition instead of rejecting.
} catch {
// Agent missing — treat as condition not applicable, continue matching.
}
}
if (conditions.taskId && ctx.taskId && conditions.taskId !== ctx.taskId) return false;
if (conditions.projectId && ctx.projectId && conditions.projectId !== ctx.projectId) return false;
if (conditions.agentId && ctx.agentId && conditions.agentId !== ctx.agentId) return false;
return true;
} catch {
return false;
} }
if (typeof conditions.budgetThresholdPct === "number" && ctx.agentId) {
try {
const agent = db.getAgent(ctx.agentId);
if (agent.budgetMonthlyUsd > 0) {
const utilization = agent.spentMonthlyUsd / agent.budgetMonthlyUsd;
if (utilization < (conditions.budgetThresholdPct as number) / 100) return false;
}
// If budget is 0 (unlimited), skip budget condition instead of rejecting.
} catch {
// Agent missing — treat as condition not applicable, continue matching.
}
}
if (conditions.taskId && ctx.taskId && conditions.taskId !== ctx.taskId) return false;
if (conditions.projectId && ctx.projectId && conditions.projectId !== ctx.projectId) return false;
if (conditions.agentId && ctx.agentId && conditions.agentId !== ctx.agentId) return false;
return true;
} }
export function matchesConditions( export function matchesConditions(