clawdie-ai/scripts/fetch-upstream.ts

60 lines
2 KiB
TypeScript

/**
* Fetch NanoClaw upstream changes without merging.
* Safe to run on a cron — read-only git operation.
*
* Usage:
* npx tsx scripts/fetch-upstream.ts
*
* Output: prints divergence summary (commits in nanoclaw/main not in HEAD)
*
* Typical cron (weekly, run as agent user):
* 0 3 * * 1 cd /home/clawdie/clawdie-ai && npx tsx scripts/fetch-upstream.ts >> logs/upstream.log 2>&1
*/
import { formatDisplayDate } from '../src/display-date.js';
import { classificationHint } from '../src/upstream/classify.js';
import {
fetchRemote,
getUpstreamConfig,
readEnvFlag,
remoteExists,
} from '../src/upstream/git.js';
import { getUpstreamStatus } from '../src/upstream/status.js';
function main(): void {
const config = getUpstreamConfig({ repoDir: process.cwd() });
if (!readEnvFlag(config.repoDir, 'NANOCLAW_UPSTREAM_ENABLED')) {
console.log('NANOCLAW_UPSTREAM_ENABLED=false — skipping fetch');
process.exit(0);
}
if (!remoteExists(config.repoDir, config.remoteName)) {
console.error(`Remote '${config.remoteName}' not configured. Run: npx tsx setup/index.ts --step upstream --enable`);
process.exit(1);
}
const timestamp = formatDisplayDate(new Date());
console.log(`[${timestamp}] Fetching ${config.remoteName}/${config.branch}...`);
fetchRemote(config.repoDir, config.remoteName);
const status = getUpstreamStatus(config);
if (status.aheadCount === 0) {
const behindText = status.behindCount > 0
? ` (${status.behindCount} local commit(s) ahead of upstream)`
: '';
console.log(`✓ Up to date with NanoClaw upstream${behindText}`);
} else {
console.log(`! ${status.aheadCount} upstream commit(s) available:`);
for (const commit of status.commits) {
console.log(`${commit.hash.slice(0, 7)} ${commit.subject}`);
console.log(` ${commit.classification}: ${classificationHint(commit.classification)}`);
}
if (status.behindCount > 0) {
console.log(` (${status.behindCount} local commit(s) ahead of upstream)`);
}
}
}
main();