65 lines
2.4 KiB
JavaScript
65 lines
2.4 KiB
JavaScript
#!/usr/bin/env node
|
|
|
|
// write-org-profile.mjs
|
|
// Purpose: atomically write the OKR org profile to the reinstall-surviving
|
|
// home path (~/.claude/okr/org/profil.md). On ANY write failure
|
|
// (EACCES/EROFS/ENOSPC/pathguard-block) it circuit-breaks to the
|
|
// project-local, gitignored .claude/okr.local.md so internal org state never
|
|
// reaches a public mirror. Never exits non-zero -- the calling command must
|
|
// not be blocked. Reads the full profile content from stdin (fd 0).
|
|
// Zero npm dependencies (node: builtins only). ASCII-clean identifiers.
|
|
//
|
|
// Mirrors the canonical home path defined in
|
|
// hooks/scripts/inject-okr-context.mjs:14 (the most-specific-wins read side).
|
|
|
|
import { readFileSync, writeFileSync, mkdirSync, renameSync } from 'node:fs';
|
|
import { join, dirname } from 'node:path';
|
|
import { homedir } from 'node:os';
|
|
|
|
// Read the entire profile content from stdin. Under execFileSync (both Claude
|
|
// Code's command call and the tests) the child's stdin is a closed pipe, so
|
|
// EOF arrives immediately -- no hang.
|
|
let content = '';
|
|
try {
|
|
content = readFileSync(0, 'utf8');
|
|
} catch {
|
|
content = '';
|
|
}
|
|
|
|
const homeTarget = join(homedir(), '.claude', 'okr', 'org', 'profil.md');
|
|
|
|
// Atomic write: temp file in the SAME directory, then renameSync over the
|
|
// target. rename is atomic on the same filesystem -- a crash mid-write can
|
|
// never leave a half-written profil.md.
|
|
function writeAtomic(target, data) {
|
|
const dir = dirname(target);
|
|
mkdirSync(dir, { recursive: true });
|
|
const tmp = join(dir, `profil.md.${process.pid}.tmp`);
|
|
writeFileSync(tmp, data);
|
|
renameSync(tmp, target);
|
|
}
|
|
|
|
try {
|
|
writeAtomic(homeTarget, content);
|
|
process.stdout.write(homeTarget);
|
|
process.exit(0);
|
|
} catch (err) {
|
|
// Circuit-breaker: the home write failed. Fall back to the project-local,
|
|
// gitignored config so org state stays off any public mirror. The cycle /
|
|
// historikk tree remains cwd-bound regardless; only the profile migrates.
|
|
const fallback = join(process.cwd(), '.claude', 'okr.local.md');
|
|
try {
|
|
writeAtomic(fallback, content);
|
|
process.stderr.write(
|
|
`notice: kunne ikke skrive hjem-profil (${err.code || err.message}); ` +
|
|
`falt tilbake til prosjektlokal ${fallback}\n`,
|
|
);
|
|
process.stdout.write(fallback);
|
|
} catch (err2) {
|
|
process.stderr.write(
|
|
`notice: kunne ikke skrive verken hjem-profil eller prosjektlokal fallback ` +
|
|
`(${err2.code || err2.message})\n`,
|
|
);
|
|
}
|
|
process.exit(0);
|
|
}
|