3318 lines
177 KiB
JavaScript
3318 lines
177 KiB
JavaScript
#!/usr/bin/env node
|
|
|
|
const fs = require("fs");
|
|
const os = require("os");
|
|
const path = require("path");
|
|
const { spawnSync } = require("child_process");
|
|
|
|
const packageRoot = path.resolve(__dirname, "..");
|
|
const requiredDigitalTables = [
|
|
"digital_plans",
|
|
"digital_plan_steps",
|
|
"digital_schedules",
|
|
"digital_schedule_runs",
|
|
"digital_tasks",
|
|
"digital_runs",
|
|
"digital_events",
|
|
"digital_artifacts",
|
|
"digital_approvals",
|
|
"digital_memories",
|
|
"digital_sync_outbox",
|
|
"digital_sync_attempts",
|
|
];
|
|
|
|
const testFiles = [
|
|
"src/main/services/digitalEmployee/stateService.test.ts",
|
|
"src/main/services/digitalEmployee/artifactAccessService.test.ts",
|
|
"src/main/services/digitalEmployee/schedulerService.test.ts",
|
|
"src/main/services/digitalEmployee/desktopNotificationService.test.ts",
|
|
"src/main/ipc/digitalEmployeeHandlers.test.ts",
|
|
"src/main/ipc/eventForwarders.test.ts",
|
|
"src/main/services/engines/acp/acpEngine.test.ts",
|
|
"src/main/services/digitalEmployee/syncService.test.ts",
|
|
"src/main/services/digitalEmployee/skillCatalogService.test.ts",
|
|
"src/main/services/digitalEmployee/planTemplateService.test.ts",
|
|
];
|
|
|
|
const selfHealingDigitalSchemaSql = `
|
|
CREATE TABLE IF NOT EXISTS digital_plan_steps (
|
|
id TEXT PRIMARY KEY,
|
|
remote_id TEXT,
|
|
plan_id TEXT NOT NULL,
|
|
title TEXT NOT NULL,
|
|
status TEXT NOT NULL,
|
|
seq INTEGER NOT NULL,
|
|
depends_on TEXT NOT NULL DEFAULT '[]',
|
|
preferred_skill_ids TEXT NOT NULL DEFAULT '[]',
|
|
payload TEXT NOT NULL DEFAULT '{}',
|
|
sync_status TEXT NOT NULL DEFAULT 'pending',
|
|
last_synced_at TEXT,
|
|
sync_error TEXT,
|
|
created_at TEXT NOT NULL,
|
|
updated_at TEXT NOT NULL,
|
|
FOREIGN KEY(plan_id) REFERENCES digital_plans(id)
|
|
);
|
|
CREATE INDEX IF NOT EXISTS idx_digital_plan_steps_plan ON digital_plan_steps(plan_id, seq);
|
|
CREATE INDEX IF NOT EXISTS idx_digital_plan_steps_sync ON digital_plan_steps(sync_status);
|
|
|
|
CREATE TABLE IF NOT EXISTS digital_schedules (
|
|
id TEXT PRIMARY KEY,
|
|
remote_id TEXT,
|
|
plan_id TEXT,
|
|
name TEXT NOT NULL,
|
|
description TEXT,
|
|
cron_expr TEXT NOT NULL,
|
|
timezone TEXT NOT NULL DEFAULT 'system',
|
|
status TEXT NOT NULL DEFAULT 'enabled',
|
|
enabled INTEGER NOT NULL DEFAULT 1,
|
|
prompt TEXT,
|
|
command TEXT,
|
|
payload TEXT NOT NULL DEFAULT '{}',
|
|
next_run_at TEXT,
|
|
last_run_at TEXT,
|
|
catch_up_on_startup INTEGER NOT NULL DEFAULT 1,
|
|
max_catch_up_runs INTEGER NOT NULL DEFAULT 5,
|
|
max_run_history INTEGER NOT NULL DEFAULT 100,
|
|
failure_count INTEGER NOT NULL DEFAULT 0,
|
|
last_error TEXT,
|
|
sync_status TEXT NOT NULL DEFAULT 'pending',
|
|
last_synced_at TEXT,
|
|
sync_error TEXT,
|
|
created_at TEXT NOT NULL,
|
|
updated_at TEXT NOT NULL,
|
|
deleted_at TEXT,
|
|
FOREIGN KEY(plan_id) REFERENCES digital_plans(id)
|
|
);
|
|
CREATE TABLE IF NOT EXISTS digital_schedule_runs (
|
|
id TEXT PRIMARY KEY,
|
|
remote_id TEXT,
|
|
schedule_id TEXT NOT NULL,
|
|
plan_id TEXT,
|
|
run_id TEXT,
|
|
due_at TEXT NOT NULL,
|
|
started_at TEXT,
|
|
finished_at TEXT,
|
|
status TEXT NOT NULL,
|
|
attempt_no INTEGER NOT NULL DEFAULT 1,
|
|
trigger_kind TEXT NOT NULL DEFAULT 'scheduled',
|
|
error TEXT,
|
|
payload TEXT NOT NULL DEFAULT '{}',
|
|
sync_status TEXT NOT NULL DEFAULT 'pending',
|
|
last_synced_at TEXT,
|
|
sync_error TEXT,
|
|
created_at TEXT NOT NULL,
|
|
updated_at TEXT NOT NULL,
|
|
FOREIGN KEY(schedule_id) REFERENCES digital_schedules(id),
|
|
FOREIGN KEY(plan_id) REFERENCES digital_plans(id),
|
|
FOREIGN KEY(run_id) REFERENCES digital_runs(id)
|
|
);
|
|
CREATE INDEX IF NOT EXISTS idx_digital_schedules_due ON digital_schedules(enabled, status, next_run_at);
|
|
CREATE INDEX IF NOT EXISTS idx_digital_schedules_plan ON digital_schedules(plan_id);
|
|
CREATE INDEX IF NOT EXISTS idx_digital_schedules_sync ON digital_schedules(sync_status);
|
|
CREATE INDEX IF NOT EXISTS idx_digital_schedule_runs_schedule ON digital_schedule_runs(schedule_id, due_at);
|
|
CREATE UNIQUE INDEX IF NOT EXISTS idx_digital_schedule_runs_attempt ON digital_schedule_runs(schedule_id, due_at, attempt_no);
|
|
CREATE INDEX IF NOT EXISTS idx_digital_schedule_runs_sync ON digital_schedule_runs(sync_status);
|
|
|
|
CREATE TABLE IF NOT EXISTS digital_memories (
|
|
id TEXT PRIMARY KEY,
|
|
remote_id TEXT,
|
|
key TEXT NOT NULL,
|
|
content TEXT NOT NULL,
|
|
category TEXT NOT NULL DEFAULT 'fact',
|
|
source TEXT NOT NULL DEFAULT 'qimingclaw',
|
|
source_path TEXT,
|
|
session_id TEXT,
|
|
score REAL,
|
|
status TEXT NOT NULL DEFAULT 'active',
|
|
payload TEXT NOT NULL DEFAULT '{}',
|
|
sync_status TEXT NOT NULL DEFAULT 'pending',
|
|
last_synced_at TEXT,
|
|
sync_error TEXT,
|
|
created_at TEXT NOT NULL,
|
|
updated_at TEXT NOT NULL,
|
|
deleted_at TEXT
|
|
);
|
|
CREATE INDEX IF NOT EXISTS idx_digital_memories_key ON digital_memories(key, status, updated_at);
|
|
CREATE INDEX IF NOT EXISTS idx_digital_memories_category ON digital_memories(category, status, updated_at);
|
|
CREATE INDEX IF NOT EXISTS idx_digital_memories_sync ON digital_memories(sync_status);
|
|
`;
|
|
|
|
function runStep(title, command, args, options = {}) {
|
|
console.log(`\n[DigitalEmployeeCheck] ${title}`);
|
|
const result = spawnSync(command, args, {
|
|
cwd: packageRoot,
|
|
stdio: "inherit",
|
|
shell: process.platform === "win32",
|
|
...options,
|
|
});
|
|
if (result.status !== 0) {
|
|
process.exitCode = result.status || 1;
|
|
throw new Error(`${title} failed`);
|
|
}
|
|
}
|
|
|
|
function checkSgrobotDigitalAssets() {
|
|
console.log("\n[DigitalEmployeeCheck] Verify embedded digital assets");
|
|
const indexPath = path.join(packageRoot, "public", "sgrobot-digital", "index.html");
|
|
const html = fs.readFileSync(indexPath, "utf8");
|
|
const assetRefs = [...html.matchAll(/(?:src|href)="\.\/(assets\/[^"]+)"/g)]
|
|
.map((match) => match[1]);
|
|
if (assetRefs.length === 0) {
|
|
throw new Error("No embedded digital assets referenced by index.html");
|
|
}
|
|
for (const assetRef of assetRefs) {
|
|
const assetPath = path.join(packageRoot, "public", "sgrobot-digital", assetRef);
|
|
if (!fs.existsSync(assetPath)) {
|
|
throw new Error(`Missing embedded digital asset: ${assetRef}`);
|
|
}
|
|
}
|
|
console.log(`[DigitalEmployeeCheck] ${assetRefs.length} asset references OK`);
|
|
}
|
|
|
|
function checkDigitalDiagnosticAuditProjection() {
|
|
console.log("\n[DigitalEmployeeCheck] Verify diagnostic/audit projection hooks");
|
|
const adapterPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "lib", "qimingclawAdapter.ts");
|
|
const typesPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "types", "api.ts");
|
|
const pagePath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "pages", "digital", "CommandDeck.tsx");
|
|
const syncServicePath = path.join(packageRoot, "src", "main", "services", "digitalEmployee", "syncService.ts");
|
|
const adapter = fs.readFileSync(adapterPath, "utf8");
|
|
const types = fs.readFileSync(typesPath, "utf8");
|
|
const page = fs.readFileSync(pagePath, "utf8");
|
|
const syncService = fs.readFileSync(syncServicePath, "utf8");
|
|
const requiredSnippets = [
|
|
[syncService, "sandboxAuditBusinessView", "sandbox audit sync business view"],
|
|
[syncService, "tokenCostBusinessView", "token/cost sync business view"],
|
|
[syncService, "toolCallAuditBusinessView", "tool call sync business view"],
|
|
[syncService, "sandbox_audit", "sandbox audit business category"],
|
|
[syncService, "token_cost", "token cost business category"],
|
|
[syncService, "tool_call_audit", "tool call business category"],
|
|
[syncService, "estimated_cost_usd", "safe estimated cost field"],
|
|
[syncService, "total_tokens", "safe total token field"],
|
|
[syncService, "input_length", "sensitive input length redaction"],
|
|
[adapter, "'audits'", "audit business view kind"],
|
|
[adapter, "buildDiagnosticSummary", "diagnostic summary builder"],
|
|
[adapter, "buildCostSummary", "cost summary builder"],
|
|
[adapter, "costSampleFromPayload", "runtime token/cost aggregation"],
|
|
[adapter, "diagnosticAuditPayload", "diagnostic audit payload redaction"],
|
|
[adapter, "sandbox_audit", "sandbox audit row category"],
|
|
[adapter, "token_cost", "token cost row category"],
|
|
[adapter, "tool_call_audit", "tool call row category"],
|
|
[adapter, "estimated_cost_usd", "audit estimated cost field"],
|
|
[adapter, "total_tokens", "audit total token field"],
|
|
[adapter, "filterAuditRows", "audit filters"],
|
|
[adapter, "diagnosticNotifications", "diagnostic notifications"],
|
|
[adapter, "auditNotifications", "audit notifications"],
|
|
[types, "DigitalEmployeeDiagnosticSummary", "diagnostic summary type"],
|
|
[types, "diagnostic_summary?: DigitalEmployeeDiagnosticSummary", "workday diagnostic field"],
|
|
[types, "estimated_cost_usd", "diagnostic summary estimated cost type"],
|
|
[types, "total_tokens", "diagnostic summary token type"],
|
|
[page, "de-diagnostic-summary-strip", "dashboard diagnostic strip"],
|
|
[page, "Token", "dashboard Token metric"],
|
|
[page, "估算成本", "dashboard estimated cost metric"],
|
|
];
|
|
const missing = requiredSnippets
|
|
.filter(([content, snippet]) => !content.includes(snippet))
|
|
.map(([, , label]) => label);
|
|
if (missing.length > 0) {
|
|
throw new Error(`Missing diagnostic/audit projection hooks: ${missing.join(", ")}`);
|
|
}
|
|
console.log("[DigitalEmployeeCheck] diagnostic/audit projection hooks OK");
|
|
}
|
|
|
|
function checkDigitalNotificationPreferences() {
|
|
console.log("\n[DigitalEmployeeCheck] Verify notification preference hooks");
|
|
const adapterPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "lib", "qimingclawAdapter.ts");
|
|
const apiPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "lib", "api.ts");
|
|
const typesPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "types", "api.ts");
|
|
const shellPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "pages", "digital", "DigitalEmployeeShell.tsx");
|
|
const stateServicePath = path.join(packageRoot, "src", "main", "services", "digitalEmployee", "stateService.ts");
|
|
const syncServicePath = path.join(packageRoot, "src", "main", "services", "digitalEmployee", "syncService.ts");
|
|
const desktopNotificationServicePath = path.join(packageRoot, "src", "main", "services", "digitalEmployee", "desktopNotificationService.ts");
|
|
const ipcHandlersPath = path.join(packageRoot, "src", "main", "ipc", "digitalEmployeeHandlers.ts");
|
|
const preloadPath = path.join(packageRoot, "src", "preload", "webviewPerfBridge.ts");
|
|
const adapter = fs.readFileSync(adapterPath, "utf8");
|
|
const api = fs.readFileSync(apiPath, "utf8");
|
|
const types = fs.readFileSync(typesPath, "utf8");
|
|
const shell = fs.readFileSync(shellPath, "utf8");
|
|
const stateService = fs.readFileSync(stateServicePath, "utf8");
|
|
const syncService = fs.readFileSync(syncServicePath, "utf8");
|
|
const desktopNotificationService = fs.readFileSync(desktopNotificationServicePath, "utf8");
|
|
const ipcHandlers = fs.readFileSync(ipcHandlersPath, "utf8");
|
|
const preload = fs.readFileSync(preloadPath, "utf8");
|
|
const requiredSnippets = [
|
|
[adapter, "/api/notifications/preferences", "adapter notification preference endpoint"],
|
|
[adapter, "route-decisions|notifications|audits", "management notification business route"],
|
|
[adapter, "notificationRows", "management notification rows"],
|
|
[adapter, "filterNotificationRows", "management notification filters"],
|
|
[adapter, "muted_by_preferences", "management notification muted marker"],
|
|
[adapter, "recordNotificationTaskInput", "notification reply task input bridge"],
|
|
[adapter, "notification_reply", "notification reply task input source"],
|
|
[adapter, "task_input_recorded", "notification reply task input result"],
|
|
[adapter, "provide_task_input", "notification reply governance command"],
|
|
[adapter, "handleNotificationPreferencesPatch", "adapter notification preference patch handler"],
|
|
[adapter, "/api/notifications/updates/pull", "adapter notification updates pull endpoint"],
|
|
[adapter, "pullBridgeNotificationUpdates", "adapter notification updates bridge pull helper"],
|
|
[adapter, "submitNotificationAction", "adapter notification action bridge declaration"],
|
|
[adapter, "submitBridgeNotificationAction", "adapter notification action bridge submit helper"],
|
|
[adapter, "showDesktopNotification", "adapter desktop notification bridge declaration"],
|
|
[adapter, "/api/notifications/desktop", "adapter desktop notification endpoint"],
|
|
[adapter, "/api/notifications/desktop/status", "adapter desktop notification status endpoint"],
|
|
[adapter, "/api/notifications/desktop/settings/open", "adapter desktop notification settings endpoint"],
|
|
[adapter, "showBridgeDesktopNotification", "adapter desktop notification helper"],
|
|
[adapter, "readBridgeDesktopNotificationStatus", "adapter desktop notification status helper"],
|
|
[adapter, "openBridgeDesktopNotificationSettings", "adapter desktop notification settings helper"],
|
|
[adapter, "notificationMatchesPreferences", "adapter notification preference filter"],
|
|
[adapter, "desktop_enabled", "adapter notification desktop preference"],
|
|
[adapter, "update_notification_preferences", "adapter notification preference save action"],
|
|
[api, "getNotificationPreferences", "notification preferences API getter"],
|
|
[api, "patchNotificationPreferences", "notification preferences API patcher"],
|
|
[api, "pullNotificationUpdates", "embedded notification updates API"],
|
|
[api, "showDesktopNotification", "embedded desktop notification API"],
|
|
[api, "getDesktopNotificationStatus", "embedded desktop notification status API"],
|
|
[api, "openDesktopNotificationSettings", "embedded desktop notification settings API"],
|
|
[types, "NotificationPreferences", "notification preferences type"],
|
|
[types, "DesktopNotificationStatus", "desktop notification status type"],
|
|
[types, "DesktopNotificationSettingsOpenResult", "desktop notification settings result type"],
|
|
[types, "desktop_enabled", "notification desktop preference type field"],
|
|
[types, "NotificationUpdatesPullResult", "notification updates pull result type"],
|
|
[shell, "de-notification-preferences", "notification preferences UI"],
|
|
[shell, "桌面通知状态", "desktop notification status UI"],
|
|
[shell, "测试桌面通知", "desktop notification test UI"],
|
|
[shell, "打开系统设置", "desktop notification settings UI"],
|
|
[shell, "自动桌面通知发送失败", "automatic desktop notification failure feedback"],
|
|
[shell, "handleNotificationSync", "notification manual sync UI action"],
|
|
[shell, "showUnreadDesktopNotifications", "notification desktop trigger helper"],
|
|
[shell, "qimingclaw:digital-desktop-notified", "notification desktop dedupe key"],
|
|
[shell, "桌面通知", "notification desktop preference UI"],
|
|
[shell, "NOTIFICATION_KIND_OPTIONS", "notification kind mute UI options"],
|
|
[stateService, "update_notification_preferences", "notification preference runtime event"],
|
|
[stateService, "desktop_enabled", "notification desktop preference state field"],
|
|
[desktopNotificationService, "showDigitalEmployeeDesktopNotification", "desktop notification service"],
|
|
[desktopNotificationService, "getDigitalEmployeeDesktopNotificationStatus", "desktop notification status service"],
|
|
[desktopNotificationService, "openDigitalEmployeeDesktopNotificationSettings", "desktop notification settings service"],
|
|
[desktopNotificationService, "Notification", "Electron Notification usage"],
|
|
[desktopNotificationService, "shell.openExternal", "Electron notification settings opener"],
|
|
[desktopNotificationService, "notification_unavailable", "desktop notification unavailable fallback"],
|
|
[stateService, "notification_updates_pulled", "notification updates pulled runtime event"],
|
|
[stateService, "notification_action_submitted", "notification action submitted runtime event"],
|
|
[syncService, "pullDigitalEmployeeNotificationUpdates", "remote notification updates pull service"],
|
|
[syncService, "submitDigitalEmployeeNotificationAction", "remote notification action submit service"],
|
|
[syncService, "/api/digital-employee/notifications/updates", "remote notification updates default path"],
|
|
[syncService, "/api/digital-employee/notifications/actions", "remote notification actions default path"],
|
|
[syncService, "notificationUpdatesEndpoint", "notification updates endpoint config"],
|
|
[syncService, "notificationActionsEndpoint", "notification actions endpoint config"],
|
|
[syncService, "notificationBusinessView", "notification sync business view"],
|
|
[syncService, "digital_workday_notification_updates_pulled", "notification updates sync event kind"],
|
|
[syncService, "digital_workday_notification_action_submitted", "notification action sync event kind"],
|
|
[syncService, "governanceCommandBusinessView", "notification reply governance sync view"],
|
|
[syncService, "provide_task_input", "task input governance command kind"],
|
|
[syncService, "input_length", "task input sync redacted length"],
|
|
[syncService, "isNotificationEvent", "notification event classifier"],
|
|
[syncService, "return \"notification\"", "notification business category"],
|
|
[ipcHandlers, "digitalEmployee:pullNotificationUpdates", "IPC notification updates pull handler"],
|
|
[ipcHandlers, "digitalEmployee:submitNotificationAction", "IPC notification action submit handler"],
|
|
[ipcHandlers, "digitalEmployee:showDesktopNotification", "IPC desktop notification handler"],
|
|
[ipcHandlers, "digitalEmployee:getDesktopNotificationStatus", "IPC desktop notification status handler"],
|
|
[ipcHandlers, "digitalEmployee:openDesktopNotificationSettings", "IPC desktop notification settings handler"],
|
|
[preload, "pullNotificationUpdates", "preload notification updates bridge"],
|
|
[preload, "submitNotificationAction", "preload notification action bridge"],
|
|
[preload, "showDesktopNotification", "preload desktop notification bridge"],
|
|
[preload, "getDesktopNotificationStatus", "preload desktop notification status bridge"],
|
|
[preload, "openDesktopNotificationSettings", "preload desktop notification settings bridge"],
|
|
];
|
|
const missing = requiredSnippets
|
|
.filter(([content, snippet]) => !content.includes(snippet))
|
|
.map(([, , label]) => label);
|
|
if (missing.length > 0) {
|
|
throw new Error(`Missing notification preference hooks: ${missing.join(", ")}`);
|
|
}
|
|
console.log("[DigitalEmployeeCheck] notification preference hooks OK");
|
|
}
|
|
|
|
function checkDigitalApprovalHistorySubscriptions() {
|
|
console.log("\n[DigitalEmployeeCheck] Verify approval history/subscription hooks");
|
|
const adapterPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "lib", "qimingclawAdapter.ts");
|
|
const apiPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "lib", "api.ts");
|
|
const typesPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "types", "api.ts");
|
|
const stateServicePath = path.join(packageRoot, "src", "main", "services", "digitalEmployee", "stateService.ts");
|
|
const syncServicePath = path.join(packageRoot, "src", "main", "services", "digitalEmployee", "syncService.ts");
|
|
const adapter = fs.readFileSync(adapterPath, "utf8");
|
|
const api = fs.readFileSync(apiPath, "utf8");
|
|
const types = fs.readFileSync(typesPath, "utf8");
|
|
const stateService = fs.readFileSync(stateServicePath, "utf8");
|
|
const syncService = fs.readFileSync(syncServicePath, "utf8");
|
|
const requiredSnippets = [
|
|
[adapter, "/api/approval/subscriptions", "adapter approval subscription endpoint"],
|
|
[adapter, "/api/digital-employee/approval-history", "adapter approval history endpoint"],
|
|
[adapter, "approvalHistoryRows", "management approval history rows"],
|
|
[adapter, "filterApprovalHistoryRows", "management approval history filters"],
|
|
[adapter, "approvalSubscriptionPreferences", "adapter approval subscription preferences"],
|
|
[adapter, "update_approval_subscriptions", "adapter approval subscription save action"],
|
|
[adapter, "approval-history", "approval history business route"],
|
|
[api, "getApprovalSubscriptionPreferences", "approval subscription API getter"],
|
|
[api, "patchApprovalSubscriptionPreferences", "approval subscription API patcher"],
|
|
[api, "getApprovalHistory", "approval history API getter"],
|
|
[types, "ApprovalSubscriptionPreferences", "approval subscription preferences type"],
|
|
[stateService, "approvalSubscriptionPreferences", "approval subscription UI state"],
|
|
[stateService, "update_approval_subscriptions", "approval subscription runtime event"],
|
|
[syncService, "approvalDecisionBusinessView", "approval decision sync business view"],
|
|
[syncService, "approvalSubscriptionBusinessView", "approval subscription sync business view"],
|
|
[syncService, "digital_workday_update_approval_subscriptions", "approval subscription sync event kind"],
|
|
];
|
|
const missing = requiredSnippets
|
|
.filter(([content, snippet]) => !content.includes(snippet))
|
|
.map(([, , label]) => label);
|
|
if (missing.length > 0) {
|
|
throw new Error(`Missing approval history/subscription hooks: ${missing.join(", ")}`);
|
|
}
|
|
console.log("[DigitalEmployeeCheck] approval history/subscription hooks OK");
|
|
}
|
|
|
|
function checkDigitalApprovalWorkflowSync() {
|
|
console.log("\n[DigitalEmployeeCheck] Verify approval workflow/sync hooks");
|
|
const adapterPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "lib", "qimingclawAdapter.ts");
|
|
const apiPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "lib", "api.ts");
|
|
const typesPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "types", "api.ts");
|
|
const commandDeckPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "pages", "digital", "CommandDeck.tsx");
|
|
const stateServicePath = path.join(packageRoot, "src", "main", "services", "digitalEmployee", "stateService.ts");
|
|
const syncServicePath = path.join(packageRoot, "src", "main", "services", "digitalEmployee", "syncService.ts");
|
|
const ipcHandlersPath = path.join(packageRoot, "src", "main", "ipc", "digitalEmployeeHandlers.ts");
|
|
const preloadPath = path.join(packageRoot, "src", "preload", "webviewPerfBridge.ts");
|
|
const adapter = fs.readFileSync(adapterPath, "utf8");
|
|
const api = fs.readFileSync(apiPath, "utf8");
|
|
const types = fs.readFileSync(typesPath, "utf8");
|
|
const commandDeck = fs.readFileSync(commandDeckPath, "utf8");
|
|
const stateService = fs.readFileSync(stateServicePath, "utf8");
|
|
const syncService = fs.readFileSync(syncServicePath, "utf8");
|
|
const ipcHandlers = fs.readFileSync(ipcHandlersPath, "utf8");
|
|
const preload = fs.readFileSync(preloadPath, "utf8");
|
|
const requiredSnippets = [
|
|
[stateService, "DigitalEmployeeApprovalWorkflow", "approval workflow type"],
|
|
[stateService, "normalizeDigitalEmployeeApprovalWorkflow", "approval workflow normalizer"],
|
|
[stateService, "applyApprovalWorkflowDecision", "approval workflow decision advancer"],
|
|
[stateService, "applyApprovalWorkflowAction", "approval workflow action updater"],
|
|
[stateService, "upsertDigitalEmployeeApprovalFromRemote", "remote approval update upsert helper"],
|
|
[stateService, "resolveDigitalEmployeeApprovalConflict", "approval conflict resolution helper"],
|
|
[stateService, "approval_conflict_detected", "approval conflict runtime event"],
|
|
[stateService, "approval_conflict_resolved", "approval conflict resolved event"],
|
|
[stateService, "terminal_status_mismatch", "approval terminal conflict reason"],
|
|
[stateService, "decision_history", "approval workflow decision history field"],
|
|
[syncService, "pullDigitalEmployeeApprovalUpdates", "remote approval updates pull service"],
|
|
[syncService, "conflicted", "approval pull conflict counter"],
|
|
[syncService, "submitDigitalEmployeeApprovalDecision", "approval decision submit service"],
|
|
[syncService, "/api/digital-employee/approvals/updates", "remote approval updates default path"],
|
|
[syncService, "/api/digital-employee/approvals/decisions", "remote approval decisions default path"],
|
|
[syncService, "approvalUpdatesEndpoint", "approval updates endpoint config"],
|
|
[syncService, "approvalDecisionsEndpoint", "approval decisions endpoint config"],
|
|
[syncService, "approvalSyncBusinessView", "approval sync business view"],
|
|
[syncService, "approvalConflictResolutionBusinessView", "approval conflict resolution business view"],
|
|
[syncService, "workflow_id", "approval workflow sync business field"],
|
|
[ipcHandlers, "digitalEmployee:pullApprovalUpdates", "IPC approval updates pull handler"],
|
|
[ipcHandlers, "digitalEmployee:submitApprovalDecision", "IPC approval decision submit handler"],
|
|
[ipcHandlers, "digitalEmployee:resolveApprovalConflict", "IPC approval conflict resolution handler"],
|
|
[preload, "pullApprovalUpdates", "preload approval updates bridge"],
|
|
[preload, "submitApprovalDecision", "preload approval decision bridge"],
|
|
[preload, "resolveApprovalConflict", "preload approval conflict resolution bridge"],
|
|
[adapter, "pullApprovalUpdates", "adapter approval updates bridge declaration"],
|
|
[adapter, "submitApprovalDecision", "adapter approval decision bridge declaration"],
|
|
[adapter, "resolveApprovalConflict", "adapter approval conflict resolution bridge declaration"],
|
|
[adapter, "/api/approval/updates/pull", "adapter approval updates pull endpoint"],
|
|
[adapter, "conflict\\/resolve", "adapter approval conflict resolution endpoint"],
|
|
[adapter, "approvalWorkflowSummary", "adapter approval workflow summary"],
|
|
[adapter, "approvalConflictSummary", "adapter approval conflict summary"],
|
|
[adapter, "approval_conflict_active", "approval conflict business field"],
|
|
[adapter, "approval_conflict_resolution", "approval conflict resolution business field"],
|
|
[api, "pullApprovalUpdates", "embedded approval updates API"],
|
|
[api, "resolveApprovalConflict", "embedded approval conflict resolution API"],
|
|
[types, "conflict?:", "approval decision conflict type field"],
|
|
[types, "current_step_label", "approval decision current step type field"],
|
|
[types, "approval_step_count", "approval decision step count type field"],
|
|
[commandDeck, "pull_approval_updates", "home approval updates pull action"],
|
|
[commandDeck, "审批更新", "home approval updates pull button"],
|
|
[commandDeck, "跨端冲突", "home approval conflict badge"],
|
|
[commandDeck, "冲突保护", "home approval conflict protection copy"],
|
|
[commandDeck, "保留本地", "home approval keep local conflict action"],
|
|
[commandDeck, "采纳管理端", "home approval accept remote conflict action"],
|
|
[commandDeck, "标记已复核", "home approval mark reviewed conflict action"],
|
|
];
|
|
const missing = requiredSnippets
|
|
.filter(([content, snippet]) => !content.includes(snippet))
|
|
.map(([, , label]) => label);
|
|
if (missing.length > 0) {
|
|
throw new Error(`Missing approval workflow/sync hooks: ${missing.join(", ")}`);
|
|
}
|
|
console.log("[DigitalEmployeeCheck] approval workflow/sync hooks OK");
|
|
}
|
|
|
|
function checkDigitalPlanStepGraphDispatchPolicy() {
|
|
console.log("\n[DigitalEmployeeCheck] Verify PlanStep graph/dispatch policy hooks");
|
|
const adapterPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "lib", "qimingclawAdapter.ts");
|
|
const apiPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "lib", "api.ts");
|
|
const typesPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "types", "api.ts");
|
|
const commandDeckPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "pages", "digital", "CommandDeck.tsx");
|
|
const cssPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "index.css");
|
|
const stateServicePath = path.join(packageRoot, "src", "main", "services", "digitalEmployee", "stateService.ts");
|
|
const schedulerServicePath = path.join(packageRoot, "src", "main", "services", "digitalEmployee", "schedulerService.ts");
|
|
const syncServicePath = path.join(packageRoot, "src", "main", "services", "digitalEmployee", "syncService.ts");
|
|
const ipcHandlersPath = path.join(packageRoot, "src", "main", "ipc", "digitalEmployeeHandlers.ts");
|
|
const preloadPath = path.join(packageRoot, "src", "preload", "webviewPerfBridge.ts");
|
|
const adapter = fs.readFileSync(adapterPath, "utf8");
|
|
const api = fs.readFileSync(apiPath, "utf8");
|
|
const types = fs.readFileSync(typesPath, "utf8");
|
|
const commandDeck = fs.readFileSync(commandDeckPath, "utf8");
|
|
const css = fs.readFileSync(cssPath, "utf8");
|
|
const stateService = fs.readFileSync(stateServicePath, "utf8");
|
|
const schedulerService = fs.readFileSync(schedulerServicePath, "utf8");
|
|
const syncService = fs.readFileSync(syncServicePath, "utf8");
|
|
const ipcHandlers = fs.readFileSync(ipcHandlersPath, "utf8");
|
|
const preload = fs.readFileSync(preloadPath, "utf8");
|
|
const requiredSnippets = [
|
|
[adapter, "/api/digital-employee/plan-steps", "adapter plan step endpoint"],
|
|
[adapter, "/api/digital-employee/plan-step-graph", "adapter plan step graph endpoint"],
|
|
[adapter, "dispatch-ready-steps", "adapter plan-scoped ready step dispatch endpoint"],
|
|
[adapter, "dispatchPlanReadySteps", "adapter plan-scoped ready step dispatcher"],
|
|
[adapter, "/api/plan-step/dispatch-policy", "adapter plan step dispatch policy endpoint"],
|
|
[adapter, "/api/plan-step/dispatch-policy/pull", "adapter plan step dispatch policy pull endpoint"],
|
|
[adapter, "pullPlanStepDispatchPolicy", "adapter plan step dispatch policy pull bridge"],
|
|
[adapter, "planStepRows", "management plan step rows"],
|
|
[adapter, "planStepGraphRows", "management plan step graph rows"],
|
|
[adapter, "filterPlanStepRows", "management plan step filters"],
|
|
[adapter, "activePlanStepDispatchLease", "adapter active plan step lease detector"],
|
|
[adapter, "lease_active", "adapter lease-active readiness skip reason"],
|
|
[adapter, "lease_state", "adapter plan step lease state projection"],
|
|
[adapter, "blocked_dependency_details", "plan step blocked dependency details"],
|
|
[adapter, "planStepDependencyDetails", "plan step blocked dependency detail mapper"],
|
|
[adapter, "update_plan_step_dispatch_policy", "adapter plan step dispatch policy save action"],
|
|
[api, "getPlanStepDispatchPolicy", "plan step dispatch policy API getter"],
|
|
[api, "patchPlanStepDispatchPolicy", "plan step dispatch policy API patcher"],
|
|
[api, "pullPlanStepDispatchPolicy", "plan step dispatch policy API puller"],
|
|
[api, "getPlanSteps", "plan steps API getter"],
|
|
[api, "getPlanStepGraph", "plan step graph API getter"],
|
|
[api, "dispatchPlanReadySteps", "plan-scoped ready step dispatch API"],
|
|
[api, "BusinessViewResponse<PlanStepBusinessRow>", "typed plan step business view API"],
|
|
[types, "trigger_source", "ready step dispatch trigger source type"],
|
|
[types, "orchestration_id", "ready step dispatch orchestration id type"],
|
|
[types, "PlanStepDispatchPolicy", "plan step dispatch policy type"],
|
|
[types, "PlanStepDispatchPolicyPullResult", "plan step dispatch policy pull result type"],
|
|
[types, "last_pull_error", "plan step dispatch policy pull error field"],
|
|
[types, "PlanStepLeaseSummary", "plan step lease summary type"],
|
|
[types, "remote_lease_id", "plan step remote lease type field"],
|
|
[types, "PlanStepDependencyDetail", "plan step blocked dependency detail type"],
|
|
[types, "lease_active", "plan step lease active type field"],
|
|
[types, "PlanStepBusinessRow", "plan step business row type"],
|
|
[types, "BusinessViewResponse", "business view response type"],
|
|
[commandDeck, "getPlanStepGraph", "home blocked plan step graph fetch"],
|
|
[commandDeck, "planStepOrchestrationSummary", "home plan step orchestration summary"],
|
|
[commandDeck, "leasedStepCount", "home plan step lease count"],
|
|
[commandDeck, "controlPlanReadySteps", "home plan-scoped ready step control"],
|
|
[commandDeck, "pull_plan_step_dispatch_policy", "home plan step dispatch policy pull action"],
|
|
[commandDeck, "controlBlockedPlanStep", "home blocked plan step control handler"],
|
|
[commandDeck, "de-blocked-step-control-strip", "home blocked plan step control strip"],
|
|
[commandDeck, "provide_task_input", "home blocked plan step input command"],
|
|
[css, "de-blocked-input-field", "home blocked plan step input styles"],
|
|
[stateService, "planStepDispatchPolicy", "plan step dispatch policy UI state"],
|
|
[stateService, "update_plan_step_dispatch_policy", "plan step dispatch policy runtime event"],
|
|
[stateService, "pull_plan_step_dispatch_policy", "plan step dispatch policy pull runtime event"],
|
|
[stateService, "last_pulled_at", "plan step dispatch policy last pulled field"],
|
|
[stateService, "last_pull_error", "plan step dispatch policy last pull error field"],
|
|
[stateService, "planIdFilter", "plan-scoped ready step candidate filter"],
|
|
[stateService, "dispatchLease", "plan step payload lease state"],
|
|
[stateService, "activeDigitalEmployeePlanStepLease", "plan step active lease helper"],
|
|
[stateService, "acquireDigitalEmployeePlanStepLease", "plan step lease acquire helper"],
|
|
[stateService, "releaseDigitalEmployeePlanStepLease", "plan step lease release helper"],
|
|
[stateService, "recordDigitalEmployeePlanStepLeaseSkipped", "plan step remote lease rejected helper"],
|
|
[stateService, "local_fallback", "plan step local fallback lease source"],
|
|
[stateService, "remote_release_error", "plan step remote release error state"],
|
|
[stateService, "plan_step_lease_acquired", "plan step lease acquired event"],
|
|
[stateService, "plan_step_lease_released", "plan step lease released event"],
|
|
[stateService, "plan_step_lease_skipped", "plan step lease skipped event"],
|
|
[schedulerService, "bypassAutoDispatchSwitch", "manual plan dispatch auto switch bypass"],
|
|
[schedulerService, "runDigitalEmployeePlanReadyStepsNow", "manual plan-scoped ready step dispatcher"],
|
|
[schedulerService, "acquireDigitalEmployeePlanStepLease", "scheduler acquire plan step lease"],
|
|
[schedulerService, "releaseDigitalEmployeePlanStepLease", "scheduler release plan step lease"],
|
|
[schedulerService, "acquireDigitalEmployeePlanStepRemoteLease", "scheduler remote plan step lease acquire"],
|
|
[schedulerService, "releaseDigitalEmployeePlanStepRemoteLease", "scheduler remote plan step lease release"],
|
|
[schedulerService, "remote_lease_rejected", "scheduler remote lease rejected skip reason"],
|
|
[schedulerService, "local_fallback", "scheduler remote lease fallback source"],
|
|
[schedulerService, "triggerSource", "ready step dispatch trigger source"],
|
|
[schedulerService, "readDigitalEmployeePlanStepDispatchPolicy", "scheduler plan step dispatch policy reader"],
|
|
[schedulerService, "pullDigitalEmployeePlanStepDispatchPolicy", "scheduler remote plan step dispatch policy pull"],
|
|
[schedulerService, "max_per_sweep", "scheduler max per sweep policy"],
|
|
[ipcHandlers, "digitalEmployee:dispatchPlanReadySteps", "IPC plan-scoped ready step dispatch handler"],
|
|
[ipcHandlers, "digitalEmployee:pullPlanStepDispatchPolicy", "IPC plan step dispatch policy pull handler"],
|
|
[preload, "dispatchPlanReadySteps", "preload plan-scoped ready step bridge"],
|
|
[preload, "pullPlanStepDispatchPolicy", "preload plan step dispatch policy pull bridge"],
|
|
[syncService, "planStepBusinessView", "plan step sync business view"],
|
|
[syncService, "pullDigitalEmployeePlanStepDispatchPolicy", "remote plan step dispatch policy pull service"],
|
|
[syncService, "planStepDispatchPolicyEndpoint", "remote plan step dispatch policy endpoint config"],
|
|
[syncService, "/api/digital-employee/policies/plan-step-dispatch", "remote plan step dispatch policy default path"],
|
|
[syncService, "acquireDigitalEmployeePlanStepRemoteLease", "remote plan step dispatch lease acquire service"],
|
|
[syncService, "releaseDigitalEmployeePlanStepRemoteLease", "remote plan step dispatch lease release service"],
|
|
[syncService, "planStepDispatchLeaseEndpoint", "remote plan step dispatch lease endpoint config"],
|
|
[syncService, "/api/digital-employee/leases/plan-step-dispatch", "remote plan step dispatch lease default path"],
|
|
[syncService, "lease_active", "plan step sync lease active field"],
|
|
[syncService, "remote_lease_error", "plan step sync remote lease error field"],
|
|
[syncService, "remote_release_error", "plan step sync remote release error field"],
|
|
[syncService, "planStepLeaseBusinessView", "plan step lease sync event view"],
|
|
[syncService, "plan_step_lease_acquired", "plan step lease acquired sync event kind"],
|
|
[syncService, "trigger_source", "plan step dispatch sync trigger source"],
|
|
[syncService, "orchestration_id", "plan step dispatch sync orchestration id"],
|
|
[syncService, "planStepDispatchPolicyBusinessView", "plan step dispatch policy sync view"],
|
|
[syncService, "digital_workday_update_plan_step_dispatch_policy", "plan step dispatch policy sync event kind"],
|
|
[syncService, "digital_workday_pull_plan_step_dispatch_policy", "plan step dispatch policy pull sync event kind"],
|
|
];
|
|
const missing = requiredSnippets
|
|
.filter(([content, snippet]) => !content.includes(snippet))
|
|
.map(([, , label]) => label);
|
|
if (missing.length > 0) {
|
|
throw new Error(`Missing PlanStep graph/dispatch policy hooks: ${missing.join(", ")}`);
|
|
}
|
|
console.log("[DigitalEmployeeCheck] PlanStep graph/dispatch policy hooks OK");
|
|
}
|
|
|
|
function checkDigitalSkillRemotePolicy() {
|
|
console.log("\n[DigitalEmployeeCheck] Verify skill remote policy hooks");
|
|
const adapterPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "lib", "qimingclawAdapter.ts");
|
|
const apiPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "lib", "api.ts");
|
|
const skillLibraryPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "pages", "digital", "SkillLibrary.tsx");
|
|
const skillExecutionPolicyPath = path.join(packageRoot, "src", "main", "services", "digitalEmployee", "skillExecutionPolicy.ts");
|
|
const skillCatalogPath = path.join(packageRoot, "src", "main", "services", "digitalEmployee", "skillCatalogService.ts");
|
|
const syncServicePath = path.join(packageRoot, "src", "main", "services", "digitalEmployee", "syncService.ts");
|
|
const ipcHandlersPath = path.join(packageRoot, "src", "main", "ipc", "digitalEmployeeHandlers.ts");
|
|
const preloadPath = path.join(packageRoot, "src", "preload", "webviewPerfBridge.ts");
|
|
const adapter = fs.readFileSync(adapterPath, "utf8");
|
|
const api = fs.readFileSync(apiPath, "utf8");
|
|
const skillLibrary = fs.readFileSync(skillLibraryPath, "utf8");
|
|
const skillExecutionPolicy = fs.readFileSync(skillExecutionPolicyPath, "utf8");
|
|
const skillCatalog = fs.readFileSync(skillCatalogPath, "utf8");
|
|
const syncService = fs.readFileSync(syncServicePath, "utf8");
|
|
const ipcHandlers = fs.readFileSync(ipcHandlersPath, "utf8");
|
|
const preload = fs.readFileSync(preloadPath, "utf8");
|
|
const requiredSnippets = [
|
|
[skillExecutionPolicy, "local_skills", "local skill policy map"],
|
|
[skillExecutionPolicy, "remote_skills", "remote skill policy map"],
|
|
[skillExecutionPolicy, "last_pull_error", "skill policy pull error metadata"],
|
|
[skillExecutionPolicy, "effectiveSkillPolicyFor", "effective skill policy merge helper"],
|
|
[skillExecutionPolicy, "matched_remote_policy", "skill call remote policy audit snapshot"],
|
|
[skillCatalog, "remote_policy", "skill catalog remote policy projection"],
|
|
[skillCatalog, "local_policy", "skill catalog local policy projection"],
|
|
[skillCatalog, "policy_source", "skill catalog policy source projection"],
|
|
[syncService, "pullDigitalEmployeeSkillPolicies", "remote skill policy pull service"],
|
|
[syncService, "skillPolicyEndpoint", "remote skill policy endpoint config"],
|
|
[syncService, "/api/digital-employee/policies/skills", "remote skill policy default path"],
|
|
[syncService, "readRemoteSkillPolicyPayload", "remote skill policy response parser"],
|
|
[syncService, "recordSkillPolicyPullFailure", "remote skill policy pull failure recorder"],
|
|
[ipcHandlers, "digitalEmployee:pullSkillPolicies", "IPC skill policy pull handler"],
|
|
[preload, "pullSkillPolicies", "preload skill policy pull bridge"],
|
|
[adapter, "pullSkillPolicies", "adapter skill policy pull bridge"],
|
|
[adapter, "/api/skill/policies/pull", "adapter skill policy pull endpoint"],
|
|
[api, "pullSkillPolicies", "embedded skill policy pull API"],
|
|
[skillLibrary, "拉取策略", "skill library pull policy action"],
|
|
[skillLibrary, "远端策略", "skill library remote policy marker"],
|
|
];
|
|
const missing = requiredSnippets
|
|
.filter(([content, snippet]) => !content.includes(snippet))
|
|
.map(([, , label]) => label);
|
|
if (missing.length > 0) {
|
|
throw new Error(`Missing skill remote policy hooks: ${missing.join(", ")}`);
|
|
}
|
|
console.log("[DigitalEmployeeCheck] skill remote policy hooks OK");
|
|
}
|
|
|
|
function checkDigitalRiskApprovalPolicy() {
|
|
console.log("\n[DigitalEmployeeCheck] Verify risk approval policy hooks");
|
|
const adapterPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "lib", "qimingclawAdapter.ts");
|
|
const apiPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "lib", "api.ts");
|
|
const commandDeckPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "pages", "digital", "CommandDeck.tsx");
|
|
const opsSettingsPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "pages", "digital", "OpsSettings.tsx");
|
|
const stateServicePath = path.join(packageRoot, "src", "main", "services", "digitalEmployee", "stateService.ts");
|
|
const syncServicePath = path.join(packageRoot, "src", "main", "services", "digitalEmployee", "syncService.ts");
|
|
const ipcHandlersPath = path.join(packageRoot, "src", "main", "ipc", "digitalEmployeeHandlers.ts");
|
|
const preloadPath = path.join(packageRoot, "src", "preload", "webviewPerfBridge.ts");
|
|
const adapter = fs.readFileSync(adapterPath, "utf8");
|
|
const api = fs.readFileSync(apiPath, "utf8");
|
|
const commandDeck = fs.readFileSync(commandDeckPath, "utf8");
|
|
const opsSettings = fs.readFileSync(opsSettingsPath, "utf8");
|
|
const stateService = fs.readFileSync(stateServicePath, "utf8");
|
|
const syncService = fs.readFileSync(syncServicePath, "utf8");
|
|
const ipcHandlers = fs.readFileSync(ipcHandlersPath, "utf8");
|
|
const preload = fs.readFileSync(preloadPath, "utf8");
|
|
const requiredSnippets = [
|
|
[stateService, "riskApprovalPolicy", "risk approval policy UI state"],
|
|
[stateService, "normalizeRiskApprovalPolicy", "risk approval policy normalizer"],
|
|
[stateService, "evaluateDigitalEmployeeRiskPolicy", "risk approval policy evaluator"],
|
|
[stateService, "risk_approval_required", "risk approval-required event kind"],
|
|
[stateService, "risk_policy_rejected", "risk policy rejected event kind"],
|
|
[stateService, "update_risk_approval_policy", "risk approval policy update UI event"],
|
|
[stateService, "pull_risk_approval_policy", "risk approval policy pull UI event"],
|
|
[syncService, "pullDigitalEmployeeRiskApprovalPolicy", "remote risk approval policy pull service"],
|
|
[syncService, "riskApprovalPolicyEndpoint", "remote risk approval policy endpoint config"],
|
|
[syncService, "/api/digital-employee/policies/risk-approval", "remote risk approval policy default path"],
|
|
[syncService, "risk_approval_required", "risk approval-required sync event kind"],
|
|
[syncService, "risk_policy_rejected", "risk policy rejected sync event kind"],
|
|
[syncService, "riskPolicyBusinessView", "risk policy sync business view"],
|
|
[ipcHandlers, "digitalEmployee:pullRiskApprovalPolicy", "IPC risk approval policy pull handler"],
|
|
[ipcHandlers, "digitalEmployee:evaluateRiskPolicy", "IPC risk policy evaluation handler"],
|
|
[preload, "pullRiskApprovalPolicy", "preload risk approval policy pull bridge"],
|
|
[preload, "evaluateRiskPolicy", "preload risk policy evaluation bridge"],
|
|
[adapter, "pullRiskApprovalPolicy", "adapter risk approval policy pull bridge"],
|
|
[adapter, "evaluateRiskPolicy", "adapter risk policy evaluation bridge"],
|
|
[adapter, "/api/risk-approval/policy", "adapter risk approval policy local endpoint"],
|
|
[adapter, "handleRiskApprovalPolicyPatch", "adapter risk approval policy patch handler"],
|
|
[adapter, "/api/risk-approval/policy/pull", "adapter risk approval policy pull endpoint"],
|
|
[adapter, "riskPolicyBlockedResponse", "adapter risk policy blocked response"],
|
|
[adapter, "governanceCommandRiskLevel", "adapter governance risk level mapper"],
|
|
[adapter, "managed_service.restart", "managed service restart risk action"],
|
|
[adapter, "artifact.access", "artifact access risk action"],
|
|
[adapter, "plan_step.dispatch_ready_steps", "ready PlanStep dispatch risk action"],
|
|
[api, "getRiskApprovalPolicy", "embedded risk approval policy getter"],
|
|
[api, "patchRiskApprovalPolicy", "embedded risk approval policy patcher"],
|
|
[api, "pullRiskApprovalPolicy", "embedded risk approval policy pull API"],
|
|
[opsSettings, "riskPolicy", "settings risk policy state"],
|
|
[opsSettings, "updateRiskPolicy", "settings risk policy update handler"],
|
|
[opsSettings, "风险审批策略", "settings risk approval policy panel"],
|
|
[commandDeck, "pull_risk_approval_policy", "home risk approval policy pull action"],
|
|
[commandDeck, "风险策略", "home risk approval policy pull button"],
|
|
];
|
|
const missing = requiredSnippets
|
|
.filter(([content, snippet]) => !content.includes(snippet))
|
|
.map(([, , label]) => label);
|
|
if (missing.length > 0) {
|
|
throw new Error(`Missing risk approval policy hooks: ${missing.join(", ")}`);
|
|
}
|
|
console.log("[DigitalEmployeeCheck] risk approval policy hooks OK");
|
|
}
|
|
|
|
function checkDigitalRouteDecisionPolicy() {
|
|
const adapterPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "lib", "qimingclawAdapter.ts");
|
|
const apiPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "lib", "api.ts");
|
|
const commandDeckPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "pages", "digital", "CommandDeck.tsx");
|
|
const typesPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "types", "api.ts");
|
|
const stateServicePath = path.join(packageRoot, "src", "main", "services", "digitalEmployee", "stateService.ts");
|
|
const syncServicePath = path.join(packageRoot, "src", "main", "services", "digitalEmployee", "syncService.ts");
|
|
const ipcHandlersPath = path.join(packageRoot, "src", "main", "ipc", "digitalEmployeeHandlers.ts");
|
|
const preloadPath = path.join(packageRoot, "src", "preload", "webviewPerfBridge.ts");
|
|
const adapter = fs.readFileSync(adapterPath, "utf8");
|
|
const api = fs.readFileSync(apiPath, "utf8");
|
|
const commandDeck = fs.readFileSync(commandDeckPath, "utf8");
|
|
const types = fs.readFileSync(typesPath, "utf8");
|
|
const stateService = fs.readFileSync(stateServicePath, "utf8");
|
|
const syncService = fs.readFileSync(syncServicePath, "utf8");
|
|
const ipcHandlers = fs.readFileSync(ipcHandlersPath, "utf8");
|
|
const preload = fs.readFileSync(preloadPath, "utf8");
|
|
const requiredSnippets = [
|
|
[stateService, "routeDecisionPolicy", "route decision policy UI state"],
|
|
[stateService, "normalizeRouteDecisionPolicy", "route decision policy normalizer"],
|
|
[stateService, "evaluateDigitalEmployeeRouteDecisionPolicy", "route decision policy evaluator"],
|
|
[stateService, "listDigitalEmployeeRouteInterventions", "route intervention list helper"],
|
|
[stateService, "recordDigitalEmployeeRouteInterventionResolution", "route intervention resolution recorder"],
|
|
[stateService, "route_decision_blocked", "route decision blocked event kind"],
|
|
[stateService, "route_decision_approval_required", "route decision approval-required event kind"],
|
|
[stateService, "route_decision_intervention_resolved", "route decision intervention resolved event kind"],
|
|
[syncService, "pullDigitalEmployeeRouteDecisionPolicy", "remote route decision policy pull service"],
|
|
[syncService, "routeDecisionPolicyEndpoint", "remote route decision policy endpoint config"],
|
|
[syncService, "/api/digital-employee/policies/route-decision", "remote route decision policy default path"],
|
|
[syncService, "routeDecisionPolicyBusinessView", "route decision policy sync business view"],
|
|
[syncService, "routeDecisionInterventionBusinessView", "route decision intervention sync business view"],
|
|
[syncService, "governanceCommandBusinessView", "governance command sync business view"],
|
|
[syncService, "kind.startsWith(\"governance_\")", "governance event business category"],
|
|
[syncService, "input_length", "governance task input redaction field"],
|
|
[ipcHandlers, "digitalEmployee:pullRouteDecisionPolicy", "IPC route decision policy pull handler"],
|
|
[ipcHandlers, "digitalEmployee:evaluateRouteDecisionPolicy", "IPC route decision policy evaluation handler"],
|
|
[ipcHandlers, "digitalEmployee:listRouteInterventions", "IPC route intervention list handler"],
|
|
[ipcHandlers, "digitalEmployee:recordRouteInterventionResolution", "IPC route intervention resolution handler"],
|
|
[preload, "pullRouteDecisionPolicy", "preload route decision policy pull bridge"],
|
|
[preload, "evaluateRouteDecisionPolicy", "preload route decision policy evaluation bridge"],
|
|
[preload, "listRouteInterventions", "preload route intervention list bridge"],
|
|
[preload, "recordRouteInterventionResolution", "preload route intervention resolution bridge"],
|
|
[adapter, "pullRouteDecisionPolicy", "adapter route decision policy pull bridge"],
|
|
[adapter, "evaluateRouteDecisionPolicy", "adapter route decision policy evaluation bridge"],
|
|
[adapter, "/api/route-decision/policy/pull", "adapter route decision policy pull endpoint"],
|
|
[adapter, "/api/route-decisions/interventions", "adapter route intervention list endpoint"],
|
|
[adapter, "handleRouteInterventionDecision", "adapter route intervention decision handler"],
|
|
[adapter, "resolveApprovedRouteInterventions", "adapter approved route intervention auto resolver"],
|
|
[adapter, "auto_create_governance_commands", "adapter route command auto-create switch"],
|
|
[adapter, "routeGovernanceActionPolicyReason", "adapter route governance action guard"],
|
|
[adapter, "route_action_policy_blocked", "adapter route action policy blocked reason"],
|
|
[api, "pullRouteDecisionPolicy", "embedded route decision policy pull API"],
|
|
[api, "decideRouteIntervention", "embedded route intervention decision API"],
|
|
[types, "RouteDecisionPolicy", "embedded route decision policy type"],
|
|
[types, "RouteInterventionRecord", "embedded route intervention type"],
|
|
[types, "governance_blocked_count", "route governance blocked summary type"],
|
|
[commandDeck, "pull_route_decision_policy", "home route decision policy pull action"],
|
|
[commandDeck, "路由策略", "home route decision policy pull button"],
|
|
[commandDeck, "治理审计", "home governance audit summary"],
|
|
];
|
|
const missing = requiredSnippets
|
|
.filter(([content, snippet]) => !content.includes(snippet))
|
|
.map(([, , label]) => label);
|
|
if (missing.length > 0) {
|
|
throw new Error(`Missing route decision policy hooks: ${missing.join(", ")}`);
|
|
}
|
|
console.log("[DigitalEmployeeCheck] route decision policy hooks OK");
|
|
}
|
|
|
|
function checkDigitalDailyReportDelivery() {
|
|
console.log("\n[DigitalEmployeeCheck] Verify daily report delivery hooks");
|
|
const adapterPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "lib", "qimingclawAdapter.ts");
|
|
const apiPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "lib", "api.ts");
|
|
const typesPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "types", "api.ts");
|
|
const pagePath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "pages", "digital", "DailyReport.tsx");
|
|
const stateServicePath = path.join(packageRoot, "src", "main", "services", "digitalEmployee", "stateService.ts");
|
|
const syncServicePath = path.join(packageRoot, "src", "main", "services", "digitalEmployee", "syncService.ts");
|
|
const ipcHandlersPath = path.join(packageRoot, "src", "main", "ipc", "digitalEmployeeHandlers.ts");
|
|
const preloadPath = path.join(packageRoot, "src", "preload", "webviewPerfBridge.ts");
|
|
const adapter = fs.readFileSync(adapterPath, "utf8");
|
|
const api = fs.readFileSync(apiPath, "utf8");
|
|
const types = fs.readFileSync(typesPath, "utf8");
|
|
const page = fs.readFileSync(pagePath, "utf8");
|
|
const stateService = fs.readFileSync(stateServicePath, "utf8");
|
|
const syncService = fs.readFileSync(syncServicePath, "utf8");
|
|
const ipcHandlers = fs.readFileSync(ipcHandlersPath, "utf8");
|
|
const preload = fs.readFileSync(preloadPath, "utf8");
|
|
const requiredSnippets = [
|
|
[stateService, "htmlArtifactId", "daily report HTML artifact result"],
|
|
[stateService, "pdfArtifactId", "daily report PDF artifact result"],
|
|
[stateService, "recordDigitalEmployeeDailyReportDelivery", "daily report delivery recorder"],
|
|
[stateService, "daily_report_send_recorded", "daily report send event"],
|
|
[stateService, "daily_report_confirmed", "daily report confirm event"],
|
|
[stateService, "daily_report_approval_requested", "daily report approval event"],
|
|
[syncService, "dailyReportEventBusinessView", "daily report sync business view"],
|
|
[syncService, "daily_report", "daily report sync category"],
|
|
[ipcHandlers, "digitalEmployee:recordDailyReportDelivery", "IPC daily report delivery handler"],
|
|
[preload, "recordDailyReportDelivery", "preload daily report delivery bridge"],
|
|
[adapter, "/api/digital-employee/daily-reports/delivery", "adapter daily report delivery endpoint"],
|
|
[adapter, "buildDailyReportHtml", "adapter HTML report builder"],
|
|
[adapter, "buildDailyReportPdfBase64", "adapter PDF report builder"],
|
|
[api, "recordDailyReportDelivery", "embedded daily report delivery API"],
|
|
[types, "html_artifact_id", "daily report HTML artifact type"],
|
|
[types, "pdf_artifact_id", "daily report PDF artifact type"],
|
|
[page, "导出 HTML", "daily report HTML export UI"],
|
|
[page, "导出 PDF", "daily report PDF export UI"],
|
|
[page, "记录发送", "daily report send UI"],
|
|
[page, "确认回执", "daily report confirm UI"],
|
|
[page, "发起审批", "daily report approval UI"],
|
|
];
|
|
const missing = requiredSnippets
|
|
.filter(([content, snippet]) => !content.includes(snippet))
|
|
.map(([, , label]) => label);
|
|
if (missing.length > 0) {
|
|
throw new Error(`Missing daily report delivery hooks: ${missing.join(", ")}`);
|
|
}
|
|
console.log("[DigitalEmployeeCheck] daily report delivery hooks OK");
|
|
}
|
|
|
|
function checkDigitalArtifactCleanup() {
|
|
console.log("\n[DigitalEmployeeCheck] Verify artifact cleanup execution hooks");
|
|
const adapterPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "lib", "qimingclawAdapter.ts");
|
|
const apiPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "lib", "api.ts");
|
|
const typesPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "types", "api.ts");
|
|
const pagePath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "pages", "digital", "DailyReport.tsx");
|
|
const businessViewPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "pages", "digital", "BusinessView.tsx");
|
|
const stateServicePath = path.join(packageRoot, "src", "main", "services", "digitalEmployee", "stateService.ts");
|
|
const artifactServicePath = path.join(packageRoot, "src", "main", "services", "digitalEmployee", "artifactAccessService.ts");
|
|
const syncServicePath = path.join(packageRoot, "src", "main", "services", "digitalEmployee", "syncService.ts");
|
|
const ipcHandlersPath = path.join(packageRoot, "src", "main", "ipc", "digitalEmployeeHandlers.ts");
|
|
const preloadPath = path.join(packageRoot, "src", "preload", "webviewPerfBridge.ts");
|
|
const adapter = fs.readFileSync(adapterPath, "utf8");
|
|
const api = fs.readFileSync(apiPath, "utf8");
|
|
const types = fs.readFileSync(typesPath, "utf8");
|
|
const page = fs.readFileSync(pagePath, "utf8");
|
|
const businessView = fs.readFileSync(businessViewPath, "utf8");
|
|
const stateService = fs.readFileSync(stateServicePath, "utf8");
|
|
const artifactService = fs.readFileSync(artifactServicePath, "utf8");
|
|
const syncService = fs.readFileSync(syncServicePath, "utf8");
|
|
const ipcHandlers = fs.readFileSync(ipcHandlersPath, "utf8");
|
|
const preload = fs.readFileSync(preloadPath, "utf8");
|
|
const requiredSnippets = [
|
|
[artifactService, "cleanupDigitalEmployeeArtifact", "artifact cleanup service"],
|
|
[stateService, "recordDigitalEmployeeArtifactCleanup", "artifact cleanup event recorder"],
|
|
[stateService, "artifact_cleanup_executed", "artifact cleanup executed event"],
|
|
[stateService, "artifact_cleanup_rejected", "artifact cleanup rejected event"],
|
|
[syncService, "cleanup_status", "artifact cleanup sync business field"],
|
|
[ipcHandlers, "digitalEmployee:cleanupArtifact", "IPC artifact cleanup handler"],
|
|
[preload, "cleanupArtifact", "preload artifact cleanup bridge"],
|
|
[adapter, "/cleanup", "adapter artifact cleanup endpoint"],
|
|
[adapter, "artifactCleanupRows", "adapter artifact cleanup projection"],
|
|
[api, "cleanupArtifact", "embedded artifact cleanup API"],
|
|
[types, "cleanup_status", "artifact cleanup type field"],
|
|
[page, "清理文件", "daily report cleanup UI"],
|
|
[businessView, "cleanup_status", "business view cleanup summary"],
|
|
];
|
|
const missing = requiredSnippets
|
|
.filter(([content, snippet]) => !content.includes(snippet))
|
|
.map(([, , label]) => label);
|
|
if (missing.length > 0) {
|
|
throw new Error(`Missing artifact cleanup execution hooks: ${missing.join(", ")}`);
|
|
}
|
|
console.log("[DigitalEmployeeCheck] artifact cleanup execution hooks OK");
|
|
}
|
|
|
|
function checkDigitalArtifactBatchGovernance() {
|
|
console.log("\n[DigitalEmployeeCheck] Verify artifact batch governance hooks");
|
|
const adapterPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "lib", "qimingclawAdapter.ts");
|
|
const apiPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "lib", "api.ts");
|
|
const typesPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "types", "api.ts");
|
|
const adapter = fs.readFileSync(adapterPath, "utf8");
|
|
const api = fs.readFileSync(apiPath, "utf8");
|
|
const types = fs.readFileSync(typesPath, "utf8");
|
|
const businessViewPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "pages", "digital", "BusinessView.tsx");
|
|
const businessView = fs.existsSync(businessViewPath) ? fs.readFileSync(businessViewPath, "utf8") : "";
|
|
const dailyReportPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "pages", "digital", "DailyReport.tsx");
|
|
const dailyReport = fs.readFileSync(dailyReportPath, "utf8");
|
|
const docs = fs.readFileSync(path.join(packageRoot, "..", "..", "docs", "digital-employee-frontend-integration-plan.md"), "utf8");
|
|
const requiredSnippets = [
|
|
[adapter, "handleArtifactRetentionBatch", "adapter artifact retention batch handler"],
|
|
[adapter, "/retention/batch", "adapter artifact retention batch endpoint"],
|
|
[adapter, "artifactGroupRows", "adapter artifact aggregate rows"],
|
|
[adapter, "/artifact-groups", "adapter artifact groups endpoint"],
|
|
[api, "setArtifactRetentionBatch", "embedded artifact retention batch API"],
|
|
[types, "artifact-groups", "business view artifact groups kind"],
|
|
[types, "artifact_count", "artifact aggregate count type field"],
|
|
[types, "device_count", "artifact aggregate device count type field"],
|
|
[businessView, "产物聚合", "business view artifact groups tab"],
|
|
[businessView, "批量保留", "business view batch retention UI"],
|
|
[dailyReport, "批量标记到期", "daily report batch retention action"],
|
|
[docs, "保留策略批量治理", "docs artifact batch governance absorption"],
|
|
[docs, "跨设备聚合视图", "docs artifact aggregate view absorption"],
|
|
];
|
|
const missing = requiredSnippets
|
|
.filter(([content, snippet]) => !content.includes(snippet))
|
|
.map(([, , label]) => label);
|
|
if (missing.length > 0) {
|
|
throw new Error(`Missing artifact batch governance hooks: ${missing.join(", ")}`);
|
|
}
|
|
console.log("[DigitalEmployeeCheck] artifact batch governance hooks OK");
|
|
}
|
|
|
|
function checkDigitalBusinessViewUi() {
|
|
console.log("\n[DigitalEmployeeCheck] Verify management business view UI hooks");
|
|
const apiPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "lib", "api.ts");
|
|
const typesPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "types", "api.ts");
|
|
const mainPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "main.tsx");
|
|
const shellPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "pages", "digital", "DigitalEmployeeShell.tsx");
|
|
const navPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "pages", "digital", "navigation.ts");
|
|
const businessViewPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "pages", "digital", "BusinessView.tsx");
|
|
if (!fs.existsSync(businessViewPath)) {
|
|
throw new Error("Missing management business view UI: BusinessView.tsx");
|
|
}
|
|
const api = fs.readFileSync(apiPath, "utf8");
|
|
const types = fs.readFileSync(typesPath, "utf8");
|
|
const main = fs.readFileSync(mainPath, "utf8");
|
|
const shell = fs.readFileSync(shellPath, "utf8");
|
|
const nav = fs.readFileSync(navPath, "utf8");
|
|
const businessView = fs.readFileSync(businessViewPath, "utf8");
|
|
const requiredSnippets = [
|
|
[api, "getDigitalEmployeeBusinessView", "embedded business view API helper"],
|
|
[api, "/api/digital-employee/plans", "embedded business view plans endpoint"],
|
|
[api, "/api/digital-employee/approvals", "embedded business view approvals endpoint"],
|
|
[types, "DigitalEmployeeBusinessViewKind", "business view kind type"],
|
|
[types, "DigitalEmployeeBusinessViewRow", "business view row type"],
|
|
[types, "DigitalEmployeeBusinessViewQuery", "business view query type"],
|
|
[main, "path=\"/digital/*\"", "business view deep route"],
|
|
[nav, "business", "business navigation tab"],
|
|
[nav, "businessKind", "business navigation kind target"],
|
|
[nav, "entityId", "business navigation entity target"],
|
|
[shell, "BusinessView", "business view shell component"],
|
|
[shell, "业务视图", "business view tab label"],
|
|
[businessView, "getDigitalEmployeeBusinessView", "business view data loader"],
|
|
[businessView, "计划", "business view plans segment"],
|
|
[businessView, "审批", "business view approvals segment"],
|
|
[businessView, "详情", "business view detail panel"],
|
|
];
|
|
const missing = requiredSnippets
|
|
.filter(([content, snippet]) => !content.includes(snippet))
|
|
.map(([, , label]) => label);
|
|
if (missing.length > 0) {
|
|
throw new Error(`Missing management business view UI hooks: ${missing.join(", ")}`);
|
|
}
|
|
console.log("[DigitalEmployeeCheck] management business view UI hooks OK");
|
|
}
|
|
|
|
function checkDigitalInterventionWorkbench() {
|
|
console.log("\n[DigitalEmployeeCheck] Verify intervention workbench hooks");
|
|
const adapterPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "lib", "qimingclawAdapter.ts");
|
|
const apiPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "lib", "api.ts");
|
|
const typesPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "types", "api.ts");
|
|
const shellPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "pages", "digital", "DigitalEmployeeShell.tsx");
|
|
const commandDeckPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "pages", "digital", "CommandDeck.tsx");
|
|
const workbenchPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "pages", "digital", "InterventionWorkbench.tsx");
|
|
const adapter = fs.readFileSync(adapterPath, "utf8");
|
|
const api = fs.readFileSync(apiPath, "utf8");
|
|
const types = fs.readFileSync(typesPath, "utf8");
|
|
const shell = fs.readFileSync(shellPath, "utf8");
|
|
const commandDeck = fs.readFileSync(commandDeckPath, "utf8");
|
|
const workbench = fs.existsSync(workbenchPath) ? fs.readFileSync(workbenchPath, "utf8") : "";
|
|
const docs = fs.readFileSync(path.join(packageRoot, "..", "..", "docs", "digital-employee-frontend-integration-plan.md"), "utf8");
|
|
const requiredSnippets = [
|
|
[adapter, "interventionWorkbenchRows", "adapter intervention workbench projection"],
|
|
[adapter, "/api/digital-employee/interventions/workbench", "adapter intervention workbench endpoint"],
|
|
[adapter, "handleApprovalConflictResolutionBatch", "adapter approval conflict batch handler"],
|
|
[adapter, "batch_accept_remote_disabled", "adapter approval batch safety guard"],
|
|
[adapter, "handleRouteInterventionsBatch", "adapter route intervention batch handler"],
|
|
[api, "getDigitalEmployeeInterventionWorkbench", "embedded intervention workbench API"],
|
|
[api, "resolveApprovalConflictsBatch", "embedded approval conflict batch API"],
|
|
[api, "decideRouteInterventionsBatch", "embedded route intervention batch API"],
|
|
[types, "DigitalEmployeeInterventionRow", "intervention row type"],
|
|
[types, "DigitalEmployeeInterventionWorkbenchResponse", "intervention response type"],
|
|
[shell, "InterventionWorkbench", "intervention shell component"],
|
|
[shell, "介入台", "intervention tab label"],
|
|
[commandDeck, "打开介入台", "command deck intervention entry"],
|
|
[workbench, "批量保留本地", "workbench keep local batch UI"],
|
|
[workbench, "批量标记复核", "workbench mark reviewed batch UI"],
|
|
[workbench, "批量忽略", "workbench route dismiss batch UI"],
|
|
[docs, "跨设备批量冲突排查", "docs approval intervention absorption"],
|
|
[docs, "批量干预入口", "docs route intervention absorption"],
|
|
];
|
|
const missing = requiredSnippets
|
|
.filter(([content, snippet]) => !content.includes(snippet))
|
|
.map(([, , label]) => label);
|
|
if (missing.length > 0) {
|
|
throw new Error(`Missing intervention workbench hooks: ${missing.join(", ")}`);
|
|
}
|
|
console.log("[DigitalEmployeeCheck] intervention workbench hooks OK");
|
|
}
|
|
|
|
function checkDigitalMemoryGovernanceAudit() {
|
|
console.log("\n[DigitalEmployeeCheck] Verify memory governance and skill audit hooks");
|
|
const adapterPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "lib", "qimingclawAdapter.ts");
|
|
const apiPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "lib", "api.ts");
|
|
const typesPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "types", "api.ts");
|
|
const shellPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "pages", "digital", "DigitalEmployeeShell.tsx");
|
|
const skillLibraryPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "pages", "digital", "SkillLibrary.tsx");
|
|
const commandDeckPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "pages", "digital", "CommandDeck.tsx");
|
|
const memoryGovernancePath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "pages", "digital", "MemoryGovernance.tsx");
|
|
const skillAuditPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "pages", "digital", "SkillAuditWorkbench.tsx");
|
|
const adapter = fs.readFileSync(adapterPath, "utf8");
|
|
const api = fs.readFileSync(apiPath, "utf8");
|
|
const types = fs.readFileSync(typesPath, "utf8");
|
|
const shell = fs.readFileSync(shellPath, "utf8");
|
|
const skillLibrary = fs.readFileSync(skillLibraryPath, "utf8");
|
|
const commandDeck = fs.readFileSync(commandDeckPath, "utf8");
|
|
const memoryGovernance = fs.existsSync(memoryGovernancePath) ? fs.readFileSync(memoryGovernancePath, "utf8") : "";
|
|
const skillAudit = fs.existsSync(skillAuditPath) ? fs.readFileSync(skillAuditPath, "utf8") : "";
|
|
const docs = fs.readFileSync(path.join(packageRoot, "..", "..", "docs", "digital-employee-frontend-integration-plan.md"), "utf8");
|
|
const requiredSnippets = [
|
|
[adapter, "memoryGovernanceRows", "adapter memory governance projection"],
|
|
[adapter, "/api/digital-employee/memory-governance", "adapter memory governance endpoint"],
|
|
[adapter, "/api/digital-employee/memory-governance/status/batch", "adapter memory governance batch endpoint"],
|
|
[adapter, "skillAuditWorkbenchRows", "adapter skill audit workbench projection"],
|
|
[adapter, "/api/digital-employee/skill-audit-workbench", "adapter skill audit workbench endpoint"],
|
|
[api, "getDigitalEmployeeMemoryGovernance", "embedded memory governance API"],
|
|
[api, "setMemoryGovernanceStatus", "embedded memory governance batch API"],
|
|
[api, "getDigitalEmployeeSkillAuditWorkbench", "embedded skill audit API"],
|
|
[types, "DigitalEmployeeMemoryGovernanceRow", "memory governance row type"],
|
|
[types, "DigitalEmployeeSkillAuditWorkbenchRow", "skill audit row type"],
|
|
[shell, "MemoryGovernance", "memory governance shell component"],
|
|
[shell, "SkillAuditWorkbench", "skill audit shell component"],
|
|
[shell, "记忆治理", "memory governance tab label"],
|
|
[shell, "技能审计", "skill audit tab label"],
|
|
[skillLibrary, "技能审计", "skill library audit entry"],
|
|
[commandDeck, "打开技能审计", "home skill audit entry"],
|
|
[memoryGovernance, "批量归档", "memory governance archive UI"],
|
|
[memoryGovernance, "批量恢复", "memory governance restore UI"],
|
|
[memoryGovernance, "重复候选", "memory governance duplicate candidate UI"],
|
|
[skillAudit, "技能审计", "skill audit workbench title"],
|
|
[docs, "记忆归档/恢复 UI", "docs memory governance absorption"],
|
|
[docs, "管理端调用审计视图", "docs skill audit absorption"],
|
|
[docs, "管理端正式审计视图预览", "docs audit preview absorption"],
|
|
];
|
|
const missing = requiredSnippets
|
|
.filter(([content, snippet]) => !content.includes(snippet))
|
|
.map(([, , label]) => label);
|
|
if (missing.length > 0) {
|
|
throw new Error(`Missing memory governance and skill audit hooks: ${missing.join(", ")}`);
|
|
}
|
|
console.log("[DigitalEmployeeCheck] memory governance and skill audit hooks OK");
|
|
}
|
|
|
|
function checkDigitalOpsNotificationReportWorkbenches() {
|
|
console.log("\n[DigitalEmployeeCheck] Verify ops, notification and daily report workbench hooks");
|
|
const adapterPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "lib", "qimingclawAdapter.ts");
|
|
const apiPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "lib", "api.ts");
|
|
const typesPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "types", "api.ts");
|
|
const shellPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "pages", "digital", "DigitalEmployeeShell.tsx");
|
|
const commandDeckPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "pages", "digital", "CommandDeck.tsx");
|
|
const businessViewPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "pages", "digital", "BusinessView.tsx");
|
|
const opsWorkbenchPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "pages", "digital", "OpsWorkbench.tsx");
|
|
const notificationWorkbenchPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "pages", "digital", "NotificationWorkbench.tsx");
|
|
const dailyReportWorkbenchPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "pages", "digital", "DailyReportWorkbench.tsx");
|
|
const adapter = fs.readFileSync(adapterPath, "utf8");
|
|
const api = fs.readFileSync(apiPath, "utf8");
|
|
const types = fs.readFileSync(typesPath, "utf8");
|
|
const shell = fs.readFileSync(shellPath, "utf8");
|
|
const commandDeck = fs.readFileSync(commandDeckPath, "utf8");
|
|
const businessView = fs.readFileSync(businessViewPath, "utf8");
|
|
const opsWorkbench = fs.existsSync(opsWorkbenchPath) ? fs.readFileSync(opsWorkbenchPath, "utf8") : "";
|
|
const notificationWorkbench = fs.existsSync(notificationWorkbenchPath) ? fs.readFileSync(notificationWorkbenchPath, "utf8") : "";
|
|
const dailyReportWorkbench = fs.existsSync(dailyReportWorkbenchPath) ? fs.readFileSync(dailyReportWorkbenchPath, "utf8") : "";
|
|
const docs = fs.readFileSync(path.join(packageRoot, "..", "..", "docs", "digital-employee-frontend-integration-plan.md"), "utf8");
|
|
const requiredSnippets = [
|
|
[adapter, "opsWorkbenchRows", "adapter ops workbench projection"],
|
|
[adapter, "/api/digital-employee/ops-workbench", "adapter ops workbench endpoint"],
|
|
[adapter, "/api/digital-employee/ops-workbench/actions/batch", "adapter ops batch endpoint"],
|
|
[adapter, "safe_restart_service", "adapter safe restart action"],
|
|
[adapter, "ops_workbench_action_recorded", "adapter ops audit action"],
|
|
[adapter, "/api/digital-employee/notifications/workbench", "adapter notification workbench endpoint"],
|
|
[adapter, "/api/digital-employee/notifications/actions/batch", "adapter notification batch endpoint"],
|
|
[adapter, "notification_workbench_action_recorded", "adapter notification audit action"],
|
|
[adapter, "/api/digital-employee/daily-reports/workbench", "adapter daily report workbench endpoint"],
|
|
[adapter, "daily_report_workbench_action_recorded", "adapter daily report audit action"],
|
|
[api, "getDigitalEmployeeOpsWorkbench", "embedded ops workbench API"],
|
|
[api, "runDigitalEmployeeOpsBatchAction", "embedded ops batch API"],
|
|
[api, "getDigitalEmployeeNotificationWorkbench", "embedded notification workbench API"],
|
|
[api, "runDigitalEmployeeNotificationBatchAction", "embedded notification batch API"],
|
|
[api, "getDigitalEmployeeDailyReportWorkbench", "embedded daily report workbench API"],
|
|
[types, "DigitalEmployeeOpsWorkbenchRow", "ops workbench row type"],
|
|
[types, "DigitalEmployeeNotificationWorkbenchRow", "notification workbench row type"],
|
|
[types, "DigitalEmployeeDailyReportWorkbenchRow", "daily report workbench row type"],
|
|
[shell, "OpsWorkbench", "ops workbench shell component"],
|
|
[shell, "NotificationWorkbench", "notification workbench shell component"],
|
|
[shell, "DailyReportWorkbench", "daily report workbench shell component"],
|
|
[shell, "处置台", "ops workbench tab label"],
|
|
[shell, "通知运营", "notification workbench tab label"],
|
|
[shell, "日报运营", "daily report workbench tab label"],
|
|
[commandDeck, "打开处置台", "home ops entry"],
|
|
[commandDeck, "打开通知运营", "home notification entry"],
|
|
[commandDeck, "打开日报运营", "home daily report entry"],
|
|
[businessView, "打开处置台", "business view ops related link"],
|
|
[opsWorkbench, "安全重启", "ops safe restart UI"],
|
|
[opsWorkbench, "策略重拉", "ops policy retry UI"],
|
|
[notificationWorkbench, "批量已读", "notification batch read UI"],
|
|
[notificationWorkbench, "打开系统设置", "notification settings UI"],
|
|
[dailyReportWorkbench, "请求审批", "daily report approval UI"],
|
|
[dailyReportWorkbench, "确认回执", "daily report confirmation UI"],
|
|
[docs, "完整人机介入入口", "docs managed service ops absorption"],
|
|
[docs, "正式管理端通知运营预览", "docs notification workbench absorption"],
|
|
[docs, "诊断修复动作预览", "docs diagnostic repair absorption"],
|
|
[docs, "管理端正式日报页面预览", "docs daily report workbench absorption"],
|
|
];
|
|
const missing = requiredSnippets
|
|
.filter(([content, snippet]) => !content.includes(snippet))
|
|
.map(([, , label]) => label);
|
|
if (missing.length > 0) {
|
|
throw new Error(`Missing ops/notification/daily report workbench hooks: ${missing.join(", ")}`);
|
|
}
|
|
console.log("[DigitalEmployeeCheck] ops, notification and daily report workbench hooks OK");
|
|
}
|
|
|
|
function checkDigitalPolicySchedulerWorkbenches() {
|
|
console.log("\n[DigitalEmployeeCheck] Verify policy center and scheduler workbench hooks");
|
|
const apiPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "lib", "api.ts");
|
|
const typesPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "types", "api.ts");
|
|
const shellPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "pages", "digital", "DigitalEmployeeShell.tsx");
|
|
const commandDeckPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "pages", "digital", "CommandDeck.tsx");
|
|
const opsSettingsPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "pages", "digital", "OpsSettings.tsx");
|
|
const policyCenterPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "pages", "digital", "PolicyCenter.tsx");
|
|
const schedulerWorkbenchPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "pages", "digital", "SchedulerWorkbench.tsx");
|
|
const api = fs.readFileSync(apiPath, "utf8");
|
|
const types = fs.readFileSync(typesPath, "utf8");
|
|
const shell = fs.readFileSync(shellPath, "utf8");
|
|
const commandDeck = fs.readFileSync(commandDeckPath, "utf8");
|
|
const opsSettings = fs.readFileSync(opsSettingsPath, "utf8");
|
|
const policyCenter = fs.existsSync(policyCenterPath) ? fs.readFileSync(policyCenterPath, "utf8") : "";
|
|
const schedulerWorkbench = fs.existsSync(schedulerWorkbenchPath) ? fs.readFileSync(schedulerWorkbenchPath, "utf8") : "";
|
|
const docs = fs.readFileSync(path.join(packageRoot, "..", "..", "docs", "digital-employee-frontend-integration-plan.md"), "utf8");
|
|
const requiredSnippets = [
|
|
[api, "getDigitalEmployeePolicyCenter", "embedded policy center API"],
|
|
[api, "pullDigitalEmployeePoliciesBatch", "embedded policy batch pull API"],
|
|
[api, "getDigitalEmployeeSchedulerWorkbench", "embedded scheduler workbench API"],
|
|
[types, "DigitalEmployeePolicyCenterRow", "policy center row type"],
|
|
[types, "DigitalEmployeePolicyCenterResponse", "policy center response type"],
|
|
[types, "DigitalEmployeeSchedulerWorkbenchRow", "scheduler workbench row type"],
|
|
[types, "DigitalEmployeeSchedulerWorkbenchResponse", "scheduler workbench response type"],
|
|
[types, "DigitalEmployeePolicyPullBatchResult", "policy pull batch result type"],
|
|
[shell, "PolicyCenter", "policy center shell component"],
|
|
[shell, "SchedulerWorkbench", "scheduler workbench shell component"],
|
|
[shell, "策略中心", "policy center tab label"],
|
|
[shell, "调度运营", "scheduler workbench tab label"],
|
|
[commandDeck, "打开策略中心", "home policy center entry"],
|
|
[commandDeck, "打开调度运营", "home scheduler workbench entry"],
|
|
[opsSettings, "策略中心", "settings policy center hint"],
|
|
[policyCenter, "批量拉取策略", "policy center batch pull UI"],
|
|
[policyCenter, "max_per_sweep", "policy center dispatch policy field"],
|
|
[policyCenter, "auto_dispatch_ready_steps", "policy center auto dispatch field"],
|
|
[policyCenter, "auto_reject_actions", "policy center risk reject field"],
|
|
[schedulerWorkbench, "立即检查调度", "scheduler immediate check UI"],
|
|
[schedulerWorkbench, "catch_up_on_startup", "scheduler catch up setting UI"],
|
|
[schedulerWorkbench, "max_run_history", "scheduler history setting UI"],
|
|
[docs, "派发策略管理 UI", "docs dispatch policy UI absorption"],
|
|
[docs, "多调度并发策略 UI", "docs scheduler policy UI absorption"],
|
|
[docs, "管理端正式路由 UI 预览", "docs route policy preview absorption"],
|
|
];
|
|
const missing = requiredSnippets
|
|
.filter(([content, snippet]) => !content.includes(snippet))
|
|
.map(([, , label]) => label);
|
|
if (missing.length > 0) {
|
|
throw new Error(`Missing policy center and scheduler workbench hooks: ${missing.join(", ")}`);
|
|
}
|
|
console.log("[DigitalEmployeeCheck] policy center and scheduler workbench hooks OK");
|
|
}
|
|
|
|
function checkDigitalAdminActionLoop() {
|
|
console.log("\n[DigitalEmployeeCheck] Verify admin action pull/apply loop hooks");
|
|
const syncServicePath = path.join(packageRoot, "src", "main", "services", "digitalEmployee", "syncService.ts");
|
|
const ipcPath = path.join(packageRoot, "src", "main", "ipc", "digitalEmployeeHandlers.ts");
|
|
const preloadPath = path.join(packageRoot, "src", "preload", "webviewPerfBridge.ts");
|
|
const adapterPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "lib", "qimingclawAdapter.ts");
|
|
const apiPath = path.join(packageRoot, "embedded", "sgrobot-digital", "src", "lib", "api.ts");
|
|
const syncService = fs.readFileSync(syncServicePath, "utf8");
|
|
const ipc = fs.readFileSync(ipcPath, "utf8");
|
|
const preload = fs.readFileSync(preloadPath, "utf8");
|
|
const adapter = fs.readFileSync(adapterPath, "utf8");
|
|
const api = fs.readFileSync(apiPath, "utf8");
|
|
const requiredSnippets = [
|
|
[syncService, "pullAndApplyDigitalEmployeeAdminActions", "admin action pull service"],
|
|
[syncService, "admin_action_applied", "admin action applied event"],
|
|
[syncService, "admin_action_rejected", "admin action rejected event"],
|
|
[syncService, "admin_action_failed", "admin action failed event"],
|
|
[syncService, "cleanup_file_batch", "high risk cleanup rejection guard"],
|
|
[ipc, "digitalEmployee:pullAdminActions", "admin action IPC"],
|
|
[preload, "pullAdminActions", "admin action preload bridge"],
|
|
[adapter, "/api/digital-employee/admin/actions/pull", "admin action adapter endpoint"],
|
|
[api, "pullAdminActions", "embedded admin action API helper"],
|
|
];
|
|
const missing = requiredSnippets
|
|
.filter(([content, snippet]) => !content.includes(snippet))
|
|
.map(([, , label]) => label);
|
|
if (missing.length > 0) {
|
|
throw new Error(`Missing admin action loop hooks: ${missing.join(", ")}`);
|
|
}
|
|
console.log("[DigitalEmployeeCheck] admin action pull/apply loop hooks OK");
|
|
}
|
|
|
|
function checkDigitalAdminPolicySnapshots() {
|
|
console.log("\n[DigitalEmployeeCheck] Verify admin policy snapshot conflict view hooks");
|
|
const syncServicePath = path.join(packageRoot, "src", "main", "services", "digitalEmployee", "syncService.ts");
|
|
const syncTestPath = path.join(packageRoot, "src", "main", "services", "digitalEmployee", "syncService.test.ts");
|
|
const docsPath = path.resolve(packageRoot, "..", "..", "docs", "digital-employee-frontend-integration-plan.md");
|
|
const qimingRoot = path.resolve(packageRoot, "..", "..", "..", "qiming");
|
|
const backendRoot = path.resolve(packageRoot, "..", "..", "..", "qiming-backend");
|
|
const qimingOpsPath = path.join(qimingRoot, "src", "pages", "SystemManagement", "Content", "DigitalEmployeeOps", "index.tsx");
|
|
const qimingServicePath = path.join(qimingRoot, "src", "services", "systemManage.ts");
|
|
const qimingTypesPath = path.join(qimingRoot, "src", "types", "interfaces", "systemManage.ts");
|
|
const backendServicePath = path.join(
|
|
backendRoot,
|
|
"app-platform-modules",
|
|
"app-platform-agent",
|
|
"app-platform-agent-core-application",
|
|
"src",
|
|
"main",
|
|
"java",
|
|
"com",
|
|
"xspaceagi",
|
|
"agent",
|
|
"core",
|
|
"application",
|
|
"service",
|
|
"DigitalEmployeeSyncApplicationServiceImpl.java",
|
|
);
|
|
const backendDtoPath = path.join(
|
|
backendRoot,
|
|
"app-platform-modules",
|
|
"app-platform-agent",
|
|
"app-platform-agent-core-adapter",
|
|
"src",
|
|
"main",
|
|
"java",
|
|
"com",
|
|
"xspaceagi",
|
|
"agent",
|
|
"core",
|
|
"adapter",
|
|
"dto",
|
|
"digital",
|
|
"DigitalEmployeePolicySnapshotRowDto.java",
|
|
);
|
|
const backendTestPath = path.join(
|
|
backendRoot,
|
|
"app-platform-modules",
|
|
"app-platform-agent",
|
|
"app-platform-agent-core-application",
|
|
"src",
|
|
"test",
|
|
"java",
|
|
"com",
|
|
"xspaceagi",
|
|
"agent",
|
|
"core",
|
|
"application",
|
|
"service",
|
|
"DigitalEmployeeSyncApplicationServiceImplTest.java",
|
|
);
|
|
const backendControllerPath = path.join(
|
|
backendRoot,
|
|
"app-platform-modules",
|
|
"app-platform-agent",
|
|
"app-platform-agent-core-ui",
|
|
"src",
|
|
"main",
|
|
"java",
|
|
"com",
|
|
"xspaceagi",
|
|
"agent",
|
|
"web",
|
|
"ui",
|
|
"controller",
|
|
"DigitalEmployeeAdminPolicyController.java",
|
|
);
|
|
const syncService = fs.readFileSync(syncServicePath, "utf8");
|
|
const syncTest = fs.readFileSync(syncTestPath, "utf8");
|
|
const docs = fs.readFileSync(docsPath, "utf8");
|
|
const qimingOps = fs.readFileSync(qimingOpsPath, "utf8");
|
|
const qimingService = fs.readFileSync(qimingServicePath, "utf8");
|
|
const qimingTypes = fs.readFileSync(qimingTypesPath, "utf8");
|
|
const backendService = fs.readFileSync(backendServicePath, "utf8");
|
|
const backendDto = fs.readFileSync(backendDtoPath, "utf8");
|
|
const backendTest = fs.readFileSync(backendTestPath, "utf8");
|
|
const backendController = fs.readFileSync(backendControllerPath, "utf8");
|
|
const requiredSnippets = [
|
|
[syncService, "policySnapshotBusinessView", "client policy snapshot business view"],
|
|
[syncService, "policy_snapshot", "client policy snapshot category"],
|
|
[syncService, "policy_kind", "client policy kind field"],
|
|
[syncService, "auto_create_governance_commands", "route policy conflict field"],
|
|
[syncService, "max_per_sweep", "dispatch policy conflict field"],
|
|
[syncService, "catch_up_on_startup", "scheduler policy conflict field"],
|
|
[syncTest, "event-route-policy-pull", "route policy snapshot sync test"],
|
|
[syncTest, "event-risk-policy-pull", "risk policy snapshot sync test"],
|
|
[backendController, "/snapshots", "backend policy snapshot endpoint"],
|
|
[backendService, "routeInterventionConflictStatus", "backend route intervention conflict aggregation"],
|
|
[backendService, "route_intervention_state", "backend route intervention conflict key"],
|
|
[backendService, "approval_policy_id", "backend approval policy conflict field"],
|
|
[backendService, "decision_guard_status", "backend approval decision guard conflict field"],
|
|
[backendDto, "intervention_conflict_status", "backend route intervention conflict status field"],
|
|
[backendDto, "approval_policy_id", "backend policy snapshot approval policy field"],
|
|
[backendDto, "auto_decision_disabled", "backend policy snapshot auto decision field"],
|
|
[backendDto, "max_per_sweep", "backend policy snapshot max per sweep field"],
|
|
[backendDto, "catch_up_on_startup", "backend policy snapshot catch up field"],
|
|
[backendDto, "route_decision_count", "backend route decision count field"],
|
|
[backendTest, "queryAdminPolicySnapshotsSummarizesRouteInterventionConflicts", "backend route intervention conflict test"],
|
|
[backendTest, "queryAdminPolicySnapshotsSummarizesApprovalPolicyConflicts", "backend approval policy conflict test"],
|
|
[backendTest, "queryAdminPolicySnapshotsSummarizesDispatchAndSchedulerPolicyConflicts", "backend dispatch scheduler policy conflict test"],
|
|
[qimingService, "apiDigitalEmployeeAdminPolicySnapshots", "qiming policy snapshot service"],
|
|
[qimingService, "/api/digital-employee/admin/policies/snapshots", "qiming policy snapshot endpoint"],
|
|
[qimingTypes, "DigitalEmployeePolicySnapshotRow", "qiming policy snapshot row type"],
|
|
[qimingTypes, "policy_conflicts", "qiming policy conflicts view type"],
|
|
[qimingTypes, "approval_policy_id", "qiming approval policy snapshot type field"],
|
|
[qimingTypes, "max_per_sweep", "qiming dispatch policy snapshot type field"],
|
|
[qimingTypes, "catch_up_on_startup", "qiming scheduler policy snapshot type field"],
|
|
[qimingTypes, "intervention_conflict_status", "qiming route intervention conflict type field"],
|
|
[qimingOps, "策略冲突", "qiming policy conflict tab text"],
|
|
[qimingOps, "conflict_keys", "qiming conflict key display"],
|
|
[qimingOps, "跨设备审批策略冲突", "qiming approval policy conflict copy"],
|
|
[qimingOps, "跨设备派发策略冲突", "qiming dispatch policy conflict copy"],
|
|
[qimingOps, "跨设备调度策略冲突", "qiming scheduler policy conflict copy"],
|
|
[qimingOps, "裁决保护", "qiming decision guard conflict copy"],
|
|
[qimingOps, "跨设备路由干预冲突", "qiming route intervention conflict copy"],
|
|
[qimingOps, "不恢复执行", "qiming route recovery guard copy"],
|
|
[qimingOps, "不绕过审批", "qiming approval guard copy"],
|
|
[qimingOps, "不远程改策略", "qiming remote policy edit guard copy"],
|
|
[docs, "跨设备策略冲突视图", "docs policy conflict absorption"],
|
|
[docs, "跨设备审批策略冲突预览", "docs approval policy conflict absorption"],
|
|
[docs, "跨设备调度派发策略冲突预览", "docs dispatch scheduler policy conflict absorption"],
|
|
[docs, "跨设备路由干预冲突可视化", "docs route intervention conflict absorption"],
|
|
];
|
|
const missing = requiredSnippets
|
|
.filter(([content, snippet]) => !content.includes(snippet))
|
|
.map(([, , label]) => label);
|
|
if (missing.length > 0) {
|
|
throw new Error(`Missing admin policy snapshot hooks: ${missing.join(", ")}`);
|
|
}
|
|
console.log("[DigitalEmployeeCheck] admin policy snapshot conflict view hooks OK");
|
|
}
|
|
|
|
function checkDigitalBackendMaterializedFacts() {
|
|
console.log("\n[DigitalEmployeeCheck] Verify backend materialized business fact hooks");
|
|
const backendRoot = path.resolve(packageRoot, "..", "..", "..", "qiming-backend");
|
|
const qimingRoot = path.resolve(packageRoot, "..", "..", "..", "qiming");
|
|
const servicePath = path.join(
|
|
backendRoot,
|
|
"app-platform-modules",
|
|
"app-platform-agent",
|
|
"app-platform-agent-core-application",
|
|
"src",
|
|
"main",
|
|
"java",
|
|
"com",
|
|
"xspaceagi",
|
|
"agent",
|
|
"core",
|
|
"application",
|
|
"service",
|
|
"DigitalEmployeeSyncApplicationServiceImpl.java",
|
|
);
|
|
const sqlPath = path.join(backendRoot, "sql", "update-20260612.sql");
|
|
const dtoPath = path.join(
|
|
backendRoot,
|
|
"app-platform-modules",
|
|
"app-platform-agent",
|
|
"app-platform-agent-core-adapter",
|
|
"src",
|
|
"main",
|
|
"java",
|
|
"com",
|
|
"xspaceagi",
|
|
"agent",
|
|
"core",
|
|
"adapter",
|
|
"dto",
|
|
"digital",
|
|
"DigitalEmployeeBusinessViewRowDto.java",
|
|
);
|
|
const qimingTypesPath = path.join(qimingRoot, "src", "types", "interfaces", "systemManage.ts");
|
|
const docsPath = path.resolve(packageRoot, "..", "..", "docs", "digital-employee-frontend-integration-plan.md");
|
|
const service = fs.readFileSync(servicePath, "utf8");
|
|
const sql = fs.readFileSync(sqlPath, "utf8");
|
|
const dto = fs.readFileSync(dtoPath, "utf8");
|
|
const qimingTypes = fs.readFileSync(qimingTypesPath, "utf8");
|
|
const docs = fs.readFileSync(docsPath, "utf8");
|
|
const requiredSnippets = [
|
|
[sql, "digital_employee_business_fact", "business fact table migration"],
|
|
[sql, "digital_employee_artifact_lifecycle", "artifact lifecycle table migration"],
|
|
[sql, "digital_employee_daily_report_fact", "daily report fact table migration"],
|
|
[service, "materializeSyncRecord", "sync materialization hook"],
|
|
[service, "upsertBySyncRecord", "materialized upsert call"],
|
|
[service, "queryMaterializedBusinessRows", "materialized query preference"],
|
|
[dto, "materialized", "business row materialized flag"],
|
|
[qimingTypes, "materialized", "qiming materialized type field"],
|
|
[docs, "业务事实物化查询", "docs materialized fact absorption"],
|
|
];
|
|
const missing = requiredSnippets
|
|
.filter(([content, snippet]) => !content.includes(snippet))
|
|
.map(([, , label]) => label);
|
|
if (missing.length > 0) {
|
|
throw new Error(`Missing backend materialized fact hooks: ${missing.join(", ")}`);
|
|
}
|
|
console.log("[DigitalEmployeeCheck] backend materialized business fact hooks OK");
|
|
}
|
|
|
|
function checkDigitalAdminRecordBillingArchiveShell() {
|
|
console.log("\n[DigitalEmployeeCheck] Verify admin send/billing/audit archive shell hooks");
|
|
const backendRoot = path.resolve(packageRoot, "..", "..", "..", "qiming-backend");
|
|
const qimingRoot = path.resolve(packageRoot, "..", "..", "..", "qiming");
|
|
const docsPath = path.resolve(packageRoot, "..", "..", "docs", "digital-employee-frontend-integration-plan.md");
|
|
const servicePath = path.join(
|
|
backendRoot,
|
|
"app-platform-modules",
|
|
"app-platform-agent",
|
|
"app-platform-agent-core-application",
|
|
"src",
|
|
"main",
|
|
"java",
|
|
"com",
|
|
"xspaceagi",
|
|
"agent",
|
|
"core",
|
|
"application",
|
|
"service",
|
|
"DigitalEmployeeSyncApplicationServiceImpl.java",
|
|
);
|
|
const controllerPath = path.join(
|
|
backendRoot,
|
|
"app-platform-modules",
|
|
"app-platform-agent",
|
|
"app-platform-agent-core-ui",
|
|
"src",
|
|
"main",
|
|
"java",
|
|
"com",
|
|
"xspaceagi",
|
|
"agent",
|
|
"web",
|
|
"ui",
|
|
"controller",
|
|
"DigitalEmployeeAdminRecordController.java",
|
|
);
|
|
const qimingServicePath = path.join(qimingRoot, "src", "services", "systemManage.ts");
|
|
const qimingTypesPath = path.join(qimingRoot, "src", "types", "interfaces", "systemManage.ts");
|
|
const qimingOpsPath = path.join(qimingRoot, "src", "pages", "SystemManagement", "Content", "DigitalEmployeeOps", "index.tsx");
|
|
const service = fs.readFileSync(servicePath, "utf8");
|
|
const controller = fs.readFileSync(controllerPath, "utf8");
|
|
const qimingService = fs.readFileSync(qimingServicePath, "utf8");
|
|
const qimingTypes = fs.readFileSync(qimingTypesPath, "utf8");
|
|
const qimingOps = fs.readFileSync(qimingOpsPath, "utf8");
|
|
const docs = fs.readFileSync(docsPath, "utf8");
|
|
const requiredSnippets = [
|
|
[controller, "/daily-reports/send-records", "backend daily report send record endpoint"],
|
|
[controller, "/billing/estimates", "backend billing estimate endpoint"],
|
|
[controller, "/audit-archives", "backend audit archive endpoint"],
|
|
[service, "recordDailyReportSendResult", "backend daily report send record service"],
|
|
[service, "queryBillingEstimates", "backend billing estimate service"],
|
|
[service, "recordAuditArchive", "backend audit archive service"],
|
|
[service, "sanitizeAdminRecordValue", "backend admin record redaction"],
|
|
[service, "authorization", "backend sensitive authorization guard"],
|
|
[service, "raw_input", "backend sensitive raw input guard"],
|
|
[qimingService, "apiDigitalEmployeeAdminDailyReportSendRecord", "qiming daily report send record helper"],
|
|
[qimingService, "apiDigitalEmployeeAdminBillingEstimates", "qiming billing estimate helper"],
|
|
[qimingService, "apiDigitalEmployeeAdminAuditArchive", "qiming audit archive helper"],
|
|
[qimingTypes, "DigitalEmployeeBillingEstimate", "qiming billing estimate type"],
|
|
[qimingTypes, "DigitalEmployeeAdminRecordSubmitParams", "qiming admin record submit type"],
|
|
[qimingOps, "记录发送结果", "qiming daily report send UI"],
|
|
[qimingOps, "标记归档", "qiming audit archive UI"],
|
|
[qimingOps, "估算 Token", "qiming billing token UI"],
|
|
[qimingOps, "估算成本 USD", "qiming billing cost UI"],
|
|
[docs, "发送账单审计外壳", "docs send billing audit shell absorption"],
|
|
];
|
|
const missing = requiredSnippets
|
|
.filter(([content, snippet]) => !content.includes(snippet))
|
|
.map(([, , label]) => label);
|
|
if (missing.length > 0) {
|
|
throw new Error(`Missing admin send/billing/audit archive shell hooks: ${missing.join(", ")}`);
|
|
}
|
|
console.log("[DigitalEmployeeCheck] admin send/billing/audit archive shell hooks OK");
|
|
}
|
|
|
|
function checkDigitalAdminApprovalGovernanceWorkbench() {
|
|
console.log("\n[DigitalEmployeeCheck] Verify admin approval governance workbench hooks");
|
|
const backendRoot = path.resolve(packageRoot, "..", "..", "..", "qiming-backend");
|
|
const qimingRoot = path.resolve(packageRoot, "..", "..", "..", "qiming");
|
|
const servicePath = path.join(
|
|
backendRoot,
|
|
"app-platform-modules",
|
|
"app-platform-agent",
|
|
"app-platform-agent-core-application",
|
|
"src",
|
|
"main",
|
|
"java",
|
|
"com",
|
|
"xspaceagi",
|
|
"agent",
|
|
"core",
|
|
"application",
|
|
"service",
|
|
"DigitalEmployeeSyncApplicationServiceImpl.java",
|
|
);
|
|
const testPath = path.join(
|
|
backendRoot,
|
|
"app-platform-modules",
|
|
"app-platform-agent",
|
|
"app-platform-agent-core-application",
|
|
"src",
|
|
"test",
|
|
"java",
|
|
"com",
|
|
"xspaceagi",
|
|
"agent",
|
|
"core",
|
|
"application",
|
|
"service",
|
|
"DigitalEmployeeSyncApplicationServiceImplTest.java",
|
|
);
|
|
const qimingOpsPath = path.join(qimingRoot, "src", "pages", "SystemManagement", "Content", "DigitalEmployeeOps", "index.tsx");
|
|
const qimingTypesPath = path.join(qimingRoot, "src", "types", "interfaces", "systemManage.ts");
|
|
const docsPath = path.resolve(packageRoot, "..", "..", "docs", "digital-employee-frontend-integration-plan.md");
|
|
const service = fs.readFileSync(servicePath, "utf8");
|
|
const test = fs.readFileSync(testPath, "utf8");
|
|
const qimingOps = fs.readFileSync(qimingOpsPath, "utf8");
|
|
const qimingTypes = fs.readFileSync(qimingTypesPath, "utf8");
|
|
const docs = fs.readFileSync(docsPath, "utf8");
|
|
const requiredSnippets = [
|
|
[service, "approval_governance", "backend approval governance view"],
|
|
[service, "isApprovalGovernanceRow", "backend approval governance matcher"],
|
|
[service, "approval_conflict_active", "backend approval conflict classifier"],
|
|
[service, "risk_approval", "backend risk approval classifier"],
|
|
[service, "approval_action_recorded", "backend approval action history classifier"],
|
|
[service, "approval_policy_id", "backend approval policy field extraction"],
|
|
[service, "batch_accept_remote_disabled", "backend batch accept remote guard field"],
|
|
[service, "auto_decision_disabled", "backend auto decision guard field"],
|
|
[test, "queryAdminWorkbenchApprovalGovernanceReturnsApprovalConflictRiskAndHistoryRowsOnly", "backend approval governance test"],
|
|
[test, "getApprovalPolicyId", "backend approval policy assertion"],
|
|
[test, "getBatchAcceptRemoteDisabled", "backend batch accept disabled assertion"],
|
|
[qimingTypes, "approval_governance", "qiming approval governance view type"],
|
|
[qimingTypes, "approval_policy_id", "qiming approval policy field"],
|
|
[qimingTypes, "decision_guard_status", "qiming decision guard field"],
|
|
[qimingOps, "审批治理", "qiming approval governance tab"],
|
|
[qimingOps, "保留本地", "qiming approval keep local action"],
|
|
[qimingOps, "标记复核", "qiming approval mark reviewed action"],
|
|
[qimingOps, "裁决保护", "qiming decision guard copy"],
|
|
[qimingOps, "批量采纳远端禁用", "qiming batch accept remote guard copy"],
|
|
[qimingOps, "自动裁决禁用", "qiming auto decision guard copy"],
|
|
[qimingOps, "批量/高风险裁决不开放", "qiming approval governance safety copy"],
|
|
[docs, "正式管理端审批工作台预览", "docs approval governance absorption"],
|
|
[docs, "正式管理端审批裁决策略预览", "docs approval decision policy absorption"],
|
|
];
|
|
const missing = requiredSnippets
|
|
.filter(([content, snippet]) => !content.includes(snippet))
|
|
.map(([, , label]) => label);
|
|
if (missing.length > 0) {
|
|
throw new Error(`Missing admin approval governance workbench hooks: ${missing.join(", ")}`);
|
|
}
|
|
console.log("[DigitalEmployeeCheck] admin approval governance workbench hooks OK");
|
|
}
|
|
|
|
function checkDigitalAdminApprovalPoliciesWorkbench() {
|
|
console.log("\n[DigitalEmployeeCheck] Verify admin approval policies workbench hooks");
|
|
const backendRoot = path.resolve(packageRoot, "..", "..", "..", "qiming-backend");
|
|
const qimingRoot = path.resolve(packageRoot, "..", "..", "..", "qiming");
|
|
const servicePath = path.join(
|
|
backendRoot,
|
|
"app-platform-modules",
|
|
"app-platform-agent",
|
|
"app-platform-agent-core-application",
|
|
"src",
|
|
"main",
|
|
"java",
|
|
"com",
|
|
"xspaceagi",
|
|
"agent",
|
|
"core",
|
|
"application",
|
|
"service",
|
|
"DigitalEmployeeSyncApplicationServiceImpl.java",
|
|
);
|
|
const testPath = path.join(
|
|
backendRoot,
|
|
"app-platform-modules",
|
|
"app-platform-agent",
|
|
"app-platform-agent-core-application",
|
|
"src",
|
|
"test",
|
|
"java",
|
|
"com",
|
|
"xspaceagi",
|
|
"agent",
|
|
"core",
|
|
"application",
|
|
"service",
|
|
"DigitalEmployeeSyncApplicationServiceImplTest.java",
|
|
);
|
|
const qimingOpsPath = path.join(qimingRoot, "src", "pages", "SystemManagement", "Content", "DigitalEmployeeOps", "index.tsx");
|
|
const qimingTypesPath = path.join(qimingRoot, "src", "types", "interfaces", "systemManage.ts");
|
|
const docsPath = path.resolve(packageRoot, "..", "..", "docs", "digital-employee-frontend-integration-plan.md");
|
|
const service = fs.readFileSync(servicePath, "utf8");
|
|
const test = fs.readFileSync(testPath, "utf8");
|
|
const qimingOps = fs.readFileSync(qimingOpsPath, "utf8");
|
|
const qimingTypes = fs.readFileSync(qimingTypesPath, "utf8");
|
|
const docs = fs.readFileSync(docsPath, "utf8");
|
|
const requiredSnippets = [
|
|
[service, "approval_policies", "backend approval policies view"],
|
|
[service, "isApprovalPolicyRow", "backend approval policy matcher"],
|
|
[service, "approval_policy_id", "backend approval policy id projection"],
|
|
[service, "conflict_policy_id", "backend conflict policy id projection"],
|
|
[service, "decision_guard_status", "backend decision guard projection"],
|
|
[service, "policy_edit_request_id", "backend policy edit request projection"],
|
|
[service, "remotePolicyEditDisabled", "backend remote policy edit projection"],
|
|
[service, "autoMergeDisabled", "backend auto merge projection"],
|
|
[test, "queryAdminWorkbenchApprovalPoliciesReturnsPolicyRowsOnly", "backend approval policies test"],
|
|
[qimingTypes, "approval_policies", "qiming approval policies view type"],
|
|
[qimingOps, "审批策略", "qiming approval policies tab"],
|
|
[qimingOps, "不远程编辑策略", "qiming no remote policy edit copy"],
|
|
[qimingOps, "不自动裁决", "qiming no auto decision copy"],
|
|
[qimingOps, "不批量采纳远端", "qiming no batch remote accept copy"],
|
|
[docs, "正式管理端审批策略预览", "docs approval policy absorption"],
|
|
[docs, "远程策略编辑安全壳预览", "docs remote policy edit shell absorption"],
|
|
];
|
|
const missing = requiredSnippets
|
|
.filter(([content, snippet]) => !content.includes(snippet))
|
|
.map(([, , label]) => label);
|
|
if (missing.length > 0) {
|
|
throw new Error(`Missing admin approval policies workbench hooks: ${missing.join(", ")}`);
|
|
}
|
|
console.log("[DigitalEmployeeCheck] admin approval policies workbench hooks OK");
|
|
}
|
|
|
|
function checkDigitalAdminMemorySkillWorkbench() {
|
|
console.log("\n[DigitalEmployeeCheck] Verify admin memory governance and skill audit workbench hooks");
|
|
const backendRoot = path.resolve(packageRoot, "..", "..", "..", "qiming-backend");
|
|
const qimingRoot = path.resolve(packageRoot, "..", "..", "..", "qiming");
|
|
const servicePath = path.join(
|
|
backendRoot,
|
|
"app-platform-modules",
|
|
"app-platform-agent",
|
|
"app-platform-agent-core-application",
|
|
"src",
|
|
"main",
|
|
"java",
|
|
"com",
|
|
"xspaceagi",
|
|
"agent",
|
|
"core",
|
|
"application",
|
|
"service",
|
|
"DigitalEmployeeSyncApplicationServiceImpl.java",
|
|
);
|
|
const dtoPath = path.join(
|
|
backendRoot,
|
|
"app-platform-modules",
|
|
"app-platform-agent",
|
|
"app-platform-agent-core-adapter",
|
|
"src",
|
|
"main",
|
|
"java",
|
|
"com",
|
|
"xspaceagi",
|
|
"agent",
|
|
"core",
|
|
"adapter",
|
|
"dto",
|
|
"digital",
|
|
"DigitalEmployeeAdminWorkbenchRowDto.java",
|
|
);
|
|
const testPath = path.join(
|
|
backendRoot,
|
|
"app-platform-modules",
|
|
"app-platform-agent",
|
|
"app-platform-agent-core-application",
|
|
"src",
|
|
"test",
|
|
"java",
|
|
"com",
|
|
"xspaceagi",
|
|
"agent",
|
|
"core",
|
|
"application",
|
|
"service",
|
|
"DigitalEmployeeSyncApplicationServiceImplTest.java",
|
|
);
|
|
const qimingOpsPath = path.join(qimingRoot, "src", "pages", "SystemManagement", "Content", "DigitalEmployeeOps", "index.tsx");
|
|
const qimingTypesPath = path.join(qimingRoot, "src", "types", "interfaces", "systemManage.ts");
|
|
const docsPath = path.resolve(packageRoot, "..", "..", "docs", "digital-employee-frontend-integration-plan.md");
|
|
const service = fs.readFileSync(servicePath, "utf8");
|
|
const dto = fs.readFileSync(dtoPath, "utf8");
|
|
const test = fs.readFileSync(testPath, "utf8");
|
|
const qimingOps = fs.readFileSync(qimingOpsPath, "utf8");
|
|
const qimingTypes = fs.readFileSync(qimingTypesPath, "utf8");
|
|
const docs = fs.readFileSync(docsPath, "utf8");
|
|
const requiredSnippets = [
|
|
[service, "memory_governance", "backend memory governance view"],
|
|
[service, "memory_policies", "backend memory policies view"],
|
|
[service, "skill_audits", "backend skill audits view"],
|
|
[service, "isMemoryGovernanceRow", "backend memory governance matcher"],
|
|
[service, "isMemoryPolicyRow", "backend memory policies matcher"],
|
|
[service, "isSkillAuditRow", "backend skill audit matcher"],
|
|
[service, "skill_call_", "backend skill call classifier"],
|
|
[service, "tool_call_audit", "backend tool audit classifier"],
|
|
[service, "token_cost", "backend token cost classifier"],
|
|
[dto, "memory_id", "backend memory id row field"],
|
|
[dto, "memory_key", "backend memory key row field"],
|
|
[dto, "governance_status", "backend memory governance status row field"],
|
|
[dto, "merge_candidate_count", "backend memory merge candidate count row field"],
|
|
[dto, "duplicate_memory_ids", "backend duplicate memory ids row field"],
|
|
[dto, "memory_policy_id", "backend memory policy id row field"],
|
|
[dto, "memory_policy_status", "backend memory policy status row field"],
|
|
[dto, "merge_policy_id", "backend merge policy id row field"],
|
|
[dto, "merge_action_disabled", "backend merge action disabled row field"],
|
|
[dto, "remote_memory_policy_disabled", "backend remote memory policy disabled row field"],
|
|
[dto, "skill_id", "backend skill id row field"],
|
|
[dto, "skill_version", "backend skill version row field"],
|
|
[dto, "install_status", "backend skill install status row field"],
|
|
[dto, "permission_scope", "backend skill permission scope row field"],
|
|
[dto, "policy_source", "backend skill policy source row field"],
|
|
[dto, "skill_install_request_id", "backend skill install request id row field"],
|
|
[dto, "skill_upgrade_request_id", "backend skill upgrade request id row field"],
|
|
[dto, "permission_policy_id", "backend skill permission policy id row field"],
|
|
[dto, "install_action_disabled", "backend skill install action disabled row field"],
|
|
[dto, "upgrade_action_disabled", "backend skill upgrade action disabled row field"],
|
|
[dto, "permission_edit_disabled", "backend skill permission edit disabled row field"],
|
|
[dto, "tool_name", "backend tool name row field"],
|
|
[dto, "server_id", "backend server id row field"],
|
|
[test, "queryAdminWorkbenchMemoryGovernanceReturnsMemoryRowsOnly", "backend memory governance test"],
|
|
[test, "getMergeCandidateCount", "backend memory merge candidate assertion"],
|
|
[test, "queryAdminWorkbenchMemoryPoliciesReturnsPolicyRowsOnly", "backend memory policies test"],
|
|
[test, "getMemoryPolicyId", "backend memory policy assertion"],
|
|
[test, "queryAdminWorkbenchSkillAuditsReturnsSkillAndToolAuditRowsOnly", "backend skill audits test"],
|
|
[test, "queryAdminWorkbenchSkillAuditsReturnsVersionPermissionAndPolicyRowsOnly", "backend skill version permission test"],
|
|
[test, "getSkillInstallRequestId", "backend skill install request assertion"],
|
|
[test, "getPermissionPolicyId", "backend skill permission policy assertion"],
|
|
[test, "getInstallActionDisabled", "backend skill install disabled assertion"],
|
|
[test, "getUpgradeActionDisabled", "backend skill upgrade disabled assertion"],
|
|
[test, "getPermissionEditDisabled", "backend skill permission edit disabled assertion"],
|
|
[qimingTypes, "memory_governance", "qiming memory governance view type"],
|
|
[qimingTypes, "merge_candidate_count", "qiming memory merge candidate count field"],
|
|
[qimingTypes, "duplicate_memory_ids", "qiming duplicate memory ids field"],
|
|
[qimingTypes, "memory_policies", "qiming memory policies view type"],
|
|
[qimingTypes, "memory_policy_id", "qiming memory policy id field"],
|
|
[qimingTypes, "remote_memory_policy_disabled", "qiming remote memory policy disabled field"],
|
|
[qimingTypes, "skill_audits", "qiming skill audits view type"],
|
|
[qimingTypes, "skill_version", "qiming skill version field"],
|
|
[qimingTypes, "permission_scope", "qiming skill permission scope field"],
|
|
[qimingTypes, "skill_install_request_id", "qiming skill install request field"],
|
|
[qimingTypes, "skill_upgrade_request_id", "qiming skill upgrade request field"],
|
|
[qimingTypes, "permission_policy_id", "qiming skill permission policy field"],
|
|
[qimingTypes, "install_action_disabled", "qiming skill install disabled field"],
|
|
[qimingTypes, "upgrade_action_disabled", "qiming skill upgrade disabled field"],
|
|
[qimingTypes, "permission_edit_disabled", "qiming skill permission edit disabled field"],
|
|
[qimingOps, "记忆治理", "qiming memory governance tab"],
|
|
[qimingOps, "记忆策略", "qiming memory policies tab"],
|
|
[qimingOps, "技能审计", "qiming skill audits tab"],
|
|
[qimingOps, "安装请求", "qiming skill install request copy"],
|
|
[qimingOps, "升级请求", "qiming skill upgrade request copy"],
|
|
[qimingOps, "权限策略", "qiming skill permission policy copy"],
|
|
[qimingOps, "权限编辑禁用", "qiming skill permission edit safety copy"],
|
|
[qimingOps, "权限范围", "qiming skill permission scope copy"],
|
|
[qimingOps, "策略来源", "qiming skill policy source copy"],
|
|
[qimingOps, "批量归档", "qiming memory archive action"],
|
|
[qimingOps, "批量恢复", "qiming memory restore action"],
|
|
[qimingOps, "重复候选", "qiming memory duplicate copy"],
|
|
[qimingOps, "不自动合并记忆", "qiming memory merge safety copy"],
|
|
[qimingOps, "远端记忆策略", "qiming memory policy copy"],
|
|
[qimingOps, "不触发自动合并", "qiming memory policy merge safety copy"],
|
|
[docs, "正式管理端记忆治理预览", "docs memory governance absorption"],
|
|
[docs, "正式管理端记忆合并候选预览", "docs memory merge candidate absorption"],
|
|
[docs, "远端记忆策略预览", "docs memory policy absorption"],
|
|
[docs, "正式管理端技能审计预览", "docs skill audit absorption"],
|
|
[docs, "正式管理端技能版本权限预览", "docs skill version permission absorption"],
|
|
[docs, "正式管理端技能安装权限预览", "docs skill install permission absorption"],
|
|
];
|
|
const missing = requiredSnippets
|
|
.filter(([content, snippet]) => !content.includes(snippet))
|
|
.map(([, , label]) => label);
|
|
if (missing.length > 0) {
|
|
throw new Error(`Missing admin memory governance and skill audit hooks: ${missing.join(", ")}`);
|
|
}
|
|
console.log("[DigitalEmployeeCheck] admin memory governance and skill audit hooks OK");
|
|
}
|
|
|
|
function checkDigitalAdminPolicySchedulerWorkbenches() {
|
|
console.log("\n[DigitalEmployeeCheck] Verify admin policy center and scheduler operation workbench hooks");
|
|
const backendRoot = path.resolve(packageRoot, "..", "..", "..", "qiming-backend");
|
|
const qimingRoot = path.resolve(packageRoot, "..", "..", "..", "qiming");
|
|
const servicePath = path.join(
|
|
backendRoot,
|
|
"app-platform-modules",
|
|
"app-platform-agent",
|
|
"app-platform-agent-core-application",
|
|
"src",
|
|
"main",
|
|
"java",
|
|
"com",
|
|
"xspaceagi",
|
|
"agent",
|
|
"core",
|
|
"application",
|
|
"service",
|
|
"DigitalEmployeeSyncApplicationServiceImpl.java",
|
|
);
|
|
const dtoPath = path.join(
|
|
backendRoot,
|
|
"app-platform-modules",
|
|
"app-platform-agent",
|
|
"app-platform-agent-core-adapter",
|
|
"src",
|
|
"main",
|
|
"java",
|
|
"com",
|
|
"xspaceagi",
|
|
"agent",
|
|
"core",
|
|
"adapter",
|
|
"dto",
|
|
"digital",
|
|
"DigitalEmployeeAdminWorkbenchRowDto.java",
|
|
);
|
|
const testPath = path.join(
|
|
backendRoot,
|
|
"app-platform-modules",
|
|
"app-platform-agent",
|
|
"app-platform-agent-core-application",
|
|
"src",
|
|
"test",
|
|
"java",
|
|
"com",
|
|
"xspaceagi",
|
|
"agent",
|
|
"core",
|
|
"application",
|
|
"service",
|
|
"DigitalEmployeeSyncApplicationServiceImplTest.java",
|
|
);
|
|
const qimingOpsPath = path.join(qimingRoot, "src", "pages", "SystemManagement", "Content", "DigitalEmployeeOps", "index.tsx");
|
|
const qimingTypesPath = path.join(qimingRoot, "src", "types", "interfaces", "systemManage.ts");
|
|
const docsPath = path.resolve(packageRoot, "..", "..", "docs", "digital-employee-frontend-integration-plan.md");
|
|
const service = fs.readFileSync(servicePath, "utf8");
|
|
const dto = fs.readFileSync(dtoPath, "utf8");
|
|
const test = fs.readFileSync(testPath, "utf8");
|
|
const qimingOps = fs.readFileSync(qimingOpsPath, "utf8");
|
|
const qimingTypes = fs.readFileSync(qimingTypesPath, "utf8");
|
|
const docs = fs.readFileSync(docsPath, "utf8");
|
|
const requiredSnippets = [
|
|
[service, "policy_center", "backend policy center view"],
|
|
[service, "scheduler_operations", "backend scheduler operations view"],
|
|
[service, "isPolicyCenterRow", "backend policy center matcher"],
|
|
[service, "isSchedulerOperationsRow", "backend scheduler operations matcher"],
|
|
[service, "edit_policy_remote_disabled", "backend policy edit disabled reason"],
|
|
[service, "remote_policy_edit_disabled", "backend remote policy edit disabled reason"],
|
|
[service, "policy_edit_request_id", "backend policy edit request projection"],
|
|
[service, "auto_merge_disabled", "backend policy auto merge guard projection"],
|
|
[service, "run_schedule_now_disabled", "backend scheduler run disabled reason"],
|
|
[service, "start_scheduler_disabled", "backend scheduler start disabled reason"],
|
|
[dto, "policy_kind", "backend policy kind row field"],
|
|
[dto, "policy_key", "backend policy key row field"],
|
|
[dto, "policy_edit_request_id", "backend policy edit request row field"],
|
|
[dto, "remote_policy_edit_disabled", "backend remote policy edit disabled row field"],
|
|
[dto, "auto_merge_disabled", "backend auto merge disabled row field"],
|
|
[dto, "schedule_id", "backend schedule id row field"],
|
|
[dto, "job_id", "backend job id row field"],
|
|
[test, "queryAdminWorkbenchPolicyCenterReturnsPolicySnapshotRowsOnly", "backend policy center test"],
|
|
[test, "getPolicyEditRequestId", "backend policy edit request assertion"],
|
|
[test, "getAutoMergeDisabled", "backend auto merge disabled assertion"],
|
|
[test, "queryAdminWorkbenchSchedulerOperationsReturnsSchedulerRowsOnly", "backend scheduler operations test"],
|
|
[test, "createAdminActionReturnsSpecificPolicyAndSchedulerDisabledReasons", "backend disabled reason test"],
|
|
[qimingTypes, "policy_center", "qiming policy center view type"],
|
|
[qimingTypes, "scheduler_operations", "qiming scheduler operations view type"],
|
|
[qimingTypes, "policy_edit_request_id", "qiming policy edit request field"],
|
|
[qimingTypes, "auto_merge_disabled", "qiming policy auto merge guard field"],
|
|
[qimingTypes, "schedule_id", "qiming schedule id field"],
|
|
[qimingOps, "策略中心", "qiming policy center tab"],
|
|
[qimingOps, "调度运营", "qiming scheduler operations tab"],
|
|
[qimingOps, "批量拉取策略", "qiming policy pull action"],
|
|
[qimingOps, "远程策略编辑请求", "qiming policy edit request detail"],
|
|
[qimingOps, "自动合并禁用", "qiming policy auto merge guard copy"],
|
|
[qimingOps, "立即检查调度", "qiming scheduler check action"],
|
|
[qimingOps, "不开放远程策略编辑", "qiming policy edit guard copy"],
|
|
[qimingOps, "不自动合并策略", "qiming policy auto merge safety copy"],
|
|
[qimingOps, "不开放 start/stop", "qiming scheduler start stop guard copy"],
|
|
[docs, "正式管理端策略中心预览", "docs policy center absorption"],
|
|
[docs, "远程策略编辑安全壳预览", "docs remote policy edit shell absorption"],
|
|
[docs, "正式管理端调度运营预览", "docs scheduler operations absorption"],
|
|
];
|
|
const missing = requiredSnippets
|
|
.filter(([content, snippet]) => !content.includes(snippet))
|
|
.map(([, , label]) => label);
|
|
if (missing.length > 0) {
|
|
throw new Error(`Missing admin policy center and scheduler operation hooks: ${missing.join(", ")}`);
|
|
}
|
|
console.log("[DigitalEmployeeCheck] admin policy center and scheduler operation hooks OK");
|
|
}
|
|
|
|
function checkDigitalAdminPlanGovernanceWorkbenches() {
|
|
console.log("\n[DigitalEmployeeCheck] Verify admin plan governance and revision workbench hooks");
|
|
const backendRoot = path.resolve(packageRoot, "..", "..", "..", "qiming-backend");
|
|
const qimingRoot = path.resolve(packageRoot, "..", "..", "..", "qiming");
|
|
const servicePath = path.join(
|
|
backendRoot,
|
|
"app-platform-modules",
|
|
"app-platform-agent",
|
|
"app-platform-agent-core-application",
|
|
"src",
|
|
"main",
|
|
"java",
|
|
"com",
|
|
"xspaceagi",
|
|
"agent",
|
|
"core",
|
|
"application",
|
|
"service",
|
|
"DigitalEmployeeSyncApplicationServiceImpl.java",
|
|
);
|
|
const dtoPath = path.join(
|
|
backendRoot,
|
|
"app-platform-modules",
|
|
"app-platform-agent",
|
|
"app-platform-agent-core-adapter",
|
|
"src",
|
|
"main",
|
|
"java",
|
|
"com",
|
|
"xspaceagi",
|
|
"agent",
|
|
"core",
|
|
"adapter",
|
|
"dto",
|
|
"digital",
|
|
"DigitalEmployeeAdminWorkbenchRowDto.java",
|
|
);
|
|
const testPath = path.join(
|
|
backendRoot,
|
|
"app-platform-modules",
|
|
"app-platform-agent",
|
|
"app-platform-agent-core-application",
|
|
"src",
|
|
"test",
|
|
"java",
|
|
"com",
|
|
"xspaceagi",
|
|
"agent",
|
|
"core",
|
|
"application",
|
|
"service",
|
|
"DigitalEmployeeSyncApplicationServiceImplTest.java",
|
|
);
|
|
const qimingOpsPath = path.join(qimingRoot, "src", "pages", "SystemManagement", "Content", "DigitalEmployeeOps", "index.tsx");
|
|
const qimingTypesPath = path.join(qimingRoot, "src", "types", "interfaces", "systemManage.ts");
|
|
const docsPath = path.resolve(packageRoot, "..", "..", "docs", "digital-employee-frontend-integration-plan.md");
|
|
const service = fs.readFileSync(servicePath, "utf8");
|
|
const dto = fs.readFileSync(dtoPath, "utf8");
|
|
const test = fs.readFileSync(testPath, "utf8");
|
|
const qimingOps = fs.readFileSync(qimingOpsPath, "utf8");
|
|
const qimingTypes = fs.readFileSync(qimingTypesPath, "utf8");
|
|
const docs = fs.readFileSync(docsPath, "utf8");
|
|
const requiredSnippets = [
|
|
[service, "plan_governance", "backend plan governance view"],
|
|
[service, "plan_revisions", "backend plan revisions view"],
|
|
[service, "isPlanGovernanceRow", "backend plan governance matcher"],
|
|
[service, "isPlanRevisionRow", "backend plan revision matcher"],
|
|
[service, "record_escalation", "backend plan escalation action"],
|
|
[service, "hard_interrupt_disabled", "backend hard interrupt disabled reason"],
|
|
[service, "high_risk_governance_action_disabled", "backend high risk governance disabled reason"],
|
|
[dto, "revision_id", "backend revision id row field"],
|
|
[test, "queryAdminWorkbenchPlanGovernanceReturnsGovernanceEscalationRowsOnly", "backend plan governance test"],
|
|
[test, "queryAdminWorkbenchPlanRevisionsReturnsRevisionRowsOnly", "backend plan revisions test"],
|
|
[qimingTypes, "plan_governance", "qiming plan governance view type"],
|
|
[qimingTypes, "plan_revisions", "qiming plan revisions view type"],
|
|
[qimingTypes, "revision_id", "qiming revision id field"],
|
|
[qimingOps, "计划治理", "qiming plan governance tab"],
|
|
[qimingOps, "计划版本", "qiming plan revisions tab"],
|
|
[qimingOps, "请求版本复核", "qiming revision review action"],
|
|
[qimingOps, "记录升级", "qiming escalation action"],
|
|
[qimingOps, "不开放 hard interrupt", "qiming hard interrupt guard copy"],
|
|
[qimingOps, "不自动激活计划", "qiming high risk execution guard copy"],
|
|
[docs, "正式管理端治理执行安全壳预览", "docs plan governance absorption"],
|
|
[docs, "正式管理端计划版本预览", "docs plan revision absorption"],
|
|
];
|
|
const missing = requiredSnippets
|
|
.filter(([content, snippet]) => !content.includes(snippet))
|
|
.map(([, , label]) => label);
|
|
if (missing.length > 0) {
|
|
throw new Error(`Missing admin plan governance and revision hooks: ${missing.join(", ")}`);
|
|
}
|
|
console.log("[DigitalEmployeeCheck] admin plan governance and revision hooks OK");
|
|
}
|
|
|
|
function checkDigitalAdminGovernancePolicyRevisionMaterialization() {
|
|
console.log("\n[DigitalEmployeeCheck] Verify admin governance policy and revision materialization hooks");
|
|
const backendRoot = path.resolve(packageRoot, "..", "..", "..", "qiming-backend");
|
|
const qimingRoot = path.resolve(packageRoot, "..", "..", "..", "qiming");
|
|
const servicePath = path.join(
|
|
backendRoot,
|
|
"app-platform-modules",
|
|
"app-platform-agent",
|
|
"app-platform-agent-core-application",
|
|
"src",
|
|
"main",
|
|
"java",
|
|
"com",
|
|
"xspaceagi",
|
|
"agent",
|
|
"core",
|
|
"application",
|
|
"service",
|
|
"DigitalEmployeeSyncApplicationServiceImpl.java",
|
|
);
|
|
const dtoPath = path.join(
|
|
backendRoot,
|
|
"app-platform-modules",
|
|
"app-platform-agent",
|
|
"app-platform-agent-core-adapter",
|
|
"src",
|
|
"main",
|
|
"java",
|
|
"com",
|
|
"xspaceagi",
|
|
"agent",
|
|
"core",
|
|
"adapter",
|
|
"dto",
|
|
"digital",
|
|
"DigitalEmployeeAdminWorkbenchRowDto.java",
|
|
);
|
|
const testPath = path.join(
|
|
backendRoot,
|
|
"app-platform-modules",
|
|
"app-platform-agent",
|
|
"app-platform-agent-core-application",
|
|
"src",
|
|
"test",
|
|
"java",
|
|
"com",
|
|
"xspaceagi",
|
|
"agent",
|
|
"core",
|
|
"application",
|
|
"service",
|
|
"DigitalEmployeeSyncApplicationServiceImplTest.java",
|
|
);
|
|
const qimingOpsPath = path.join(qimingRoot, "src", "pages", "SystemManagement", "Content", "DigitalEmployeeOps", "index.tsx");
|
|
const qimingTypesPath = path.join(qimingRoot, "src", "types", "interfaces", "systemManage.ts");
|
|
const docsPath = path.resolve(packageRoot, "..", "..", "docs", "digital-employee-frontend-integration-plan.md");
|
|
const service = fs.readFileSync(servicePath, "utf8");
|
|
const dto = fs.readFileSync(dtoPath, "utf8");
|
|
const test = fs.readFileSync(testPath, "utf8");
|
|
const qimingOps = fs.readFileSync(qimingOpsPath, "utf8");
|
|
const qimingTypes = fs.readFileSync(qimingTypesPath, "utf8");
|
|
const docs = fs.readFileSync(docsPath, "utf8");
|
|
const requiredSnippets = [
|
|
[service, "governance_policies", "backend governance policies view"],
|
|
[service, "plan_revision_materialization", "backend plan revision materialization view"],
|
|
[service, "isGovernancePolicyRow", "backend governance policy matcher"],
|
|
[service, "isPlanRevisionMaterializationRow", "backend revision materialization matcher"],
|
|
[service, "governance_policy:pull_policy", "backend governance policy pull action"],
|
|
[service, "hard_interrupt_disabled", "backend hard interrupt disabled reason"],
|
|
[dto, "governance_policy_id", "backend governance policy id field"],
|
|
[dto, "policy_guard_status", "backend policy guard status field"],
|
|
[dto, "revision_fact_id", "backend revision fact id field"],
|
|
[dto, "revision_materialized", "backend revision materialized field"],
|
|
[dto, "changed_fields", "backend changed fields row field"],
|
|
[test, "queryAdminWorkbenchGovernancePoliciesReturnsPolicyRowsOnly", "backend governance policies test"],
|
|
[test, "queryAdminWorkbenchPlanRevisionMaterializationReturnsRevisionRowsOnly", "backend revision materialization test"],
|
|
[test, "createAdminActionAllowsGovernancePolicyRevisionLowRiskActions", "backend low risk action test"],
|
|
[qimingTypes, "governance_policies", "qiming governance policies view type"],
|
|
[qimingTypes, "plan_revision_materialization", "qiming revision materialization view type"],
|
|
[qimingTypes, "governance_policy_id", "qiming governance policy id field"],
|
|
[qimingTypes, "revision_fact_id", "qiming revision fact id field"],
|
|
[qimingOps, "治理策略", "qiming governance policies tab"],
|
|
[qimingOps, "版本物化", "qiming revision materialization tab"],
|
|
[qimingOps, "策略保护", "qiming policy guard copy"],
|
|
[qimingOps, "版本事实来源", "qiming revision fact source copy"],
|
|
[qimingOps, "不开放 ACP 硬中断", "qiming ACP hard interrupt guard copy"],
|
|
[docs, "正式管理端治理策略预览", "docs governance policy absorption"],
|
|
[docs, "计划版本物化预览", "docs revision materialization absorption"],
|
|
];
|
|
const missing = requiredSnippets
|
|
.filter(([content, snippet]) => !content.includes(snippet))
|
|
.map(([, , label]) => label);
|
|
if (missing.length > 0) {
|
|
throw new Error(`Missing admin governance policy and revision materialization hooks: ${missing.join(", ")}`);
|
|
}
|
|
console.log("[DigitalEmployeeCheck] admin governance policy and revision materialization hooks OK");
|
|
}
|
|
|
|
function checkDigitalAdminPolicyGovernanceClosure() {
|
|
console.log("\n[DigitalEmployeeCheck] Verify admin policy governance approval route closure hooks");
|
|
const backendRoot = path.resolve(packageRoot, "..", "..", "..", "qiming-backend");
|
|
const qimingRoot = path.resolve(packageRoot, "..", "..", "..", "qiming");
|
|
const servicePath = path.join(
|
|
backendRoot,
|
|
"app-platform-modules",
|
|
"app-platform-agent",
|
|
"app-platform-agent-core-application",
|
|
"src",
|
|
"main",
|
|
"java",
|
|
"com",
|
|
"xspaceagi",
|
|
"agent",
|
|
"core",
|
|
"application",
|
|
"service",
|
|
"DigitalEmployeeSyncApplicationServiceImpl.java",
|
|
);
|
|
const dtoPath = path.join(
|
|
backendRoot,
|
|
"app-platform-modules",
|
|
"app-platform-agent",
|
|
"app-platform-agent-core-adapter",
|
|
"src",
|
|
"main",
|
|
"java",
|
|
"com",
|
|
"xspaceagi",
|
|
"agent",
|
|
"core",
|
|
"adapter",
|
|
"dto",
|
|
"digital",
|
|
"DigitalEmployeeAdminWorkbenchRowDto.java",
|
|
);
|
|
const testPath = path.join(
|
|
backendRoot,
|
|
"app-platform-modules",
|
|
"app-platform-agent",
|
|
"app-platform-agent-core-application",
|
|
"src",
|
|
"test",
|
|
"java",
|
|
"com",
|
|
"xspaceagi",
|
|
"agent",
|
|
"core",
|
|
"application",
|
|
"service",
|
|
"DigitalEmployeeSyncApplicationServiceImplTest.java",
|
|
);
|
|
const qimingOpsPath = path.join(qimingRoot, "src", "pages", "SystemManagement", "Content", "DigitalEmployeeOps", "index.tsx");
|
|
const qimingTypesPath = path.join(qimingRoot, "src", "types", "interfaces", "systemManage.ts");
|
|
const docsPath = path.resolve(packageRoot, "..", "..", "docs", "digital-employee-frontend-integration-plan.md");
|
|
const service = fs.readFileSync(servicePath, "utf8");
|
|
const dto = fs.readFileSync(dtoPath, "utf8");
|
|
const test = fs.readFileSync(testPath, "utf8");
|
|
const qimingOps = fs.readFileSync(qimingOpsPath, "utf8");
|
|
const qimingTypes = fs.readFileSync(qimingTypesPath, "utf8");
|
|
const docs = fs.readFileSync(docsPath, "utf8");
|
|
const requiredSnippets = [
|
|
[service, "policy_center", "backend policy center view"],
|
|
[service, "governance_policies", "backend governance policies view"],
|
|
[service, "approval_policies", "backend approval policies view"],
|
|
[service, "route_governance", "backend route governance view"],
|
|
[service, "request_policy_edit", "backend low risk policy edit request action"],
|
|
[service, "request_policy_merge_review", "backend low risk policy merge review action"],
|
|
[service, "auto_merge_policy_disabled", "backend auto merge disabled reason"],
|
|
[service, "auto_decision_disabled", "backend auto decision disabled reason"],
|
|
[service, "route_recovery_disabled", "backend route recovery disabled reason"],
|
|
[dto, "merge_request_id", "backend merge request row field"],
|
|
[dto, "merge_recommendation", "backend merge recommendation row field"],
|
|
[dto, "approval_policy_edit_disabled", "backend approval policy edit guard field"],
|
|
[dto, "route_policy_edit_disabled", "backend route policy edit guard field"],
|
|
[dto, "route_recovery_disabled", "backend route recovery guard field"],
|
|
[dto, "high_risk_execution_disabled", "backend high risk execution guard field"],
|
|
[test, "queryAdminWorkbenchPolicyCenterReturnsPolicyEditAndMergeShellRows", "backend policy center closure test"],
|
|
[test, "queryAdminWorkbenchGovernancePoliciesReturnsExecutionGuardRows", "backend governance execution guard test"],
|
|
[test, "queryAdminWorkbenchApprovalPoliciesReturnsDecisionGuardShellRows", "backend approval decision guard test"],
|
|
[test, "queryAdminWorkbenchRouteGovernanceReturnsRecoveryGuardRows", "backend route recovery guard test"],
|
|
[test, "createAdminActionAllowsLowRiskPolicyGovernanceIntents", "backend low risk policy governance actions test"],
|
|
[test, "createAdminActionRejectsHighRiskPolicyGovernanceExecution", "backend high risk policy governance rejection test"],
|
|
[qimingTypes, "merge_request_id", "qiming merge request type field"],
|
|
[qimingTypes, "merge_recommendation", "qiming merge recommendation type field"],
|
|
[qimingTypes, "approval_policy_edit_disabled", "qiming approval policy guard type field"],
|
|
[qimingTypes, "route_policy_edit_disabled", "qiming route policy guard type field"],
|
|
[qimingTypes, "route_recovery_disabled", "qiming route recovery guard type field"],
|
|
[qimingTypes, "high_risk_execution_disabled", "qiming high risk guard type field"],
|
|
[qimingOps, "策略中心", "qiming policy center tab"],
|
|
[qimingOps, "治理策略", "qiming governance policies tab"],
|
|
[qimingOps, "审批策略", "qiming approval policies tab"],
|
|
[qimingOps, "路由治理", "qiming route governance tab"],
|
|
[qimingOps, "请求策略编辑", "qiming policy edit request action"],
|
|
[qimingOps, "请求合并复核", "qiming merge review action"],
|
|
[qimingOps, "策略编辑/合并安全壳", "qiming policy edit merge shell copy"],
|
|
[qimingOps, "合并建议", "qiming merge recommendation copy"],
|
|
[qimingOps, "审批策略编辑/裁决安全壳", "qiming approval decision shell copy"],
|
|
[qimingOps, "路由策略编辑/恢复安全壳", "qiming route recovery shell copy"],
|
|
[qimingOps, "高风险恢复执行不开放", "qiming high risk route recovery guard copy"],
|
|
[qimingOps, "真实远程策略强编辑不开放", "qiming remote force edit guard copy"],
|
|
[docs, "策略治理审批路由总收口已开始吸收", "docs policy governance closure absorption"],
|
|
];
|
|
const missing = requiredSnippets
|
|
.filter(([content, snippet]) => !content.includes(snippet))
|
|
.map(([, , label]) => label);
|
|
if (missing.length > 0) {
|
|
throw new Error(`Missing admin policy governance closure hooks: ${missing.join(", ")}`);
|
|
}
|
|
console.log("[DigitalEmployeeCheck] admin policy governance closure hooks OK");
|
|
}
|
|
|
|
function checkDigitalAdminPlanStepDispatchWorkbench() {
|
|
console.log("\n[DigitalEmployeeCheck] Verify admin plan step dispatch workbench hooks");
|
|
const backendRoot = path.resolve(packageRoot, "..", "..", "..", "qiming-backend");
|
|
const qimingRoot = path.resolve(packageRoot, "..", "..", "..", "qiming");
|
|
const servicePath = path.join(
|
|
backendRoot,
|
|
"app-platform-modules",
|
|
"app-platform-agent",
|
|
"app-platform-agent-core-application",
|
|
"src",
|
|
"main",
|
|
"java",
|
|
"com",
|
|
"xspaceagi",
|
|
"agent",
|
|
"core",
|
|
"application",
|
|
"service",
|
|
"DigitalEmployeeSyncApplicationServiceImpl.java",
|
|
);
|
|
const dtoPath = path.join(
|
|
backendRoot,
|
|
"app-platform-modules",
|
|
"app-platform-agent",
|
|
"app-platform-agent-core-adapter",
|
|
"src",
|
|
"main",
|
|
"java",
|
|
"com",
|
|
"xspaceagi",
|
|
"agent",
|
|
"core",
|
|
"adapter",
|
|
"dto",
|
|
"digital",
|
|
"DigitalEmployeeAdminWorkbenchRowDto.java",
|
|
);
|
|
const testPath = path.join(
|
|
backendRoot,
|
|
"app-platform-modules",
|
|
"app-platform-agent",
|
|
"app-platform-agent-core-application",
|
|
"src",
|
|
"test",
|
|
"java",
|
|
"com",
|
|
"xspaceagi",
|
|
"agent",
|
|
"core",
|
|
"application",
|
|
"service",
|
|
"DigitalEmployeeSyncApplicationServiceImplTest.java",
|
|
);
|
|
const qimingOpsPath = path.join(qimingRoot, "src", "pages", "SystemManagement", "Content", "DigitalEmployeeOps", "index.tsx");
|
|
const qimingTypesPath = path.join(qimingRoot, "src", "types", "interfaces", "systemManage.ts");
|
|
const docsPath = path.resolve(packageRoot, "..", "..", "docs", "digital-employee-frontend-integration-plan.md");
|
|
const service = fs.readFileSync(servicePath, "utf8");
|
|
const dto = fs.readFileSync(dtoPath, "utf8");
|
|
const test = fs.readFileSync(testPath, "utf8");
|
|
const qimingOps = fs.readFileSync(qimingOpsPath, "utf8");
|
|
const qimingTypes = fs.readFileSync(qimingTypesPath, "utf8");
|
|
const docs = fs.readFileSync(docsPath, "utf8");
|
|
const requiredSnippets = [
|
|
[service, "plan_step_dispatch", "backend plan step dispatch view"],
|
|
[service, "isPlanStepDispatchRow", "backend plan step dispatch matcher"],
|
|
[service, "plan_step:retry_policy_check", "backend plan step retry policy action"],
|
|
[service, "remote_lease_rejected", "backend remote lease rejection matcher"],
|
|
[service, "local_fallback", "backend local fallback matcher"],
|
|
[dto, "step_id", "backend step id field"],
|
|
[dto, "lease_state", "backend lease state field"],
|
|
[dto, "dispatch_status", "backend dispatch status field"],
|
|
[dto, "dispatch_policy_key", "backend dispatch policy key field"],
|
|
[test, "queryAdminWorkbenchPlanStepDispatchReturnsStepLeaseAndDispatchRowsOnly", "backend plan step dispatch test"],
|
|
[qimingTypes, "plan_step_dispatch", "qiming plan step dispatch view type"],
|
|
[qimingTypes, "step_id", "qiming step id field"],
|
|
[qimingTypes, "lease_state", "qiming lease state field"],
|
|
[qimingTypes, "dispatch_status", "qiming dispatch status field"],
|
|
[qimingTypes, "dispatch_policy_key", "qiming dispatch policy field"],
|
|
[qimingOps, "步骤调度", "qiming plan step dispatch tab"],
|
|
[qimingOps, "重试策略检查", "qiming plan step retry policy action"],
|
|
[qimingOps, "不远程派发", "qiming remote dispatch guard copy"],
|
|
[qimingOps, "不抢占租约", "qiming lease takeover guard copy"],
|
|
[qimingOps, "不释放租约", "qiming lease release guard copy"],
|
|
[docs, "正式管理端步骤调度预览", "docs plan step dispatch absorption"],
|
|
];
|
|
const missing = requiredSnippets
|
|
.filter(([content, snippet]) => !content.includes(snippet))
|
|
.map(([, , label]) => label);
|
|
if (missing.length > 0) {
|
|
throw new Error(`Missing admin plan step dispatch hooks: ${missing.join(", ")}`);
|
|
}
|
|
console.log("[DigitalEmployeeCheck] admin plan step dispatch hooks OK");
|
|
}
|
|
|
|
function checkDigitalAdminCollaborationOperationsClosure() {
|
|
console.log("\n[DigitalEmployeeCheck] Verify admin artifact, notification and daily report collaboration closure hooks");
|
|
const backendRoot = path.resolve(packageRoot, "..", "..", "..", "qiming-backend");
|
|
const qimingRoot = path.resolve(packageRoot, "..", "..", "..", "qiming");
|
|
const servicePath = path.join(
|
|
backendRoot,
|
|
"app-platform-modules",
|
|
"app-platform-agent",
|
|
"app-platform-agent-core-application",
|
|
"src",
|
|
"main",
|
|
"java",
|
|
"com",
|
|
"xspaceagi",
|
|
"agent",
|
|
"core",
|
|
"application",
|
|
"service",
|
|
"DigitalEmployeeSyncApplicationServiceImpl.java",
|
|
);
|
|
const dtoPath = path.join(
|
|
backendRoot,
|
|
"app-platform-modules",
|
|
"app-platform-agent",
|
|
"app-platform-agent-core-adapter",
|
|
"src",
|
|
"main",
|
|
"java",
|
|
"com",
|
|
"xspaceagi",
|
|
"agent",
|
|
"core",
|
|
"adapter",
|
|
"dto",
|
|
"digital",
|
|
"DigitalEmployeeAdminWorkbenchRowDto.java",
|
|
);
|
|
const testPath = path.join(
|
|
backendRoot,
|
|
"app-platform-modules",
|
|
"app-platform-agent",
|
|
"app-platform-agent-core-application",
|
|
"src",
|
|
"test",
|
|
"java",
|
|
"com",
|
|
"xspaceagi",
|
|
"agent",
|
|
"core",
|
|
"application",
|
|
"service",
|
|
"DigitalEmployeeSyncApplicationServiceImplTest.java",
|
|
);
|
|
const qimingOpsPath = path.join(qimingRoot, "src", "pages", "SystemManagement", "Content", "DigitalEmployeeOps", "index.tsx");
|
|
const qimingTypesPath = path.join(qimingRoot, "src", "types", "interfaces", "systemManage.ts");
|
|
const docsPath = path.resolve(packageRoot, "..", "..", "docs", "digital-employee-frontend-integration-plan.md");
|
|
const service = fs.readFileSync(servicePath, "utf8");
|
|
const dto = fs.readFileSync(dtoPath, "utf8");
|
|
const test = fs.readFileSync(testPath, "utf8");
|
|
const qimingOps = fs.readFileSync(qimingOpsPath, "utf8");
|
|
const qimingTypes = fs.readFileSync(qimingTypesPath, "utf8");
|
|
const docs = fs.readFileSync(docsPath, "utf8");
|
|
const requiredSnippets = [
|
|
[service, "record_cleanup_request", "backend cleanup request admin action"],
|
|
[service, "record_send_request", "backend send request admin action"],
|
|
[service, "record_send_result", "backend send result admin action"],
|
|
[service, "remote_delete_disabled", "backend remote delete disabled reason"],
|
|
[service, "real_push_disabled", "backend real push disabled reason"],
|
|
[service, "external_send_disabled", "backend external send disabled reason"],
|
|
[service, "third_party_channel_disabled", "backend third party send disabled reason"],
|
|
[service, "artifact_graph_id", "backend artifact graph projection"],
|
|
[service, "cleanup_request_id", "backend cleanup request projection"],
|
|
[service, "batch_cleanup_disabled", "backend batch cleanup disabled projection"],
|
|
[service, "retention_conflict_status", "backend retention conflict projection"],
|
|
[service, "cleanup_conflict_status", "backend cleanup conflict projection"],
|
|
[service, "collaboration_thread_id", "backend collaboration thread projection"],
|
|
[service, "subscription_policy_id", "backend subscription policy projection"],
|
|
[service, "delivery_attempt_id", "backend delivery attempt projection"],
|
|
[service, "send_request_id", "backend send request projection"],
|
|
[service, "daily_report_fact_id", "backend daily report fact projection"],
|
|
[service, "daily_report_physical_fact_status", "backend daily report physical fact projection"],
|
|
[service, "advanced_query_supported", "backend advanced query projection"],
|
|
[dto, "cleanup_request_id", "backend cleanup request row field"],
|
|
[dto, "artifact_graph_id", "backend artifact graph row field"],
|
|
[dto, "related_artifact_ids", "backend related artifact ids row field"],
|
|
[dto, "cleanup_eligible_count", "backend cleanup eligible count row field"],
|
|
[dto, "batch_cleanup_disabled", "backend batch cleanup disabled row field"],
|
|
[dto, "retention_conflict_status", "backend retention conflict row field"],
|
|
[dto, "cleanup_conflict_status", "backend cleanup conflict row field"],
|
|
[dto, "remote_delete_disabled", "backend remote delete row field"],
|
|
[dto, "collaboration_thread_id", "backend collaboration thread row field"],
|
|
[dto, "subscription_policy_id", "backend subscription policy row field"],
|
|
[dto, "subscription_conflict_status", "backend subscription conflict row field"],
|
|
[dto, "delivery_attempt_id", "backend delivery attempt row field"],
|
|
[dto, "send_request_id", "backend send request row field"],
|
|
[dto, "real_push_disabled", "backend real push disabled row field"],
|
|
[dto, "daily_report_fact_id", "backend daily report fact row field"],
|
|
[dto, "daily_report_physical_fact_status", "backend daily report physical fact row field"],
|
|
[dto, "external_send_disabled", "backend external send disabled row field"],
|
|
[dto, "third_party_channel_disabled", "backend third party disabled row field"],
|
|
[dto, "advanced_query_supported", "backend advanced query row field"],
|
|
[test, "getCleanupRequestId", "backend cleanup request test assertion"],
|
|
[test, "queryAdminWorkbenchArtifactLifecycleReturnsGraphAndConflictRows", "backend artifact graph test"],
|
|
[test, "queryAdminWorkbenchNotificationsReturnsCollaborationAndDeliveryRows", "backend notification collaboration test"],
|
|
[test, "queryAdminWorkbenchDailyReportsReturnsPhysicalFactAndSendShellRows", "backend daily report send shell test"],
|
|
[test, "queryBusinessViewsExposeAdvancedQueryAndMaterializedSource", "backend business query shell test"],
|
|
[test, "createAdminActionAllowsLowRiskAssetNotificationReportIntents", "backend low risk asset notification report actions test"],
|
|
[test, "createAdminActionRejectsHighRiskAssetNotificationReportExecution", "backend high risk asset notification report rejection test"],
|
|
[test, "getSubscriptionPolicyId", "backend subscription policy test assertion"],
|
|
[test, "getDailyReportFactId", "backend daily report fact test assertion"],
|
|
[qimingTypes, "cleanup_request_id", "qiming cleanup request type field"],
|
|
[qimingTypes, "artifact_graph_id", "qiming artifact graph type field"],
|
|
[qimingTypes, "related_artifact_ids", "qiming related artifacts type field"],
|
|
[qimingTypes, "retention_conflict_status", "qiming retention conflict type field"],
|
|
[qimingTypes, "cleanup_conflict_status", "qiming cleanup conflict type field"],
|
|
[qimingTypes, "remote_delete_disabled", "qiming remote delete guard type field"],
|
|
[qimingTypes, "collaboration_thread_id", "qiming collaboration thread type field"],
|
|
[qimingTypes, "subscription_policy_id", "qiming subscription policy type field"],
|
|
[qimingTypes, "subscription_conflict_status", "qiming subscription conflict type field"],
|
|
[qimingTypes, "delivery_attempt_id", "qiming delivery attempt type field"],
|
|
[qimingTypes, "send_request_id", "qiming send request type field"],
|
|
[qimingTypes, "real_push_disabled", "qiming real push guard type field"],
|
|
[qimingTypes, "daily_report_fact_id", "qiming daily report fact type field"],
|
|
[qimingTypes, "daily_report_physical_fact_status", "qiming daily physical fact type field"],
|
|
[qimingTypes, "external_send_disabled", "qiming external send guard type field"],
|
|
[qimingTypes, "third_party_channel_disabled", "qiming third party send guard type field"],
|
|
[qimingTypes, "advanced_query_supported", "qiming advanced query type field"],
|
|
[qimingOps, "记录批量清理申请", "qiming cleanup request action"],
|
|
[qimingOps, "跨设备/跨版本图谱摘要", "qiming artifact graph copy"],
|
|
[qimingOps, "保留冲突", "qiming retention conflict copy"],
|
|
[qimingOps, "清理冲突", "qiming cleanup conflict copy"],
|
|
[qimingOps, "远端删除禁用", "qiming remote delete guard copy"],
|
|
[qimingOps, "协作线程", "qiming collaboration thread copy"],
|
|
[qimingOps, "订阅策略", "qiming subscription policy copy"],
|
|
[qimingOps, "投递尝试", "qiming delivery attempt copy"],
|
|
[qimingOps, "发送请求", "qiming send request copy"],
|
|
[qimingOps, "真实推送禁用", "qiming real push guard copy"],
|
|
[qimingOps, "审批状态", "qiming daily approval status copy"],
|
|
[qimingOps, "物理事实状态", "qiming daily physical fact copy"],
|
|
[qimingOps, "外部发送禁用", "qiming external send guard copy"],
|
|
[qimingOps, "第三方发送", "qiming third party send guard copy"],
|
|
[qimingOps, "高级查询", "qiming advanced query copy"],
|
|
[qimingOps, "物化来源", "qiming materialized source copy"],
|
|
[docs, "正式管理端协作运营收口", "docs collaboration closure absorption"],
|
|
[docs, "资产通知日报业务查询总收口已开始吸收", "docs asset notification report closure absorption"],
|
|
];
|
|
const missing = requiredSnippets
|
|
.filter(([content, snippet]) => !content.includes(snippet))
|
|
.map(([, , label]) => label);
|
|
if (missing.length > 0) {
|
|
throw new Error(`Missing admin collaboration operations closure hooks: ${missing.join(", ")}`);
|
|
}
|
|
console.log("[DigitalEmployeeCheck] admin collaboration operations closure hooks OK");
|
|
}
|
|
|
|
function checkDigitalAdminServiceOperationsWorkbench() {
|
|
console.log("\n[DigitalEmployeeCheck] Verify admin service operations workbench hooks");
|
|
const backendRoot = path.resolve(packageRoot, "..", "..", "..", "qiming-backend");
|
|
const qimingRoot = path.resolve(packageRoot, "..", "..", "..", "qiming");
|
|
const servicePath = path.join(
|
|
backendRoot,
|
|
"app-platform-modules",
|
|
"app-platform-agent",
|
|
"app-platform-agent-core-application",
|
|
"src",
|
|
"main",
|
|
"java",
|
|
"com",
|
|
"xspaceagi",
|
|
"agent",
|
|
"core",
|
|
"application",
|
|
"service",
|
|
"DigitalEmployeeSyncApplicationServiceImpl.java",
|
|
);
|
|
const dtoPath = path.join(
|
|
backendRoot,
|
|
"app-platform-modules",
|
|
"app-platform-agent",
|
|
"app-platform-agent-core-adapter",
|
|
"src",
|
|
"main",
|
|
"java",
|
|
"com",
|
|
"xspaceagi",
|
|
"agent",
|
|
"core",
|
|
"adapter",
|
|
"dto",
|
|
"digital",
|
|
"DigitalEmployeeAdminWorkbenchRowDto.java",
|
|
);
|
|
const testPath = path.join(
|
|
backendRoot,
|
|
"app-platform-modules",
|
|
"app-platform-agent",
|
|
"app-platform-agent-core-application",
|
|
"src",
|
|
"test",
|
|
"java",
|
|
"com",
|
|
"xspaceagi",
|
|
"agent",
|
|
"core",
|
|
"application",
|
|
"service",
|
|
"DigitalEmployeeSyncApplicationServiceImplTest.java",
|
|
);
|
|
const qimingOpsPath = path.join(qimingRoot, "src", "pages", "SystemManagement", "Content", "DigitalEmployeeOps", "index.tsx");
|
|
const qimingTypesPath = path.join(qimingRoot, "src", "types", "interfaces", "systemManage.ts");
|
|
const docsPath = path.resolve(packageRoot, "..", "..", "docs", "digital-employee-frontend-integration-plan.md");
|
|
const service = fs.readFileSync(servicePath, "utf8");
|
|
const dto = fs.readFileSync(dtoPath, "utf8");
|
|
const test = fs.readFileSync(testPath, "utf8");
|
|
const qimingOps = fs.readFileSync(qimingOpsPath, "utf8");
|
|
const qimingTypes = fs.readFileSync(qimingTypesPath, "utf8");
|
|
const docs = fs.readFileSync(docsPath, "utf8");
|
|
const requiredSnippets = [
|
|
[service, "service_operations", "backend service operations view"],
|
|
[service, "isServiceOperationsRow", "backend service operations matcher"],
|
|
[service, "managed_service", "backend managed service classifier"],
|
|
[service, "managed_service_snapshot", "backend managed service snapshot classifier"],
|
|
[service, "service_lease", "backend service lease classifier"],
|
|
[service, "service_restart", "backend service restart classifier"],
|
|
[service, "service_recovery", "backend service recovery classifier"],
|
|
[dto, "service_id", "backend service id row field"],
|
|
[dto, "service_lease_id", "backend service lease row field"],
|
|
[dto, "restart_record_id", "backend service restart record row field"],
|
|
[dto, "recovery_policy_id", "backend service recovery policy row field"],
|
|
[dto, "auto_recovery_status", "backend auto recovery status row field"],
|
|
[dto, "service_start_disabled", "backend service start disabled row field"],
|
|
[dto, "service_stop_disabled", "backend service stop disabled row field"],
|
|
[dto, "lease_takeover_disabled", "backend lease takeover disabled row field"],
|
|
[dto, "auto_recovery_disabled", "backend auto recovery disabled row field"],
|
|
[dto, "recovery_action_request_id", "backend recovery action request row field"],
|
|
[test, "queryAdminWorkbenchServiceOperationsReturnsServiceHealthAndRestartRowsOnly", "backend service operations test"],
|
|
[test, "queryAdminWorkbenchServiceOperationsReturnsLeaseRestartAndRecoveryRowsOnly", "backend service recovery operations test"],
|
|
[test, "queryAdminWorkbenchServiceOperationsReturnsSafetyShellFields", "backend service recovery safety shell test"],
|
|
[qimingTypes, "service_operations", "qiming service operations view type"],
|
|
[qimingTypes, "service_id", "qiming service id field"],
|
|
[qimingTypes, "service_lease_id", "qiming service lease id field"],
|
|
[qimingTypes, "restart_record_id", "qiming restart record id field"],
|
|
[qimingTypes, "recovery_policy_id", "qiming recovery policy id field"],
|
|
[qimingTypes, "auto_recovery_status", "qiming auto recovery status field"],
|
|
[qimingTypes, "service_start_disabled", "qiming service start disabled field"],
|
|
[qimingTypes, "service_stop_disabled", "qiming service stop disabled field"],
|
|
[qimingTypes, "lease_takeover_disabled", "qiming lease takeover disabled field"],
|
|
[qimingTypes, "auto_recovery_disabled", "qiming auto recovery disabled field"],
|
|
[qimingTypes, "recovery_action_request_id", "qiming recovery action request field"],
|
|
[qimingOps, "服务运营", "qiming service operations tab"],
|
|
[qimingOps, "只记录复核/忽略意图", "qiming service operations safety copy"],
|
|
[qimingOps, "不开放 start/stop", "qiming service start stop guard copy"],
|
|
[qimingOps, "不接管 lease", "qiming service lease takeover guard copy"],
|
|
[qimingOps, "不自动恢复服务", "qiming service auto recovery guard copy"],
|
|
[qimingOps, "恢复请求", "qiming service recovery request copy"],
|
|
[docs, "正式管理端服务恢复运营预览", "docs service recovery absorption"],
|
|
[docs, "恢复请求状态", "docs service recovery request absorption"],
|
|
];
|
|
const missing = requiredSnippets
|
|
.filter(([content, snippet]) => !content.includes(snippet))
|
|
.map(([, , label]) => label);
|
|
if (missing.length > 0) {
|
|
throw new Error(`Missing admin service operations workbench hooks: ${missing.join(", ")}`);
|
|
}
|
|
console.log("[DigitalEmployeeCheck] admin service operations workbench hooks OK");
|
|
}
|
|
|
|
function checkDigitalAdminRouteGovernanceWorkbench() {
|
|
console.log("\n[DigitalEmployeeCheck] Verify admin route governance workbench hooks");
|
|
const backendRoot = path.resolve(packageRoot, "..", "..", "..", "qiming-backend");
|
|
const qimingRoot = path.resolve(packageRoot, "..", "..", "..", "qiming");
|
|
const servicePath = path.join(
|
|
backendRoot,
|
|
"app-platform-modules",
|
|
"app-platform-agent",
|
|
"app-platform-agent-core-application",
|
|
"src",
|
|
"main",
|
|
"java",
|
|
"com",
|
|
"xspaceagi",
|
|
"agent",
|
|
"core",
|
|
"application",
|
|
"service",
|
|
"DigitalEmployeeSyncApplicationServiceImpl.java",
|
|
);
|
|
const testPath = path.join(
|
|
backendRoot,
|
|
"app-platform-modules",
|
|
"app-platform-agent",
|
|
"app-platform-agent-core-application",
|
|
"src",
|
|
"test",
|
|
"java",
|
|
"com",
|
|
"xspaceagi",
|
|
"agent",
|
|
"core",
|
|
"application",
|
|
"service",
|
|
"DigitalEmployeeSyncApplicationServiceImplTest.java",
|
|
);
|
|
const qimingOpsPath = path.join(qimingRoot, "src", "pages", "SystemManagement", "Content", "DigitalEmployeeOps", "index.tsx");
|
|
const qimingTypesPath = path.join(qimingRoot, "src", "types", "interfaces", "systemManage.ts");
|
|
const docsPath = path.resolve(packageRoot, "..", "..", "docs", "digital-employee-frontend-integration-plan.md");
|
|
const service = fs.readFileSync(servicePath, "utf8");
|
|
const test = fs.readFileSync(testPath, "utf8");
|
|
const qimingOps = fs.readFileSync(qimingOpsPath, "utf8");
|
|
const qimingTypes = fs.readFileSync(qimingTypesPath, "utf8");
|
|
const docs = fs.readFileSync(docsPath, "utf8");
|
|
const requiredSnippets = [
|
|
[service, "route_governance", "backend route governance view"],
|
|
[service, "isRouteGovernanceRow", "backend route governance matcher"],
|
|
[service, "route_decision_blocked", "backend route blocked classifier"],
|
|
[service, "route_action_policy_blocked", "backend route action policy blocked classifier"],
|
|
[service, "route_action_missing_context", "backend route action missing context classifier"],
|
|
[service, "governance_", "backend governance event classifier"],
|
|
[test, "queryAdminWorkbenchRouteGovernanceReturnsRouteAndGovernanceRowsOnly", "backend route governance test"],
|
|
[qimingTypes, "route_governance", "qiming route governance view type"],
|
|
[qimingOps, "路由治理", "qiming route governance tab"],
|
|
[qimingOps, "重试策略检查", "qiming route policy retry action"],
|
|
[qimingOps, "标记已看", "qiming route mark reviewed action"],
|
|
[qimingOps, "忽略", "qiming route dismiss action"],
|
|
[docs, "正式管理端路由治理预览", "docs route governance absorption"],
|
|
];
|
|
const missing = requiredSnippets
|
|
.filter(([content, snippet]) => !content.includes(snippet))
|
|
.map(([, , label]) => label);
|
|
if (missing.length > 0) {
|
|
throw new Error(`Missing admin route governance workbench hooks: ${missing.join(", ")}`);
|
|
}
|
|
console.log("[DigitalEmployeeCheck] admin route governance workbench hooks OK");
|
|
}
|
|
|
|
function checkDigitalAdminNotificationWorkbench() {
|
|
console.log("\n[DigitalEmployeeCheck] Verify admin notification workbench hooks");
|
|
const backendRoot = path.resolve(packageRoot, "..", "..", "..", "qiming-backend");
|
|
const qimingRoot = path.resolve(packageRoot, "..", "..", "..", "qiming");
|
|
const servicePath = path.join(
|
|
backendRoot,
|
|
"app-platform-modules",
|
|
"app-platform-agent",
|
|
"app-platform-agent-core-application",
|
|
"src",
|
|
"main",
|
|
"java",
|
|
"com",
|
|
"xspaceagi",
|
|
"agent",
|
|
"core",
|
|
"application",
|
|
"service",
|
|
"DigitalEmployeeSyncApplicationServiceImpl.java",
|
|
);
|
|
const dtoPath = path.join(
|
|
backendRoot,
|
|
"app-platform-modules",
|
|
"app-platform-agent",
|
|
"app-platform-agent-core-adapter",
|
|
"src",
|
|
"main",
|
|
"java",
|
|
"com",
|
|
"xspaceagi",
|
|
"agent",
|
|
"core",
|
|
"adapter",
|
|
"dto",
|
|
"digital",
|
|
"DigitalEmployeeAdminWorkbenchRowDto.java",
|
|
);
|
|
const testPath = path.join(
|
|
backendRoot,
|
|
"app-platform-modules",
|
|
"app-platform-agent",
|
|
"app-platform-agent-core-application",
|
|
"src",
|
|
"test",
|
|
"java",
|
|
"com",
|
|
"xspaceagi",
|
|
"agent",
|
|
"core",
|
|
"application",
|
|
"service",
|
|
"DigitalEmployeeSyncApplicationServiceImplTest.java",
|
|
);
|
|
const qimingOpsPath = path.join(qimingRoot, "src", "pages", "SystemManagement", "Content", "DigitalEmployeeOps", "index.tsx");
|
|
const qimingTypesPath = path.join(qimingRoot, "src", "types", "interfaces", "systemManage.ts");
|
|
const docsPath = path.resolve(packageRoot, "..", "..", "docs", "digital-employee-frontend-integration-plan.md");
|
|
const service = fs.readFileSync(servicePath, "utf8");
|
|
const dto = fs.readFileSync(dtoPath, "utf8");
|
|
const test = fs.readFileSync(testPath, "utf8");
|
|
const qimingOps = fs.readFileSync(qimingOpsPath, "utf8");
|
|
const qimingTypes = fs.readFileSync(qimingTypesPath, "utf8");
|
|
const docs = fs.readFileSync(docsPath, "utf8");
|
|
const requiredSnippets = [
|
|
[service, "notifications", "backend notification view"],
|
|
[service, "isNotificationRow", "backend notification matcher"],
|
|
[dto, "notification_id", "backend notification id row field"],
|
|
[service, "action_notification", "backend action notification classifier"],
|
|
[service, "notification", "backend notification kind classifier"],
|
|
[test, "queryAdminWorkbenchNotificationsReturnsNotificationRowsOnly", "backend notification workbench test"],
|
|
[qimingTypes, "notifications", "qiming notification view type"],
|
|
[qimingOps, "通知运营", "qiming notification workbench tab"],
|
|
[qimingOps, "标记已读", "qiming notification read action"],
|
|
[qimingOps, "忽略", "qiming notification dismiss action"],
|
|
[docs, "正式管理端通知运营预览", "docs notification workbench absorption"],
|
|
];
|
|
const missing = requiredSnippets
|
|
.filter(([content, snippet]) => !content.includes(snippet))
|
|
.map(([, , label]) => label);
|
|
if (missing.length > 0) {
|
|
throw new Error(`Missing admin notification workbench hooks: ${missing.join(", ")}`);
|
|
}
|
|
console.log("[DigitalEmployeeCheck] admin notification workbench hooks OK");
|
|
}
|
|
|
|
function checkDigitalAdminNotificationPoliciesWorkbench() {
|
|
console.log("\n[DigitalEmployeeCheck] Verify admin notification policies workbench hooks");
|
|
const backendRoot = path.resolve(packageRoot, "..", "..", "..", "qiming-backend");
|
|
const qimingRoot = path.resolve(packageRoot, "..", "..", "..", "qiming");
|
|
const servicePath = path.join(
|
|
backendRoot,
|
|
"app-platform-modules",
|
|
"app-platform-agent",
|
|
"app-platform-agent-core-application",
|
|
"src",
|
|
"main",
|
|
"java",
|
|
"com",
|
|
"xspaceagi",
|
|
"agent",
|
|
"core",
|
|
"application",
|
|
"service",
|
|
"DigitalEmployeeSyncApplicationServiceImpl.java",
|
|
);
|
|
const dtoPath = path.join(
|
|
backendRoot,
|
|
"app-platform-modules",
|
|
"app-platform-agent",
|
|
"app-platform-agent-core-adapter",
|
|
"src",
|
|
"main",
|
|
"java",
|
|
"com",
|
|
"xspaceagi",
|
|
"agent",
|
|
"core",
|
|
"adapter",
|
|
"dto",
|
|
"digital",
|
|
"DigitalEmployeeAdminWorkbenchRowDto.java",
|
|
);
|
|
const testPath = path.join(
|
|
backendRoot,
|
|
"app-platform-modules",
|
|
"app-platform-agent",
|
|
"app-platform-agent-core-application",
|
|
"src",
|
|
"test",
|
|
"java",
|
|
"com",
|
|
"xspaceagi",
|
|
"agent",
|
|
"core",
|
|
"application",
|
|
"service",
|
|
"DigitalEmployeeSyncApplicationServiceImplTest.java",
|
|
);
|
|
const qimingOpsPath = path.join(qimingRoot, "src", "pages", "SystemManagement", "Content", "DigitalEmployeeOps", "index.tsx");
|
|
const qimingTypesPath = path.join(qimingRoot, "src", "types", "interfaces", "systemManage.ts");
|
|
const docsPath = path.resolve(packageRoot, "..", "..", "docs", "digital-employee-frontend-integration-plan.md");
|
|
const service = fs.readFileSync(servicePath, "utf8");
|
|
const dto = fs.readFileSync(dtoPath, "utf8");
|
|
const test = fs.readFileSync(testPath, "utf8");
|
|
const qimingOps = fs.readFileSync(qimingOpsPath, "utf8");
|
|
const qimingTypes = fs.readFileSync(qimingTypesPath, "utf8");
|
|
const docs = fs.readFileSync(docsPath, "utf8");
|
|
const requiredSnippets = [
|
|
[service, "notification_policies", "backend notification policies view"],
|
|
[service, "isNotificationPolicyRow", "backend notification policies matcher"],
|
|
[dto, "notification_policy_id", "backend notification policy id row field"],
|
|
[dto, "subscription_status", "backend subscription status row field"],
|
|
[dto, "desktop_enabled", "backend desktop enabled row field"],
|
|
[dto, "minimum_level", "backend minimum level row field"],
|
|
[test, "queryAdminWorkbenchNotificationPoliciesReturnsSubscriptionPolicyRowsOnly", "backend notification policies test"],
|
|
[qimingTypes, "notification_policies", "qiming notification policies view type"],
|
|
[qimingOps, "通知策略", "qiming notification policies tab"],
|
|
[qimingOps, "拉取通知策略", "qiming notification policy pull action"],
|
|
[qimingOps, "不远程编辑策略", "qiming notification policy safety copy"],
|
|
[qimingOps, "不触发真实推送", "qiming notification push safety copy"],
|
|
[docs, "正式管理端通知订阅策略预览", "docs notification policies absorption"],
|
|
];
|
|
const missing = requiredSnippets
|
|
.filter(([content, snippet]) => !content.includes(snippet))
|
|
.map(([, , label]) => label);
|
|
if (missing.length > 0) {
|
|
throw new Error(`Missing admin notification policies workbench hooks: ${missing.join(", ")}`);
|
|
}
|
|
console.log("[DigitalEmployeeCheck] admin notification policies workbench hooks OK");
|
|
}
|
|
|
|
function checkDigitalAdminArtifactLifecycleWorkbench() {
|
|
console.log("\n[DigitalEmployeeCheck] Verify admin artifact lifecycle workbench hooks");
|
|
const backendRoot = path.resolve(packageRoot, "..", "..", "..", "qiming-backend");
|
|
const qimingRoot = path.resolve(packageRoot, "..", "..", "..", "qiming");
|
|
const servicePath = path.join(
|
|
backendRoot,
|
|
"app-platform-modules",
|
|
"app-platform-agent",
|
|
"app-platform-agent-core-application",
|
|
"src",
|
|
"main",
|
|
"java",
|
|
"com",
|
|
"xspaceagi",
|
|
"agent",
|
|
"core",
|
|
"application",
|
|
"service",
|
|
"DigitalEmployeeSyncApplicationServiceImpl.java",
|
|
);
|
|
const dtoPath = path.join(
|
|
backendRoot,
|
|
"app-platform-modules",
|
|
"app-platform-agent",
|
|
"app-platform-agent-core-adapter",
|
|
"src",
|
|
"main",
|
|
"java",
|
|
"com",
|
|
"xspaceagi",
|
|
"agent",
|
|
"core",
|
|
"adapter",
|
|
"dto",
|
|
"digital",
|
|
"DigitalEmployeeAdminWorkbenchRowDto.java",
|
|
);
|
|
const testPath = path.join(
|
|
backendRoot,
|
|
"app-platform-modules",
|
|
"app-platform-agent",
|
|
"app-platform-agent-core-application",
|
|
"src",
|
|
"test",
|
|
"java",
|
|
"com",
|
|
"xspaceagi",
|
|
"agent",
|
|
"core",
|
|
"application",
|
|
"service",
|
|
"DigitalEmployeeSyncApplicationServiceImplTest.java",
|
|
);
|
|
const qimingOpsPath = path.join(qimingRoot, "src", "pages", "SystemManagement", "Content", "DigitalEmployeeOps", "index.tsx");
|
|
const qimingTypesPath = path.join(qimingRoot, "src", "types", "interfaces", "systemManage.ts");
|
|
const docsPath = path.resolve(packageRoot, "..", "..", "docs", "digital-employee-frontend-integration-plan.md");
|
|
const service = fs.readFileSync(servicePath, "utf8");
|
|
const dto = fs.readFileSync(dtoPath, "utf8");
|
|
const test = fs.readFileSync(testPath, "utf8");
|
|
const qimingOps = fs.readFileSync(qimingOpsPath, "utf8");
|
|
const qimingTypes = fs.readFileSync(qimingTypesPath, "utf8");
|
|
const docs = fs.readFileSync(docsPath, "utf8");
|
|
const requiredSnippets = [
|
|
[service, "artifact_lifecycle", "backend artifact lifecycle view"],
|
|
[service, "isArtifactLifecycleRow", "backend artifact lifecycle matcher"],
|
|
[service, "artifact_", "backend artifact event classifier"],
|
|
[dto, "artifact_id", "backend artifact id row field"],
|
|
[dto, "artifact_group_id", "backend artifact group id row field"],
|
|
[dto, "artifact_count", "backend artifact count row field"],
|
|
[dto, "version_count", "backend artifact version count row field"],
|
|
[dto, "latest_artifact_id", "backend latest artifact id row field"],
|
|
[test, "queryAdminWorkbenchArtifactLifecycleReturnsArtifactRowsOnly", "backend artifact lifecycle test"],
|
|
[test, "getArtifactGroupId", "backend artifact group assertion"],
|
|
[qimingTypes, "artifact_lifecycle", "qiming artifact lifecycle view type"],
|
|
[qimingTypes, "artifact_group_id", "qiming artifact group id field"],
|
|
[qimingTypes, "version_count", "qiming artifact version count field"],
|
|
[qimingOps, "产物治理", "qiming artifact lifecycle tab"],
|
|
[qimingOps, "跨设备/跨版本聚合", "qiming artifact aggregate copy"],
|
|
[qimingOps, "标记保留", "qiming artifact keep action"],
|
|
[qimingOps, "标记到期", "qiming artifact expire action"],
|
|
[qimingOps, "标记复核", "qiming artifact reviewed action"],
|
|
[docs, "正式管理端产物生命周期预览", "docs artifact lifecycle absorption"],
|
|
[docs, "正式管理端产物跨设备聚合预览", "docs artifact aggregate absorption"],
|
|
];
|
|
const missing = requiredSnippets
|
|
.filter(([content, snippet]) => !content.includes(snippet))
|
|
.map(([, , label]) => label);
|
|
if (missing.length > 0) {
|
|
throw new Error(`Missing admin artifact lifecycle workbench hooks: ${missing.join(", ")}`);
|
|
}
|
|
console.log("[DigitalEmployeeCheck] admin artifact lifecycle workbench hooks OK");
|
|
}
|
|
|
|
function checkDigitalAdminAuditDiagnosticsWorkbench() {
|
|
console.log("\n[DigitalEmployeeCheck] Verify admin audit diagnostics workbench hooks");
|
|
const backendRoot = path.resolve(packageRoot, "..", "..", "..", "qiming-backend");
|
|
const qimingRoot = path.resolve(packageRoot, "..", "..", "..", "qiming");
|
|
const servicePath = path.join(
|
|
backendRoot,
|
|
"app-platform-modules",
|
|
"app-platform-agent",
|
|
"app-platform-agent-core-application",
|
|
"src",
|
|
"main",
|
|
"java",
|
|
"com",
|
|
"xspaceagi",
|
|
"agent",
|
|
"core",
|
|
"application",
|
|
"service",
|
|
"DigitalEmployeeSyncApplicationServiceImpl.java",
|
|
);
|
|
const testPath = path.join(
|
|
backendRoot,
|
|
"app-platform-modules",
|
|
"app-platform-agent",
|
|
"app-platform-agent-core-application",
|
|
"src",
|
|
"test",
|
|
"java",
|
|
"com",
|
|
"xspaceagi",
|
|
"agent",
|
|
"core",
|
|
"application",
|
|
"service",
|
|
"DigitalEmployeeSyncApplicationServiceImplTest.java",
|
|
);
|
|
const dtoPath = path.join(
|
|
backendRoot,
|
|
"app-platform-modules",
|
|
"app-platform-agent",
|
|
"app-platform-agent-core-adapter",
|
|
"src",
|
|
"main",
|
|
"java",
|
|
"com",
|
|
"xspaceagi",
|
|
"agent",
|
|
"core",
|
|
"adapter",
|
|
"dto",
|
|
"digital",
|
|
"DigitalEmployeeAdminWorkbenchRowDto.java",
|
|
);
|
|
const qimingOpsPath = path.join(qimingRoot, "src", "pages", "SystemManagement", "Content", "DigitalEmployeeOps", "index.tsx");
|
|
const qimingTypesPath = path.join(qimingRoot, "src", "types", "interfaces", "systemManage.ts");
|
|
const docsPath = path.resolve(packageRoot, "..", "..", "docs", "digital-employee-frontend-integration-plan.md");
|
|
const service = fs.readFileSync(servicePath, "utf8");
|
|
const dto = fs.readFileSync(dtoPath, "utf8");
|
|
const test = fs.readFileSync(testPath, "utf8");
|
|
const qimingOps = fs.readFileSync(qimingOpsPath, "utf8");
|
|
const qimingTypes = fs.readFileSync(qimingTypesPath, "utf8");
|
|
const docs = fs.readFileSync(docsPath, "utf8");
|
|
const requiredSnippets = [
|
|
[service, "audits", "backend audits view"],
|
|
[service, "isAuditRow", "backend audit matcher"],
|
|
[service, "sandbox_audit", "backend sandbox audit category"],
|
|
[service, "token_cost", "backend token cost category"],
|
|
[service, "tool_call_audit", "backend tool call audit category"],
|
|
[service, "sync_failure", "backend sync failure audit category"],
|
|
[service, "audit_archive", "backend audit archive category"],
|
|
[service, "billing_estimate", "backend billing estimate category"],
|
|
[dto, "audit_archive_id", "backend audit archive id row field"],
|
|
[dto, "archive_status", "backend archive status row field"],
|
|
[dto, "archive_location", "backend archive location row field"],
|
|
[dto, "billing_estimate_id", "backend billing estimate id row field"],
|
|
[dto, "billing_source", "backend billing source row field"],
|
|
[test, "queryAdminWorkbenchAuditsReturnsAuditRowsOnly", "backend audit diagnostics test"],
|
|
[test, "getAuditArchiveId", "backend audit archive assertion"],
|
|
[test, "getBillingEstimateId", "backend billing estimate assertion"],
|
|
[test, "doesNotContainKeys(\"token\", \"authorization\", \"raw_input\", \"command\", \"prompt\")", "backend audit redaction assertion"],
|
|
[qimingTypes, "audits", "qiming audits view type"],
|
|
[qimingTypes, "audit_archive_id", "qiming audit archive id field"],
|
|
[qimingTypes, "billing_source", "qiming billing source field"],
|
|
[qimingOps, "审计诊断", "qiming audit diagnostics tab"],
|
|
[qimingOps, "归档位置", "qiming audit archive location copy"],
|
|
[qimingOps, "估算来源", "qiming billing source copy"],
|
|
[qimingOps, "标记复核", "qiming audit reviewed action"],
|
|
[qimingOps, "忽略", "qiming audit dismiss action"],
|
|
[qimingOps, "标记归档", "qiming audit archive action"],
|
|
[docs, "正式管理端审计诊断预览", "docs audit diagnostics absorption"],
|
|
[docs, "正式管理端审计归档账单预览", "docs audit archive billing absorption"],
|
|
];
|
|
const missing = requiredSnippets
|
|
.filter(([content, snippet]) => !content.includes(snippet))
|
|
.map(([, , label]) => label);
|
|
if (missing.length > 0) {
|
|
throw new Error(`Missing admin audit diagnostics workbench hooks: ${missing.join(", ")}`);
|
|
}
|
|
console.log("[DigitalEmployeeCheck] admin audit diagnostics workbench hooks OK");
|
|
}
|
|
|
|
function checkDigitalAdminDiagnosticRepairPreview() {
|
|
console.log("\n[DigitalEmployeeCheck] Verify admin diagnostic repair preview hooks");
|
|
const backendRoot = path.resolve(packageRoot, "..", "..", "..", "qiming-backend");
|
|
const qimingRoot = path.resolve(packageRoot, "..", "..", "..", "qiming");
|
|
const servicePath = path.join(
|
|
backendRoot,
|
|
"app-platform-modules",
|
|
"app-platform-agent",
|
|
"app-platform-agent-core-application",
|
|
"src",
|
|
"main",
|
|
"java",
|
|
"com",
|
|
"xspaceagi",
|
|
"agent",
|
|
"core",
|
|
"application",
|
|
"service",
|
|
"DigitalEmployeeSyncApplicationServiceImpl.java",
|
|
);
|
|
const dtoPath = path.join(
|
|
backendRoot,
|
|
"app-platform-modules",
|
|
"app-platform-agent",
|
|
"app-platform-agent-core-adapter",
|
|
"src",
|
|
"main",
|
|
"java",
|
|
"com",
|
|
"xspaceagi",
|
|
"agent",
|
|
"core",
|
|
"adapter",
|
|
"dto",
|
|
"digital",
|
|
"DigitalEmployeeAdminWorkbenchRowDto.java",
|
|
);
|
|
const testPath = path.join(
|
|
backendRoot,
|
|
"app-platform-modules",
|
|
"app-platform-agent",
|
|
"app-platform-agent-core-application",
|
|
"src",
|
|
"test",
|
|
"java",
|
|
"com",
|
|
"xspaceagi",
|
|
"agent",
|
|
"core",
|
|
"application",
|
|
"service",
|
|
"DigitalEmployeeSyncApplicationServiceImplTest.java",
|
|
);
|
|
const qimingOpsPath = path.join(qimingRoot, "src", "pages", "SystemManagement", "Content", "DigitalEmployeeOps", "index.tsx");
|
|
const qimingTypesPath = path.join(qimingRoot, "src", "types", "interfaces", "systemManage.ts");
|
|
const docsPath = path.resolve(packageRoot, "..", "..", "docs", "digital-employee-frontend-integration-plan.md");
|
|
const service = fs.readFileSync(servicePath, "utf8");
|
|
const dto = fs.readFileSync(dtoPath, "utf8");
|
|
const test = fs.readFileSync(testPath, "utf8");
|
|
const qimingOps = fs.readFileSync(qimingOpsPath, "utf8");
|
|
const qimingTypes = fs.readFileSync(qimingTypesPath, "utf8");
|
|
const docs = fs.readFileSync(docsPath, "utf8");
|
|
const requiredSnippets = [
|
|
[service, "isDiagnosticRepairRow", "backend diagnostic repair matcher"],
|
|
[service, "diagnostic:retry_check", "backend diagnostic retry action"],
|
|
[service, "diagnostic:record_repair_intent", "backend diagnostic repair intent action"],
|
|
[service, "run_shell_repair_disabled", "backend shell repair disabled reason"],
|
|
[service, "modify_system_config_disabled", "backend system config disabled reason"],
|
|
[dto, "diagnostic_id", "backend diagnostic id field"],
|
|
[dto, "issue_code", "backend issue code field"],
|
|
[dto, "repair_action", "backend repair action field"],
|
|
[dto, "repair_status", "backend repair status field"],
|
|
[dto, "safe_repair_disabled", "backend safe repair disabled field"],
|
|
[test, "queryAdminWorkbenchAuditsReturnsDiagnosticRepairRowsOnly", "backend diagnostic repair workbench test"],
|
|
[test, "createAdminActionAllowsLowRiskDiagnosticRepairIntent", "backend diagnostic low risk action test"],
|
|
[test, "createAdminActionRejectsHighRiskDiagnosticRepair", "backend diagnostic high risk action test"],
|
|
[qimingTypes, "diagnostic_id", "qiming diagnostic id field"],
|
|
[qimingTypes, "repair_action", "qiming repair action field"],
|
|
[qimingTypes, "safe_repair_disabled", "qiming safe repair disabled field"],
|
|
[qimingOps, "记录修复意图", "qiming repair intent action"],
|
|
[qimingOps, "重试诊断", "qiming retry diagnostic action"],
|
|
[qimingOps, "不执行 shell", "qiming shell repair guard copy"],
|
|
[qimingOps, "不修改系统配置", "qiming system config guard copy"],
|
|
[docs, "正式管理端诊断修复预览", "docs diagnostic repair absorption"],
|
|
];
|
|
const missing = requiredSnippets
|
|
.filter(([content, snippet]) => !content.includes(snippet))
|
|
.map(([, , label]) => label);
|
|
if (missing.length > 0) {
|
|
throw new Error(`Missing admin diagnostic repair preview hooks: ${missing.join(", ")}`);
|
|
}
|
|
console.log("[DigitalEmployeeCheck] admin diagnostic repair preview hooks OK");
|
|
}
|
|
|
|
function checkDigitalAdminDailyReportWorkbench() {
|
|
console.log("\n[DigitalEmployeeCheck] Verify admin daily report workbench hooks");
|
|
const backendRoot = path.resolve(packageRoot, "..", "..", "..", "qiming-backend");
|
|
const qimingRoot = path.resolve(packageRoot, "..", "..", "..", "qiming");
|
|
const servicePath = path.join(
|
|
backendRoot,
|
|
"app-platform-modules",
|
|
"app-platform-agent",
|
|
"app-platform-agent-core-application",
|
|
"src",
|
|
"main",
|
|
"java",
|
|
"com",
|
|
"xspaceagi",
|
|
"agent",
|
|
"core",
|
|
"application",
|
|
"service",
|
|
"DigitalEmployeeSyncApplicationServiceImpl.java",
|
|
);
|
|
const dtoPath = path.join(
|
|
backendRoot,
|
|
"app-platform-modules",
|
|
"app-platform-agent",
|
|
"app-platform-agent-core-adapter",
|
|
"src",
|
|
"main",
|
|
"java",
|
|
"com",
|
|
"xspaceagi",
|
|
"agent",
|
|
"core",
|
|
"adapter",
|
|
"dto",
|
|
"digital",
|
|
"DigitalEmployeeAdminWorkbenchRowDto.java",
|
|
);
|
|
const testPath = path.join(
|
|
backendRoot,
|
|
"app-platform-modules",
|
|
"app-platform-agent",
|
|
"app-platform-agent-core-application",
|
|
"src",
|
|
"test",
|
|
"java",
|
|
"com",
|
|
"xspaceagi",
|
|
"agent",
|
|
"core",
|
|
"application",
|
|
"service",
|
|
"DigitalEmployeeSyncApplicationServiceImplTest.java",
|
|
);
|
|
const qimingOpsPath = path.join(qimingRoot, "src", "pages", "SystemManagement", "Content", "DigitalEmployeeOps", "index.tsx");
|
|
const qimingTypesPath = path.join(qimingRoot, "src", "types", "interfaces", "systemManage.ts");
|
|
const docsPath = path.resolve(packageRoot, "..", "..", "docs", "digital-employee-frontend-integration-plan.md");
|
|
const service = fs.readFileSync(servicePath, "utf8");
|
|
const dto = fs.readFileSync(dtoPath, "utf8");
|
|
const test = fs.readFileSync(testPath, "utf8");
|
|
const qimingOps = fs.readFileSync(qimingOpsPath, "utf8");
|
|
const qimingTypes = fs.readFileSync(qimingTypesPath, "utf8");
|
|
const docs = fs.readFileSync(docsPath, "utf8");
|
|
const requiredSnippets = [
|
|
[service, "daily_reports", "backend daily report view"],
|
|
[service, "isDailyReportRow", "backend daily report matcher"],
|
|
[service, "daily_report", "backend daily report category"],
|
|
[service, "daily_report:record_approval_decision", "backend daily report approval decision action"],
|
|
[dto, "report_id", "backend report id row field"],
|
|
[dto, "daily_report_approval_id", "backend daily report approval id row field"],
|
|
[dto, "daily_report_approval_action", "backend daily report approval action row field"],
|
|
[dto, "daily_report_approval_recorded_at", "backend daily report approval recorded at row field"],
|
|
[test, "queryAdminWorkbenchDailyReportsReturnsDailyReportRowsOnly", "backend daily report workbench test"],
|
|
[test, "getDailyReportApprovalId", "backend daily report approval assertion"],
|
|
[qimingTypes, "daily_reports", "qiming daily report view type"],
|
|
[qimingTypes, "daily_report_approval_id", "qiming daily report approval id type field"],
|
|
[qimingOps, "日报运营", "qiming daily report tab"],
|
|
[qimingOps, "记录已送达", "qiming daily report delivered action"],
|
|
[qimingOps, "确认回执", "qiming daily report confirmed action"],
|
|
[qimingOps, "请求审批", "qiming daily report approval action"],
|
|
[qimingOps, "记录审批裁决", "qiming daily report approval decision action"],
|
|
[qimingOps, "记录发送结果", "qiming daily report send record action"],
|
|
[docs, "正式管理端日报运营预览", "docs daily report absorption"],
|
|
[docs, "管理端日报审批裁决回写预览", "docs daily report approval decision absorption"],
|
|
];
|
|
const missing = requiredSnippets
|
|
.filter(([content, snippet]) => !content.includes(snippet))
|
|
.map(([, , label]) => label);
|
|
if (missing.length > 0) {
|
|
throw new Error(`Missing admin daily report workbench hooks: ${missing.join(", ")}`);
|
|
}
|
|
console.log("[DigitalEmployeeCheck] admin daily report workbench hooks OK");
|
|
}
|
|
|
|
function checkDigitalAdminGovernanceCommandWorkbench() {
|
|
console.log("\n[DigitalEmployeeCheck] Verify admin governance command workbench hooks");
|
|
const backendRoot = path.resolve(packageRoot, "..", "..", "..", "qiming-backend");
|
|
const qimingRoot = path.resolve(packageRoot, "..", "..", "..", "qiming");
|
|
const servicePath = path.join(
|
|
backendRoot,
|
|
"app-platform-modules",
|
|
"app-platform-agent",
|
|
"app-platform-agent-core-application",
|
|
"src",
|
|
"main",
|
|
"java",
|
|
"com",
|
|
"xspaceagi",
|
|
"agent",
|
|
"core",
|
|
"application",
|
|
"service",
|
|
"DigitalEmployeeSyncApplicationServiceImpl.java",
|
|
);
|
|
const testPath = path.join(
|
|
backendRoot,
|
|
"app-platform-modules",
|
|
"app-platform-agent",
|
|
"app-platform-agent-core-application",
|
|
"src",
|
|
"test",
|
|
"java",
|
|
"com",
|
|
"xspaceagi",
|
|
"agent",
|
|
"core",
|
|
"application",
|
|
"service",
|
|
"DigitalEmployeeSyncApplicationServiceImplTest.java",
|
|
);
|
|
const qimingOpsPath = path.join(qimingRoot, "src", "pages", "SystemManagement", "Content", "DigitalEmployeeOps", "index.tsx");
|
|
const qimingTypesPath = path.join(qimingRoot, "src", "types", "interfaces", "systemManage.ts");
|
|
const docsPath = path.resolve(packageRoot, "..", "..", "docs", "digital-employee-frontend-integration-plan.md");
|
|
const service = fs.readFileSync(servicePath, "utf8");
|
|
const test = fs.readFileSync(testPath, "utf8");
|
|
const qimingOps = fs.readFileSync(qimingOpsPath, "utf8");
|
|
const qimingTypes = fs.readFileSync(qimingTypesPath, "utf8");
|
|
const docs = fs.readFileSync(docsPath, "utf8");
|
|
const requiredSnippets = [
|
|
[service, "governance_commands", "backend governance command view"],
|
|
[service, "isGovernanceCommandRow", "backend governance command matcher"],
|
|
[service, "governance_", "backend governance command kind classifier"],
|
|
[service, "command_id", "backend governance command id classifier"],
|
|
[test, "queryAdminWorkbenchGovernanceCommandsReturnsGovernanceRowsOnly", "backend governance command test"],
|
|
[qimingTypes, "governance_commands", "qiming governance command view type"],
|
|
[qimingOps, "治理命令", "qiming governance command tab"],
|
|
[qimingOps, "标记已看", "qiming governance reviewed action"],
|
|
[qimingOps, "忽略", "qiming governance dismiss action"],
|
|
[qimingOps, "ACP 硬中断", "qiming high-risk governance copy"],
|
|
[docs, "正式管理端治理命令预览", "docs governance command absorption"],
|
|
];
|
|
const missing = requiredSnippets
|
|
.filter(([content, snippet]) => !content.includes(snippet))
|
|
.map(([, , label]) => label);
|
|
if (missing.length > 0) {
|
|
throw new Error(`Missing admin governance command workbench hooks: ${missing.join(", ")}`);
|
|
}
|
|
console.log("[DigitalEmployeeCheck] admin governance command workbench hooks OK");
|
|
}
|
|
|
|
function checkLocalDatabaseSchema() {
|
|
console.log("\n[DigitalEmployeeCheck] Verify local SQLite digital schema");
|
|
const dbPath = path.join(os.homedir(), ".qimingclaw", "qimingclaw.db");
|
|
if (!fs.existsSync(dbPath)) {
|
|
console.log(`[DigitalEmployeeCheck] Skip DB schema check; database not found: ${dbPath}`);
|
|
return;
|
|
}
|
|
|
|
const healResult = spawnSync("sqlite3", [dbPath, selfHealingDigitalSchemaSql], {
|
|
encoding: "utf8",
|
|
shell: process.platform === "win32",
|
|
});
|
|
if (healResult.error) {
|
|
console.log(`[DigitalEmployeeCheck] Skip DB schema check; sqlite3 unavailable: ${healResult.error.message}`);
|
|
return;
|
|
}
|
|
if (healResult.status !== 0) {
|
|
throw new Error(healResult.stderr || "sqlite3 digital schema self-heal failed");
|
|
}
|
|
|
|
const result = spawnSync("sqlite3", [dbPath, ".tables"], {
|
|
encoding: "utf8",
|
|
shell: process.platform === "win32",
|
|
});
|
|
if (result.status !== 0) {
|
|
throw new Error(result.stderr || "sqlite3 .tables failed");
|
|
}
|
|
|
|
const tables = new Set(result.stdout.split(/\s+/).filter(Boolean));
|
|
const missing = requiredDigitalTables.filter((table) => !tables.has(table));
|
|
if (missing.length > 0) {
|
|
throw new Error(`Missing digital employee tables: ${missing.join(", ")}`);
|
|
}
|
|
console.log(`[DigitalEmployeeCheck] ${requiredDigitalTables.length} digital tables OK`);
|
|
}
|
|
|
|
function main() {
|
|
try {
|
|
runStep("Run digital employee unit tests", "npm", ["run", "test:run", "--", ...testFiles]);
|
|
runStep("Build Electron main process", "npm", ["run", "build:main:dev"]);
|
|
runStep("Build embedded digital employee", "npm", ["run", "build:sgrobot-digital"]);
|
|
checkSgrobotDigitalAssets();
|
|
checkDigitalDiagnosticAuditProjection();
|
|
checkDigitalNotificationPreferences();
|
|
checkDigitalApprovalHistorySubscriptions();
|
|
checkDigitalApprovalWorkflowSync();
|
|
checkDigitalPlanStepGraphDispatchPolicy();
|
|
checkDigitalSkillRemotePolicy();
|
|
checkDigitalRiskApprovalPolicy();
|
|
checkDigitalRouteDecisionPolicy();
|
|
checkDigitalDailyReportDelivery();
|
|
checkDigitalArtifactCleanup();
|
|
checkDigitalArtifactBatchGovernance();
|
|
checkDigitalBusinessViewUi();
|
|
checkDigitalInterventionWorkbench();
|
|
checkDigitalMemoryGovernanceAudit();
|
|
checkDigitalOpsNotificationReportWorkbenches();
|
|
checkDigitalPolicySchedulerWorkbenches();
|
|
checkDigitalAdminActionLoop();
|
|
checkDigitalAdminPolicySnapshots();
|
|
checkDigitalBackendMaterializedFacts();
|
|
checkDigitalAdminRecordBillingArchiveShell();
|
|
checkDigitalAdminApprovalGovernanceWorkbench();
|
|
checkDigitalAdminApprovalPoliciesWorkbench();
|
|
checkDigitalAdminMemorySkillWorkbench();
|
|
checkDigitalAdminPolicySchedulerWorkbenches();
|
|
checkDigitalAdminPlanGovernanceWorkbenches();
|
|
checkDigitalAdminGovernancePolicyRevisionMaterialization();
|
|
checkDigitalAdminPolicyGovernanceClosure();
|
|
checkDigitalAdminPlanStepDispatchWorkbench();
|
|
checkDigitalAdminCollaborationOperationsClosure();
|
|
checkDigitalAdminServiceOperationsWorkbench();
|
|
checkDigitalAdminRouteGovernanceWorkbench();
|
|
checkDigitalAdminNotificationWorkbench();
|
|
checkDigitalAdminNotificationPoliciesWorkbench();
|
|
checkDigitalAdminArtifactLifecycleWorkbench();
|
|
checkDigitalAdminAuditDiagnosticsWorkbench();
|
|
checkDigitalAdminDiagnosticRepairPreview();
|
|
checkDigitalAdminDailyReportWorkbench();
|
|
checkDigitalAdminGovernanceCommandWorkbench();
|
|
checkLocalDatabaseSchema();
|
|
console.log("\n[DigitalEmployeeCheck] All checks passed");
|
|
} catch (error) {
|
|
console.error(`\n[DigitalEmployeeCheck] ${error instanceof Error ? error.message : String(error)}`);
|
|
process.exit(process.exitCode || 1);
|
|
}
|
|
}
|
|
|
|
main();
|