fix(ai-file): verify ES index topology instead of creating indexes
ensure_indexes() created a concrete index whenever HEAD returned 404, with a payload carrying mappings but no settings. If a knowledge job ran before the infrastructure created the rollover alias, the application claimed the alias name as a concrete index — permanently blocking the ILM rollover setup and leaving the index on the cluster default of one primary shard.
Add agent_knowledge_es_managed_externally (false on local, true on dev/stg/prod). When set, the client never writes to ES and instead verifies the topology with read-only APIs: the chunk name must be a write alias with exactly one write index, and the attachment name must be a concrete index — a multi-index alias would break _mget and GET _doc and take down knowledge search.
Verification runs at three points: ensure_indexes() (replacing the create path), search() entry, and knowledge pod startup. Startup failures only log ERROR so a transient ES outage cannot crash-loop the pod; jobs and search stay blocked until the topology is valid. Only successes are memoized per process, so recovery needs no restart.
Also extract create_es_client(cfg) out of AgentKnowledgeService so the startup check can build a client without a DB session.
Co-Authored-By: Claude Opus 5 (1M context) noreply@anthropic.com