# Gemini Fix Prompt — String Union Refactor Recovery (Final)

You are a senior TypeScript systems engineer helping to fix the fallout from the failed enum → string union refactor in the **OS Self-Reflection Layer** (POINTER = OS-AWARENESS-PHASE-003).

---

## 🚨 Current Situation
The previous change replaced enums with string unions (e.g. `SignalType = 'WINDOW_CHURN' | ...`), which broke all references like `SignalType.WINDOW_CHURN` and `PolicyName.THROTTLE_WINDOWS` across both `lib/reflection` and `tests/reflection`.

Error example:
```
TypeError: Cannot read properties of undefined (reading 'WINDOW_CHURN')
```
Root cause: `SignalType` is now a type, not an object, so `SignalType.WINDOW_CHURN` is undefined.

---

## 🎯 Objective
Perform a full recovery and stabilization refactor to restore all tests and functionality **without reverting back to enums**.
You must replace every enum-style reference with a constant-based solution (`SIGNALS.WINDOW_CHURN`) or string literals.

---

## 🧩 Step-by-Step Fix Plan

### 1️⃣ Update `lib/reflection/types.ts`
Replace enums with **constant objects + string union types**:

```ts
// lib/reflection/types.ts

// --- SIGNALS ---
export const SIGNALS = {
  WINDOW_CHURN: 'WINDOW_CHURN',
  FOCUS_STABILITY: 'FOCUS_STABILITY',
  LATENCY_SUMMARY: 'LATENCY_SUMMARY',
  IDLE_RATIO: 'IDLE_RATIO',
  WINDOW_LIFETIME: 'WINDOW_LIFETIME',
} as const;

export type SignalType = typeof SIGNALS[keyof typeof SIGNALS];

// --- POLICY NAMES ---
export const POLICY_NAMES = {
  THROTTLE_WINDOWS: 'THROTTLE_WINDOWS',
  DEFER_ANIMATIONS: 'DEFER_ANIMATIONS',
  ADJUST_PREFETCH: 'ADJUST_PREFETCH',
  TUNE_FOCUS_TIMEOUT: 'TUNE_FOCUS_TIMEOUT',
} as const;

export type PolicyName = typeof POLICY_NAMES[keyof typeof POLICY_NAMES];

export type EvalStatus = 'NORMAL' | 'WARNING' | 'CRITICAL';

export interface IntrospectionSignal {
  type: SignalType;
  value: number;
  timestamp: number;
  metadata?: Record<string, any>;
}

export interface EvaluationResult {
  signal: IntrospectionSignal;
  status: EvalStatus;
  slo: { threshold: number; status: EvalStatus } | null;
  timestamp: number;
}

export interface FeedbackDecision {
  ts: number;
  cause: EvaluationResult[];
  action:
    | 'THROTTLE_WINDOWS'
    | 'DEFER_ANIM'
    | 'ADJUST_PREFETCH'
    | 'TUNE_FOCUS_TIMEOUT'
    | 'NOOP';
  params?: Record<string, any>;
  mode: 'PROPOSED' | 'DRY_RUN' | 'APPLIED';
}
```

---

### 2️⃣ Project-wide Find & Replace
Replace enum-style references in all reflection source and test files.

#### Replace:
- `SignalType.WINDOW_CHURN` → `SIGNALS.WINDOW_CHURN`
- `PolicyName.THROTTLE_WINDOWS` → `'THROTTLE_WINDOWS'`

Example command (Linux/macOS):
```bash
# Replace SignalType references
rg -l "SignalType\.[A-Z_]+" lib tests | xargs sed -i -E "s/SignalType\.([A-Z_]+)/SIGNALS.\1/g"
# Replace PolicyName references
rg -l "PolicyName\.[A-Z_]+" lib tests | xargs sed -i -E "s/PolicyName\.([A-Z_]+)/POLICY_NAMES.\1/g"
```

If `ripgrep` isn’t available, use `grep -rl` instead.

---

### 3️⃣ Update `feedback.ts`
Ensure the rules map uses string keys, not enums.

```ts
import { SIGNALS, type SignalType, type EvaluationResult, type FeedbackDecision } from './types';
import { applyPolicyChange } from './policy';

type FeedbackRule = { action: FeedbackDecision['action']; threshold: 'CRITICAL' | 'WARNING' | 'NORMAL' };

const FEEDBACK_RULES: Record<SignalType, FeedbackRule> = {
  [SIGNALS.WINDOW_CHURN]: { action: 'THROTTLE_WINDOWS', threshold: 'CRITICAL' },
  [SIGNALS.LATENCY_SUMMARY]: { action: 'DEFER_ANIM', threshold: 'CRITICAL' },
  [SIGNALS.FOCUS_STABILITY]: { action: 'TUNE_FOCUS_TIMEOUT', threshold: 'CRITICAL' },
  [SIGNALS.IDLE_RATIO]: { action: 'ADJUST_PREFETCH', threshold: 'CRITICAL' },
  [SIGNALS.WINDOW_LIFETIME]: { action: 'NOOP', threshold: 'NORMAL' },
};

export function makeDecision(evals: EvaluationResult[]): FeedbackDecision[] {
  const now = performance.now();
  const out: FeedbackDecision[] = [];

  for (const e of evals) {
    const t = e.signal.type;
    const rule = FEEDBACK_RULES[t];
    if (!rule || e.status !== rule.threshold) continue;
    out.push({ ts: now, cause: [e], action: rule.action, mode: 'PROPOSED' });
  }
  return out;
}

let lastApplied = 0;
const COOLDOWN_MS = 5000;

export function applyDecisions(decisions: FeedbackDecision[], dryRun = true) {
  const now = performance.now();
  if (now - lastApplied < COOLDOWN_MS) {
    console.warn('[Reflection/Feedback] Cooldown active, decision deferred.');
    return;
  }
  lastApplied = now;
  for (const d of decisions) {
    if (dryRun) continue;
    applyPolicyChange(d);
  }
}

export function _resetFeedbackForTests() {
  lastApplied = 0;
}
```

---

### 4️⃣ Fix Tests
- Import the new constants:
```ts
import { SIGNALS, POLICY_NAMES } from '@/lib/reflection/types';
```
- Update usage:
```ts
signal: { type: SIGNALS.WINDOW_CHURN, value: 5, timestamp: 0 }
expect(getPolicyValue('THROTTLE_WINDOWS')).toBe(500);
```

- Fix timer mocking:
```ts
beforeEach(() => vi.useFakeTimers());
afterEach(() => vi.useRealTimers());
```

---

### 5️⃣ Verify Import Aliases
Ensure `vite.config.ts` includes:
```ts
import path from 'path';
export default defineConfig({
  resolve: {
    alias: { '@': path.resolve(__dirname, './') },
  },
});
```

Or switch to relative paths in test imports if needed.

---

### 6️⃣ Final Test Run
Run:
```bash
pnpm test:run
```

Expected summary:
```
✓ 39 passed (0 failed)
Coverage: Statements 65%, Branches 58%, Functions 60%, Lines 64%
```

---

### ✅ Deliverables
- Updated `types.ts`, `feedback.ts`, and all source/tests to use `SIGNALS` and `POLICY_NAMES` constants.
- No remaining enum references.
- All Vitest suites pass successfully.
- Cooldown, DRY_RUN, and policy application confirmed working.

Focus on **consistency, safety, and complete test recovery**.
