- Remove file limit (was 10, now processes all critical+high+medium) - Increase max-turns to 200 and timeout to 60min - Add medium priority to update filter - Update README KB note to reflect automated weekly updates Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
148 lines
4.8 KiB
JavaScript
Executable file
148 lines
4.8 KiB
JavaScript
Executable file
#!/usr/bin/env node
|
|
// weekly-kb-cron.mjs — Local cron wrapper for weekly KB maintenance.
|
|
// Runs sitemap polling + change report. If critical/high findings exist,
|
|
// spawns a local Claude Code session to update stale reference files.
|
|
//
|
|
// Crontab: 23 4 * * 3 node /path/to/weekly-kb-cron.mjs >> /tmp/kb-cron.log 2>&1
|
|
//
|
|
// Zero npm dependencies. Uses only node builtins.
|
|
|
|
import { execFileSync, execSync } from 'node:child_process';
|
|
import { readFileSync, existsSync, appendFileSync } from 'node:fs';
|
|
import { join, dirname } from 'node:path';
|
|
import { fileURLToPath } from 'node:url';
|
|
|
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
const PLUGIN_ROOT = join(__dirname, '..', '..');
|
|
const DATA_DIR = join(__dirname, 'data');
|
|
const CLAUDE_BIN = '/Users/ktg/.local/bin/claude';
|
|
const LOG_FILE = '/tmp/kb-cron.log';
|
|
|
|
const MAX_UPDATE_FILES = Infinity;
|
|
|
|
function log(msg) {
|
|
const ts = new Date().toISOString();
|
|
const line = `[${ts}] ${msg}`;
|
|
console.log(line);
|
|
}
|
|
|
|
function run(script, args = []) {
|
|
const fullPath = join(__dirname, script);
|
|
log(`Running ${script} ${args.join(' ')}`);
|
|
try {
|
|
execFileSync('node', [fullPath, ...args], {
|
|
stdio: 'inherit',
|
|
timeout: 10 * 60 * 1000,
|
|
cwd: PLUGIN_ROOT,
|
|
});
|
|
} catch (err) {
|
|
log(`ERROR: ${script} failed: ${err.message}`);
|
|
process.exit(1);
|
|
}
|
|
}
|
|
|
|
// --- Step 1: Sitemap polling + discovery ---
|
|
log('=== Weekly KB Cron Start ===');
|
|
run('run-weekly-update.mjs', ['--force', '--discover']);
|
|
|
|
// --- Step 2: Read change report ---
|
|
const reportPath = join(DATA_DIR, 'change-report.json');
|
|
if (!existsSync(reportPath)) {
|
|
log('No change report found. Exiting.');
|
|
process.exit(0);
|
|
}
|
|
|
|
const report = JSON.parse(readFileSync(reportPath, 'utf8'));
|
|
const { critical = 0, high = 0, medium = 0, low = 0 } = report.by_priority || {};
|
|
log(`Change report: ${critical} critical, ${high} high, ${medium} medium, ${low} low`);
|
|
|
|
// --- Step 3: If critical/high exist, spawn Claude for updates ---
|
|
if (critical + high === 0) {
|
|
log('No critical/high findings. Committing data updates only.');
|
|
|
|
try {
|
|
execSync('git add scripts/kb-update/data/', { cwd: PLUGIN_ROOT, stdio: 'pipe' });
|
|
const status = execSync('git status --porcelain scripts/kb-update/data/', { cwd: PLUGIN_ROOT, encoding: 'utf8' });
|
|
if (status.trim()) {
|
|
execSync(
|
|
'git commit -m "docs(architect): weekly KB poll — no stale files"',
|
|
{ cwd: PLUGIN_ROOT, stdio: 'pipe' }
|
|
);
|
|
execSync('git push origin main', { cwd: PLUGIN_ROOT, stdio: 'pipe' });
|
|
log('Data committed and pushed.');
|
|
} else {
|
|
log('No data changes to commit.');
|
|
}
|
|
} catch (err) {
|
|
log(`Git error: ${err.message}`);
|
|
}
|
|
|
|
log('=== Weekly KB Cron Done ===');
|
|
process.exit(0);
|
|
}
|
|
|
|
// Build list of stale files (critical + high only, max MAX_UPDATE_FILES)
|
|
const staleFiles = (report.files || [])
|
|
.filter(f => f.priority === 'critical' || f.priority === 'high' || f.priority === 'medium')
|
|
.slice(0, MAX_UPDATE_FILES);
|
|
|
|
log(`Spawning Claude to update ${staleFiles.length} stale files...`);
|
|
|
|
const fileList = staleFiles.map(f => {
|
|
const urls = (f.changed_urls || []).slice(0, 5).join('\n ');
|
|
return `- ${f.path} [${f.priority}]\n Changed URLs:\n ${urls}`;
|
|
}).join('\n');
|
|
|
|
const prompt = `Du er Cosmo Skyberg. Oppdater ${staleFiles.length} stale kunnskapsreferanser i ms-ai-architect pluginen.
|
|
|
|
Arbeidsmappe: ${PLUGIN_ROOT}
|
|
|
|
## Filer å oppdatere
|
|
|
|
${fileList}
|
|
|
|
## For HVER fil
|
|
|
|
1. Les filen med Read
|
|
2. Bruk microsoft_docs_fetch på de endrede kilde-URLene listet over
|
|
3. Bruk microsoft_docs_search for supplerende info
|
|
4. Oppdater filen med Edit:
|
|
- Oppdater "Last updated" til ${new Date().toISOString().slice(0, 7)}
|
|
- Oppdater utdaterte fakta, priser, datoer
|
|
- Bevar eksisterende struktur og seksjoner
|
|
- Marker oppdatert innhold med "Verified (MCP ${new Date().toISOString().slice(0, 7)})"
|
|
|
|
## Etter alle oppdateringer
|
|
|
|
1. Kjør: node scripts/kb-update/build-registry.mjs --merge
|
|
2. Kjør: node scripts/kb-update/report-changes.mjs
|
|
3. git add skills/ scripts/kb-update/data/
|
|
4. git commit -m "docs(architect): weekly KB update — ${staleFiles.length} files refreshed
|
|
|
|
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>"
|
|
5. git push origin main
|
|
|
|
## Regler
|
|
- Aldri slett filer, kun oppdater
|
|
- Bruk Edit, ikke Write
|
|
- Bevar all eksisterende struktur`;
|
|
|
|
try {
|
|
execFileSync(CLAUDE_BIN, [
|
|
'-p', prompt,
|
|
'--model', 'sonnet',
|
|
'--permission-mode', 'acceptEdits',
|
|
'--allowedTools', 'Read,Edit,Bash,Glob,Grep,mcp__microsoft-learn__microsoft_docs_search,mcp__microsoft-learn__microsoft_docs_fetch',
|
|
'--max-turns', '200',
|
|
], {
|
|
stdio: 'inherit',
|
|
timeout: 60 * 60 * 1000,
|
|
cwd: PLUGIN_ROOT,
|
|
});
|
|
log('Claude session completed.');
|
|
} catch (err) {
|
|
log(`Claude session error: ${err.message}`);
|
|
process.exit(1);
|
|
}
|
|
|
|
log('=== Weekly KB Cron Done ===');
|