function createIndexedDbTransaction(indexedDB, dbName = 'stackchain-background-outbox-v1') {
  let databasePromise;
  function database() {
    if (!databasePromise) databasePromise = new Promise((resolve, reject) => {
      const request = indexedDB.open(dbName, 1);
      request.onupgradeneeded = () => {
        if (!request.result.objectStoreNames.contains('issues')) {
          request.result.createObjectStore('issues', { keyPath: 'id' });
        }
      };
      request.onsuccess = () => {
        const db = request.result;
        db.onversionchange = () => {
          db.close();
          databasePromise = undefined;
        };
        resolve(db);
      };
      request.onerror = () => reject(request.error);
    });
    return databasePromise;
  }
  const requested = request => new Promise((resolve, reject) => {
    request.onsuccess = () => resolve(request.result);
    request.onerror = () => reject(request.error);
  });
  const transact = async work => {
    const db = await database();
    return new Promise((resolve, reject) => {
      const transaction = db.transaction('issues', 'readwrite');
      const objectStore = transaction.objectStore('issues');
      let result;
      let failed = false;
      transaction.oncomplete = () => failed ? undefined : resolve(result);
      transaction.onerror = () => reject(transaction.error);
      transaction.onabort = () => reject(transaction.error || new Error('Issue outbox transaction aborted'));
      Promise.resolve(work({
        get: id => requested(objectStore.get(id)),
        getAll: () => requested(objectStore.getAll()),
        put: value => requested(objectStore.put(value)),
        delete: id => requested(objectStore.delete(id)),
      })).then(value => { result = value; }).catch(error => {
        failed = true;
        try { transaction.abort(); } catch (_abortError) { reject(error); }
        reject(error);
      });
    });
  };
  transact.close = async () => {
    if (!databasePromise) return;
    const db = await databasePromise;
    db.close();
    databasePromise = undefined;
  };
  return transact;
}

function createUnfiledAttachmentStore(indexedDB = globalThis.indexedDB) {
  const transact = createIndexedDbTransaction(indexedDB, 'stackchain-unfiled-captures-v1');
  return {
    put: (id, value) => transact(records => records.put({id, ...value})),
    get: id => transact(async records => {
      const value = await records.get(id);
      if (!value) return null;
      const {id: _id, ...attachment} = value;
      return attachment;
    }),
    delete: id => transact(records => records.delete(id)),
  };
}

function createIssueSyncStore({
  transaction, indexedDB = globalThis.indexedDB, now = () => Date.now(), claimMs = 30000,
  createToken = () => globalThis.crypto?.randomUUID?.() ||
    (Date.now().toString(36) + '-' + Math.random().toString(36).slice(2)),
} = {}) {
  const transact = transaction || createIndexedDbTransaction(indexedDB);

  async function reconcile(items, outboxLane = 'issue') {
    return transact(async records => {
      const existing = await records.getAll();
      const incoming = new Map(items.map(item => [item.id, { ...item, outboxLane }]));
      for (const current of existing) {
        if (current.recordType === 'receipt-preference') continue;
        const currentLane = current.outboxLane || 'issue';
        if (currentLane !== outboxLane) continue;
        let replacement = incoming.get(current.id);
        if (!replacement) {
          if (current.status !== 'sending' || Number(current.claimUntil) <= Number(now())) {
            await records.delete(current.id);
          }
          continue;
        }
        const preservedBundle = current.operationId === replacement.operationId &&
          current.attachments?.every(value => value?.data || value?.blob) &&
          replacement.attachments?.every(value => value?.stored && !value.data && !value.blob)
          ? current.attachments : null;
        if (current.operationId === replacement.operationId &&
            (current.attachment?.data || current.attachment?.blob) &&
            replacement.attachment?.stored &&
            !replacement.attachment.data && !replacement.attachment.blob || preservedBundle) {
          replacement = {
            ...replacement,
            ...(preservedBundle ? {attachments:preservedBundle} : {attachment:current.attachment}),
          };
          incoming.set(current.id, replacement);
        }
        if (current.kind === 'issue-content' && replacement.kind === 'issue-content' &&
            current.operationId !== replacement.operationId && current.status === 'sending' &&
            Number(current.claimUntil) > Number(now())) {
          throw new Error('Checklist sync is already delivering. Retry this change.');
        }
        if ((current.status === 'sending' && Number(current.claimUntil) > Number(now())) ||
            (['attention', 'authorization'].includes(current.status) &&
              replacement.status === current.status) ||
            current.status === 'sent') {
          incoming.set(current.id, current);
        }
      }
      for (const item of incoming.values()) await records.put(item);
    });
  }

  async function claimNext(ownerLogin) {
    return transact(async records => {
      const timestamp = Number(now());
      const items = await records.getAll();
      const item = items.find(candidate => candidate.ownerLogin === ownerLogin &&
        candidate.kind !== 'issue-close' &&
        (candidate.status === 'queued' || candidate.status === 'sending') &&
        (candidate.status !== 'sending' || Number(candidate.claimUntil) <= timestamp));
      if (!item) return null;
      const claimed = {
        ...item, status: 'sending', claimUntil: timestamp + claimMs, claimToken: createToken(),
      };
      await records.put(claimed);
      return claimed;
    });
  }

  async function planBatch(ownerLogin, limit = 70) {
    return transact(async records => {
      const timestamp = Number(now());
      const eligible = (await records.getAll()).filter(candidate =>
        candidate.recordType !== 'receipt-preference' &&
        candidate.ownerLogin === ownerLogin &&
        candidate.kind !== 'issue-close' &&
        (candidate.status === 'queued' || candidate.status === 'sending') &&
        (candidate.status !== 'sending' || Number(candidate.claimUntil) <= timestamp));
      const lanes = {
        issue: eligible.filter(item => (item.outboxLane || 'issue') !== 'authored'),
        authored: eligible.filter(item => item.outboxLane === 'authored'),
      };
      const selected = [];
      const maximum = Math.max(0, Number(limit) || 0);
      while (selected.length < maximum && (lanes.issue.length || lanes.authored.length)) {
        if (lanes.issue.length) selected.push(lanes.issue.shift().id);
        if (selected.length < maximum && lanes.authored.length) selected.push(lanes.authored.shift().id);
      }
      return selected;
    });
  }

  async function claim(id, ownerLogin) {
    return transact(async records => {
      const timestamp = Number(now());
      const item = (await records.getAll()).find(candidate => candidate.id === id);
      if (!item || item.ownerLogin !== ownerLogin ||
          !['queued', 'sending'].includes(item.status) ||
          (item.status === 'sending' && Number(item.claimUntil) > timestamp)) return null;
      const claimed = {
        ...item, status: 'sending', claimUntil: timestamp + claimMs, claimToken: createToken(),
      };
      await records.put(claimed);
      return claimed;
    });
  }

  async function upsert(item) {
    return transact(async records => {
      const current = (await records.getAll()).find(candidate => candidate.id === item.id);
      if (current && ((current.status === 'sending' && Number(current.claimUntil) > Number(now())) ||
          (['attention', 'authorization'].includes(current.status) &&
            item.status === current.status) ||
          current.status === 'sent')) return current;
      const preservedAttachment = (current?.attachment?.data || current?.attachment?.blob) &&
        item?.attachment?.stored && !item.attachment.data && !item.attachment.blob
        ? { attachment: current.attachment } : {};
      const preservedAttachments = current?.operationId === item?.operationId &&
        current?.attachments?.every(value => value?.data || value?.blob) &&
        item?.attachments?.every(value => value?.stored && !value.data && !value.blob)
        ? { attachments:current.attachments } : {};
      const next = current && current.operationId === item.operationId ? {
        ...item, ...preservedAttachment, ...preservedAttachments,
        ...(current.deliveredIssue ? { deliveredIssue: current.deliveredIssue } : {}),
        ...(current.attachmentMarkdown ? { attachmentMarkdown: current.attachmentMarkdown } : {}),
        ...(current.attachmentMarkdowns ? { attachmentMarkdowns:current.attachmentMarkdowns } : {}),
      } : { ...item };
      await records.put(next);
      return next;
    });
  }

  async function update(id, transform) {
    return transact(async records => {
      const item = (await records.getAll()).find(candidate => candidate.id === id);
      if (item) await records.put(transform(item));
    });
  }

  async function updateClaim(id, claimToken, transform) {
    return transact(async records => {
      const item = records.get ? await records.get(id) :
        (await records.getAll()).find(candidate => candidate.id === id);
      if (!item || item.status !== 'sending' || !claimToken || item.claimToken !== claimToken) {
        return false;
      }
      await records.put(transform(item));
      return true;
    });
  }

  function clearClaim(item, changes) {
    const { claimToken: _claimToken, ...unclaimed } = item;
    return { ...unclaimed, ...changes, claimUntil: 0 };
  }

  async function renew(id, claimToken) {
    let renewed = null;
    await updateClaim(id, claimToken, item => {
      renewed = { ...item, claimUntil: Number(now()) + claimMs };
      return renewed;
    });
    return renewed;
  }

  function preferenceId(ownerLogin) {
    return 'receipt-preference:' + String(ownerLogin || '').trim();
  }

  async function setReceiptPreference(ownerLogin, enabled) {
    const login = String(ownerLogin || '').trim();
    if (!login) return;
    return transact(async records => {
      const id = preferenceId(login);
      if (!enabled) return records.delete(id);
      return records.put({ id, recordType: 'receipt-preference', ownerLogin: login, enabled: true });
    });
  }

  async function getReceiptPreference(ownerLogin) {
    const id = preferenceId(ownerLogin);
    return transact(async records => Boolean(
      (await records.getAll()).find(item => item.id === id)?.enabled
    ));
  }

  return {
    get: id => transact(records => records.get(id)),
    reconcile,
    upsert,
    update,
    claim,
    claimNext,
    planBatch,
    supportsClaimTokens: true,
    renew,
    checkpoint: updateClaim,
    complete: (id, claimToken, deliveredIssue) => updateClaim(id, claimToken, item => clearClaim(item, {
      status: 'sent',
      ...(item.completionIntent === 'create-and-start' && deliveredIssue ? { deliveredIssue } : {}),
    })),
    release: (id, claimToken) => updateClaim(id, claimToken,
      item => clearClaim(item, { status: 'queued' })),
    fail: (id, claimToken, error, deliveryState) => updateClaim(id, claimToken, item => clearClaim(item, {
      status: 'attention', error,
      ...(deliveryState ? { deliveryState } : {}),
    })),
    authorization: (id, claimToken, error) => updateClaim(
      id, claimToken, item => clearClaim(item, { status: 'authorization', error })
    ),
    snapshot: () => transact(async records =>
      (await records.getAll()).filter(item => item.recordType !== 'receipt-preference')),
    countBlocked: ownerLogin => transact(async records =>
      (await records.getAll()).filter(item => item.recordType !== 'receipt-preference' &&
        item.status !== 'sent' && item.ownerLogin !== ownerLogin).length),
    setReceiptPreference,
    getReceiptPreference,
    close: () => transact.close?.(),
  };
}

function createBackgroundIssueSync({
  store, fetchJson, base = '', maxConcurrency = 3, batchSize = 70,
  batch = work => work(), requestTimeoutMs = 15000,
}) {
  let purgeRequested = false;
  let activePurge = null;
  let activeFlush = null;
  const activeRequests = new Set();
  const timeoutMs = Math.max(1, Number(requestTimeoutMs) || 15000);

  const completeClaim = (item, delivered) => store.supportsClaimTokens
    ? store.complete(item.id, item.claimToken, delivered) : store.complete(item.id, delivered);
  const releaseClaim = item => store.supportsClaimTokens
    ? store.release(item.id, item.claimToken) : store.release(item.id);
  const failClaim = (item, error, deliveryState) => store.supportsClaimTokens
    ? store.fail(item.id, item.claimToken, error, deliveryState)
    : store.fail(item.id, error, deliveryState);
  const requireAuthorization = (item, error) => store.supportsClaimTokens
    ? store.authorization(item.id, item.claimToken, error)
    : store.authorization(item.id, error);
  const checkpointClaim = (item, transform) => store.supportsClaimTokens
    ? store.checkpoint(item.id, item.claimToken, transform) : store.update?.(item.id, transform);

  async function requestStage(item, url, options) {
    if (store.renew) {
      const renewed = await store.renew(item.id, item.claimToken);
      if (!renewed) throw new Error('Background delivery claim was lost.');
    }
    return requestJson(url, options);
  }

  async function requestJson(url, options = {}) {
    const controller = new AbortController();
    activeRequests.add(controller);
    let timer;
    const interrupted = new Promise((resolve, reject) => {
      controller.signal.addEventListener('abort', () => {
        reject(new Error(purgeRequested
          ? 'Background request canceled.'
          : 'Background request timed out.'));
      }, { once: true });
      timer = setTimeout(() => controller.abort(), timeoutMs);
    });
    try {
      return await Promise.race([
        Promise.resolve().then(() => fetchJson(url, { ...options, signal: controller.signal })),
        interrupted,
      ]);
    } finally {
      clearTimeout(timer);
      activeRequests.delete(controller);
    }
  }
  function receiptFor(item, status, delivered = {}) {
    if (status === 'attention') {
      return { id: item.id, status, kind: item.kind ? 'message' : 'issue', route: '#/my-work/drafts' };
    }
    if (item.kind === 'notification-read') {
      return { id: item.id, status, kind: 'notification-read', route: '#/my-work/updates' };
    }
    if (item.kind === 'update-reply' || item.kind === 'update-reply-read') {
      return { id: item.id, status, kind: 'message', route: '#/my-work/update/' + encodeURIComponent(item.notificationId) };
    }
    const repository = String(item.repository || '').split('/').map(encodeURIComponent).join('/');
    if (item.kind === 'pull-review') {
      return {
        id: item.id, status, kind: 'message',
        route: '#/my-work/review/' + repository + '/' + encodeURIComponent(item.number),
      };
    }
    if (item.kind === 'issue-close') {
      return {
        id: item.id, status, kind: 'message',
        route: '#/my-work/issue/' + repository + '/' + encodeURIComponent(item.number),
      };
    }
    if (item.kind === 'issue-comment' || item.kind === 'pull-comment') {
      const resource = item.kind === 'pull-comment' ? 'pull' : 'issue';
      return { id: item.id, status, kind: 'message', route: '#/my-work/' + resource + '/' + repository + '/' + encodeURIComponent(item.number) };
    }
    if (typeof delivered.url === 'string' && /^https?:\/\//.test(delivered.url)) {
      return { id: item.id, status, kind: 'issue', url: delivered.url };
    }
    return { id: item.id, status, kind: 'issue', route: '#/my-work/issue/' + repository + '/' + encodeURIComponent(delivered.number) };
  }

  function deliveryRequest(item) {
    if (item.kind === 'notification-read') {
      return {
        url: base + 'api/v1/notifications/' + encodeURIComponent(item.notificationId) + '/read',
        options: { method: 'PATCH', headers: { Accept: 'application/json' } },
      };
    }
    if (item.kind === 'update-reply') {
      return authoredRequest('api/v1/notifications/' + encodeURIComponent(item.notificationId) + '/reply', item);
    }
    if (item.kind === 'update-reply-read') {
      return {
        url: base + 'api/v1/notifications/' + encodeURIComponent(item.notificationId) + '/read',
        options: { method: 'PATCH', headers: { Accept: 'application/json' } },
      };
    }
    const repository = String(item.repository || '').split('/').map(encodeURIComponent).join('/');
    if (item.kind === 'issue-close') {
      return {
        url: base + 'api/v1/repos/' + repository + '/issues/' + encodeURIComponent(item.number) + '/close',
        options: {
          method: 'PATCH',
          headers: { Accept: 'application/json', 'Idempotency-Key': item.operationId },
        },
      };
    }
    if (item.kind === 'issue-blocker') {
      return {
        url: base + 'api/v1/repos/' + repository + '/issues/' + encodeURIComponent(item.number) + '/blockers',
        options: {
          method: 'PATCH',
          headers: {
            Accept: 'application/json',
            'Content-Type': 'application/json',
            'Idempotency-Key': item.operationId,
          },
          body: JSON.stringify({
            repository: item.blockerRepository,
            number: item.blockerNumber,
            present: item.present === true,
          }),
        },
      };
    }
    if (item.kind === 'issue-content') {
      return {
        url: base + 'api/v1/repos/' + repository + '/issues/' + encodeURIComponent(item.number) + '/content',
        options: {
          method: 'PATCH',
          headers: {
            Accept: 'application/json',
            'Content-Type': 'application/json',
            'Idempotency-Key': item.operationId,
          },
          body: JSON.stringify({
            title: item.title,
            body: item.body,
            expected_updated_at: item.expectedUpdatedAt,
          }),
        },
      };
    }
    if (item.kind === 'pull-review') {
      return {
        url: base + 'api/v1/repos/' + repository + '/pulls/' + encodeURIComponent(item.number) + '/review',
        options: {
          method: 'POST',
          headers: {
            Accept: 'application/json',
            'Content-Type': 'application/json',
            'Idempotency-Key': item.operationId,
          },
          body: JSON.stringify({
            body: item.body,
            decision: item.decision,
            expected_head_sha: item.expectedHeadSha,
            comments: item.comments || [],
          }),
        },
      };
    }
    if (item.kind === 'issue-comment' || item.kind === 'pull-comment') {
      const resource = item.kind === 'pull-comment' ? 'pulls' : 'issues';
      return authoredRequest(
        'api/v1/repos/' + repository + '/' + resource + '/' + encodeURIComponent(item.number) + '/comments',
        item,
      );
    }
    if (item.kind === 'search-reply') {
      return authoredRequest(
        'api/v1/repos/' + repository + '/issues/' + encodeURIComponent(item.number) +
          '/preview/comments?kind=' + encodeURIComponent(item.targetKind),
        item,
      );
    }
    return {
      url: base + 'api/v1/repos/' + repository + '/issues',
      options: {
        method: 'POST',
        headers: {
          Accept: 'application/json',
          'Content-Type': 'application/json',
          'Idempotency-Key': item.operationId,
        },
        body: JSON.stringify({
          title: item.title,
          body: item.body,
          label_ids: item.labelIds,
          ...(item.unassigned ? { unassigned: true } : {}),
          ...(item.assignee ? { assignee: item.assignee } : {}),
          ...(item.milestoneId ? { milestone_id: item.milestoneId } : {}),
          ...(item.dueDate ? { due_date: item.dueDate + 'T23:59:59Z' } : {}),
        }),
      },
    };
  }

  function authoredRequest(url, item) {
    return {
      url: base + url,
      options: {
        method: 'POST',
        headers: {
          Accept: 'application/json',
          'Content-Type': 'application/json',
          'Idempotency-Key': item.operationId,
        },
        body: JSON.stringify({ body: item.body }),
      },
    };
  }

  function stageOperationId(operationId, stage) {
    const suffix = ':' + stage;
    return String(operationId || '').slice(0, 128 - suffix.length) + suffix;
  }

  function evidenceMarkdown(attachment, markdown, index) {
    const note = String(attachment?.note || '').replace(/\s+/g, ' ').trim().slice(0, 240);
    if (!note) return markdown;
    const escaped = note.replace(/([\\`*_[\]{}()<>#+\-.!|])/g, '\\$1');
    return '**Screenshot ' + (index + 1) + ' — ' + escaped + '**\n\n' + markdown;
  }

  function conversationAttachments(item) {
    return (Array.isArray(item?.attachments) ? item.attachments : [item?.attachment]).filter(Boolean);
  }

  async function uploadConversationAttachments(item, url) {
    let current = item;
    const attachments = conversationAttachments(current);
    const confirmedMarkdowns = attachments.map(value => String(value?.confirmed?.markdown || ''));
    const firstMissing = confirmedMarkdowns.findIndex(value => !value);
    const leadingConfirmed = confirmedMarkdowns.slice(0, firstMissing < 0 ? confirmedMarkdowns.length : firstMissing);
    const markdowns = Array.isArray(current.attachmentMarkdowns) ?
      current.attachmentMarkdowns.slice(0, attachments.length) :
      (current.attachmentMarkdown ? [current.attachmentMarkdown] : leadingConfirmed);
    for (let index = markdowns.length; index < attachments.length; index += 1) {
      const uploaded = await requestStage(current, url, {
        method:'POST',
        headers:{
          Accept:'application/json',
          'Idempotency-Key':String(attachments[index]?.operationId || stageOperationId(
            current.operationId, attachments.length === 1 ? 'attachment' : 'attachment-' + index,
          )).slice(0, 128),
        },
        body:attachmentMultipart(attachments[index]),
      });
      const markdown = String(uploaded?.markdown || '');
      if (!markdown) {
        const error = new Error('The server did not confirm the screenshot upload.');
        error.status = 422;
        throw error;
      }
      markdowns.push(markdown);
      await checkpointClaim(current, stored => ({
        ...stored, attachmentMarkdowns:markdowns.slice(),
        ...(attachments.length === 1 ? {attachmentMarkdown:markdown} : {}),
      }));
      current = {
        ...current, attachmentMarkdowns:markdowns.slice(),
        ...(attachments.length === 1 ? {attachmentMarkdown:markdown} : {}),
      };
    }
    return {
      current,
      markdown:markdowns.map((value, index) =>
        evidenceMarkdown(attachments[index], value, index)).join('\n\n'),
    };
  }

  async function deliverReplyRead(item) {
    let current = item;
    if (!current.replyConfirmed) {
      let attachmentMarkdown = '';
      if (conversationAttachments(current).length) {
        const uploaded = await uploadConversationAttachments(current,
          base + 'api/v1/notifications/' + encodeURIComponent(current.notificationId) + '/attachments');
        current = uploaded.current;
        attachmentMarkdown = uploaded.markdown;
      }
      const text = String(current.body || '').trim();
      const replyBody = attachmentMarkdown ?
        (text ? text + '\n\n' + attachmentMarkdown : attachmentMarkdown) : text;
      const options = authoredRequest('', { ...current, body:replyBody }).options;
      if (conversationAttachments(current).length) options.headers['Idempotency-Key'] = stageOperationId(current.operationId, 'reply');
      await requestStage(
        current,
        base + 'api/v1/notifications/' + encodeURIComponent(current.notificationId) + '/reply',
        options,
      );
      const checkpointed = await checkpointClaim(current, stored => ({ ...stored, replyConfirmed: true }));
      if (checkpointed === false) throw new Error('Background delivery claim was lost.');
      current = { ...current, replyConfirmed: true };
    }
    const request = deliveryRequest(current);
    return requestStage(current, request.url, request.options);
  }

  function attachmentMultipart(attachment) {
    let blob = attachment?.blob;
    if (!blob && attachment?.data) {
      const binary = atob(String(attachment.data));
      const bytes = Uint8Array.from(binary, character => character.charCodeAt(0));
      blob = new Blob([bytes], { type: String(attachment.contentType || '') });
    }
    if (!blob) throw new Error('The saved screenshot is unavailable. Retry before sending.');
    const form = new FormData();
    form.append('file', blob, String(attachment.filename || 'screenshot'));
    return form;
  }

  async function deliverIssueCapture(item) {
    const repository = String(item.repository || '').split('/').map(encodeURIComponent).join('/');
    let deliveredIssue = item.deliveredIssue;
    if (!deliveredIssue) {
      const request = deliveryRequest(item);
      deliveredIssue = await requestStage(item, request.url, request.options);
      await checkpointClaim(item, current => ({ ...current, deliveredIssue }));
    }
    const blockers = Array.isArray(item.blockers) ? item.blockers : [];
    let deliveredBlockers = Math.min(Number(item.deliveredBlockers) || 0, blockers.length);
    for (let index = deliveredBlockers; index < blockers.length; index += 1) {
      const blocker = blockers[index];
      await requestStage(
        item,
        base + 'api/v1/repos/' + repository + '/issues/' + encodeURIComponent(deliveredIssue.number) + '/blockers',
        {
          method:'PATCH',
          headers:{
            Accept:'application/json', 'Content-Type':'application/json',
            'Idempotency-Key':stageOperationId(item.operationId, 'blocker-' + index),
          },
          body:JSON.stringify({repository:blocker.repository, number:blocker.number, present:true}),
        },
      );
      deliveredBlockers = index + 1;
      await checkpointClaim(item, current => ({ ...current, deliveredIssue, deliveredBlockers }));
    }
    const attachments = (Array.isArray(item.attachments) ? item.attachments : [item.attachment]).filter(Boolean);
    if (!attachments.length) return deliveredIssue;
    const attachmentMarkdowns = Array.isArray(item.attachmentMarkdowns)
      ? item.attachmentMarkdowns.slice(0, attachments.length)
      : (item.attachmentMarkdown ? [item.attachmentMarkdown] : []);
    for (let index = attachmentMarkdowns.length; index < attachments.length; index += 1) {
      const uploaded = await requestStage(
        item,
        base + 'api/v1/repos/' + repository + '/issues/' + encodeURIComponent(deliveredIssue.number) + '/attachments',
        {
          method: 'POST',
          headers: {
            Accept: 'application/json',
            'Idempotency-Key': stageOperationId(
              item.operationId, attachments.length === 1 ? 'attachment' : 'attachment-' + index,
            ),
          },
          body: attachmentMultipart(attachments[index]),
        },
      );
      const markdown = String(uploaded?.markdown || '');
      if (!markdown) {
        const error = new Error('The server did not confirm the screenshot upload.');
        error.status = 422;
        throw error;
      }
      attachmentMarkdowns.push(markdown);
      await checkpointClaim(item, current => ({
        ...current, deliveredIssue, attachmentMarkdowns:attachmentMarkdowns.slice(),
        ...(attachments.length === 1 ? {attachmentMarkdown:markdown} : {}),
      }));
    }
    const attachmentMarkdown = attachmentMarkdowns.map((markdown, index) =>
      evidenceMarkdown(attachments[index], markdown, index)).join('\n\n');
    await requestStage(
      item,
      base + 'api/v1/repos/' + repository + '/issues/' + encodeURIComponent(deliveredIssue.number) + '/comments',
      {
        method: 'POST',
        headers: {
          Accept: 'application/json', 'Content-Type': 'application/json',
          'Idempotency-Key': stageOperationId(item.operationId, 'attachment-comment'),
        },
        body: JSON.stringify({ body: attachmentMarkdown }),
      },
    );
    return deliveredIssue;
  }

  async function deliverScreenshotComment(item) {
    const repository = String(item.repository || '').split('/').map(encodeURIComponent).join('/');
    const resource = item.kind === 'pull-comment' ? 'pulls' : 'issues';
    const uploaded = await uploadConversationAttachments(item,
      base + 'api/v1/repos/' + repository + '/' + resource + '/' + encodeURIComponent(item.number) + '/attachments');
    const attachmentMarkdown = uploaded.markdown;
    const text = String(item.body || '').trim();
    return requestStage(
      item,
      base + 'api/v1/repos/' + repository + '/' + resource + '/' + encodeURIComponent(item.number) + '/comments',
      {
        method: 'POST',
        headers: {
          Accept: 'application/json', 'Content-Type': 'application/json',
          'Idempotency-Key': stageOperationId(item.operationId, 'comment'),
        },
        body: JSON.stringify({ body: text ? text + '\n\n' + attachmentMarkdown : attachmentMarkdown }),
      },
    );
  }

  async function deliverSearchReply(item) {
    const repository = String(item.repository || '').split('/').map(encodeURIComponent).join('/');
    let current = item;
    let attachmentMarkdown = '';
    if (conversationAttachments(current).length) {
      const uploaded = await uploadConversationAttachments(current,
        base + 'api/v1/repos/' + repository + '/issues/' + encodeURIComponent(current.number) +
          '/preview/attachments?kind=' + encodeURIComponent(current.targetKind));
      current = uploaded.current;
      attachmentMarkdown = uploaded.markdown;
    }
    const text = String(current.body || '').trim();
    return requestStage(current,
      base + 'api/v1/repos/' + repository + '/issues/' + encodeURIComponent(current.number) +
        '/preview/comments?kind=' + encodeURIComponent(current.targetKind), {
        method:'POST',
        headers:{Accept:'application/json','Content-Type':'application/json',
          'Idempotency-Key':stageOperationId(current.operationId, 'comment')},
        body:JSON.stringify({body:attachmentMarkdown ?
          (text ? text + '\n\n' + attachmentMarkdown : attachmentMarkdown) : text}),
      });
  }

  async function deliverUpdateScreenshotReply(item) {
    const uploaded = await uploadConversationAttachments(item,
      base + 'api/v1/notifications/' + encodeURIComponent(item.notificationId) + '/attachments');
    const current = uploaded.current;
    const attachmentMarkdown = uploaded.markdown;
    const text = String(current.body || '').trim();
    return requestStage(current,
      base + 'api/v1/notifications/' + encodeURIComponent(current.notificationId) + '/reply', {
        method:'POST',
        headers:{ Accept:'application/json', 'Content-Type':'application/json',
          'Idempotency-Key':stageOperationId(current.operationId, 'reply') },
        body:JSON.stringify({ body:text ? text + '\n\n' + attachmentMarkdown : attachmentMarkdown }),
      });
  }

  async function deliver(item) {
    const request = deliveryRequest(item);
    try {
      const delivered = item.kind === 'update-reply-read' ? await deliverReplyRead(item) :
        item.kind === 'search-reply' ? await deliverSearchReply(item) :
        item.kind === 'update-reply' && conversationAttachments(item).length ? await deliverUpdateScreenshotReply(item) :
        conversationAttachments(item).length && ['issue-comment', 'pull-comment'].includes(item.kind) ?
        await deliverScreenshotComment(item) : item.attachment && !item.kind ?
          await deliverIssueCapture(item) : item.attachments?.length && !item.kind ?
            await deliverIssueCapture(item) : item.blockers?.length && !item.kind ?
              await deliverIssueCapture(item) : await requestStage(item, request.url, request.options);
      if (item.kind === 'issue-close' && delivered?.state !== 'closed') {
        const error = new Error('Issue closure was not confirmed.');
        error.status = 422;
        throw error;
      }
      if (item.kind === 'issue-blocker') {
        const dependencies = Array.isArray(delivered?.dependencies) ? delivered.dependencies : [];
        const present = dependencies.some(candidate => candidate?.repository === item.blockerRepository &&
          Number(candidate?.number) === item.blockerNumber);
        if (delivered?.number !== item.number || delivered?.dependencies_available !== true || present !== item.present) {
          const error = new Error('Blocker change was not confirmed.');
          error.status = 422;
          throw error;
        }
      }
      if (item.kind === 'issue-content' &&
          (delivered?.number !== item.number || delivered?.title !== item.title || delivered?.body !== item.body)) {
        const error = new Error('Checklist update was not confirmed.');
        error.status = 422;
        throw error;
      }
      await completeClaim(item, delivered);
      const receipt = receiptFor(item, 'confirmed', delivered);
      return item.kind ? { message: delivered, receipt } : { issue: delivered, receipt };
    } catch (error) {
      const status = Number(error?.status || 0);
      if (status === 401) {
        await releaseClaim(item);
        throw error;
      }
      if (status === 428 && item.kind === 'pull-review') {
        const message = String(error?.message || 'Fresh authorization required').slice(0, 240);
        await requireAuthorization(item, message);
        return {
          authorization: true,
          error,
          receipt: receiptFor(item, 'authorization'),
        };
      }
      if (status >= 400 && status < 500) {
        await failClaim(
          item,
          String(error?.message || 'Issue needs attention').slice(0, 240),
          error?.code === 'delivery_uncertain' ? 'uncertain' : undefined,
        );
        return { attention: true, error, receipt: receiptFor(item, 'attention') };
      }
      await releaseClaim(item);
      throw error;
    }
  }

  async function send(item, currentLogin) {
    if (purgeRequested) return { blocked: true };
    if (!currentLogin || item.ownerLogin !== currentLogin) return { blocked: true };
    await store.upsert(item);
    const claimed = await store.claim(item.id, currentLogin);
    if (!claimed) return { busy: true };
    return deliver(claimed);
  }

  async function runFlush() {
    const identity = await requestJson(base + 'api/v1/background-identity', {
      headers: { Accept: 'application/json' }, cache: 'no-store',
    });
    const login = String(identity?.login || '').trim();
    const confirmed = [];
    const receipts = [];
    let attention = 0;
    let authorization = 0;
    if (!login) return { confirmed, blocked: 0, attention, authorization, login, receipts };
    const collect = result => {
      if (result.issue) confirmed.push(result.issue);
      if (result.message) confirmed.push(result.message);
      if (result.attention) attention += 1;
      if (result.authorization) authorization += 1;
      if (result.receipt) receipts.push(result.receipt);
    };
    if (store.planBatch) {
      const planned = await store.planBatch(login, batchSize);
      let next = 0;
      let authenticationError = null;
      let transientError = null;
      const worker = async () => {
        while (!purgeRequested && !authenticationError && next < planned.length) {
          const id = planned[next++];
          const item = await store.claim(id, login);
          if (!item) continue;
          try {
            collect(await deliver(item));
          } catch (error) {
            if (Number(error?.status || 0) === 401) authenticationError = error;
            else if (!transientError) transientError = error;
          }
        }
      };
      const concurrency = Math.max(1, Math.min(Number(maxConcurrency) || 1, planned.length));
      await Promise.all(Array.from({ length: concurrency }, worker));
      if (purgeRequested) throw new Error('Background delivery canceled.');
      if (authenticationError) throw authenticationError;
      if (transientError) throw transientError;
    } else if (store.claimBatch) {
      const claimed = await store.claimBatch(login, batchSize);
      let next = 0;
      let authenticationError = null;
      let transientError = null;
      const worker = async () => {
        while (!purgeRequested && !authenticationError && next < claimed.length) {
          const item = claimed[next++];
          try {
            collect(await deliver(item));
          } catch (error) {
            if (Number(error?.status || 0) === 401) authenticationError = error;
            else if (!transientError) transientError = error;
          }
        }
      };
      const concurrency = Math.max(1, Math.min(Number(maxConcurrency) || 1, claimed.length));
      await Promise.all(Array.from({ length: concurrency }, worker));
      if (purgeRequested) {
        await Promise.all(claimed.slice(next).map(item => store.release(item.id)));
        throw new Error('Background delivery canceled.');
      }
      if (authenticationError) {
        await Promise.all(claimed.slice(next).map(item => store.release(item.id)));
        throw authenticationError;
      }
      if (transientError) throw transientError;
    } else {
      while (!purgeRequested) {
        const item = await store.claimNext(login);
        if (!item) break;
        collect(await deliver(item));
      }
    }
    const blocked = store.countBlocked ? await store.countBlocked(login) : 0;
    return { confirmed, blocked, attention, authorization, login, receipts };
  }

  function flush() {
    if (purgeRequested) return Promise.resolve({ confirmed: [], blocked: 0, attention: 0, login: '', receipts: [] });
    if (activeFlush) return activeFlush;
    activeFlush = Promise.resolve().then(() => batch(runFlush)).finally(() => { activeFlush = null; });
    return activeFlush;
  }

  function purge() {
    if (activePurge) return activePurge;
    purgeRequested = true;
    activeRequests.forEach(controller => controller.abort());
    activePurge = (async () => {
      if (activeFlush) await activeFlush.catch(() => {});
      await store.close?.();
    })();
    return activePurge;
  }

  async function resume() {
    const pendingPurge = activePurge;
    if (pendingPurge) await pendingPurge;
    if (activePurge === pendingPurge) activePurge = null;
    purgeRequested = false;
  }

  return {
    flush, send, purge, resume,
    get: id => store.get(id),
    reconcile: (items, outboxLane) => store.reconcile(items, outboxLane),
    snapshot: () => store.snapshot(),
    setReceiptPreference: (ownerLogin, enabled) => store.setReceiptPreference(ownerLogin, enabled),
    getReceiptPreference: ownerLogin => store.getReceiptPreference(ownerLogin),
  };
}

createBackgroundIssueSync.createIssueSyncStore = createIssueSyncStore;
if (typeof module !== 'undefined' && module.exports) module.exports = createBackgroundIssueSync;
if (typeof globalThis !== 'undefined') {
  globalThis.createBackgroundIssueSync = createBackgroundIssueSync;
  globalThis.createIssueSyncStore = createIssueSyncStore;
  globalThis.createUnfiledAttachmentStore = createUnfiledAttachmentStore;
}
