feat: complete governed knowledge lifecycle

This commit is contained in:
key
2026-08-03 14:34:54 +08:00
parent a275f98fad
commit df77998e0c
41 changed files with 4921 additions and 225 deletions
+228
View File
@@ -187,6 +187,129 @@ export type LegacyStagePreview = {
moreAvailable: boolean;
};
export type KnowledgeRolloutMode = 'LEGACY' | 'SHADOW' | 'ENFORCED';
export type KnowledgeRolloutScope = {
knowledgeId: number;
spaceCode: string;
spaceName: string;
mode: KnowledgeRolloutMode;
governedCollection: string;
activeGeneration: number;
candidateGeneration?: number;
updatedBy?: number;
reason?: string;
updatedTime?: string;
readyAttachments: number;
enforcementBlockers: number;
};
export type KnowledgeVersion = {
id: number;
versionNo: number;
versionStatus: string;
revisionOfVersionId?: number;
revisionReason?: string;
contentSha256: string;
parserName?: string;
parserVersion?: string;
semanticAnalysisStatus: string;
privacyStatus: string;
published: boolean;
candidate: boolean;
chunkCount: number;
openIssueCount: number;
createTime: string;
};
export type ReviewPackage = {
assetId: number;
versionId: number;
versionNo: number;
riskLevel: 'LOW' | 'MEDIUM' | 'HIGH' | 'CRITICAL';
batchEligible: boolean;
summary: {
sourceName: string;
contentPreview: string;
headings: string[];
chunkCount: number;
issueCount: number;
duplicateCount: number;
conflictCount: number;
};
suggestion: { decision: string; reasonCodes: string[]; recommendedActions: string[]; disclaimer: string };
};
export type DeletionImpact = {
assetId: number;
lifecycleStatus: string;
retentionClass: string;
legalHold: boolean;
chunks: number;
publishedFragments: number;
queryEvidence: number;
learningTasks: number;
broadcasts: number;
generations: number;
canRequestPurge: boolean;
blockers: string[];
};
export type PurgeRequest = {
id: number;
requestKey: string;
assetId: number;
retentionClass: string;
reason: string;
status: string;
requesterId: number;
requestedTime: string;
approverId?: number;
approvalReason?: string;
executeAfter: string;
executedTime?: string;
lastError?: string;
};
export type MigrationRun = {
id: number;
runKey: string;
knowledgeId?: number;
riskScope: string;
dryRun: boolean;
batchSize: number;
cursorAttachmentId: number;
status: string;
discoveredCount: number;
stagedCount: number;
quarantinedCount: number;
failedCount: number;
manifestSha256: string;
verifiedDryRunId?: number;
};
export type GenerationBuild = {
knowledgeId: number;
generation: number;
collection: string;
status: string;
expectedVersions: number;
includedVersions: number;
outstandingJobs: number;
};
export type ActivationGate = {
gateId: number;
knowledgeId: number;
candidateGeneration: number;
status: 'PASSED' | 'BLOCKED';
sampleCount: number;
top1AgreementRate: number;
overlapAt5Avg: number;
governedEmptyRate: number;
evidence: { blockingAssets: number; openCriticalIssues: number; deadLetters: number; generationStatus: string };
};
export type KnowledgeGlossaryTerm = {
id: number;
term: string;
@@ -601,6 +724,111 @@ export function previewLegacyQualityAssets(limit = 50, afterAttachmentId = 0): P
});
}
export function listKnowledgeRolloutScopes(): Promise<ApiResult<KnowledgeRolloutScope[]>> {
return request({
url: '/api/knowledge/quality/rollout/scopes',
method: 'get'
});
}
export function transitionKnowledgeRollout(
knowledgeId: number,
targetMode: KnowledgeRolloutMode,
reason: string,
activeGeneration?: number
): Promise<ApiResult<KnowledgeRolloutScope>> {
return request({
url: `/api/knowledge/quality/rollout/spaces/${knowledgeId}/transition`,
method: 'post',
data: { targetMode, reason, activeGeneration },
headers: { repeatSubmit: false }
});
}
export function listAssetVersions(assetId: number): Promise<ApiResult<KnowledgeVersion[]>> {
return request({ url: `/api/knowledge/quality/assets/${assetId}/versions`, method: 'get' });
}
export function getAssetReviewPackage(assetId: number): Promise<ApiResult<ReviewPackage>> {
return request({ url: `/api/knowledge/quality/assets/${assetId}/review-package`, method: 'get' });
}
export function getDeletionImpact(assetId: number): Promise<ApiResult<DeletionImpact>> {
return request({ url: `/api/knowledge/quality/assets/${assetId}/impact`, method: 'get' });
}
export function createPurgeRequest(assetId: number, reason: string): Promise<ApiResult<PurgeRequest>> {
return request({
url: `/api/knowledge/quality/assets/${assetId}/purge-requests`,
method: 'post',
data: { requestKey: `purge:${assetId}:${Date.now()}`, reason },
headers: { repeatSubmit: false }
});
}
export function listPurgeRequests(status = '', limit = 100): Promise<ApiResult<PurgeRequest[]>> {
return request({ url: '/api/knowledge/quality/purge-requests', method: 'get', params: { status, limit } });
}
export function decidePurgeRequest(id: number, decision: 'APPROVE' | 'REJECT', reason: string): Promise<ApiResult<PurgeRequest>> {
return request({ url: `/api/knowledge/quality/purge-requests/${id}/decision`, method: 'post', data: { decision, reason } });
}
export function executePurgeRequest(id: number): Promise<ApiResult<PurgeRequest>> {
return request({ url: `/api/knowledge/quality/purge-requests/${id}/execute`, method: 'post' });
}
export function runKnowledgeReconciliation(): Promise<ApiResult<{ runId: number; status: string; issues: unknown[] }>> {
return request({ url: '/api/knowledge/quality/reconciliation-runs', method: 'post' });
}
export function listMigrationRuns(limit = 50): Promise<ApiResult<MigrationRun[]>> {
return request({ url: '/api/knowledge/quality/migration-runs', method: 'get', params: { limit } });
}
export function createMigrationRun(data: {
runKey: string;
knowledgeId?: number;
riskScope: string;
dryRun: boolean;
batchSize: number;
verifiedDryRunId?: number;
}): Promise<ApiResult<MigrationRun>> {
return request({ url: '/api/knowledge/quality/migration-runs', method: 'post', data, headers: { repeatSubmit: false } });
}
export function runNextMigrationBatch(id: number): Promise<ApiResult<{ moreAvailable: boolean; failed: number }>> {
return request({ url: `/api/knowledge/quality/migration-runs/${id}/next`, method: 'post', headers: { repeatSubmit: false } });
}
export function startGenerationBuild(knowledgeId: number, reason: string): Promise<ApiResult<GenerationBuild>> {
return request({ url: `/api/knowledge/quality/rollout/spaces/${knowledgeId}/generation-builds`, method: 'post', data: { reason } });
}
export function refreshGenerationBuild(knowledgeId: number): Promise<ApiResult<GenerationBuild>> {
return request({ url: `/api/knowledge/quality/rollout/spaces/${knowledgeId}/generation-builds/refresh`, method: 'post' });
}
export function compareShadowQuery(knowledgeId: number, queryText: string): Promise<ApiResult<unknown>> {
return request({
url: `/api/knowledge/quality/rollout/spaces/${knowledgeId}/shadow-comparisons`,
method: 'post',
data: { queryText, source: 'ADMIN_WORKBENCH' }
});
}
export function evaluateActivationGate(knowledgeId: number): Promise<ApiResult<ActivationGate>> {
return request({ url: `/api/knowledge/quality/rollout/spaces/${knowledgeId}/activation-gates`, method: 'post' });
}
export function activateGeneration(knowledgeId: number, gateId: number, reason: string): Promise<ApiResult<unknown>> {
return request({ url: `/api/knowledge/quality/rollout/spaces/${knowledgeId}/activate`, method: 'post', data: { gateId, reason } });
}
export function rollbackGeneration(knowledgeId: number, reason: string): Promise<ApiResult<unknown>> {
return request({ url: `/api/knowledge/quality/rollout/spaces/${knowledgeId}/generation-rollback`, method: 'post', data: { reason } });
}
export function listKnowledgeGlossary(status: KnowledgeGlossaryTerm['status'] = 'ACTIVE', limit = 200): Promise<ApiResult<KnowledgeGlossaryTerm[]>> {
return request({
url: '/api/knowledge/quality/glossary',