吸收数字员工治理审计补齐
This commit is contained in:
@@ -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';
|
||||
|
||||
@@ -2455,6 +2455,8 @@ export default function CommandDeck({ onNavigate }: { onNavigate: (target: Digit
|
||||
<div className="de-route-summary-strip">
|
||||
<span><em>入口路由</em><strong>{routeSummary.total}</strong></span>
|
||||
<span><em>已映射</em><strong>{routeSummary.mapped_count}</strong></span>
|
||||
<span><em>治理审计</em><strong>{routeSummary.governance_mapped_count ?? routeSummary.mapped_count}</strong></span>
|
||||
{(routeSummary.governance_blocked_count ?? 0) > 0 && <span className="is-warning"><em>治理拦截</em><strong>{routeSummary.governance_blocked_count}</strong></span>}
|
||||
<span className={routeSummary.attention_count > 0 ? 'is-warning' : ''}><em>需关注</em><strong>{routeSummary.attention_count}</strong></span>
|
||||
{(routeSummary.blocked_count ?? 0) > 0 && <span className="is-warning"><em>阻断</em><strong>{routeSummary.blocked_count}</strong></span>}
|
||||
{(routeSummary.approval_required_count ?? 0) > 0 && <span className="is-warning"><em>待审</em><strong>{routeSummary.approval_required_count}</strong></span>}
|
||||
@@ -2463,6 +2465,8 @@ export default function CommandDeck({ onNavigate }: { onNavigate: (target: Digit
|
||||
<small>
|
||||
{latestRoute ? `${latestRoute.route_kind} / ${latestRoute.intent_kind} · ${latestRoute.status_label}` : '暂无路由决策'}
|
||||
{routeSummary.policy_source ? ` · 策略${routeSummary.policy_source === 'remote' ? '远端' : '本地'}` : ''}
|
||||
{` · 治理审计已映射 ${routeSummary.governance_mapped_count ?? routeSummary.mapped_count} 项`}
|
||||
{(routeSummary.governance_blocked_count ?? 0) > 0 ? ` · 拦截/失败 ${routeSummary.governance_blocked_count} 项` : ''}
|
||||
{routeSummary.latest_intervention_status ? ` · 干预${routeSummary.latest_intervention_status}` : ''}
|
||||
{routeSummary.policy_last_pull_error ? ` · 拉取失败` : ''}
|
||||
</small>
|
||||
|
||||
@@ -1084,6 +1084,8 @@ export interface DigitalEmployeeDailyReport {
|
||||
export interface DigitalEmployeeRouteSummary {
|
||||
total: number;
|
||||
mapped_count: number;
|
||||
governance_mapped_count?: number;
|
||||
governance_blocked_count?: number;
|
||||
attention_count: number;
|
||||
blocked_count?: number;
|
||||
approval_required_count?: number;
|
||||
|
||||
Reference in New Issue
Block a user