Files
upstream-atomic-crm/.claude/hooks/turn-complete.mjs
upstream-mirror 93ecc1a6f8
Some checks failed
✅ Check / 🔬 ESLint (push) Failing after 21s
✅ Check / 🏷️ Typecheck (push) Failing after 11s
✅ Check / 🔎 Test (push) Failing after 11s
✅ Check / e2e-test (push) Failing after 11s
✅ Check / 🔨 Build (push) Failing after 11s
🚀 Deploy / 🚀 Deploy (doc) (push) Failing after 12s
🚀 Deploy / 🚀 Deploy (demo) (push) Failing after 12s
🚀 Deploy / 🚀 Deploy (supabase) (push) Failing after 18s
snapshot of https://github.com/marmelab/atomic-crm.git (main, 2026-09-18; blobs > 131072B omitted)
2026-09-18 01:48:50 +05:00

35 lines
1.2 KiB
JavaScript
Executable File

#!/usr/bin/env node
// Stop: drop a per-session sentinel file so a managed launcher (e.g. CRM
// Builder's chat-service PtySession) knows the turn is complete. Stop fires after
// the JSONL transcript is fully written, so the watcher can emit its result event
// only once the transcript is flushed.
//
// The sentinel directory is a launcher extension point: config.launcher
// .turnSentinelDir (see .claude/rules/launcher-interface.md). When it is unset
// (no managed launcher), this hook is INERT: no directory is created, no path is
// hardcoded. Atomic CRM's config sets it to /tmp/pty-sentinels, preserving the
// current CRM Builder behavior.
import { closeSync, mkdirSync, openSync, readFileSync } from "node:fs";
import { join } from "node:path";
import { loadConfig, launcher } from "./lib/config.mjs";
let sid = "";
try {
sid = JSON.parse(readFileSync(0, "utf8")).session_id || "";
} catch {
// no session id -> nothing to signal
}
let dir = null;
try {
dir = launcher(loadConfig()).turnSentinelDir || null;
} catch {
dir = null; // fail-open: a config error must never break the Stop hook
}
if (sid && dir) {
mkdirSync(dir, { recursive: true });
closeSync(openSync(join(dir, `pty-turn-done-${sid}`), "w"));
}