export const GOOSE_CANARY_MEMORY_POLICY = Object.freeze({ MEMORY_BACKEND: 'legacy', MEMORY_VECTOR_ENABLED: '0', MEMORY_AGENT_RESOLVE_ENABLED: '0', MEMORY_AGENT_INJECTION_MODE: 'off', MEMORY_LIFECYCLE_ENABLED: '0', MEMORY_LIFECYCLE_WORKER_ENABLED: '0', MEMORY_LIFECYCLE_ROLLOUT_MODE: 'off', MEMORY_CANDIDATE_ENABLED: '0', MEMORY_PROMOTION_ENABLED: '0', MEMORY_COMPACTION_V2_ENABLED: '0', MEMORY_REFLECTION_ENABLED: '0', }); export function applyGooseCanaryMemoryPolicy(effectiveEnv, processEnv) { const mode = String(processEnv.TKMIND_GOOSE_CANARY ?? 'off').trim().toLowerCase(); if (mode === 'off' || mode === '') return { ...effectiveEnv }; if (!['all', 'users'].includes(mode)) throw new Error(`Invalid Goose canary mode: ${mode}`); const target = new URL(processEnv.TKMIND_API_TARGET_V149 ?? 'https://127.0.0.1:18049'); if (!['http:', 'https:'].includes(target.protocol) || !['127.0.0.1', 'localhost', '[::1]'].includes(target.hostname)) { throw new Error('Goose canary memory policy requires a loopback runtime'); } return { ...effectiveEnv, ...GOOSE_CANARY_MEMORY_POLICY }; } function gooseCanaryMemoryStatusViolations(memory) { if (!memory) return ['memory status unavailable']; const violations = []; if (memory.backend !== 'legacy') violations.push(`backend=${memory.backend}`); if (memory.selectedBackend !== 'legacy-conversation-memory') { violations.push(`selectedBackend=${memory.selectedBackend}`); } if (memory.vectorEnabled !== false) violations.push('vectorEnabled=true'); if (memory.runtimeControl?.agentInjectionMode !== 'off') { violations.push(`agentInjectionMode=${memory.runtimeControl?.agentInjectionMode}`); } if (memory.runtimeControl?.agentResolveEnabled !== false) violations.push('agentResolveEnabled=true'); if (memory.runtimeControl?.lifecycleWorkerEnabled !== false) { violations.push('lifecycleWorkerEnabled=true'); } if (memory.runtimeControl?.lifecycleRolloutMode !== 'off') { violations.push(`lifecycleRolloutMode=${memory.runtimeControl?.lifecycleRolloutMode}`); } if (memory.runtimeControl?.promotionEnabled !== false) violations.push('promotionEnabled=true'); if (memory.runtimeControl?.compactionV2Enabled !== false) violations.push('compactionV2Enabled=true'); if (memory.runtimeControl?.reflectionEnabled !== false) violations.push('reflectionEnabled=true'); if (memory.personalMemory?.enabled === true) violations.push('personalMemory.enabled=true'); return violations; } export function assertGooseCanaryMemoryStatus(memory) { const violations = gooseCanaryMemoryStatusViolations(memory); if (violations.length) { throw new Error( `Goose canary requires legacy memory with vector/candidate/lifecycle/injection off; ` + `actual ${violations.join(', ')}, source=${memory?.configSource ?? 'unknown'}`, ); } } /** Portal smoke: admin-db may override local canary memory env; warn instead of blocking routing checks. */ export function assertGooseCanaryMemoryStatusForPortalSmoke(memory) { const violations = gooseCanaryMemoryStatusViolations(memory); if (!violations.length) return; if (memory?.configSource === 'admin-db') { console.log( `GOOSE_V149_PORTAL_SMOKE_WARN: memory ${violations.join(', ')} from admin-db; ` + 'goose canary routing verified (admin-db overrides local canary memory env)', ); return; } assertGooseCanaryMemoryStatus(memory); }