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 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 | 1x 1x 1x 1x 2490x 2490x 2490x 94365x 59445x 59445x 59445x 2040x 57405x 57405x 2490x 54975x 15x 15x 15x 510x 480x 465x 15x 480x 480x 3465x 2490x 2745x 480x 2490x 2490x 2490x 2490x 480x 15x | /**
* @module Infrastructure/PoliticalIntelligence/DailyStreams
* @category Intelligence Operations / Supporting Infrastructure
* @name Daily-stream artifact discovery
*
* @description
* Walks `analysis/daily/<YYYY-MM-DD>/<stream>/` to produce a structured
* `DailyDay[]` with one entry per date and one `DailyStream` per workflow
* stream. Recursively counts `.md` / `.json` artifacts. Sorted newest-first.
*
* Round-6 split: extracted from `scripts/generate-political-intelligence.ts`.
*
* @author Hack23 AB (Infrastructure Team)
* @license Apache-2.0
*/
import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
import { buildGithubUrl } from './catalog.js';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const ROOT_DIR = path.join(__dirname, '..', '..');
const DAILY_DIR = path.join(ROOT_DIR, 'analysis', 'daily');
export interface DailyArtifact {
readonly file: string;
/** Path relative to analysis/daily (e.g. 2026-04-23/propositions/executive-brief.md). */
readonly relative: string;
readonly githubUrl: string;
}
export interface DailyStream {
readonly name: string;
readonly githubUrl: string;
readonly artifactCount: number;
readonly artifacts: DailyArtifact[];
}
export interface DailyDay {
readonly date: string;
readonly githubUrl: string;
readonly streams: DailyStream[];
readonly totalArtifacts: number;
}
export function countArtifactsRecursive(dir: string): number {
let n = 0;
for (const e of fs.readdirSync(dir, { withFileTypes: true })) {
const full = path.join(dir, e.name);
if (e.isDirectory()) {
n += countArtifactsRecursive(full);
} else if (e.isFile() && /\.(md|json)$/i.test(e.name)) {
n += 1;
}
}
return n;
}
/** Recursively collect every `.md`/`.json` artifact under a stream folder, sorted by relative path. */
export function collectStreamArtifacts(streamDir: string, streamRelativeBase: string): DailyArtifact[] {
Iif (!fs.existsSync(streamDir)) return [];
const out: DailyArtifact[] = [];
const walk = (dir: string, relBase: string): void => {
for (const e of fs.readdirSync(dir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
const full = path.join(dir, e.name);
const rel = relBase ? `${relBase}/${e.name}` : e.name;
if (e.isDirectory()) {
walk(full, rel);
} else if (Ee.isFile() && /\.(md|json)$/i.test(e.name)) {
out.push({
file: rel,
relative: `${streamRelativeBase}/${rel}`,
githubUrl: buildGithubUrl('blob', `analysis/daily/${streamRelativeBase}/${rel}`),
});
}
}
};
walk(streamDir, '');
return out.sort((a, b) => a.file.localeCompare(b.file));
}
export function collectDailyDays(): DailyDay[] {
Iif (!fs.existsSync(DAILY_DIR)) return [];
const days: DailyDay[] = [];
const dateEntries = fs.readdirSync(DAILY_DIR, { withFileTypes: true })
.filter((e) => e.isDirectory() && /^\d{4}-\d{2}-\d{2}$/.test(e.name))
.map((e) => e.name)
.sort((a, b) => b.localeCompare(a)); // newest first
for (const date of dateEntries) {
const dateDir = path.join(DAILY_DIR, date);
const streamNames = fs.readdirSync(dateDir, { withFileTypes: true })
.filter((e) => e.isDirectory())
.map((e) => e.name)
.sort((a, b) => a.localeCompare(b));
const streams: DailyStream[] = streamNames.map((name) => {
const streamDir = path.join(dateDir, name);
const artifacts = collectStreamArtifacts(streamDir, `${date}/${name}`);
return {
name,
githubUrl: buildGithubUrl('tree', `analysis/daily/${date}/${name}`),
artifactCount: artifacts.length || countArtifactsRecursive(streamDir),
artifacts,
};
});
const totalArtifacts = streams.reduce((a, s) => a + s.artifactCount, 0);
days.push({
date,
githubUrl: buildGithubUrl('tree', `analysis/daily/${date}`),
streams,
totalArtifacts,
});
}
return days;
}
|