fix: disable board audit coverage validation

This commit is contained in:
Codex
2026-05-23 03:16:44 +00:00
parent 7ea2f77b70
commit 2bd36e7e9c
4 changed files with 67 additions and 139 deletions
+22 -19
View File
@@ -654,29 +654,32 @@ export async function runGhCliIssueGuardContract(): Promise<JsonRecord> {
assertCondition(boardAudit.status === 0, "issue board-audit should succeed as a read-only audit", boardAudit.json ?? { stdout: boardAudit.stdout, stderr: boardAudit.stderr });
const boardAuditData = dataOf(boardAudit.json ?? {});
assertCondition(boardAuditData.command === "issue board-audit" && boardAuditData.dryRun === true && boardAuditData.readOnly === true, "board-audit should be explicit read-only dry-run", boardAuditData);
const boardAuditIssue = boardAuditData.boardIssue as JsonRecord;
assertCondition(typeof boardAuditIssue.bodySha === "string" && String(boardAuditIssue.bodySha).length === 64, "board-audit should expose board body sha", boardAuditIssue);
const boardAuditSummary = boardAuditData.summary as JsonRecord;
assertCondition(boardAuditSummary.openIssues === null && boardAuditSummary.closedIssues === null, "board-audit should not fetch GitHub open/closed issue lists", boardAuditSummary);
assertCondition(boardAuditSummary.openRows === 4 && boardAuditSummary.closedRows === 3 && boardAuditSummary.parsedSections === 2, "board-audit should report parsed board structure", boardAuditSummary);
const boardAuditValidation = boardAuditData.validation as JsonRecord;
const openClosedCoverage = boardAuditValidation.openClosedCoverage as JsonRecord;
assertCondition(openClosedCoverage.enabled === false, "board-audit should disable OPEN/CLOSED coverage validation", boardAuditValidation);
const missingOpenIssues = boardAuditData.missingOpenIssues as JsonRecord[];
assertCondition(Array.isArray(missingOpenIssues) && missingOpenIssues.some((issue) => issue.number === 36), "board-audit should report open issue missing from OPEN table", missingOpenIssues);
assertCondition(!missingOpenIssues.some((issue) => issue.number === 45), "board-audit should use the primary markdown issue link as the Issue-column row key", missingOpenIssues);
assertCondition(!missingOpenIssues.some((issue) => issue.number === 46), "board-audit should not require daily commander briefs in the OPEN table", missingOpenIssues);
assertCondition(Array.isArray(missingOpenIssues) && missingOpenIssues.length === 0, "board-audit should not report missing OPEN rows", missingOpenIssues);
const closedInOpenRows = boardAuditData.closedInOpenRows as JsonRecord[];
assertCondition(Array.isArray(closedInOpenRows) && closedInOpenRows.some((issue) => issue.number === 40), "board-audit should report closed issue still in OPEN table", closedInOpenRows);
assertCondition(Array.isArray(closedInOpenRows) && closedInOpenRows.length === 0, "board-audit should not report closed issues in OPEN rows", closedInOpenRows);
const missingClosedRows = boardAuditData.missingClosedRows as JsonRecord[];
assertCondition(Array.isArray(missingClosedRows) && missingClosedRows.some((issue) => issue.number === 40) && missingClosedRows.some((issue) => issue.number === 41), "board-audit should report closed issues missing from CLOSED table", missingClosedRows);
assertCondition(!missingClosedRows.some((issue) => issue.number === 18), "board-audit should ignore explanatory issue references after the primary Issue-column markdown link", missingClosedRows);
assertCondition(Array.isArray(missingClosedRows) && missingClosedRows.length === 0, "board-audit should not report missing CLOSED rows", missingClosedRows);
const openInClosedRows = boardAuditData.openInClosedRows as JsonRecord[];
assertCondition(Array.isArray(openInClosedRows) && openInClosedRows.some((issue) => issue.number === 36), "board-audit should report open issue placed in CLOSED table", openInClosedRows);
assertCondition(Array.isArray(openInClosedRows) && openInClosedRows.length === 0, "board-audit should not report open issues in CLOSED rows", openInClosedRows);
const rowValidationWarnings = boardAuditData.rowValidationWarnings as JsonRecord[];
assertCondition(Array.isArray(rowValidationWarnings) && rowValidationWarnings.some((warning) => warning.issueNumber === 40 && Array.isArray(warning.missingColumns) && (warning.missingColumns as unknown[]).includes("branch") && (warning.missingColumns as unknown[]).includes("acceptance") && (warning.missingColumns as unknown[]).includes("progress")), "board-audit should report missing required board columns", rowValidationWarnings);
assertCondition(!rowValidationWarnings.some((warning) => warning.kind === "multiple-issue-references"), "board-audit should not treat explanatory issue references outside the Issue column as row-key conflicts", rowValidationWarnings);
assertCondition(!rowValidationWarnings.some((warning) => warning.kind === "multiple-issue-references" && String(warning.rowPreview ?? "").includes("#20 总看板")), "board-audit should not warn when an Issue-column title mentions #20 after primary #45 link", rowValidationWarnings);
assertCondition(!rowValidationWarnings.some((warning) => warning.kind === "multiple-issue-references" && String(warning.rowPreview ?? "").includes("基于 #4")), "board-audit should not warn when an Issue-column title mentions #4 after primary #18 link", rowValidationWarnings);
assertCondition(!rowValidationWarnings.some((warning) => Array.isArray(warning.missingColumns) && (warning.missingColumns as unknown[]).includes("relatedTask")), "board-audit should recognize relatedTask from the current header", rowValidationWarnings);
assertCondition(Array.isArray(rowValidationWarnings) && rowValidationWarnings.length === 0, "board-audit should not report required-column row warnings", rowValidationWarnings);
const parserWarnings = boardAuditData.parserWarnings as JsonRecord[];
assertCondition(Array.isArray(parserWarnings), "board-audit should expose parser warnings separately", boardAuditData);
const ignoredIssues = boardAuditData.ignoredIssues as JsonRecord[];
assertCondition(Array.isArray(ignoredIssues) && ignoredIssues.some((issue) => issue.number === 20 && issue.reason === "known-meta") && ignoredIssues.some((issue) => issue.number === 24 && issue.reason === "known-meta"), "board-audit should ignore configured known meta issues", ignoredIssues);
assertCondition(ignoredIssues.some((issue) => issue.number === 46 && issue.reason === "brief-index-managed"), "board-audit should ignore daily commander briefs managed by the #20 brief index", ignoredIssues);
assertCondition(Array.isArray(ignoredIssues) && ignoredIssues.length === 0, "board-audit should not produce ignored issue coverage output", ignoredIssues);
const recommendedActions = boardAuditData.recommendedActions as JsonRecord[];
assertCondition(Array.isArray(recommendedActions) && recommendedActions.some((action) => action.action === "add-open-row" && action.issueNumber === 36) && recommendedActions.some((action) => action.action === "move-open-row-to-closed" && action.issueNumber === 40), "board-audit should emit machine-readable recommended actions", recommendedActions);
assertCondition(!recommendedActions.some((action) => action.action === "add-open-row" && action.issueNumber === 46), "board-audit should not recommend adding daily commander briefs to the OPEN table", recommendedActions);
assertCondition(Array.isArray(recommendedActions) && recommendedActions.length === 0, "board-audit should not emit OPEN/CLOSED coverage actions", recommendedActions);
const boardAuditGetRequests = mock.requests.slice(boardAuditRequestCountBefore).filter((request) => request.method === "GET");
assertCondition(boardAuditGetRequests.length === 1 && boardAuditGetRequests[0]?.url === "/repos/pikasTech/unidesk/issues/20", "board-audit should only fetch the board issue body", boardAuditGetRequests);
const boardAuditWriteCount = mock.requests.slice(boardAuditRequestCountBefore).filter((request) => request.method === "PATCH" || request.method === "DELETE" || request.method === "POST").length;
assertCondition(boardAuditWriteCount === 0, "board-audit must not write GitHub", { requests: mock.requests.slice(boardAuditRequestCountBefore) });
@@ -684,8 +687,8 @@ export async function runGhCliIssueGuardContract(): Promise<JsonRecord> {
const legacyBoardAudit = await runCli(["gh", "issue", "board-audit", "--repo", "pikasTech/unidesk", "--board-issue", "60", "--limit", "60", "--dry-run"], env);
assertCondition(legacyBoardAudit.status === 0, "legacy board-audit fixture should succeed", legacyBoardAudit.json ?? { stdout: legacyBoardAudit.stdout, stderr: legacyBoardAudit.stderr });
const legacyBoardAuditData = dataOf(legacyBoardAudit.json ?? {});
const legacyWarnings = legacyBoardAuditData.rowValidationWarnings as JsonRecord[];
assertCondition(Array.isArray(legacyWarnings) && legacyWarnings.some((warning) => warning.kind === "multiple-issue-references" && warning.issueNumber === 101), "legacy board-audit fixture should keep whole-row fallback when no Issue column exists", legacyWarnings);
const legacyWarnings = legacyBoardAuditData.parserWarnings as JsonRecord[];
assertCondition(Array.isArray(legacyWarnings) && legacyWarnings.some((warning) => warning.kind === "multiple-issue-references" && warning.issueNumber === 101), "legacy board-audit fixture should keep parser warnings when no Issue column exists", legacyWarnings);
const legacyBoardWriteCount = mock.requests.slice(legacyBoardAuditRequestCountBefore).filter((request) => request.method === "PATCH" || request.method === "DELETE" || request.method === "POST").length;
assertCondition(legacyBoardWriteCount === 0, "legacy board-audit must not write GitHub", { requests: mock.requests.slice(legacyBoardAuditRequestCountBefore) });
@@ -1326,7 +1329,7 @@ export async function runGhCliIssueGuardContract(): Promise<JsonRecord> {
"issue list default fields include labels and filter pull requests",
"issue scan-escape classifies pollution, explanatory mentions, and body risks",
"issue cleanup-plan remains dry-run with body/comment cleanup suggestions",
"issue board-audit reports missing open rows, closed/open section mismatches, missing closed rows, meta/brief-index ignores, and row validation warnings without writes",
"issue board-audit returns read-only board structure, disables OPEN/CLOSED coverage validation, and keeps compatibility fields empty without writes",
"issue board-row list/get expose parsed #20 rows without writes",
"issue board-row upsert updates existing rows, adds missing rows, reports operation, preserves table trailers, rejects ambiguous rows, blocks stale body SHA writes, and stays dry-run without concurrency guards",
"issue board-row add/delete without guard stay on dry-run and do not PATCH",