Files
nanoclaw/scripts/upgrade-state.ts
T
gavrielc e734e5cddd feat(upgrade): startup tripwire + upgrade marker
Refuse to start unless this install reached the current version through a
sanctioned path (setup / update / migrate). A raw `git pull` that skips
migrations now fails loudly with a self-healing message instead of
silently breaking.

- src/upgrade-state.ts: marker at data/upgrade-state.json, getCodeVersion,
  isUpgradeCurrent, enforceUpgradeTripwire (fails closed on missing /
  corrupt / mismatched marker)
- src/index.ts: gate wired in at startup step 0.5, before DB init
- scripts/upgrade-state.ts: get/set CLI (also the override / recovery cmd)
- setup/service.ts, /update-nanoclaw, /migrate-nanoclaw: stamp on success;
  update/migrate also self-update their own skill first
- CHANGELOG [BREAKING] entry bridges existing installs via the skills'
  breaking-change check
- docs/upgrade-recovery.md: clearing the tripwire

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 13:02:12 +03:00

27 lines
1.0 KiB
TypeScript

/**
* scripts/upgrade-state.ts — read or stamp the upgrade marker.
*
* Usage:
* pnpm exec tsx scripts/upgrade-state.ts get
* pnpm exec tsx scripts/upgrade-state.ts set [version] [via]
*
* `set` with no version stamps the current package.json version. The
* sanctioned upgrade paths (setup / update / migrate) call `set` on
* success; running it by hand is also the documented way to clear the
* startup tripwire — see docs/upgrade-recovery.md.
*/
import { getCodeVersion, markerPath, readUpgradeState, writeUpgradeState } from '../src/upgrade-state.js';
const [, , cmd, versionArg, viaArg] = process.argv;
if (cmd === 'get') {
const state = readUpgradeState();
console.log(state ? JSON.stringify(state) : 'none');
} else if (cmd === 'set') {
const state = writeUpgradeState({ version: versionArg || getCodeVersion(), via: viaArg || 'manual' });
console.log(`Stamped ${markerPath()}: ${JSON.stringify(state)}`);
} else {
console.error('Usage: pnpm exec tsx scripts/upgrade-state.ts get | set [version] [via]');
process.exit(2);
}