feat: 定义NapCat自动化审计契约

This commit is contained in:
sunlei 2026-06-24 23:12:21 +08:00
parent 32d02b5a8f
commit efc6f50199
4 changed files with 164 additions and 0 deletions

View File

@ -0,0 +1,34 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"additionalProperties": false,
"required": [
"sourceValidation",
"imageValidation",
"apiPromotionReadiness",
"onlineSmokeReadiness",
"rollbackPointer"
],
"properties": {
"sourceValidation": {
"type": "string",
"minLength": 1
},
"imageValidation": {
"type": "string",
"minLength": 1
},
"apiPromotionReadiness": {
"type": "string",
"minLength": 1
},
"onlineSmokeReadiness": {
"type": "string",
"minLength": 1
},
"rollbackPointer": {
"type": "string",
"minLength": 1
}
}
}

View File

@ -0,0 +1,33 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"additionalProperties": false,
"required": ["classification", "reasonCodes", "recommendedAction", "summary"],
"properties": {
"classification": {
"enum": ["safe-candidate", "manual-review", "blocked"]
},
"reasonCodes": {
"type": "array",
"minItems": 1,
"items": {
"enum": [
"NO_UPSTREAM_CHANGE",
"HOT_ZONE_CHANGED",
"FORK_PATCH_OVERLAP",
"DRY_MERGE_CONFLICT",
"BUILD_GRAPH_CHANGED",
"METADATA_UNAVAILABLE",
"CODEX_SCHEMA_INVALID"
]
}
},
"recommendedAction": {
"enum": ["no-op", "create-candidate-branch", "request-human-review", "block"]
},
"summary": {
"type": "string",
"minLength": 1
}
}
}

View File

@ -35,6 +35,11 @@ import {
findTaskRecordGovernanceFindings,
isBenignCredentialReviewValue,
} from "./tools/review.js";
import {
napcatAutomationReasonCodes,
parseNapcatAutomationClassification,
upstreamAuditOutputSchema,
} from "./tools/napcatAutomation.types.js";
import {
buildBusinessTestPlan,
buildNapcatDeviceProfileCheck,
@ -54,7 +59,27 @@ import {
buildPushPlan,
buildRemoteHealthCheck,
} from "./tools/workflow.js";
/**
* Runs ktWorkflow guardrail smoke checks from the CLI self-test entry; writes local evidence under the KT workspace and throws on any broken workflow contract.
* @returns A promise that resolves after all contract checks and evidence writing complete.
*/
export async function runSelfTest(): Promise<void> {
const napcatAuditSchemaSmoke = upstreamAuditOutputSchema.safeParse({
classification: "manual-review",
reasonCodes: ["HOT_ZONE_CHANGED"],
recommendedAction: "request-human-review",
summary: "Login hot-zone changed.",
});
if (!napcatAuditSchemaSmoke.success) {
throw new Error("NapCat upstream audit schema self-check failed");
}
if (!napcatAutomationReasonCodes.includes("HOT_ZONE_CHANGED")) {
throw new Error("NapCat reason-code list self-check failed");
}
if (parseNapcatAutomationClassification("manual-review") !== "manual-review") {
throw new Error("NapCat classification parser self-check failed");
}
const reviewClassifier = {
localizedSecretLabelAllowed: isBenignCredentialReviewValue("密钥"),
realTokenRejected: !isBenignCredentialReviewValue(

View File

@ -0,0 +1,72 @@
import { z } from 'zod';
export const napcatAutomationClassifications = [
'safe-candidate',
'manual-review',
'blocked',
] as const;
export const napcatAutomationReasonCodes = [
'NO_UPSTREAM_CHANGE',
'HOT_ZONE_CHANGED',
'FORK_PATCH_OVERLAP',
'DRY_MERGE_CONFLICT',
'BUILD_GRAPH_CHANGED',
'METADATA_UNAVAILABLE',
'CODEX_SCHEMA_INVALID',
] as const;
export const upstreamAuditOutputSchema = z.object({
classification: z.enum(napcatAutomationClassifications),
reasonCodes: z.array(z.enum(napcatAutomationReasonCodes)).min(1),
recommendedAction: z.enum([
'no-op',
'create-candidate-branch',
'request-human-review',
'block',
]),
summary: z.string().min(1),
});
export type NapcatAutomationClassification =
(typeof napcatAutomationClassifications)[number];
export interface NapcatUpstreamAuditInput {
artifactRoot?: string;
createCandidateBranch?: boolean;
execute?: boolean;
forkBranch?: string;
forkRepo?: string;
lastAcceptedUpstreamBase?: string;
upstreamReleaseTag?: string;
upstreamRepo?: string;
useCodex?: boolean;
}
export interface NapcatAutomationArtifact {
path: string;
type: 'context' | 'json' | 'jsonl' | 'markdown' | 'script';
}
export interface NapcatAutomationResult {
artifacts: NapcatAutomationArtifact[];
classification: NapcatAutomationClassification;
execute: boolean;
recommendedAction: string;
summary: string;
}
/**
* Parses the upstream audit classification emitted by deterministic collectors or Codex.
* @param value - Raw classification string from deterministic audit metadata or Codex JSON output; must match the shared NapCat automation taxonomy.
* @returns A supported NapCat automation classification for downstream workflow decisions.
*/
export function parseNapcatAutomationClassification(
value: string,
): NapcatAutomationClassification {
const parsed = z.enum(napcatAutomationClassifications).safeParse(value);
if (!parsed.success) {
throw new Error(`Unsupported NapCat audit classification: ${value}`);
}
return parsed.data;
}