import { buildTelemetryEventEnvelope, } from './native/telemetry-envelope.js';
export const FITNESS_TIERS = [
    'tier1_fault_injection',
    'tier2_semi_automated',
    'tier3_manual_terminal',
];
export const FITNESS_GATES = [
    'ci',
    'doctor',
    'manual',
];
export const FITNESS_OBSERVABLE_SURFACES = [
    'cli',
    'http',
    'doctor',
    'status',
    'daemon_log',
    'telemetry',
    'admin',
    'config',
];
export const FITNESS_TIER1_FAULT_INJECTION_CELLS = [
    {
        id: 'runtime.unreachable',
        tier: 'tier1_fault_injection',
        fault: 'Local runtime socket is closed or unreachable.',
        injectionPoint: 'Probe a closed localhost runtime URL.',
        observableAssertions: [
            'preflight reports missing local runtime with the target URL',
            'init model detection returns an empty list instead of throwing',
        ],
        surfaces: ['cli', 'doctor', 'status'],
        gate: 'ci',
        telemetryOrigin: 'runtime',
        directProbe: true,
        currentEvidence: [
            'tests/init-router-detect.test.ts',
            'tests/fitness-tier1-fault-injection.test.ts',
        ],
    },
    {
        id: 'runtime.upstream_502',
        tier: 'tier1_fault_injection',
        fault: 'Upstream provider returns a 5xx response.',
        injectionPoint: 'Fake provider route returns 500/502/503.',
        observableAssertions: [
            'messages endpoint returns structured provider diagnostics',
            'fallback attempts are visible in stderr/log output',
        ],
        surfaces: ['http', 'telemetry'],
        gate: 'ci',
        telemetryOrigin: 'runtime',
        directProbe: true,
        currentEvidence: [
            'tests/messages-integration.test.ts',
            'tests/middleware-integration.test.ts',
            'tests/fitness-tier1-fault-injection.test.ts',
        ],
    },
    {
        id: 'config.router_url_v1',
        tier: 'tier1_fault_injection',
        fault: 'User stores an OpenAI-style router URL ending in /v1.',
        injectionPoint: 'Load config and init probes with routerUrl ending in /v1.',
        observableAssertions: [
            'loaded config stores the bare router base',
            'model discovery probes exactly one /v1/models path',
        ],
        surfaces: ['config', 'cli'],
        gate: 'ci',
        telemetryOrigin: 'admin',
        directProbe: true,
        currentEvidence: [
            'tests/router-url-normalize.test.ts',
            'tests/init-router-detect.test.ts',
            'tests/fitness-tier1-fault-injection.test.ts',
        ],
    },
    {
        id: 'daemon.orphan',
        tier: 'tier1_fault_injection',
        fault: 'OwlCoda daemon is alive but PID metadata is missing or stale.',
        injectionPoint: 'Probe /healthz and recover daemon PID without a pid file.',
        observableAssertions: [
            'status message identifies a stale OwlCoda daemon rather than a non-OwlCoda process',
            'stop --force can recover the orphan PID from /healthz',
        ],
        surfaces: ['cli', 'status'],
        gate: 'ci',
        telemetryOrigin: 'daemon',
        directProbe: true,
        currentEvidence: [
            'tests/daemon.test.ts',
            'tests/cli-lifecycle.test.ts',
            'tests/fitness-tier1-fault-injection.test.ts',
        ],
    },
    {
        id: 'daemon.request_throw',
        tier: 'tier1_fault_injection',
        fault: 'A request handler throws synchronously.',
        injectionPoint: 'Invoke the request dispatcher with a throwing handler.',
        observableAssertions: [
            'single request receives a JSON 500 response',
            'the exception does not escape to daemon process scope',
        ],
        surfaces: ['http', 'daemon_log'],
        gate: 'ci',
        telemetryOrigin: 'daemon',
        directProbe: true,
        currentEvidence: [
            'tests/server-request-isolation.test.ts',
            'tests/fitness-tier1-fault-injection.test.ts',
        ],
    },
    {
        id: 'task.no_progress_advisory',
        tier: 'tier1_fault_injection',
        fault: 'Long read-heavy work crosses the no-progress threshold.',
        injectionPoint: 'Run a task loop with many distinct reads and no touched artifact paths.',
        observableAssertions: [
            'the task emits one advisory notice',
            'the loop does not hard-stop by default',
        ],
        surfaces: ['cli', 'telemetry'],
        gate: 'ci',
        telemetryOrigin: 'task',
        directProbe: false,
        currentEvidence: [
            'tests/native/conversation-loop-guard.test.ts',
        ],
    },
    {
        id: 'config.migration_preserves_models',
        tier: 'tier1_fault_injection',
        fault: 'Old config schema is loaded after upgrades.',
        injectionPoint: 'Load legacy config fixtures through migration.',
        observableAssertions: [
            'models are preserved and backendModel is filled',
            'existing backendModel and port are not overwritten',
        ],
        surfaces: ['config', 'cli'],
        gate: 'ci',
        telemetryOrigin: 'admin',
        directProbe: true,
        currentEvidence: [
            'tests/config-migrate.test.ts',
            'tests/config.test.ts',
            'tests/fitness-tier1-fault-injection.test.ts',
        ],
    },
];
export function listTier1FaultInjectionCells() {
    return FITNESS_TIER1_FAULT_INJECTION_CELLS;
}
/**
 * Project a fitness cell plus a probe outcome onto the shared telemetry
 * envelope. This is the envelope's first real producer: it proves the schema
 * is sufficient to describe every Tier-1 cell (see the mapping test) instead
 * of leaving the "shared spine" claim aspirational. Pure — no emit/IO here.
 */
export function buildFitnessCellTelemetry(cell, observation) {
    return buildTelemetryEventEnvelope({
        eventType: `fitness.${cell.id}`,
        surface: observation.surface ?? cell.surfaces[0] ?? 'telemetry',
        subject: observation.subject ?? cell.id,
        origin: cell.telemetryOrigin,
        severity: observation.severity ?? 'info',
        decision: observation.decision,
        reasonCode: observation.reasonCode,
        evidenceRef: observation.evidenceRef ?? cell.currentEvidence[0] ?? cell.id,
        ...(observation.observedAt !== undefined ? { observedAt: observation.observedAt } : {}),
        attributes: { tier: cell.tier, gate: cell.gate, ...(observation.attributes ?? {}) },
    });
}
//# sourceMappingURL=fitness-matrix.js.map