/**
 * telemetry.ts — Local time-to-value (TTV) tracker.
 *
 * Records first-occurrence timestamps for key product milestones and emits
 * structured events on nexusEventBus + appends to ~/.nexus-prime/events.jsonl.
 * All data stays local — nothing leaves the machine.
 */
import { promises as fsPromises } from 'fs';
import * as path from 'path';
import { nexusEventBus } from './event-bus.js';
import { resolveNexusStateDir } from './runtime-registry.js';
let _state = null;
let _eventsFilePath = null;
function getState() {
    if (!_state) {
        _state = {
            daemonStartAt: Date.now(),
            firstBootstrapAt: null,
            firstMemoryAt: null,
            firstInteractionAt: null,
            firstMissionCompleteAt: null,
        };
    }
    return _state;
}
function eventsFile() {
    if (!_eventsFilePath) {
        _eventsFilePath = path.join(resolveNexusStateDir(), 'events.jsonl');
    }
    return _eventsFilePath;
}
async function emitTTV(name, durationMs) {
    nexusEventBus.emit(name, { durationMs, at: Date.now() });
    try {
        const line = JSON.stringify({ type: name, durationMs, at: Date.now() }) + '\n';
        await fsPromises.appendFile(eventsFile(), line, 'utf8');
    }
    catch { /* non-fatal — disk write failure must not break the caller */ }
}
/** Reset the epoch (call at daemon/MCP process startup). */
export function recordDaemonStart() {
    getState().daemonStartAt = Date.now();
}
/** Call at the end of the first successful nexus_session_bootstrap. */
export async function recordFirstBootstrap() {
    const s = getState();
    if (s.firstBootstrapAt !== null)
        return;
    s.firstBootstrapAt = Date.now();
    await emitTTV('feature.time_to_first_bootstrap', s.firstBootstrapAt - s.daemonStartAt);
}
/** Call when the first memory is stored in this process lifetime. */
export async function recordFirstMemory() {
    const s = getState();
    if (s.firstMemoryAt !== null)
        return;
    s.firstMemoryAt = Date.now();
    await emitTTV('feature.time_to_first_memory', s.firstMemoryAt - s.daemonStartAt);
}
/** Call on any user-initiated dashboard action (goal submit, hire click). */
export async function recordFirstInteraction() {
    const s = getState();
    if (s.firstInteractionAt !== null)
        return;
    s.firstInteractionAt = Date.now();
    await emitTTV('feature.time_to_first_interaction', s.firstInteractionAt - s.daemonStartAt);
}
/** Call when the first operative sortie completes. */
export async function recordFirstMissionComplete() {
    const s = getState();
    if (s.firstMissionCompleteAt !== null)
        return;
    s.firstMissionCompleteAt = Date.now();
    await emitTTV('feature.time_to_first_mission_complete', s.firstMissionCompleteAt - s.daemonStartAt);
}
/** Returns current TTV snapshot for diagnostics (nexus_doctor). */
export function getTTVSnapshot() {
    return { ...getState() };
}
