fix: P2-24 memory dedup + P2-25 audit logging + P3-02 whiteboard unification
Some checks failed
CI / Lint & TypeCheck (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Build Frontend (push) Has been cancelled
CI / Rust Check (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled

P2-24: Add content_hash column to memories table with index.
Before INSERT, check for existing entry with same normalized content
hash within agent scope; merge importance and bump access_count.

P2-25: Add hand_executed/hand_approved/hand_denied/skill_executed
event types to security-audit.ts. Insert audit logging calls in
kernel-hands.ts triggerHand/approveHand and kernel-skills.ts
executeSkill execution paths.

P3-02: SceneRenderer now imports WhiteboardCanvas component instead
of inline SVG rendering, gaining chart/latex support. Deleted 27
lines of duplicated renderWhiteboardItem code.

Update DEFECT_LIST.md: P1-01  (Fantoccini confirmed), P3-02 ,
add P2-24/P2-25 entries. Active count: 48→50 fixed, 3→1 remaining.
This commit is contained in:
iven
2026-04-06 11:40:53 +08:00
parent 38e7c7bd9b
commit 7f9799b7e0
5 changed files with 104 additions and 11 deletions

View File

@@ -96,6 +96,13 @@ export function installHandMethods(ClientClass: { prototype: KernelClient }): vo
input: params || {},
...(autonomyLevel ? { autonomyLevel } : {}),
});
// P2-25: Audit hand execution
try {
const { logSecurityEvent } = await import('./security-audit');
logSecurityEvent('hand_executed', `Hand "${name}" executed (runId: ${result.instance_id}, status: ${result.status})`, {
handId: name, runId: result.instance_id, status: result.status, autonomyLevel,
});
} catch { /* audit failure is non-blocking */ }
return { runId: result.instance_id, status: result.status };
};
@@ -116,7 +123,15 @@ export function installHandMethods(ClientClass: { prototype: KernelClient }): vo
* Approve a hand execution
*/
proto.approveHand = async function (this: KernelClient, name: string, runId: string, approved: boolean, reason?: string): Promise<{ status: string }> {
return await invoke('hand_approve', { handName: name, runId, approved, reason });
const result = await invoke<{ status: string }>('hand_approve', { handName: name, runId, approved, reason });
// P2-25: Audit hand approval
try {
const { logSecurityEvent } = await import('./security-audit');
logSecurityEvent(approved ? 'hand_approved' : 'hand_denied',
`Hand "${name}" ${approved ? 'approved' : 'denied'} (runId: ${runId})`,
{ handId: name, runId, approved, reason });
} catch { /* non-blocking */ }
return result;
};
/**

View File

@@ -114,7 +114,12 @@ export function installSkillMethods(ClientClass: { prototype: KernelClient }): v
const agent = convStore.currentAgent;
const sessionKey = convStore.sessionKey;
return invoke('skill_execute', {
const result = await invoke<{
success: boolean;
output?: unknown;
error?: string;
durationMs?: number;
}>('skill_execute', {
id,
context: {
agentId: agent?.id || 'zclaw-main',
@@ -123,5 +128,17 @@ export function installSkillMethods(ClientClass: { prototype: KernelClient }): v
},
input: input || {},
});
// P2-25: Audit skill execution
try {
const { logSecurityEvent } = await import('./security-audit');
logSecurityEvent(
'skill_executed',
`Skill "${id}" ${result.success ? 'executed' : 'failed'} (duration: ${result.durationMs ?? '?'}ms)`,
{ skillId: id, success: result.success, durationMs: result.durationMs, error: result.error },
);
} catch { /* audit failure is non-blocking */ }
return result;
};
}

View File

@@ -41,7 +41,11 @@ export type SecurityEventType =
| 'session_started'
| 'session_ended'
| 'rate_limit_exceeded'
| 'suspicious_activity';
| 'suspicious_activity'
| 'hand_executed'
| 'hand_approved'
| 'hand_denied'
| 'skill_executed';
export type SecurityEventSeverity = 'info' | 'warning' | 'error' | 'critical';
@@ -190,6 +194,10 @@ function getDefaultSeverity(type: SecurityEventType): SecurityEventSeverity {
session_ended: 'info',
rate_limit_exceeded: 'warning',
suspicious_activity: 'critical',
hand_executed: 'info',
hand_approved: 'info',
hand_denied: 'warning',
skill_executed: 'info',
};
return severityMap[type] || 'info';