feat: 定义NapCat自动化审计契约
This commit is contained in:
parent
32d02b5a8f
commit
efc6f50199
34
prompts/napcat/schemas/runtime-release-readiness.schema.json
Normal file
34
prompts/napcat/schemas/runtime-release-readiness.schema.json
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
33
prompts/napcat/schemas/upstream-audit.schema.json
Normal file
33
prompts/napcat/schemas/upstream-audit.schema.json
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -35,6 +35,11 @@ import {
|
|||||||
findTaskRecordGovernanceFindings,
|
findTaskRecordGovernanceFindings,
|
||||||
isBenignCredentialReviewValue,
|
isBenignCredentialReviewValue,
|
||||||
} from "./tools/review.js";
|
} from "./tools/review.js";
|
||||||
|
import {
|
||||||
|
napcatAutomationReasonCodes,
|
||||||
|
parseNapcatAutomationClassification,
|
||||||
|
upstreamAuditOutputSchema,
|
||||||
|
} from "./tools/napcatAutomation.types.js";
|
||||||
import {
|
import {
|
||||||
buildBusinessTestPlan,
|
buildBusinessTestPlan,
|
||||||
buildNapcatDeviceProfileCheck,
|
buildNapcatDeviceProfileCheck,
|
||||||
@ -54,7 +59,27 @@ import {
|
|||||||
buildPushPlan,
|
buildPushPlan,
|
||||||
buildRemoteHealthCheck,
|
buildRemoteHealthCheck,
|
||||||
} from "./tools/workflow.js";
|
} 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> {
|
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 = {
|
const reviewClassifier = {
|
||||||
localizedSecretLabelAllowed: isBenignCredentialReviewValue("密钥"),
|
localizedSecretLabelAllowed: isBenignCredentialReviewValue("密钥"),
|
||||||
realTokenRejected: !isBenignCredentialReviewValue(
|
realTokenRejected: !isBenignCredentialReviewValue(
|
||||||
|
|||||||
72
src/tools/napcatAutomation.types.ts
Normal file
72
src/tools/napcatAutomation.types.ts
Normal 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;
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user