Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | 7x 7x 7x 2x 5x 5x 5x 1x 1x 4x 4x 9x 9x 4x 9x 9x 9x 6x 9x 9x 22x 22x | /**
* @module scripts/agentic/gate-checks/per-document-coverage
* @description Check 2 — Per-document coverage (Family E vs manifest).
*
* Extracts dok_ids from the data-download-manifest and verifies each has
* a corresponding analysis document in the `documents/` subdirectory.
*
* @see .github/prompts/05-analysis-gate.md §Check 2
* @author Hack23 AB
* @license Apache-2.0
*/
import { readFile } from 'node:fs/promises';
import { existsSync, statSync } from 'node:fs';
import { join } from 'node:path';
import { DOK_ID_PATTERN } from '../artifact-inventory.js';
import type { GateCheckResult } from '../gate-shared/types.js';
/**
* Extract dok_ids from the data-download-manifest and verify each has
* a corresponding analysis document in the `documents/` subdirectory.
*/
export async function checkPerDocumentCoverage(
analysisDir: string,
): Promise<GateCheckResult[]> {
const results: GateCheckResult[] = [];
const manifestPath = join(analysisDir, 'data-download-manifest.md');
if (!existsSync(manifestPath)) {
return results;
}
const content = await readFile(manifestPath, 'utf-8');
const dokIds = extractDokIds(content);
if (dokIds.length === 0) {
results.push({
checkId: 'per-document-coverage',
passed: false,
message: 'Manifest has no dok_id entries',
});
return results;
}
const documentsDir = join(analysisDir, 'documents');
for (const dokId of dokIds) {
const found = hasDocumentAnalysis(documentsDir, dokId);
results.push({
checkId: 'per-document-coverage',
passed: found,
message: found
? `Document analysis found for ${dokId}`
: `documents/${dokId}.md or documents/${dokId}-analysis.md missing (any case)`,
artifact: `documents/${dokId}-analysis.md`,
});
}
return results;
}
/**
* Extract unique dok_ids from markdown content.
*/
export function extractDokIds(content: string): string[] {
const globalPattern = new RegExp(DOK_ID_PATTERN.source, 'g');
const matches = content.match(globalPattern);
if (!matches) return [];
return [...new Set(matches)];
}
/**
* Check if a document analysis file exists and is non-empty (any case variant).
* Mirrors the prompt gate's `-s` check (file exists AND size > 0).
*/
function hasDocumentAnalysis(documentsDir: string, dokId: string): boolean {
const variants = [
`${dokId}.md`,
`${dokId}-analysis.md`,
`${dokId.toLowerCase()}.md`,
`${dokId.toLowerCase()}-analysis.md`,
];
return variants.some((v) => {
const p = join(documentsDir, v);
return existsSync(p) && statSync(p).size > 0;
});
}
|