吸收数字员工治理审计补齐

This commit is contained in:
baiyanyun
2026-06-12 10:33:46 +08:00
parent e473b5c147
commit 3a159e2f5a
11 changed files with 230 additions and 57 deletions

View File

@@ -3387,7 +3387,12 @@ function routeDecisionFromRuntimePayload(payload: Record<string, unknown>, event
function routeDecisionAttentionLevel(decision: RouteDecisionRecord): 'info' | 'action' | 'warn' | 'error' {
if (decision.policy_result === 'approval_required') return 'action';
if (decision.policy_result && decision.policy_result !== 'accepted') return 'error';
if (decision.reason_codes.includes('candidate_skills_disabled') || decision.reason_codes.includes('route_action_missing_context')) return 'warn';
if (
decision.reason_codes.includes('candidate_skills_disabled')
|| decision.reason_codes.includes('route_action_missing_context')
|| decision.reason_codes.includes('route_action_policy_blocked')
|| decision.reason_codes.includes('route_action_not_mapped')
) return 'warn';
if (decision.created_command_id) return 'action';
return 'info';
}
@@ -3412,6 +3417,13 @@ function buildRouteDecisionSummary(snapshot: QimingclawSnapshot | null): Digital
return {
total: rows.length,
mapped_count: rows.filter((row) => stringValue(row.created_command_id)).length,
governance_mapped_count: rows.filter((row) => stringValue(row.created_command_id)).length,
governance_blocked_count: rows.filter((row) => {
const reasonCodes = arrayValue(row.reason_codes).map(stringValue);
return reasonCodes.includes('route_action_policy_blocked')
|| reasonCodes.includes('route_action_missing_context')
|| reasonCodes.includes('route_action_not_mapped');
}).length,
attention_count: rows.filter((row) => ['warn', 'error'].includes(stringValue(row.attention_level))).length,
blocked_count: rows.filter((row) => stringValue(row.policy_result) === 'blocked').length,
approval_required_count: rows.filter((row) => stringValue(row.policy_result) === 'approval_required').length,
@@ -6558,7 +6570,10 @@ function buildGovernanceCommandForRouteDecision(
if (decision.route_kind === 'PlanExecution' && decision.intent_kind === 'schedule') {
const scheduleId = stringValue(contextRefs.schedule_id) || stringValue(payload.schedule_id) || stringValue(payload.scheduleId);
if (!scheduleId) return { command: null, reasonCode: 'route_action_missing_context' };
return { command: baseCommand('run_schedule_now', { schedule_id: scheduleId }), reasonCode: 'route_action_mapped' };
const commandKind = 'run_schedule_now';
const policyReason = routeGovernanceActionPolicyReason(commandKind);
if (policyReason) return { command: null, reasonCode: policyReason };
return { command: baseCommand(commandKind, { schedule_id: scheduleId }), reasonCode: 'route_action_mapped' };
}
if (decision.route_kind === 'PlanExecution' && decision.intent_kind === 'execute') {
@@ -6566,8 +6581,11 @@ function buildGovernanceCommandForRouteDecision(
const taskId = stringValue(contextRefs.task_id) || stringValue(payload.task_id) || stringValue(payload.taskId) || taskIdForRouteStep(snapshot, stepId);
if (!taskId) return { command: null, reasonCode: 'route_action_missing_context' };
const task = runtimeTasks(snapshot).find((candidate) => candidate.id === taskId) ?? null;
const commandKind = 'start_run';
const policyReason = routeGovernanceActionPolicyReason(commandKind);
if (policyReason) return { command: null, reasonCode: policyReason };
return {
command: baseCommand('start_run', {
command: baseCommand(commandKind, {
plan_id: stringValue(contextRefs.plan_id) || task?.planId || stringValue(payload.plan_id) || stringValue(payload.planId),
task_id: taskId,
step_id: stepId || (task ? taskStepId(task) : ''),
@@ -6583,6 +6601,8 @@ function buildGovernanceCommandForRouteDecision(
const planId = stringValue(contextRefs.plan_id) || stringValue(payload.plan_id) || stringValue(payload.planId);
const commandKind = routeControlCommandKind(actionText, Boolean(taskId));
if (!commandKind || (!taskId && !planId)) return { command: null, reasonCode: 'route_action_missing_context' };
const policyReason = routeGovernanceActionPolicyReason(commandKind);
if (policyReason) return { command: null, reasonCode: policyReason };
return {
command: baseCommand(commandKind, {
plan_id: planId,
@@ -6777,6 +6797,32 @@ function compactRecord(record: Record<string, unknown>): Record<string, unknown>
return Object.fromEntries(Object.entries(record).filter(([, value]) => value !== undefined && value !== null && value !== ''));
}
const ROUTE_LOW_RISK_GOVERNANCE_COMMANDS = new Set<GovernanceCommandRequest['command_kind']>([
'submit_plan',
'approve_plan',
'amend_plan',
'resume_plan',
'pause_plan',
'retry_task',
'skip_task',
'resume_task',
'provide_task_input',
]);
const ROUTE_RISK_PROTECTED_GOVERNANCE_COMMANDS = new Set<GovernanceCommandRequest['command_kind']>([
'activate_plan',
'run_schedule_now',
'start_run',
'cancel_run',
'cancel_task',
'delete_schedule',
]);
function routeGovernanceActionPolicyReason(commandKind: GovernanceCommandRequest['command_kind']): string | null {
if (ROUTE_LOW_RISK_GOVERNANCE_COMMANDS.has(commandKind)) return null;
if (ROUTE_RISK_PROTECTED_GOVERNANCE_COMMANDS.has(commandKind)) return null;
return 'route_action_policy_blocked';
}
function governanceCommandRiskLevel(commandKind: string): string {
if (['activate_plan', 'run_schedule_now', 'start_run', 'cancel_run', 'cancel_task'].includes(commandKind)) return 'high';
if (['delete_schedule', 'pause_schedule', 'skip_task', 'retry_task', 'provide_task_input'].includes(commandKind)) return 'medium';