(function (root, factory) {
  "use strict";

  const api = Object.freeze(factory());
  if (typeof module === "object" && module.exports) module.exports = api;
  if (root) root.MbnOperatorCatalogWorkflow = api;
})(typeof globalThis === "object" ? globalThis : this, function () {
  "use strict";

  const MAXIMUM_THEME_ITEMS = 240;
  const MAXIMUM_RECOMMENDATIONS = 100;
  const MAXIMUM_RESULTS = 500;
  const MAXIMUM_QUERY_LENGTH = 64;
  const MAXIMUM_WEB_SAFE_INTEGER = Number.MAX_SAFE_INTEGER;
  const requestIdPattern = /^[A-Za-z0-9_-]{1,128}$/;
  const newThemeCodePattern = /^[0-9]{8}$/;
  const existingThemeCodePattern = /^[0-9]{3,8}$/;
  const expertCodePattern = /^[0-9]{4}$/;
  const stockCodePattern = /^[A-Za-z0-9]{1,32}$/;
  const stockMarkets = Object.freeze(["kospi", "kosdaq", "nxt-kospi", "nxt-kosdaq"]);
  const uuidPattern = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
  const unsafeTextPattern = /[\p{Cc}\p{Cf}\p{Cs}\p{Zl}\p{Zp}\uFFFD]/u;

  const bridgeContract = Object.freeze({
    requests: Object.freeze({
      themeList: "request-theme-catalog-list",
      expertList: "request-expert-catalog-list",
      schemaPreflight: "request-operator-catalog-schema",
      themeNextCode: "request-theme-catalog-next-code",
      expertNextCode: "request-expert-catalog-next-code",
      themeCreate: "create-theme-catalog",
      themeReplace: "replace-theme-catalog",
      themeDelete: "delete-theme-catalog",
      expertCreate: "create-expert-catalog",
      expertReplace: "replace-expert-catalog",
      expertDelete: "delete-expert-catalog"
    }),
    events: Object.freeze({
      themeList: "theme-catalog-list-results",
      expertList: "expert-catalog-list-results",
      schemaPreflight: "operator-catalog-schema-results",
      themeNextCode: "theme-catalog-next-code-results",
      expertNextCode: "expert-catalog-next-code-results",
      mutation: "operator-catalog-mutation-results",
      error: "operator-catalog-error"
    })
  });

  const stockMasterContract = Object.freeze({
    request: "search-stocks",
    result: "stock-search-results",
    error: "stock-search-error"
  });

  function hasExactKeys(value, keys) {
    if (!value || typeof value !== "object" || Array.isArray(value)) return false;
    const actual = Object.keys(value).sort();
    const expected = [...keys].sort();
    return actual.length === expected.length &&
      actual.every((key, index) => key === expected[index]);
  }

  function hasOnlyKeys(value, keys) {
    return value && typeof value === "object" && !Array.isArray(value) &&
      Object.keys(value).every(key => keys.includes(key));
  }

  function isSafeCanonicalText(value, maximumLength, allowEmpty = false) {
    return typeof value === "string" &&
      (allowEmpty ? value.length >= 0 : value.length > 0) &&
      value.length <= maximumLength && value === value.trim() &&
      !unsafeTextPattern.test(value);
  }

  function requireRequestId(value) {
    if (typeof value !== "string" || !requestIdPattern.test(value)) {
      throw new TypeError("A safe operator-catalog request id is required.");
    }
    return value;
  }

  function normalizeQuery(value) {
    if (typeof value !== "string" || unsafeTextPattern.test(value)) return null;
    const query = value.trim();
    return query.length <= MAXIMUM_QUERY_LENGTH && !unsafeTextPattern.test(query)
      ? query
      : null;
  }

  function normalizeMarket(value) {
    return value === "krx" || value === "nxt" ? value : null;
  }

  function normalizeSession(value, market) {
    if (market === "krx") return value === "notApplicable" ? value : null;
    if (market === "nxt") {
      return value === "preMarket" || value === "afterMarket" ? value : null;
    }
    return null;
  }

  function normalizeThemeIdentity(value) {
    if (!hasExactKeys(value, ["market", "session", "themeCode", "themeTitle"])) return null;
    const market = normalizeMarket(value.market);
    if (!market || !normalizeSession(value.session, market) ||
        !existingThemeCodePattern.test(value.themeCode) ||
        !isSafeCanonicalText(value.themeTitle, 128) ||
        (market === "nxt" && /\(NXT\)/i.test(value.themeTitle))) return null;
    return Object.freeze({
      market,
      session: value.session,
      themeCode: value.themeCode,
      themeTitle: value.themeTitle
    });
  }

  function normalizeThemeItem(value, expectedIndex, market) {
    if (!hasExactKeys(value, ["inputIndex", "itemCode", "itemName"]) ||
        value.inputIndex !== expectedIndex || !Number.isInteger(value.inputIndex) ||
        !isSafeCanonicalText(value.itemCode, 13) ||
        !isSafeCanonicalText(value.itemName, 200)) return null;
    const prefix = value.itemCode[0];
    const suffix = value.itemCode.slice(1);
    if (!/^[A-Za-z0-9]{1,12}$/.test(suffix) ||
        (market === "krx" && prefix !== "P" && prefix !== "D") ||
        (market === "nxt" && prefix !== "X" && prefix !== "T")) return null;
    return Object.freeze({
      inputIndex: value.inputIndex,
      itemCode: value.itemCode,
      itemName: value.itemName
    });
  }

  function normalizeThemeItems(value, market) {
    if (!Array.isArray(value) || value.length > MAXIMUM_THEME_ITEMS) return null;
    const items = [];
    const codes = new Set();
    const names = new Set();
    for (let index = 0; index < value.length; index += 1) {
      const item = normalizeThemeItem(value[index], index, market);
      if (!item || codes.has(item.itemCode) || names.has(item.itemName)) return null;
      codes.add(item.itemCode);
      names.add(item.itemName);
      items.push(item);
    }
    return Object.freeze(items);
  }

  function normalizeThemeDraft(value) {
    if (!hasExactKeys(value, ["market", "themeCode", "themeTitle", "items"])) return null;
    const market = normalizeMarket(value.market);
    if (!market || !existingThemeCodePattern.test(value.themeCode) ||
        !isSafeCanonicalText(value.themeTitle, 128) ||
        (market === "nxt" && /\(NXT\)/i.test(value.themeTitle))) return null;
    const items = normalizeThemeItems(value.items, market);
    return items && Object.freeze({
      market,
      themeCode: value.themeCode,
      themeTitle: value.themeTitle,
      items
    });
  }

  function normalizeExpertIdentity(value) {
    if (!hasExactKeys(value, ["expertCode", "expertName"]) ||
        !expertCodePattern.test(value.expertCode) ||
        !isSafeCanonicalText(value.expertName, 128)) return null;
    return Object.freeze({
      expertCode: value.expertCode,
      expertName: value.expertName
    });
  }

  function normalizeRecommendation(value, expectedIndex) {
    if (!hasExactKeys(value, ["playIndex", "stockCode", "stockName", "buyAmount"]) ||
        value.playIndex !== expectedIndex || !Number.isInteger(value.playIndex) ||
        !stockCodePattern.test(value.stockCode) ||
        !isSafeCanonicalText(value.stockName, 200) ||
        !Number.isSafeInteger(value.buyAmount) || value.buyAmount <= 0 ||
        value.buyAmount > MAXIMUM_WEB_SAFE_INTEGER) return null;
    return Object.freeze({
      playIndex: value.playIndex,
      stockCode: value.stockCode,
      stockName: value.stockName,
      buyAmount: value.buyAmount
    });
  }

  function normalizeRecommendations(value) {
    if (!Array.isArray(value) || value.length > MAXIMUM_RECOMMENDATIONS) return null;
    const items = [];
    const codes = new Set();
    const names = new Set();
    for (let index = 0; index < value.length; index += 1) {
      const item = normalizeRecommendation(value[index], index);
      if (!item || codes.has(item.stockCode) || names.has(item.stockName)) return null;
      codes.add(item.stockCode);
      names.add(item.stockName);
      items.push(item);
    }
    return Object.freeze(items);
  }

  function normalizeExpertDraft(value) {
    if (!hasExactKeys(value, ["expertCode", "expertName", "recommendations"])) return null;
    const identity = normalizeExpertIdentity({
      expertCode: value.expertCode,
      expertName: value.expertName
    });
    const recommendations = normalizeRecommendations(value.recommendations);
    return identity && recommendations && Object.freeze({
      expertCode: identity.expertCode,
      expertName: identity.expertName,
      recommendations
    });
  }

  function createThemeCatalogListRequest(requestId, query = "", nxtSession = "preMarket", maximumResults) {
    requireRequestId(requestId);
    const normalizedQuery = normalizeQuery(query);
    if (normalizedQuery === null) throw new TypeError("A safe theme catalog query is required.");
    if (nxtSession !== "preMarket" && nxtSession !== "afterMarket") {
      throw new TypeError("An explicit NXT catalog session is required.");
    }
    if (maximumResults !== undefined &&
        (!Number.isInteger(maximumResults) || maximumResults < 1 || maximumResults > MAXIMUM_RESULTS)) {
      throw new RangeError("Theme catalog results must be limited from 1 through 500.");
    }
    const request = { requestId, query: normalizedQuery, nxtSession };
    if (maximumResults !== undefined) request.maximumResults = maximumResults;
    return Object.freeze(request);
  }

  function createExpertCatalogListRequest(requestId, query = "", maximumResults) {
    requireRequestId(requestId);
    const normalizedQuery = normalizeQuery(query);
    if (normalizedQuery === null) throw new TypeError("A safe expert catalog query is required.");
    if (maximumResults !== undefined &&
        (!Number.isInteger(maximumResults) || maximumResults < 1 || maximumResults > MAXIMUM_RESULTS)) {
      throw new RangeError("Expert catalog results must be limited from 1 through 500.");
    }
    const request = { requestId, query: normalizedQuery };
    if (maximumResults !== undefined) request.maximumResults = maximumResults;
    return Object.freeze(request);
  }

  function createSchemaPreflightRequest(requestId) {
    return Object.freeze({ requestId: requireRequestId(requestId) });
  }

  function createThemeNextCodeRequest(requestId, market) {
    requireRequestId(requestId);
    if (!normalizeMarket(market)) throw new TypeError("A KRX or NXT market is required.");
    return Object.freeze({ requestId, market });
  }

  function createExpertNextCodeRequest(requestId) {
    return Object.freeze({ requestId: requireRequestId(requestId) });
  }

  function createStockMasterSearchRequest(requestId, query, maximumResults = MAXIMUM_RESULTS) {
    requireRequestId(requestId);
    const normalizedQuery = normalizeQuery(query);
    if (!normalizedQuery) throw new TypeError("A non-empty stock-master search query is required.");
    if (!Number.isInteger(maximumResults) || maximumResults < 1 ||
        maximumResults > MAXIMUM_RESULTS) {
      throw new RangeError("Stock-master results must be limited from 1 through 500.");
    }
    return Object.freeze({ requestId, query: normalizedQuery, maximumResults });
  }

  function normalizeStockMasterIdentity(value) {
    if (!hasExactKeys(value, ["market", "source", "name", "code"]) ||
        !stockMarkets.includes(value.market) || !stockCodePattern.test(value.code) ||
        !isSafeCanonicalText(value.name, 200)) return null;
    const expectedSource = value.market === "kospi" || value.market === "kosdaq"
      ? "oracle"
      : "mariaDb";
    if (value.source !== expectedSource) return null;
    return Object.freeze({
      market: value.market,
      source: value.source,
      name: value.name,
      code: value.code
    });
  }

  function normalizeStockMasterSearchResult(value, expectedRequest) {
    if (!hasExactKeys(value, [
      "requestId", "query", "retrievedAt", "totalRowCount", "truncated", "results"
    ]) || !expectedRequest || value.requestId !== expectedRequest.requestId ||
        value.query !== expectedRequest.query || !requestIdPattern.test(value.requestId) ||
        normalizeQuery(value.query) !== value.query ||
        !isSafeCanonicalText(value.retrievedAt, 64) ||
        !Number.isFinite(Date.parse(value.retrievedAt)) ||
        !Number.isInteger(value.totalRowCount) || value.totalRowCount < 0 ||
        value.truncated !== false || !Array.isArray(value.results) ||
        value.results.length !== value.totalRowCount ||
        value.results.length > expectedRequest.maximumResults) return null;

    const results = [];
    const identities = new Set();
    const names = new Set();
    for (const raw of value.results) {
      const item = normalizeStockMasterIdentity(raw);
      const identity = item && `${item.market}\u0000${item.source}\u0000${item.code}\u0000${item.name}`;
      if (!item || identities.has(identity) || names.has(item.name)) return null;
      identities.add(identity);
      names.add(item.name);
      results.push(item);
    }
    return Object.freeze({
      requestId: value.requestId,
      query: value.query,
      retrievedAt: value.retrievedAt,
      totalRowCount: value.totalRowCount,
      truncated: false,
      results: Object.freeze(results)
    });
  }

  function normalizeStockMasterSearchError(value, expectedRequest) {
    if (!hasExactKeys(value, ["requestId", "query", "message"]) || !expectedRequest ||
        value.requestId !== expectedRequest.requestId || value.query !== expectedRequest.query ||
        !requestIdPattern.test(value.requestId) || normalizeQuery(value.query) !== value.query ||
        !isSafeCanonicalText(value.message, 512)) return null;
    return Object.freeze({ ...value });
  }

  function normalizeThemeCatalogSelection(value) {
    if (!hasExactKeys(value, ["market", "session", "themeCode", "themeTitle", "source"])) return null;
    const identity = normalizeThemeIdentity({
      market: value.market,
      session: value.session,
      themeCode: value.themeCode,
      themeTitle: value.themeTitle
    });
    if (!identity ||
        (identity.market === "krx" && value.source !== "oracle") ||
        (identity.market === "nxt" && value.source !== "mariaDb")) return null;
    return Object.freeze({ ...identity, source: value.source });
  }

  function normalizeExpertCatalogSelection(value) {
    if (!hasExactKeys(value, ["expertCode", "expertName", "source"]) || value.source !== "oracle") {
      return null;
    }
    const identity = normalizeExpertIdentity({
      expertCode: value.expertCode,
      expertName: value.expertName
    });
    return identity && Object.freeze({ ...identity, source: "oracle" });
  }

  function normalizeThemePreviewForEdit(value, selection) {
    if (!hasExactKeys(value, [
      "requestId", "selection", "retrievedAt", "totalRowCount", "truncated", "items"
    ]) || !requestIdPattern.test(value.requestId) ||
        !isSafeCanonicalText(value.retrievedAt, 64) || !Number.isFinite(Date.parse(value.retrievedAt)) ||
        !Number.isInteger(value.totalRowCount) || value.totalRowCount < 0 ||
        value.totalRowCount > MAXIMUM_THEME_ITEMS || value.truncated !== false ||
        !hasExactKeys(value.selection, ["market", "session", "themeCode", "title"])) return null;
    const previewIdentity = normalizeThemeIdentity({
      market: value.selection.market,
      session: value.selection.session,
      themeCode: value.selection.themeCode,
      themeTitle: value.selection.title
    });
    if (!previewIdentity || ["market", "session", "themeCode", "themeTitle"]
      .some(key => previewIdentity[key] !== selection[key])) return null;
    if (!Array.isArray(value.items) || value.items.length !== value.totalRowCount) return null;
    const items = [];
    const codes = new Set();
    const names = new Set();
    let previousIndex = -1;
    for (const raw of value.items) {
      if (!hasExactKeys(raw, ["inputIndex", "itemCode", "itemName"]) ||
          !Number.isInteger(raw.inputIndex) || raw.inputIndex <= previousIndex || raw.inputIndex > 9999 ||
          !isSafeCanonicalText(raw.itemCode, 13) || !isSafeCanonicalText(raw.itemName, 200)) return null;
      const prefix = raw.itemCode[0];
      const suffix = raw.itemCode.slice(1);
      if (!/^[A-Za-z0-9]{1,12}$/.test(suffix) ||
          (selection.market === "krx" && prefix !== "P" && prefix !== "D") ||
          (selection.market === "nxt" && prefix !== "X" && prefix !== "T") ||
          codes.has(raw.itemCode) || names.has(raw.itemName)) return null;
      previousIndex = raw.inputIndex;
      codes.add(raw.itemCode);
      names.add(raw.itemName);
      items.push(Object.freeze({
        inputIndex: items.length,
        itemCode: raw.itemCode,
        itemName: raw.itemName
      }));
    }
    return Object.freeze(items);
  }

  function normalizeExpertPreviewForEdit(value, selection) {
    if (!hasExactKeys(value, [
      "requestId", "selection", "retrievedAt", "totalRowCount", "truncated", "items"
    ]) || !requestIdPattern.test(value.requestId) ||
        !isSafeCanonicalText(value.retrievedAt, 64) || !Number.isFinite(Date.parse(value.retrievedAt)) ||
        !Number.isInteger(value.totalRowCount) || value.totalRowCount < 0 ||
        value.totalRowCount > MAXIMUM_RECOMMENDATIONS || value.truncated !== false) return null;
    const previewIdentity = normalizeExpertIdentity(value.selection);
    if (!previewIdentity || previewIdentity.expertCode !== selection.expertCode ||
        previewIdentity.expertName !== selection.expertName) return null;
    if (!Array.isArray(value.items) || value.items.length !== value.totalRowCount) return null;
    const items = [];
    const codes = new Set();
    const names = new Set();
    let previousIndex = -1;
    for (const raw of value.items) {
      if (!hasExactKeys(raw, ["playIndex", "stockCode", "stockName", "buyAmount"]) ||
          !Number.isInteger(raw.playIndex) || raw.playIndex <= previousIndex || raw.playIndex > 9999 ||
          !stockCodePattern.test(raw.stockCode) || !isSafeCanonicalText(raw.stockName, 200) ||
          !Number.isSafeInteger(raw.buyAmount) || raw.buyAmount <= 0 ||
          codes.has(raw.stockCode) || names.has(raw.stockName)) return null;
      previousIndex = raw.playIndex;
      codes.add(raw.stockCode);
      names.add(raw.stockName);
      items.push(Object.freeze({
        playIndex: items.length,
        stockCode: raw.stockCode,
        stockName: raw.stockName,
        buyAmount: raw.buyAmount
      }));
    }
    return Object.freeze(items);
  }

  function createThemeEditDraft(selectionValue, previewValue) {
    const selection = normalizeThemeCatalogSelection(selectionValue);
    if (!selection) throw new TypeError("A typed theme catalog selection is required.");
    const items = normalizeThemePreviewForEdit(previewValue, selection);
    if (!items) throw new TypeError("A complete, correlated theme preview is required for editing.");
    return {
      expectedIdentity: {
        market: selection.market,
        session: selection.session,
        themeCode: selection.themeCode,
        themeTitle: selection.themeTitle
      },
      draft: {
        market: selection.market,
        themeCode: selection.themeCode,
        themeTitle: selection.themeTitle,
        items: items.map(item => ({ ...item }))
      }
    };
  }

  function createExpertEditDraft(selectionValue, previewValue) {
    const selection = normalizeExpertCatalogSelection(selectionValue);
    if (!selection) throw new TypeError("A typed expert catalog selection is required.");
    const recommendations = normalizeExpertPreviewForEdit(previewValue, selection);
    if (!recommendations) throw new TypeError("A complete, correlated expert preview is required for editing.");
    return {
      expectedIdentity: {
        expertCode: selection.expertCode,
        expertName: selection.expertName
      },
      draft: {
        expertCode: selection.expertCode,
        expertName: selection.expertName,
        recommendations: recommendations.map(item => ({ ...item }))
      }
    };
  }

  function createBlankThemeDraft(market, themeCode) {
    if (!normalizeMarket(market) || !newThemeCodePattern.test(themeCode)) {
      throw new TypeError("A typed market and suggested eight-digit theme code are required.");
    }
    return { market, themeCode, themeTitle: "", items: [] };
  }

  function createBlankExpertDraft(expertCode) {
    if (!expertCodePattern.test(expertCode)) {
      throw new TypeError("A suggested four-digit expert code is required.");
    }
    return { expertCode, expertName: "", recommendations: [] };
  }

  function cloneThemeDraft(draft) {
    const normalized = normalizeThemeDraft(draft);
    return normalized && {
      market: normalized.market,
      themeCode: normalized.themeCode,
      themeTitle: normalized.themeTitle,
      items: normalized.items.map(item => ({ ...item }))
    };
  }

  function cloneExpertDraft(draft) {
    const normalized = normalizeExpertDraft(draft);
    return normalized && {
      expertCode: normalized.expertCode,
      expertName: normalized.expertName,
      recommendations: normalized.recommendations.map(item => ({ ...item }))
    };
  }

  function createThemeCreateRequest(requestId, draftValue) {
    requireRequestId(requestId);
    const draft = cloneThemeDraft(draftValue);
    if (!draft || !newThemeCodePattern.test(draft.themeCode)) {
      throw new TypeError("A complete theme draft with a new eight-digit code is required.");
    }
    return Object.freeze({ requestId, draft });
  }

  function createThemeReplaceRequest(requestId, editValue) {
    requireRequestId(requestId);
    if (!hasExactKeys(editValue, ["expectedIdentity", "draft"])) {
      throw new TypeError("An explicit theme edit identity and draft are required.");
    }
    const identity = normalizeThemeIdentity(editValue.expectedIdentity);
    const draft = cloneThemeDraft(editValue.draft);
    if (!identity || !draft || identity.market !== draft.market ||
        identity.themeCode !== draft.themeCode) {
      throw new TypeError("The theme edit identity does not match its draft.");
    }
    return Object.freeze({
      requestId,
      expectedIdentity: { ...identity },
      newTitle: draft.themeTitle,
      items: draft.items
    });
  }

  function createThemeDeleteRequest(requestId, identityValue) {
    requireRequestId(requestId);
    const identity = normalizeThemeIdentity(identityValue);
    if (!identity) throw new TypeError("An explicit theme identity is required.");
    return Object.freeze({ requestId, identity: { ...identity } });
  }

  function createExpertCreateRequest(requestId, draftValue) {
    requireRequestId(requestId);
    const draft = cloneExpertDraft(draftValue);
    if (!draft) throw new TypeError("A complete expert draft is required.");
    return Object.freeze({ requestId, draft });
  }

  function createExpertReplaceRequest(requestId, editValue) {
    requireRequestId(requestId);
    if (!hasExactKeys(editValue, ["expectedIdentity", "draft"])) {
      throw new TypeError("An explicit expert edit identity and draft are required.");
    }
    const identity = normalizeExpertIdentity(editValue.expectedIdentity);
    const draft = cloneExpertDraft(editValue.draft);
    if (!identity || !draft || identity.expertCode !== draft.expertCode) {
      throw new TypeError("The expert edit identity does not match its draft.");
    }
    return Object.freeze({
      requestId,
      expectedIdentity: { ...identity },
      newName: draft.expertName,
      recommendations: draft.recommendations
    });
  }

  function createExpertDeleteRequest(requestId, identityValue) {
    requireRequestId(requestId);
    const identity = normalizeExpertIdentity(identityValue);
    if (!identity) throw new TypeError("An explicit expert identity is required.");
    return Object.freeze({ requestId, identity: { ...identity } });
  }

  function normalizeThemeListResult(value, expectedRequest) {
    if (!hasExactKeys(value, [
      "requestId", "query", "nxtSession", "retrievedAt", "totalRowCount", "truncated",
      "canMutate", "writeQuarantined", "results"
    ]) || !requestIdPattern.test(value.requestId) || normalizeQuery(value.query) !== value.query ||
        (value.nxtSession !== "preMarket" && value.nxtSession !== "afterMarket") ||
        !isSafeCanonicalText(value.retrievedAt, 64) || !Number.isFinite(Date.parse(value.retrievedAt)) ||
        !Number.isInteger(value.totalRowCount) || value.totalRowCount < 0 ||
        value.totalRowCount > MAXIMUM_RESULTS || typeof value.truncated !== "boolean" ||
        typeof value.canMutate !== "boolean" || typeof value.writeQuarantined !== "boolean" ||
        (value.writeQuarantined && value.canMutate) || !Array.isArray(value.results) ||
        value.results.length !== value.totalRowCount) return null;
    if (expectedRequest && (value.requestId !== expectedRequest.requestId ||
        value.query !== expectedRequest.query || value.nxtSession !== expectedRequest.nxtSession ||
        value.results.length > (expectedRequest.maximumResults ?? 100))) return null;
    const results = [];
    const identities = new Set();
    const titles = new Set();
    for (const raw of value.results) {
      const item = normalizeThemeCatalogSelection(raw);
      const key = item && `${item.market}:${item.themeCode}`;
      const titleKey = item && `${item.market}:${item.themeTitle}`;
      if (!item || identities.has(key) || titles.has(titleKey)) return null;
      identities.add(key);
      titles.add(titleKey);
      results.push(item);
    }
    return Object.freeze({ ...value, results: Object.freeze(results) });
  }

  function normalizeExpertListResult(value, expectedRequest) {
    if (!hasExactKeys(value, [
      "requestId", "query", "retrievedAt", "totalRowCount", "truncated", "canMutate",
      "writeQuarantined", "results"
    ]) || !requestIdPattern.test(value.requestId) || normalizeQuery(value.query) !== value.query ||
        !isSafeCanonicalText(value.retrievedAt, 64) || !Number.isFinite(Date.parse(value.retrievedAt)) ||
        !Number.isInteger(value.totalRowCount) || value.totalRowCount < 0 ||
        value.totalRowCount > MAXIMUM_RESULTS || typeof value.truncated !== "boolean" ||
        typeof value.canMutate !== "boolean" || typeof value.writeQuarantined !== "boolean" ||
        (value.writeQuarantined && value.canMutate) || !Array.isArray(value.results) ||
        value.results.length !== value.totalRowCount) return null;
    if (expectedRequest && (value.requestId !== expectedRequest.requestId ||
        value.query !== expectedRequest.query ||
        value.results.length > (expectedRequest.maximumResults ?? 100))) return null;
    const results = [];
    const codes = new Set();
    const names = new Set();
    for (const raw of value.results) {
      const item = normalizeExpertCatalogSelection(raw);
      if (!item || codes.has(item.expertCode) || names.has(item.expertName)) return null;
      codes.add(item.expertCode);
      names.add(item.expertName);
      results.push(item);
    }
    return Object.freeze({ ...value, results: Object.freeze(results) });
  }

  function normalizeThemeNextCodeResult(value, expectedRequest) {
    if (!hasExactKeys(value, [
      "requestId", "market", "themeCode", "canMutate", "writeQuarantined"
    ]) || !requestIdPattern.test(value.requestId) || !normalizeMarket(value.market) ||
        !newThemeCodePattern.test(value.themeCode) || typeof value.canMutate !== "boolean" ||
        typeof value.writeQuarantined !== "boolean" ||
        (value.writeQuarantined && value.canMutate)) return null;
    if (expectedRequest && (value.requestId !== expectedRequest.requestId ||
        value.market !== expectedRequest.market)) return null;
    return Object.freeze({ ...value });
  }

  function normalizeExpertNextCodeResult(value, expectedRequest) {
    if (!hasExactKeys(value, [
      "requestId", "expertCode", "canMutate", "writeQuarantined"
    ]) || !requestIdPattern.test(value.requestId) || !expertCodePattern.test(value.expertCode) ||
        typeof value.canMutate !== "boolean" || typeof value.writeQuarantined !== "boolean" ||
        (value.writeQuarantined && value.canMutate)) return null;
    if (expectedRequest && value.requestId !== expectedRequest.requestId) return null;
    return Object.freeze({ ...value });
  }

  function normalizeSchemaResult(value, expectedRequest) {
    if (!hasExactKeys(value, [
      "requestId", "validatedAt", "validatedSources", "themeCanMutate", "expertCanMutate",
      "writeQuarantined"
    ]) || !requestIdPattern.test(value.requestId) ||
        !isSafeCanonicalText(value.validatedAt, 64) || !Number.isFinite(Date.parse(value.validatedAt)) ||
        !Array.isArray(value.validatedSources) || value.validatedSources.length !== 2 ||
        value.validatedSources[0] !== "oracle" || value.validatedSources[1] !== "mariaDb" ||
        typeof value.themeCanMutate !== "boolean" || typeof value.expertCanMutate !== "boolean" ||
        typeof value.writeQuarantined !== "boolean" ||
        (value.writeQuarantined && (value.themeCanMutate || value.expertCanMutate))) return null;
    if (expectedRequest && value.requestId !== expectedRequest.requestId) return null;
    return Object.freeze({ ...value, validatedSources: Object.freeze([...value.validatedSources]) });
  }

  const mutationOperations = new Set(["create", "replace", "delete"]);
  function normalizeMutationResult(value, expected) {
    if (!hasExactKeys(value, [
      "requestId", "entity", "operation", "identityCode", "operationId", "committedAt",
      "writeQuarantined"
    ]) || !requestIdPattern.test(value.requestId) ||
        (value.entity !== "theme" && value.entity !== "expert") ||
        !mutationOperations.has(value.operation) ||
        !(value.entity === "theme" ? existingThemeCodePattern : expertCodePattern)
          .test(value.identityCode) ||
        !uuidPattern.test(value.operationId) || !isSafeCanonicalText(value.committedAt, 64) ||
        !Number.isFinite(Date.parse(value.committedAt)) || value.writeQuarantined !== false) return null;
    if (expected && ["requestId", "entity", "operation", "identityCode"]
      .some(key => value[key] !== expected[key])) return null;
    return Object.freeze({ ...value });
  }

  const errorCodes = new Set([
    "INVALID_REQUEST", "DATABASE_UNAVAILABLE", "INVALID_DATA", "INVALID_SCHEMA", "DATABASE_ERROR",
    "PLAYOUT_PRIORITY", "PLAYOUT_ACTIVE", "DATABASE_BUSY", "WRITE_BUSY", "CONFLICT", "WRITE_FAILED",
    "CANCELLED", "OUTCOME_UNKNOWN"
  ]);
  function normalizeCatalogError(value, expected) {
    if (!hasExactKeys(value, [
      "requestId", "entity", "operation", "identityCode", "code", "message", "retryable",
      "outcomeUnknown", "writeQuarantined"
    ]) || (value.requestId !== "" && !requestIdPattern.test(value.requestId)) ||
        !["theme", "expert", "catalog"].includes(value.entity) ||
        !["list", "nextCode", "create", "replace", "delete", "schemaPreflight"].includes(value.operation) ||
        typeof value.identityCode !== "string" || value.identityCode.length > 8 ||
        !errorCodes.has(value.code) || !isSafeCanonicalText(value.message, 512) ||
        typeof value.retryable !== "boolean" || typeof value.outcomeUnknown !== "boolean" ||
        typeof value.writeQuarantined !== "boolean" ||
        (value.outcomeUnknown && (value.retryable || !value.writeQuarantined)) ||
        (mutationOperations.has(value.operation) && value.retryable)) return null;
    if (expected && ["requestId", "entity", "operation", "identityCode"]
      .some(key => value[key] !== expected[key])) return null;
    return Object.freeze({ ...value });
  }

  function describeMutationRequest(type, payload) {
    try {
      switch (type) {
        case bridgeContract.requests.themeCreate: {
          const request = createThemeCreateRequest(payload?.requestId, payload?.draft);
          return Object.freeze({ requestId: request.requestId, entity: "theme", operation: "create",
            identityCode: request.draft.themeCode });
        }
        case bridgeContract.requests.themeReplace: {
          if (!hasExactKeys(payload, ["requestId", "expectedIdentity", "newTitle", "items"])) return null;
          const request = createThemeReplaceRequest(payload.requestId, {
            expectedIdentity: payload.expectedIdentity,
            draft: {
              market: payload.expectedIdentity?.market,
              themeCode: payload.expectedIdentity?.themeCode,
              themeTitle: payload.newTitle,
              items: payload.items
            }
          });
          return Object.freeze({ requestId: request.requestId, entity: "theme", operation: "replace",
            identityCode: request.expectedIdentity.themeCode });
        }
        case bridgeContract.requests.themeDelete: {
          if (!hasExactKeys(payload, ["requestId", "identity"])) return null;
          const request = createThemeDeleteRequest(payload.requestId, payload.identity);
          return Object.freeze({ requestId: request.requestId, entity: "theme", operation: "delete",
            identityCode: request.identity.themeCode });
        }
        case bridgeContract.requests.expertCreate: {
          const request = createExpertCreateRequest(payload?.requestId, payload?.draft);
          return Object.freeze({ requestId: request.requestId, entity: "expert", operation: "create",
            identityCode: request.draft.expertCode });
        }
        case bridgeContract.requests.expertReplace: {
          if (!hasExactKeys(payload, ["requestId", "expectedIdentity", "newName", "recommendations"])) return null;
          const request = createExpertReplaceRequest(payload.requestId, {
            expectedIdentity: payload.expectedIdentity,
            draft: {
              expertCode: payload.expectedIdentity?.expertCode,
              expertName: payload.newName,
              recommendations: payload.recommendations
            }
          });
          return Object.freeze({ requestId: request.requestId, entity: "expert", operation: "replace",
            identityCode: request.expectedIdentity.expertCode });
        }
        case bridgeContract.requests.expertDelete: {
          if (!hasExactKeys(payload, ["requestId", "identity"])) return null;
          const request = createExpertDeleteRequest(payload.requestId, payload.identity);
          return Object.freeze({ requestId: request.requestId, entity: "expert", operation: "delete",
            identityCode: request.identity.expertCode });
        }
        default:
          return null;
      }
    } catch {
      return null;
    }
  }

  function createMutationCoordinator() {
    let active = null;
    let quarantined = false;
    return Object.freeze({
      begin(type, payload) {
        if (quarantined) throw new Error("Operator catalog writes are quarantined for this process.");
        if (active) throw new Error("Another operator catalog write is already active.");
        const description = describeMutationRequest(type, payload);
        if (!description) throw new TypeError("A valid operator catalog mutation request is required.");
        active = description;
        return description;
      },
      acceptResult(payload) {
        if (!active) return null;
        const result = normalizeMutationResult(payload, active);
        if (!result) return null;
        active = null;
        return result;
      },
      acceptError(payload) {
        if (!active) return null;
        const error = normalizeCatalogError(payload, active);
        if (!error) return null;
        if (error.outcomeUnknown || error.writeQuarantined) quarantined = true;
        active = null;
        return error;
      },
      loseCorrelation() {
        if (active) quarantined = true;
        active = null;
      },
      getState() {
        return Object.freeze({ active, quarantined });
      }
    });
  }

  return {
    bridgeContract,
    stockMasterContract,
    limits: Object.freeze({
      maximumThemeItems: MAXIMUM_THEME_ITEMS,
      maximumRecommendations: MAXIMUM_RECOMMENDATIONS,
      maximumResults: MAXIMUM_RESULTS,
      maximumQueryLength: MAXIMUM_QUERY_LENGTH
    }),
    normalizeThemeIdentity,
    normalizeThemeDraft,
    normalizeExpertIdentity,
    normalizeExpertDraft,
    createThemeCatalogListRequest,
    createExpertCatalogListRequest,
    createSchemaPreflightRequest,
    createThemeNextCodeRequest,
    createExpertNextCodeRequest,
    createStockMasterSearchRequest,
    normalizeStockMasterIdentity,
    normalizeStockMasterSearchResult,
    normalizeStockMasterSearchError,
    normalizeThemeCatalogSelection,
    normalizeExpertCatalogSelection,
    createThemeEditDraft,
    createExpertEditDraft,
    createBlankThemeDraft,
    createBlankExpertDraft,
    createThemeCreateRequest,
    createThemeReplaceRequest,
    createThemeDeleteRequest,
    createExpertCreateRequest,
    createExpertReplaceRequest,
    createExpertDeleteRequest,
    normalizeThemeListResult,
    normalizeExpertListResult,
    normalizeThemeNextCodeResult,
    normalizeExpertNextCodeResult,
    normalizeSchemaResult,
    normalizeMutationResult,
    normalizeCatalogError,
    describeMutationRequest,
    createMutationCoordinator
  };
});
