Skip to content

Coherence Weekly Rollup #2

Coherence Weekly Rollup

Coherence Weekly Rollup #2

name: Coherence Weekly Rollup
on:
schedule:
- cron: '0 9 * * 1' # Monday 9:00 UTC
workflow_dispatch:
inputs:
coherence_root:
description: 'Coherence root directory (default: coherence)'
required: false
default: 'coherence'
type: string
telemetry_out_dir:
description: 'Override telemetry output directory (leave blank for auto)'
required: false
default: ''
type: string
commit_results:
description: 'Commit results to repo (set false for protected branches)'
required: false
default: 'true'
type: string
permissions:
contents: write
jobs:
rollup:
name: Weekly Rollup
runs-on: ubuntu-latest
env:
COHERENCE_ROOT: ${{ inputs.coherence_root || 'coherence' }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Resolve output directory
id: resolve
run: |
ROOT="${COHERENCE_ROOT}"
OVERRIDE="${{ inputs.telemetry_out_dir }}"
if [ -n "$OVERRIDE" ]; then
OUT_DIR="$OVERRIDE"
elif [ "$ROOT" = "coherence" ]; then
OUT_DIR="coherence/telemetry"
else
SANITIZED=$(echo "$ROOT" | tr '/' '_')
OUT_DIR="telemetry_out/${SANITIZED}"
fi
echo "out_dir=${OUT_DIR}" >> "$GITHUB_OUTPUT"
mkdir -p "$OUT_DIR"
- name: Validate root
run: |
if [ ! -f "${COHERENCE_ROOT}/intel/assumptions.yaml" ]; then
echo "::warning::No assumptions.yaml found at ${COHERENCE_ROOT}/intel/assumptions.yaml"
fi
if [ ! -d "${COHERENCE_ROOT}/drift" ]; then
echo "::warning::No drift directory found at ${COHERENCE_ROOT}/drift/"
fi
- name: Generate Rollup
env:
TELEMETRY_OUT_DIR: ${{ steps.resolve.outputs.out_dir }}
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const root = process.env.COHERENCE_ROOT;
const outDir = process.env.TELEMETRY_OUT_DIR;
const today = new Date();
today.setHours(0, 0, 0, 0);
const warnDate = new Date(today);
warnDate.setDate(warnDate.getDate() + 14);
// ── Assumptions ──
let totalActive = 0;
let expiredCount = 0;
let nearExpiryCount = 0;
const expiredList = [];
const nearExpiryList = [];
const asmPath = `${root}/intel/assumptions.yaml`;
if (fs.existsSync(asmPath)) {
const content = fs.readFileSync(asmPath, 'utf8');
// Parse assumptions from YAML.
// Handles: empty files, assumptions: [], indented lists, multi-line statements.
const blocks = content.includes('- id:')
? content.split(/^\s*- id:/m).slice(1) : [];
for (const block of blocks) {
const id = (block.match(/^\s*(.+)/m) || ['', ''])[1].trim();
const status = (block.match(/^\s*status:\s*(.+)/m) || ['', ''])[1].trim();
const expires = (block.match(/^\s*expires:\s*(.+)/m) || ['', ''])[1].trim();
// Handle multi-line statements (> or | YAML folding)
let statement = '';
const stmtMatch = block.match(/^\s*statement:\s*(.+)/m);
if (stmtMatch) {
const val = stmtMatch[1].trim().replace(/^["']|["']$/g, '');
if (/^[>|][-+]?$/.test(val)) {
const lines = block.split('\n');
const idx = lines.findIndex(l => /^\s*statement:/.test(l));
const keyIndent = (lines[idx].match(/^(\s*)/)||['',''])[1].length;
const parts = [];
for (let i = idx + 1; i < lines.length; i++) {
const indent = (lines[i].match(/^(\s*)/)||['',''])[1].length;
if (lines[i].trim() && indent <= keyIndent) break;
if (lines[i].trim()) parts.push(lines[i].trim());
}
statement = parts.join(' ');
} else {
statement = val;
}
}
if (status !== 'active') continue;
totalActive++;
if (!expires) continue;
const exp = new Date(expires + 'T00:00:00');
const asmId = id.startsWith('ASM-') ? id : `ASM-${id}`;
if (exp < today) {
expiredCount++;
expiredList.push({ id: asmId, expires, statement });
} else if (exp <= warnDate) {
nearExpiryCount++;
nearExpiryList.push({ id: asmId, expires, statement });
}
}
}
// ── Drift ──
let openDriftCount = 0;
const openDrifts = [];
const driftDir = `${root}/drift`;
if (fs.existsSync(driftDir)) {
const driftFiles = fs.readdirSync(driftDir)
.filter(f => /^DRIFT-[\d-]+\.md$/.test(f));
for (const df of driftFiles) {
const content = fs.readFileSync(`${driftDir}/${df}`, 'utf8');
const statusMatch = content.match(/## Status\s*\n+\s*(.+)/);
if (statusMatch) {
const st = statusMatch[1].trim().toLowerCase();
if (st === 'open' || st === 'in_progress') {
openDriftCount++;
const sevMatch = content.match(/## Severity\s*\n+\s*(.+)/);
const sev = sevMatch ? sevMatch[1].trim() : 'unknown';
openDrifts.push({ id: df.replace('.md', ''), severity: sev });
}
}
}
}
// ── Score ──
let score = null;
const scorePath = `${root}/telemetry/coherence_score.json`;
if (fs.existsSync(scorePath)) {
try { score = JSON.parse(fs.readFileSync(scorePath, 'utf8')); } catch {}
}
// ── Write rollup JSON ──
const dateStr = today.toISOString().split('T')[0];
const rollup = {
date: dateStr,
assumptions: { total_active: totalActive, expired: expiredCount, near_expiry: nearExpiryCount },
drift: { open: openDriftCount },
score: score ? score.score : null,
};
fs.writeFileSync(`${outDir}/weekly_rollup.json`,
JSON.stringify(rollup, null, 2) + '\n');
// ── Write top risks ──
const risks = [];
// Sort: expired assumptions first, then near-expiry, then open drift
for (const a of expiredList) {
risks.push({ priority: 1, label: 'EXPIRED', detail: `${a.id} — ${a.statement} (expired ${a.expires})` });
}
for (const a of nearExpiryList) {
risks.push({ priority: 2, label: 'EXPIRING', detail: `${a.id} — ${a.statement} (expires ${a.expires})` });
}
for (const d of openDrifts) {
risks.push({ priority: d.severity === 'critical' ? 1 : 3, label: `DRIFT/${d.severity}`, detail: d.id });
}
risks.sort((a, b) => a.priority - b.priority);
const lines = [
`# Top Risks — ${dateStr}`,
'',
];
if (risks.length === 0) {
lines.push('No active risks. All assumptions current, no open drift.');
} else {
lines.push('| Priority | Type | Detail |');
lines.push('|----------|------|--------|');
for (const r of risks.slice(0, 10)) {
lines.push(`| ${r.priority === 1 ? 'HIGH' : r.priority === 2 ? 'MED' : 'LOW'} | ${r.label} | ${r.detail} |`);
}
}
lines.push('');
fs.writeFileSync(`${outDir}/top_risks.md`, lines.join('\n'));
- name: Commit Rollup
if: ${{ inputs.commit_results != 'false' }}
env:
TELEMETRY_OUT_DIR: ${{ steps.resolve.outputs.out_dir }}
run: |
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add "${TELEMETRY_OUT_DIR}/weekly_rollup.json" "${TELEMETRY_OUT_DIR}/top_risks.md"
git diff --staged --quiet && echo "No changes to commit" && exit 0
git commit -m "chore: weekly coherence rollup [skip ci]"
git push