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:
1 parent
6b391887c3
commit
4ebd98bb99
1 file changed
+29
-31
@@ -10,39 +10,37 @@ export function matchesEventConfig(
|
||||
if (sourceDepartment && ctx.department && sourceDepartment !== ctx.department) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
const conditions = JSON.parse(configJson) as Record<string, unknown>;
|
||||
if (Object.keys(conditions).length === 0) return true;
|
||||
if (conditions.status && ctx.newStatus && conditions.status !== ctx.newStatus) return false;
|
||||
if (conditions.previousStatus && ctx.previousStatus && conditions.previousStatus !== ctx.previousStatus) return false;
|
||||
if (conditions.priority) {
|
||||
try {
|
||||
const task = ctx.taskId ? db.getTask(ctx.taskId) : null;
|
||||
if (task && task.priority !== conditions.priority) return false;
|
||||
// If task was deleted, skip this condition instead of rejecting the rule.
|
||||
} catch {
|
||||
// Entity missing — treat as condition not applicable, continue matching.
|
||||
}
|
||||
// Surface malformed condition JSON to the caller (automation service) so the
|
||||
// operator sees it in logs instead of silently filtering out the rule.
|
||||
const conditions = JSON.parse(configJson) as Record<string, unknown>;
|
||||
if (Object.keys(conditions).length === 0) return true;
|
||||
if (conditions.status && ctx.newStatus && conditions.status !== ctx.newStatus) return false;
|
||||
if (conditions.previousStatus && ctx.previousStatus && conditions.previousStatus !== ctx.previousStatus) return false;
|
||||
if (conditions.priority) {
|
||||
try {
|
||||
const task = ctx.taskId ? db.getTask(ctx.taskId) : null;
|
||||
if (task && task.priority !== conditions.priority) return false;
|
||||
// If task was deleted, skip this condition instead of rejecting the rule.
|
||||
} 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(
|
||||
|
||||
Reference in new issue
Block a user