#!/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); }