{"version":3,"file":"lint.mjs","names":[],"sources":["../../../src/batteries/media/lint.ts"],"sourcesContent":["/**\n * @module @nhtio/adk/batteries/media/lint\n *\n * ESLint rules for consumers of the media pipeline battery: machine-checkable enforcement of\n * the engine-composition contracts implementors are most likely to get wrong.\n *\n * @remarks\n * Battery-scoped rules ship with the battery, not with the core `@nhtio/adk/eslint` plugin —\n * they only matter to deployments that compose this battery, and they version with the\n * battery's own API. The rules are report-only (no autofix); carve out a deliberate exception\n * with an inline `// eslint-disable-next-line adk-media/{rule} -- {reason}` comment.\n *\n * `@typescript-eslint/utils` and `eslint` are OPTIONAL peer dependencies of `@nhtio/adk` —\n * installed only by consumers who lint with this plugin. The battery never imports this\n * module at runtime.\n *\n * @example Flat config\n * ```ts\n * import adkMedia from '@nhtio/adk/batteries/media/lint'\n *\n * export default [\n *   { plugins: { 'adk-media': adkMedia.plugin }, rules: adkMedia.configs.recommended.rules },\n * ]\n * ```\n */\n\nimport { createRequire } from 'node:module'\nimport { ESLintUtils } from '@typescript-eslint/utils'\nimport type { TSESTree } from '@typescript-eslint/utils'\nimport type { FlatConfig } from '@typescript-eslint/utils/ts-eslint'\n\nconst createRule = ESLintUtils.RuleCreator(\n  (name) => `https://adk.nht.io/batteries/media/lint#${name}`\n)\n\n// ── prefer-engine-resolver ───────────────────────────────────────────────────\n\nconst ENGINE_SUBPATH = /^@nhtio\\/adk\\/batteries\\/media\\/engines\\//\n\n/**\n * Flags a static value import of a bundled engine subpath. The documented canonical supply\n * form is the dynamic-import resolver, which keeps the engine wrapper module out of every\n * bundle that merely might use it. Type-only imports are fine.\n */\nconst preferEngineResolver = createRule({\n  name: 'prefer-engine-resolver',\n  meta: {\n    type: 'suggestion',\n    docs: {\n      description:\n        'Supply bundled media engines as dynamic-import resolvers, not static imports — a static import puts the engine wrapper in every bundle, even when the engine is conditional.',\n    },\n    schema: [],\n    messages: {\n      preferResolver:\n        \"Import bundled engines lazily: supply `() => import('{{source}}').then((m) => m.{{hint}}(…))` in the engines array instead of a static import. Static imports put the engine wrapper module in every bundle. Opt out with an eslint-disable-next-line adk-media/prefer-engine-resolver comment + reason.\",\n    },\n  },\n  defaultOptions: [],\n  create(context) {\n    return {\n      ImportDeclaration(node: TSESTree.ImportDeclaration) {\n        if (typeof node.source.value !== 'string') return\n        if (!ENGINE_SUBPATH.test(node.source.value)) return\n        if (node.importKind === 'type') return\n        const valueSpecifiers = node.specifiers.filter(\n          (s) => !(s.type === 'ImportSpecifier' && s.importKind === 'type')\n        )\n        if (valueSpecifiers.length === 0) return\n        const first = valueSpecifiers[0]\n        const hint =\n          first.type === 'ImportSpecifier' && first.imported.type === 'Identifier'\n            ? first.imported.name\n            : 'engineFactory'\n        context.report({\n          node,\n          messageId: 'preferResolver',\n          data: { source: node.source.value, hint },\n        })\n      },\n    }\n  },\n})\n\n// ── no-shadowed-engine ───────────────────────────────────────────────────────\n\n/** A statically-derived capability summary for one engines-array element. */\nexport interface EngineSummary {\n  /** Display label for the diagnostic. */\n  label: string\n  /** Mutate groups: input patterns, ops, encodes. */\n  mutates: Array<{ over: string[]; ops: string[]; encodes: string[] }>\n  /** Convert groups: input patterns, target tokens. */\n  converts: Array<{ from: string[]; to: string[] }>\n  /** Edit groups: input patterns, ops. */\n  edits: Array<{ over: string[]; ops: string[] }>\n}\n\nconst SHEET_OPS = [\n  'sheet.add_rows',\n  'sheet.add_columns',\n  'sheet.update_cells',\n  'sheet.delete_rows',\n  'sheet.delete_columns',\n  'sheet.rename_sheet',\n  'sheet.add_sheet',\n  'sheet.remove_sheet',\n  'sheet.reorder_sheets',\n  'sheet.transform_table',\n]\n\nconst SHEET_WRITE_TARGETS = [\n  'xlsx',\n  'xlsm',\n  'xlsb',\n  'xls',\n  'ods',\n  'fods',\n  'csv',\n  'txt',\n  'html',\n  'rtf',\n  'sylk',\n  'dif',\n  'dbf',\n  'numbers',\n  'json',\n]\n\nconst SHEET_READ_MIMES = [\n  'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',\n  'application/vnd.ms-excel.sheet.macroEnabled.12',\n  'application/vnd.ms-excel.sheet.binary.macroEnabled.12',\n  'application/vnd.ms-excel',\n  'application/vnd.oasis.opendocument.spreadsheet',\n  'application/vnd.oasis.opendocument.spreadsheet-flat-xml',\n  'text/csv',\n  'application/x-iwork-numbers-sffnumbers',\n  'application/x-sylk',\n  'application/x-dif',\n  'application/x-dbf',\n]\n\n/**\n * Known declarations of the bundled engine factories, for shadow analysis. An ESLint rule\n * cannot execute the factories it lints, so this table mirrors their declarations by hand —\n * and is pinned against the live factories by a drift test (`lint_drift.node.spec.ts`).\n * Exported for that test only.\n */\nexport const BUNDLED_SUMMARIES: Record<string, EngineSummary> = {\n  dataEngine: {\n    label: 'dataEngine',\n    mutates: [],\n    converts: [\n      { from: ['application/x-adk-empty'], to: ['txt', 'md', 'json', 'yaml', 'csv', 'html'] },\n      { from: ['application/json'], to: ['yaml', 'txt', 'csv'] },\n      { from: ['application/yaml'], to: ['json'] },\n      { from: ['text/csv'], to: ['json'] },\n    ],\n    edits: [],\n  },\n  exceljsEngine: {\n    label: 'exceljsEngine',\n    mutates: [],\n    converts: [{ from: ['application/x-adk-empty'], to: ['xlsx'] }],\n    edits: [\n      {\n        over: ['application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'],\n        ops: SHEET_OPS,\n      },\n    ],\n  },\n  jimpEngine: {\n    label: 'jimpEngine',\n    mutates: [\n      {\n        over: ['image/png', 'image/jpeg', 'image/bmp', 'image/gif', 'image/tiff'],\n        ops: ['resize', 'rotate', 'flip', 'strip_metadata'],\n        encodes: ['png', 'jpg', 'jpeg', 'bmp', 'gif', 'tiff'],\n      },\n    ],\n    converts: [\n      { from: ['application/x-adk-empty'], to: ['png', 'jpg', 'jpeg', 'bmp', 'gif', 'tiff'] },\n    ],\n    edits: [],\n  },\n  sharpEngine: {\n    label: 'sharpEngine',\n    mutates: [\n      {\n        over: ['image/*'],\n        ops: ['resize', 'rotate', 'flip', 'strip_metadata', 'annotate'],\n        encodes: ['png', 'jpg', 'jpeg', 'webp', 'tiff', 'avif', 'gif'],\n      },\n    ],\n    converts: [\n      {\n        from: ['application/x-adk-empty'],\n        to: ['png', 'jpg', 'jpeg', 'webp', 'tiff', 'avif', 'gif'],\n      },\n    ],\n    edits: [],\n  },\n  sheetjsEngine: {\n    label: 'sheetjsEngine',\n    mutates: [],\n    converts: [\n      { from: ['application/x-adk-empty'], to: SHEET_WRITE_TARGETS },\n      { from: SHEET_READ_MIMES, to: SHEET_WRITE_TARGETS },\n    ],\n    edits: [{ over: SHEET_READ_MIMES, ops: SHEET_OPS }],\n  },\n}\n\nconst literalStrings = (node: TSESTree.Node | undefined): string[] | undefined => {\n  if (!node || node.type !== 'ArrayExpression') return undefined\n  const out: string[] = []\n  for (const el of node.elements) {\n    if (!el || el.type !== 'Literal' || typeof el.value !== 'string') return undefined\n    out.push(el.value)\n  }\n  return out\n}\n\nconst propOf = (obj: TSESTree.ObjectExpression, name: string): TSESTree.Node | undefined =>\n  obj.properties.find(\n    (p): p is TSESTree.Property =>\n      p.type === 'Property' && !p.computed && p.key.type === 'Identifier' && p.key.name === name\n  )?.value\n\n/** Find the bundled factory name referenced by an element (direct call or resolver arrow). */\nconst bundledFactoryName = (node: TSESTree.Node): string | undefined => {\n  if (\n    node.type === 'CallExpression' &&\n    node.callee.type === 'Identifier' &&\n    node.callee.name in BUNDLED_SUMMARIES\n  ) {\n    return node.callee.name\n  }\n  // Resolver forms: () => …; scan the body for m.jimpEngine(…) / jimpEngine(…).\n  if (node.type === 'ArrowFunctionExpression' || node.type === 'FunctionExpression') {\n    let found: string | undefined\n    const visit = (n: TSESTree.Node): void => {\n      if (found) return\n      if (n.type === 'CallExpression') {\n        if (n.callee.type === 'Identifier' && n.callee.name in BUNDLED_SUMMARIES) {\n          found = n.callee.name\n        } else if (\n          n.callee.type === 'MemberExpression' &&\n          n.callee.property.type === 'Identifier' &&\n          n.callee.property.name in BUNDLED_SUMMARIES\n        ) {\n          found = n.callee.property.name\n        }\n      }\n      for (const key of Object.keys(n)) {\n        if (key === 'parent') continue\n        const value = (n as unknown as Record<string, unknown>)[key]\n        const children = Array.isArray(value) ? value : [value]\n        for (const child of children) {\n          if (!child || typeof child !== 'object') continue\n          const childNode = child as TSESTree.Node\n          if (typeof childNode.type !== 'string') continue\n          visit(childNode)\n        }\n      }\n    }\n    visit(node.body)\n    return found\n  }\n  return undefined\n}\n\n/** Derive a capability summary from an element, or undefined when not statically known. */\nconst summarize = (node: TSESTree.Node): EngineSummary | undefined => {\n  const factory = bundledFactoryName(node)\n  if (factory) return BUNDLED_SUMMARIES[factory]\n  if (node.type !== 'ObjectExpression') return undefined\n  const idNode = propOf(node, 'id')\n  const label =\n    idNode?.type === 'Literal' && typeof idNode.value === 'string' ? idNode.value : 'engine'\n  const summary: EngineSummary = { label, mutates: [], converts: [], edits: [] }\n  const mutates = propOf(node, 'mutates')\n  if (mutates) {\n    if (mutates.type !== 'ArrayExpression') return undefined\n    for (const el of mutates.elements) {\n      if (!el || el.type !== 'ObjectExpression') return undefined\n      const over = literalStrings(propOf(el, 'over'))\n      const ops = literalStrings(propOf(el, 'ops'))\n      const encodes = literalStrings(propOf(el, 'encodes'))\n      if (!over || !ops || !encodes) return undefined\n      summary.mutates.push({ over, ops, encodes })\n    }\n  }\n  const converts = propOf(node, 'converts')\n  if (converts) {\n    if (converts.type !== 'ArrayExpression') return undefined\n    for (const el of converts.elements) {\n      if (!el || el.type !== 'ObjectExpression') return undefined\n      const from = literalStrings(propOf(el, 'from'))\n      const to = literalStrings(propOf(el, 'to'))\n      if (!from || !to) return undefined\n      summary.converts.push({ from, to })\n    }\n  }\n  const edits = propOf(node, 'edits')\n  if (edits) {\n    if (edits.type !== 'ArrayExpression') return undefined\n    for (const el of edits.elements) {\n      if (!el || el.type !== 'ObjectExpression') return undefined\n      const over = literalStrings(propOf(el, 'over'))\n      const ops = literalStrings(propOf(el, 'ops'))\n      if (!over || !ops) return undefined\n      summary.edits.push({ over, ops })\n    }\n  }\n  if (summary.mutates.length + summary.converts.length + summary.edits.length === 0) {\n    return undefined\n  }\n  return summary\n}\n\nconst patternCovers = (broad: string, narrow: string): boolean => {\n  if (broad === narrow) return true\n  if (broad.endsWith('/*')) return narrow.startsWith(broad.slice(0, -1))\n  return false\n}\n\nconst patternsCover = (broad: string[], narrow: string[]): boolean =>\n  narrow.every((n) => broad.some((b) => patternCovers(b, n)))\n\nconst subset = (sup: string[], sub: string[]): boolean => sub.every((s) => sup.includes(s))\n\n/** `true` when EVERY capability of `later` is subsumed by some capability of `earlier`. */\nconst shadows = (earlier: EngineSummary, later: EngineSummary): boolean => {\n  if (later.mutates.length + later.converts.length + later.edits.length === 0) return false\n  const mutatesCovered = later.mutates.every((lm) =>\n    earlier.mutates.some(\n      (em) =>\n        patternsCover(em.over, lm.over) && subset(em.ops, lm.ops) && subset(em.encodes, lm.encodes)\n    )\n  )\n  const convertsCovered = later.converts.every((lc) =>\n    earlier.converts.some((ec) => patternsCover(ec.from, lc.from) && subset(ec.to, lc.to))\n  )\n  const editsCovered = later.edits.every((le) =>\n    earlier.edits.some((ee) => patternsCover(ee.over, le.over) && subset(ee.ops, le.ops))\n  )\n  return mutatesCovered && convertsCovered && editsCovered\n}\n\n/**\n * Flags an engines-array element whose statically-known capabilities are entirely covered by\n * an EARLIER element — dispatch is first-capable-wins, so the later engine is dead code.\n */\nconst noShadowedEngine = createRule({\n  name: 'no-shadowed-engine',\n  meta: {\n    type: 'problem',\n    docs: {\n      description:\n        'An engine whose declared capabilities are a subset of an earlier engine in the array can never be selected — first-capable-wins dispatch makes it dead code. Reorder (narrow before broad) or remove it.',\n    },\n    schema: [],\n    messages: {\n      shadowed:\n        'Engine \"{{later}}\" can never be selected: \"{{earlier}}\" appears earlier in the array and declares a superset of its capabilities (dispatch is first-capable-wins). Put the narrower engine first, or remove it. Opt out with an eslint-disable-next-line adk-media/no-shadowed-engine comment + reason.',\n    },\n  },\n  defaultOptions: [],\n  create(context) {\n    return {\n      CallExpression(node: TSESTree.CallExpression) {\n        if (node.callee.type !== 'Identifier' || node.callee.name !== 'createMediaPipeline') {\n          return\n        }\n        const config = node.arguments[0]\n        if (!config || config.type !== 'ObjectExpression') return\n        const engines = propOf(config, 'engines')\n        if (!engines || engines.type !== 'ArrayExpression') return\n        const summaries = engines.elements.map((el) => (el ? summarize(el) : undefined))\n        for (let i = 1; i < summaries.length; i++) {\n          const later = summaries[i]\n          if (!later) continue\n          for (let j = 0; j < i; j++) {\n            const earlier = summaries[j]\n            if (!earlier) continue\n            if (shadows(earlier, later)) {\n              context.report({\n                node: engines.elements[i]!,\n                messageId: 'shadowed',\n                data: { earlier: earlier.label, later: later.label },\n              })\n              break\n            }\n          }\n        }\n      },\n    }\n  },\n})\n\n// ── augment-contracts-module ─────────────────────────────────────────────────\n\nconst CONTRACTS_SUBPATH = '@nhtio/adk/batteries/media/contracts'\n\n/**\n * Flags a `ConvertOptions` declaration-merging block whose module specifier is not the\n * contracts subpath. Augmenting the barrel (or any other module) silently does nothing —\n * the keys never merge, and the typo costs hours.\n */\nconst augmentContractsModule = createRule({\n  name: 'augment-contracts-module',\n  meta: {\n    type: 'problem',\n    docs: {\n      description:\n        'ConvertOptions augmentation must target the contracts subpath — declaration merging against any other module specifier silently fails to merge.',\n    },\n    schema: [],\n    messages: {\n      wrongModule:\n        'This ConvertOptions augmentation targets \"{{actual}}\", so it will silently never merge. Declaration merging must target the module that declares the interface: declare module \\'{{expected}}\\'.',\n    },\n  },\n  defaultOptions: [],\n  create(context) {\n    return {\n      TSModuleDeclaration(node: TSESTree.TSModuleDeclaration) {\n        if (node.global) return\n        if (node.id.type !== 'Literal' || typeof node.id.value !== 'string') return\n        const specifier = node.id.value\n        if (specifier === CONTRACTS_SUBPATH || specifier.endsWith('/media/contracts')) return\n        // Only flag specifiers that are plausibly aimed at this battery.\n        if (!specifier.includes('media') && !specifier.includes('@nhtio/adk')) return\n        const body = node.body\n        if (!body || body.type !== 'TSModuleBlock') return\n        const declaresConvertOptions = body.body.some(\n          (stmt) => stmt.type === 'TSInterfaceDeclaration' && stmt.id.name === 'ConvertOptions'\n        )\n        if (!declaresConvertOptions) return\n        context.report({\n          node: node.id,\n          messageId: 'wrongModule',\n          data: { actual: specifier, expected: CONTRACTS_SUBPATH },\n        })\n      },\n    }\n  },\n})\n\n// ── require-engine-peers ─────────────────────────────────────────────────────\n\n/**\n * The optional peer dependencies each bundled engine subpath lazily imports at runtime.\n * Keyed by the engine's subpath suffix (after `engines/`). An engine with no external peer\n * (soffice, fs_workspace) is absent — there's nothing to install. Kept in lockstep with the\n * engines' actual `import(...)` calls by `engine_peers_drift.node.spec.ts`.\n */\nexport const ENGINE_PEERS: Record<string, readonly string[]> = {\n  jimp: ['jimp'],\n  sharp: ['sharp'],\n  sheetjs: ['xlsx'],\n  exceljs: ['exceljs'],\n  data: ['js-yaml', 'papaparse'],\n  tesseract_js: ['tesseract.js'],\n  audio_decode: ['audio-decode'],\n  transformers_asr: ['@huggingface/transformers'],\n  execa_executor: ['execa'],\n}\n\n/** Map a bundled engine subpath to its peer list, or undefined when it isn't a known engine. */\nconst peersForSubpath = (source: string): readonly string[] | undefined => {\n  const m = /^@nhtio\\/adk\\/batteries\\/media\\/engines\\/([a-z_]+)$/.exec(source)\n  if (!m) return undefined\n  return ENGINE_PEERS[m[1]]\n}\n\n/**\n * Flags an import of a bundled engine subpath whose optional peer dependency cannot be\n * resolved from the linting file — the \"I composed `sheetjsEngine()` but never installed\n * `xlsx`, and now my pipeline throws `E_INVALID_MEDIA_PIPELINE_CONFIG` at the first sheet\n * op\" footgun, caught at lint time instead of runtime. Resolution uses Node's resolver from\n * the file's own directory, so it honors the consumer's real `node_modules` layout.\n *\n * Reports once per missing peer per engine import (whether the import is a static value\n * import or a dynamic-import resolver — both reference the engine and both need the peer).\n */\n/**\n * The peer-resolution probe: returns `true` when `peer` resolves from `fromFile`. Defaults to\n * Node's resolver anchored at the linted file (so it sees the consumer's `node_modules`).\n * Exposed as a settable seam so the rule's spec can simulate installed/missing peers without\n * depending on the test runner's own `node_modules` layout — production never sets it.\n */\nexport type PeerResolver = (peer: string, fromFile: string) => boolean\n\nconst defaultPeerResolver: PeerResolver = (peer, fromFile) => {\n  try {\n    createRequire(fromFile).resolve(peer)\n    return true\n  } catch {\n    return false\n  }\n}\n\nlet activePeerResolver: PeerResolver = defaultPeerResolver\n\n/** Override the peer resolver (spec-only seam). Pass nothing to restore the Node default. */\nexport const setPeerResolverForTesting = (resolver?: PeerResolver): void => {\n  activePeerResolver = resolver ?? defaultPeerResolver\n}\n\nconst requireEnginePeers = createRule<[{ ignore?: readonly string[] }], 'missingPeer'>({\n  name: 'require-engine-peers',\n  meta: {\n    type: 'problem',\n    docs: {\n      description:\n        \"A bundled media engine's optional peer dependency must be installed where it's composed — otherwise the pipeline throws at first use, not at construction.\",\n    },\n    schema: [\n      {\n        type: 'object',\n        properties: {\n          ignore: {\n            type: 'array',\n            items: { type: 'string' },\n            description:\n              'Peer package names to skip (e.g. one resolved via a custom loader the linter cannot see).',\n          },\n        },\n        additionalProperties: false,\n      },\n    ],\n    messages: {\n      missingPeer:\n        'The \"{{engine}}\" media engine requires the optional peer \"{{peer}}\", which cannot be resolved from this file. Install it ({{install}}) or the pipeline will throw E_INVALID_MEDIA_PIPELINE_CONFIG the first time this engine runs. Opt out with an eslint-disable-next-line adk-media/require-engine-peers comment + reason.',\n    },\n  },\n  defaultOptions: [{ ignore: [] }],\n  create(context, [options]) {\n    const ignore = new Set(options?.ignore ?? [])\n\n    /** SheetJS ships only from its CDN tarball, so the install hint must not say the registry. */\n    const installHint = (peer: string): string =>\n      peer === 'xlsx'\n        ? 'pnpm add xlsx@https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz'\n        : `pnpm add ${peer}`\n\n    const checkSource = (source: string, reportNode: TSESTree.Node): void => {\n      const peers = peersForSubpath(source)\n      if (!peers) return\n      const engine = source.slice(source.lastIndexOf('/') + 1)\n      for (const peer of peers) {\n        if (ignore.has(peer)) continue\n        if (!activePeerResolver(peer, context.filename)) {\n          context.report({\n            node: reportNode,\n            messageId: 'missingPeer',\n            data: { engine, peer, install: installHint(peer) },\n          })\n        }\n      }\n    }\n\n    return {\n      // Static value/type import of an engine subpath.\n      ImportDeclaration(node: TSESTree.ImportDeclaration) {\n        if (typeof node.source.value === 'string') checkSource(node.source.value, node.source)\n      },\n      // The canonical resolver form: import('@nhtio/adk/batteries/media/engines/…').\n      ImportExpression(node: TSESTree.ImportExpression) {\n        if (node.source.type === 'Literal' && typeof node.source.value === 'string') {\n          checkSource(node.source.value, node.source)\n        }\n      },\n    }\n  },\n})\n\n// ── plugin assembly ──────────────────────────────────────────────────────────\n\n/**\n * Map of rule id (without the `adk-media/` plugin prefix) to its rule object. Registered on\n * the plugin as `rules`, so configs reference them as `adk-media/{id}`.\n */\nexport const rules = {\n  'prefer-engine-resolver': preferEngineResolver,\n  'no-shadowed-engine': noShadowedEngine,\n  'augment-contracts-module': augmentContractsModule,\n  'require-engine-peers': requireEnginePeers,\n} satisfies FlatConfig.Plugin['rules']\n\n/**\n * The media battery's ESLint plugin object. Register under the `adk-media` namespace:\n * `plugins: { 'adk-media': plugin }`.\n */\nexport const plugin: FlatConfig.Plugin = {\n  meta: { name: '@nhtio/adk/batteries/media/lint', version: __VERSION__ },\n  rules,\n}\n\nconst recommendedRules: NonNullable<FlatConfig.Config['rules']> = Object.fromEntries(\n  Object.keys(rules).map((id) => [`adk-media/${id}`, 'error'])\n)\n\n/**\n * Named config presets. `recommended` enables every rule at `error` and registers the plugin\n * under the `adk-media` namespace — spread it into a flat config to adopt the full set.\n */\nexport const configs = {\n  recommended: {\n    name: '@nhtio/adk/batteries/media/lint/recommended',\n    plugins: { 'adk-media': plugin },\n    rules: recommendedRules,\n  } satisfies FlatConfig.Config,\n}\n\n/**\n * Default export bundles the plugin and its config presets, mirroring the shape ESLint flat\n * configs expect from a plugin module.\n */\nexport default { plugin, rules, configs }\n"],"mappings":"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"}