# Attachment Failure Retry And Escalation

## Current Design

- Jira is the source of raw comment media references and attachment metadata.
- `src/attachment-inputs.ts` maps visible references to attachments, downloads
  them, and writes the canonical `input/attachment-manifest.json`.
- `src/runner.ts` reads the manifest and supplies available images to Codex.
- `src/auto-analysis.ts` writes a Jira internal comment for any otherwise valid
  analysis result; manifest failures are currently only model-visible context.
- APID-29178 is a Slack-bridge case: the visible customer identity is embedded
  in a Jira comment authored by TiDB Support Bot, and the attachment is also
  authored by that bot. The current mapper replaces the raw author identity
  with the bridged customer identity, so the attachment cannot be correlated.

## Risks

- A broad order-only fallback could attach support-authored or hidden evidence
  to a customer-visible analysis context.
- Treating every omitted or unsupported attachment as retryable could block an
  otherwise valid case indefinitely.
- Letting Codex decide whether an attachment failure is fatal can leak internal
  parser errors into Jira and incorrectly mark a job successful.
- Re-running before the fixed image is live would update the existing Jira
  comment with the same bad result.

## Target Contract

- Reply visibility continues to use the resolved bridge/customer identity.
- Attachment correlation uses the raw Jira comment author plus timestamp. A
  bridge attachment is eligible only when its reference is reply-safe and the
  raw uploader matches that exact comment; there is no global bot allowlist or
  filename/order fallback.
- `input/attachment-manifest.json` remains the only attachment source of truth.
- In live mode, an expected image that is unresolved, unavailable, or invalid
  is a backend failure before Codex and before Jira writes.
- Retryable attachment failures use the existing job backoff. Exhausted or
  deterministic failures become `permanently_failed` and use the existing
  Feishu failure notification. Internal attachment failure reasons never enter
  `commentDraftMarkdown`.
- Dry-run keeps the manifest-visible limitation contract and does not mutate
  Jira or job state.

## Implementation Steps

1. Preserve both resolved reply identity and raw Jira author identity on each
   comment attachment reference.
2. Correlate bridge uploads through the raw author/time pair and allow them only
   for a reference already accepted by the reply-safe visibility boundary.
3. Add a typed live attachment preflight after workspace materialization and
   before diagnostics/Codex execution.
4. Carry the workspace/run identity through failed live attempts so DB and
   notifications retain inspectable evidence.
5. Add local contract tests for APID-29178-shaped bridge data, transient failure,
   exhausted failure notification, and zero Jira writes.
6. Deploy through the repository staging workflow and app-delivery image bump.
7. Requeue APID-29178 and verify that idempotency updates comment `23153520`.

## Verification Checklist

- [x] APID-shaped bridge image becomes `status=available`, `kind=image`.
- [x] Support-authored/hidden bridge attachments remain excluded.
- [x] A live unresolved or failed image never calls Codex or Jira write.
- [x] Retryable failure records the workspace and schedules backoff.
- [x] Final failure sends the configured Feishu alert.
- [x] Typecheck, focused contract tests, and full test suite pass.
- [x] Staging Deployment runs the merged image and is ready.
- [x] APID-29178 rerun succeeds with an available image manifest.
- [x] Jira internal comment `23153520` is updated, not duplicated.
- [x] DB job/run status, attempt state, and Jira comment JSON agree.

## Non-Goals

- Do not write or update customer-visible comments.
- Do not add a generic bot-uploader allowlist or uncontrolled fallback mapping.
- Do not let read paths clean up or rewrite attachment state.
- Do not change production automation or deployment configuration.
