Skip to content

feat(email): deterministic dedupe provenance — gate strong fingerprints on genuine Date (naruon#1086) - #1195

Open
seonghobae wants to merge 47 commits into
developfrom
claude/contextualwisdomlab-audit-governance-qyxe67
Open

feat(email): deterministic dedupe provenance — gate strong fingerprints on genuine Date (naruon#1086)#1195
seonghobae wants to merge 47 commits into
developfrom
claude/contextualwisdomlab-audit-governance-qyxe67

Conversation

@seonghobae

@seonghobae seonghobae commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Summary

Prevent synthetic collection timestamps from becoming strong duplicate evidence.

  • expose date_provenance, header_date, and message_id_provenance from the email parser while preserving the existing effective date contract;
  • normalize RFC 5322 -0000 dates to timezone-aware UTC;
  • seed strong import, IMAP, and POP3 identities only from genuine source evidence;
  • bind fallback identities to immutable raw RFC822 bytes, or to a deterministic canonical source projection when raw bytes are unavailable;
  • persist date_provenance on email_records through Alembic revision 0018_email_date_provenance, conservatively backfilling existing rows to unknown;
  • add deterministic auto_link, review_required, and distinct classification plus 1:N disposition resolution.

Data and compatibility boundary

  • New database object: date_provenance (two-word snake_case).
  • Existing rows use unknown, which can widen clerical review but cannot manufacture an automatic duplicate.
  • Existing effective date behavior remains parsed-header-or-fallback.
  • Collection timestamps never become strong duplicate evidence unless the sender Date header was genuinely parsed.
  • No irreversible provider action or automatic deletion is introduced.

Current exact candidate

  • Previous head (pre-reconcile): f6e60ef85e6877df7e978a6f86f019c2c32cf795.
  • New head (normal merge of live develop): f98c6fe4f7b452c988f8fae3bb963c97aa8da43b.
  • Live protected develop: dd8d15191338b841f9e6f3a06507c6a5643b95d0 (includes feat(calendar): prevent status-weighted double booking #1367).
  • Merge parents: f6e60ef85e6877df7e978a6f86f019c2c32cf795 + dd8d15191338b841f9e6f3a06507c6a5643b95d0.
  • Ancestry after merge: 44 commits ahead, 0 behind; merge base is the exact live protected base.
  • Alembic after merge: single head 0018_email_date_provenance (develop still ended at 0017_merge_newsdom_carddav_heads; no retarget required).
  • Semantic-path overlap with develop since ddd05c5a: none. The merge was conflict-free and did not change dedupe-provenance product code.
  • Local focused provenance/dedupe tests on exact head f98c6fe4f7b452c988f8fae3bb963c97aa8da43b: 101 passed, 0 failed in 0.36s. No Timeout / Fatal / Warn / Denied output.
cd backend
PYTHONWARNINGS=error DISABLE_BACKGROUND_WORKERS=1 python -m pytest \
  tests/test_email_dedupe_service.py \
  tests/test_email_import_service.py \
  tests/test_email_parser_provenance.py \
  tests/test_imap_worker.py \
  tests/test_pop3_worker.py \
  tests/test_source_bound_email_dedupe.py -q
# 101 passed in 0.36s

The exact current product diff remains fourteen durable files:

  • backend/alembic/versions/0018_email_date_provenance.py
  • backend/db/models.py
  • backend/services/email_dedupe_service.py
  • backend/services/email_import_service.py
  • backend/services/email_parser.py
  • backend/services/imap_worker.py
  • backend/services/pop3_worker.py
  • backend/tests/test_email_dedupe_service.py
  • backend/tests/test_email_import_service.py
  • backend/tests/test_email_parser_provenance.py
  • backend/tests/test_imap_worker.py
  • backend/tests/test_pop3_worker.py
  • backend/tests/test_source_bound_email_dedupe.py
  • docs/doctoring/email-source-identity-provenance.md

Verification boundary

Predecessor-head test, check, and review results do not transfer. This exact head must establish its own complete repository CI, migration/single-head, coverage, security, container, and current-head review evidence. Queued, skipped, stale, predecessor-head, author-only, or model-only evidence is non-passing.

Focused contracts cover parsed/missing/invalid Date provenance, -0000 normalization, source-bound identities, collection-time independence, import/IMAP/POP3 parity, conservative migration/backfill behavior, deterministic 1:N disposition, and distinct raw messages collected at the same instant.

Customer next action

Do not merge from this reconcile. Wait for exact-head product CI on f98c6fe4f7b452c988f8fae3bb963c97aa8da43b, then obtain an independent non-author APPROVE. Author, merge-bot, and predecessor-head approvals are not sufficient.

Reference

Fellegi, I. P., & Sunter, A. B. (1969). A theory for record linkage. Journal of the American Statistical Association, 64(328), 1183–1210. https://doi.org/10.1080/01621459.1969.10501049

Refs #1086

Merge gate

Merge only after every required unchanged exact-head check is terminal-success, all actionable current-head review threads are resolved, a qualifying independent non-author APPROVE exists where live organization policy requires it, and normal protected-branch rules accept the head without bypass. Predecessor evidence does not transfer. The central trusted-uv materializer repair remains an external control-plane prerequisite for fresh coverage-evidence; an infrastructure failure must not be represented as a source-code finding.


Open in Devin Review

@coderabbitai

coderabbitai Bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The email pipeline now tracks Date and Message-ID provenance, persists Date provenance, preserves source bytes, gates strong fingerprints on trusted dates, and classifies duplicates as auto_link, review_required, or distinct. Documentation and changelog entries record the behavior.

Changes

Email deduplication

Layer / File(s) Summary
Parse header provenance
backend/services/email_parser.py, backend/tests/test_email_parser_provenance.py
The parser returns effective dates, header dates, Date provenance, and Message-ID provenance. RFC 5322 -0000 dates normalize to UTC.
Persist provenance and source bytes
backend/alembic/versions/0018_email_date_provenance.py, backend/db/models.py, backend/services/email_import_service.py, backend/services/imap_worker.py, backend/services/pop3_worker.py, backend/tests/test_email_import_service.py, backend/tests/test_imap_worker.py, backend/tests/test_pop3_worker.py
The database stores date_provenance. Import workers pass raw source bytes and use source-bound fallback fingerprints when parsed Date provenance is unavailable.
Classify and resolve duplicate candidates
backend/services/email_dedupe_service.py, backend/tests/test_email_dedupe_service.py, backend/tests/test_source_bound_email_dedupe.py, docs/doctoring/email-source-identity-provenance.md, CHANGELOG.md
The deduplication service adds source and content fingerprints, three decision zones, and multi-row disposition precedence. Tests and documentation cover the resulting identity rules.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant RFC822Message
  participant email_parser
  participant import_worker
  participant email_dedupe_service
  participant Email
  RFC822Message->>email_parser: provide Date and Message-ID headers
  email_parser-->>import_worker: return parsed fields and provenance
  import_worker->>email_dedupe_service: provide candidate and source bytes
  email_dedupe_service->>Email: compare fingerprints and identity
  Email-->>email_dedupe_service: return stored row data
  email_dedupe_service-->>import_worker: return dedupe decision
Loading
🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main change: provenance-gated deterministic email deduplication based on genuine Date headers.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/contextualwisdomlab-audit-governance-qyxe67

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@seonghobae seonghobae changed the title feat(email): expose Date/Message-ID provenance in the parser (naruon#1086 foundation) feat(email): Date/Message-ID provenance + strong-fingerprint dedupe gating (naruon#1086) Jul 30, 2026
@seonghobae seonghobae changed the title feat(email): Date/Message-ID provenance + strong-fingerprint dedupe gating (naruon#1086) feat(email): deterministic dedupe provenance — gate strong fingerprints on genuine Date (naruon#1086) Jul 30, 2026
coderabbitai[bot]

This comment was marked as resolved.

@github-actions

github-actions Bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

PR governance metadata gate is not ready for 0b74befc6d4ccdd49db3a33b7565e4b224c4a30b:

  • Required check strix is FAILURE on the current head.

coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 30, 2026
@seonghobae
seonghobae enabled auto-merge July 31, 2026 12:48
@seonghobae

Copy link
Copy Markdown
Contributor Author

Closing after Loop drain: permanently blocked — branch was updated onto develop for mergeability, which cleared prior APPROVED robot evidence; re-review (CodeRabbit/OpenCode) and/or central gate jobs (metadata-only gate evaluation, coverage-evidence) remained pending/stuck without a re-runnable workflow handle. Not force-merging (merge-gate policy). Re-open a focused PR when robot capacity is available. Related product security fixes that reimplemented cleanly remain on branch goal/carddav-path-traversal-decode (#1206) for relaunch.

@seonghobae seonghobae left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Current-head provenance and deduplication revalidation completed: parser evidence classification, import and IMAP persistence, conservative migration backfill, strong-fingerprint gating, and review-required decisions are covered. Refresh central review evidence for this exact head.

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

Please re-review the current head c14fcae24b99a65d7755a2d4db7eaf93bf431f6e. All actionable findings are resolved or withdrawn with code-path evidence; five required workflows are green and the current-head container validation is completing.

@coderabbitai

coderabbitai Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

@seonghobae I will re-review the current head c14fcae24b99a65d7755a2d4db7eaf93bf431f6e. I will evaluate the current diff and the resolved findings. The completing container validation remains a separate verification signal.

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@seonghobae seonghobae left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Current head c14fcae24b99a65d7755a2d4db7eaf93bf431f6e has all repository-local required workflows successful and every current review thread resolved. Re-triggering central current-head OpenCode review and merge scheduling after its RFC 5322 prerequisite PR.

@seonghobae
seonghobae marked this pull request as draft August 3, 2026 05:07
auto-merge was automatically disabled August 3, 2026 05:07

Pull request was converted to draft

@seonghobae
seonghobae marked this pull request as ready for review August 3, 2026 05:07
@seonghobae
seonghobae marked this pull request as draft August 3, 2026 05:27

Copy link
Copy Markdown
Contributor Author

Temporarily sequencing this provenance/deduplication PR behind #1192 because both modify RFC 5322 date parsing and email-ingest contracts. Keeping this PR in draft prevents an overlapping merge race. After #1192 lands, update onto current develop, resolve the shared parser changes without weakening timezone-awareness or provenance classification, rerun migration/email/dedupe coverage, then mark ready for independent review and guarded merge.

Copy link
Copy Markdown
Contributor Author

@jules Refresh this PR onto the current develop head 0484ac3c137dcd31b02f6718773f276476015444 now that #1192 is merged.

Resolve the overlap in backend/services/email_parser.py by preserving every RFC 5322/RFC 2047 correctness change already on develop and layering the provenance contract on top:

  • keep Unicode display-name handling, attachment/body fallbacks, provider-byte parsing, and timezone-aware -0000 behavior;
  • add header_date, date_provenance, and message_id_provenance without changing the effective date semantics;
  • retain a backward-compatible _extract_date wrapper if the provenance implementation introduces a new helper;
  • a missing/whitespace Date must be missing, an unparseable Date invalid, a valid or -0000 Date parsed; only genuine parsed metadata may seed strong fingerprints;
  • keep the Alembic history single-headed and the date_provenance database name unchanged.

Use test-first conflict resolution. Preserve all current #1192 tests and add the provenance regressions in a separate focused test module if that avoids destructive edits. Rebase or rebuild the branch so it is zero commits behind develop, contains only the intended ten-file provenance scope (or an equivalent non-destructive test split), has no temporary workflow, and passes Ruff, Alembic/model reconciliation, focused email/import/IMAP/dedupe tests, and 100% coverage for newly introduced production branches. Do not merge the PR.

@seonghobae
seonghobae force-pushed the claude/contextualwisdomlab-audit-governance-qyxe67 branch from c14fcae to d948528 Compare August 4, 2026 06:35
@seonghobae
seonghobae dismissed coderabbitai[bot]’s stale review August 4, 2026 06:35

All actionable findings were addressed or explicitly withdrawn in resolved threads. The branch is now rebuilt as one current-develop commit at d948528, preserving later address-display hardening and isolating provenance tests in a focused module.

@seonghobae
seonghobae marked this pull request as ready for review August 4, 2026 06:36

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

Please review exact head d9485287b0115d0b9dbbd0bef9d9144fd416e72c, rebuilt as one current-develop commit. All prior inline findings are resolved or withdrawn; the merge preserves later address-display hardening and moves provenance regressions into a focused test module.

@coderabbitai

coderabbitai Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

@seonghobae I will review pull request #1195 at head d9485287b0115d0b9dbbd0bef9d9144fd416e72c. I will check the provenance contract, deduplication gate, migration consistency, and preservation of the parser hardening.

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@seonghobae

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 17, 2026

Copy link
Copy Markdown
Contributor
⚠️ Action not completed

Review rate limited.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

…ce-qyxe67

Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>
@seonghobae

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

Please review the unchanged exact current head f98c6fe4f7b452c988f8fae3bb963c97aa8da43b (normal merge of live develop@dd8d1519). Predecessor f6e60ef8 evidence does not transfer. Local provenance/dedupe tests: 101 passed. Independent non-author APPROVE is still required; this comment is not an approval.

@coderabbitai

coderabbitai Bot commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

expected='f98c6fe4f7b452c988f8fae3bb963c97aa8da43b'

printf '%s\n' '== Exact requested commit =='
printf 'checked_out='; git rev-parse HEAD
git cat-file -t "$expected"
git show -s --format='commit=%H%nparents=%P%nsubject=%s' "$expected"

printf '%s\n' '== Merge parents and changed scope =='
git diff-tree --no-commit-id --name-status -r "$expected"
git diff --check "${expected}^1" "$expected"
printf '%s\n' '-- Delta from first parent --'
git diff --stat "${expected}^1" "$expected"
printf '%s\n' '-- Delta from second parent --'
git diff --stat "${expected}^2" "$expected"

printf '%s\n' '== Aggregate scope from current develop merge base =='
base="$(git merge-base "$expected" origin/develop 2>/dev/null || git merge-base "$expected" develop)"
printf 'merge_base=%s\n' "$base"
git diff --name-status "$base" "$expected"
git diff --check "$base" "$expected"

printf '%s\n' '== Focused source identity and provenance symbols =='
rg -n -C 4 --glob '*.py' \
  '(def (_extract_date|_extract_date_with_provenance|_email_fingerprint|source_email_fingerprint|canonical_email_source_content|process_fetched_email|_message_bytes)|date_provenance|header_date|message_id_provenance|source_content|strong_email_fingerprint|generate_email_fingerprint|resolve_candidate_disposition|classify_dedupe_decision|process_fetched_email\s*\()' \
  backend/services backend/db backend/tests || true

printf '%s\n' '== Relevant file outlines =='
for f in \
  backend/services/email_parser.py \
  backend/services/email_dedupe_service.py \
  backend/services/email_import_service.py \
  backend/services/imap_worker.py \
  backend/services/pop3_worker.py \
  backend/db/models.py \
  backend/alembic/versions/0018_email_date_provenance.py \
  backend/tests/test_email_parser_provenance.py \
  backend/tests/test_email_dedupe_service.py \
  backend/tests/test_email_import_service.py \
  backend/tests/test_imap_worker.py \
  backend/tests/test_pop3_worker.py \
  backend/tests/test_source_bound_email_dedupe.py
do
  if [ -f "$f" ]; then
    echo "--- $f"
    ast-grep outline "$f" --items all || true
  fi
done

printf '%s\n' '== Migration graph declarations =='
rg -n -C 1 --glob '*.py' \
  '^(revision|down_revision|branch_labels|depends_on)\s*=' \
  backend/alembic/versions || true

printf '%s\n' '== Workflow changes in aggregate diff =='
git diff --name-status "$base" "$expected" -- '.github/workflows/**' || true

printf '%s\n' '== Current PR state and checks =='
gh pr view 1195 --repo ContextualWisdomLab/naruon \
  --json state,headRefOid,baseRefOid,mergeStateStatus,reviewDecision,statusCheckRollup 2>&1 || true
gh pr checks 1195 --repo ContextualWisdomLab/naruon \
  --json name,state,conclusion,workflow,link,completedAt 2>&1 || true

Length of output: 156685


🏁 Script executed:

#!/bin/bash
set -euo pipefail

show_range() {
  local file="$1" start="$2" end="$3"
  printf '\n--- %s, Lines %s-%s ---\n' "$file" "$start" "$end"
  nl -ba "$file" | sed -n "${start},${end}p"
}

show_range backend/services/email_dedupe_service.py 49 320
show_range backend/services/email_import_service.py 173 365
show_range backend/services/email_import_service.py 805 925
show_range backend/services/imap_worker.py 27 115
show_range backend/services/imap_worker.py 315 365
show_range backend/services/pop3_worker.py 85 210
show_range backend/services/email_parser.py 166 280
show_range backend/alembic/versions/0018_email_date_provenance.py 1 100
show_range backend/tests/test_source_bound_email_dedupe.py 1 230
show_range backend/tests/test_imap_worker.py 50 140
show_range backend/tests/test_pop3_worker.py 85 195

printf '%s\n' '== Every direct process_fetched_email call =='
rg -n -C 4 --glob '*.py' '\bprocess_fetched_email\s*\(' backend || true

printf '%s\n' '== Email fingerprint lookup predicates =='
rg -n -C 5 --glob '*.py' \
  '(select\(Email\)|Email\.fingerprint|Email\.message_id|fingerprint\s*==|message_id\s*==)' \
  backend/services/email_import_service.py backend/services/imap_worker.py || true

printf '%s\n' '== Parser compatibility wrapper and references =='
rg -n -C 3 --glob '*.py' '\b_extract_date\s*\(' backend || true

printf '%s\n' '== Current checks, supported fields =='
gh pr checks 1195 --repo ContextualWisdomLab/naruon \
  --json name,state,workflow,link,completedAt,description 2>&1 || true

printf '%s\n' '== Coverage-evidence status, if present =='
gh pr view 1195 --repo ContextualWisdomLab/naruon \
  --json statusCheckRollup --jq '.statusCheckRollup[] | select(.name == "coverage-evidence" or .name == "backend (Python 3.14)") | {name, status, conclusion, detailsUrl, startedAt, completedAt}' \
  2>&1 || true

Length of output: 2261


🏁 Script executed:

#!/bin/bash
set -euo pipefail

show_range() {
  local file="$1" start="$2" end="$3"
  printf '\n--- %s, Lines %s-%s ---\n' "$file" "$start" "$end"
  awk -v start="$start" -v end="$end" \
    'NR >= start && NR <= end { printf "%d\t%s\n", NR, $0 }' "$file"
}

show_range backend/services/email_dedupe_service.py 49 320
show_range backend/services/email_import_service.py 173 365
show_range backend/services/email_import_service.py 805 925
show_range backend/services/imap_worker.py 27 115
show_range backend/services/imap_worker.py 315 365
show_range backend/services/pop3_worker.py 85 210
show_range backend/services/email_parser.py 166 280
show_range backend/alembic/versions/0018_email_date_provenance.py 1 100
show_range backend/tests/test_source_bound_email_dedupe.py 1 230
show_range backend/tests/test_imap_worker.py 50 140
show_range backend/tests/test_pop3_worker.py 85 195

printf '%s\n' '== Every direct process_fetched_email call =='
rg -n -C 4 --glob '*.py' '\bprocess_fetched_email\s*\(' backend || true

printf '%s\n' '== Email fingerprint lookup predicates =='
rg -n -C 5 --glob '*.py' \
  '(select\(Email\)|Email\.fingerprint|Email\.message_id|fingerprint\s*==|message_id\s*==)' \
  backend/services/email_import_service.py backend/services/imap_worker.py || true

printf '%s\n' '== Parser compatibility wrapper and references =='
rg -n -C 3 --glob '*.py' '\b_extract_date\s*\(' backend || true

printf '%s\n' '== Current checks, supported fields =='
gh pr checks 1195 --repo ContextualWisdomLab/naruon \
  --json name,state,workflow,link,completedAt,description 2>&1 || true

printf '%s\n' '== Coverage-evidence status, if present =='
gh pr view 1195 --repo ContextualWisdomLab/naruon \
  --json statusCheckRollup --jq '.statusCheckRollup[] | select(.name == "coverage-evidence" or .name == "backend (Python 3.14)") | {name, status, conclusion, detailsUrl, startedAt, completedAt}' \
  2>&1 || true

Length of output: 73545


@seonghobae I reviewed exact head f98c6fe4f7b452c988f8fae3bb963c97aa8da43b against merged develop@dd8d1519.

I found no new code blocker in the requested scope.

  • IMAP and POP3 pass RFC822 source bytes to process_fetched_email.
  • Fallback fingerprints use source bytes when available.
  • Canonical fallback content excludes collection-time date and date_provenance.
  • Only date_provenance == "parsed" can create a strong fingerprint.
  • Missing, invalid, and unknown dates cannot create an automatic strong-match link.
  • Import fallback Message-ID generation uses a SHA-256 digest of source bytes.
  • The parser classifies missing, invalid, and valid Date values. It normalizes -0000 values to timezone-aware UTC.
  • Migration 0018_email_date_provenance adds the non-null date_provenance column with conservative "unknown" backfill behavior.
  • The 1:N disposition logic gives auto_link priority over review_required, then returns distinct.

I verified that the aggregate PR delta contains no workflow changes.

backend (Python 3.14) completed successfully. Several required checks remain queued or in progress. The PR remains CHANGES_REQUESTED and merge-blocked until those checks and the required independent approval complete.

I did not emit an approval action.

You are interacting with an AI system.

@opencode-agent opencode-agent Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

OpenCode cannot approve yet because required coverage evidence did not pass.

Review outcome

1. HIGH .github/workflows/opencode-review.yml:1 - Coverage evidence did not prove required test/docstring evidence

  • Problem: The required coverage-evidence job result was failure, so OpenCode cannot establish approval sufficiency for this head.

  • Root cause: Automated approval is only valid when the same-head coverage-evidence job proves supported repository test suites passed and configured docstring gates passed or were advisory, or reports not applicable because no supported source files or package manifests exist. Missing, failed, skipped, unavailable, or unsupported-tooling test evidence is a blocker.

  • Fix: Install or configure the repository test/docstring evidence tooling when source files or package manifests exist, rerun the current-head coverage-evidence job, and approve only after it reports success with required evidence or explicit no-source not-applicable evidence.

  • Regression test: Keep the approval branch checking needs.coverage-evidence.result == success before posting APPROVE, and publish REQUEST_CHANGES when coverage-evidence blocker states such as cancelled, skipped, failed, unsupported-tooling, or below-100 evidence are present.

  • Result: REQUEST_CHANGES

  • Reason: coverage-evidence result was failure, so required test/docstring evidence was not proven for current head f98c6fe4f7b452c988f8fae3bb963c97aa8da43b.

  • Head SHA: f98c6fe4f7b452c988f8fae3bb963c97aa8da43b

  • Workflow run: 32068450034

  • Workflow attempt: 1

Coverage evidence

Coverage evidence job did not run or did not publish coverage evidence.

Changed-File Evidence Map

flowchart LR
  PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
  Evidence --> S1["Backend (13 files)"]
  S1 --> I1["API and service runtime"]
  I1 --> R1["Review risk: Backend (13 files)"]
  R1 --> V1["backend tests"]
  Evidence --> S2["Docs: email-source-identity-provenance.md"]
  S2 --> I2["operator or user guidance"]
  I2 --> R2["Review risk: Docs: email-source-identity-provenance.md"]
  R2 --> V2["docs review"]
Loading

@seonghobae

Copy link
Copy Markdown
Contributor Author

@opencode-agent @cwl-noema-review please independently re-review exact current head f98c6fe4f7b452c988f8fae3bb963c97aa8da43b. The prior request was solely due to the then-failed coverage-evidence job; current-head coverage-evidence and all required source/security checks now report success. Please re-check the source-bound Date/Message-ID/raw-source contracts and approve only with current-head evidence.

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 1 additional finding.

Open in Devin Review

@seonghobae
seonghobae enabled auto-merge (squash) August 20, 2026 20:10

@opencode-agent opencode-agent Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

OpenCode cannot approve yet because required coverage evidence did not pass.

Review outcome

1. HIGH .github/workflows/opencode-review.yml:1 - Coverage evidence did not prove required test/docstring evidence

  • Problem: The required coverage-evidence job result was failure, so OpenCode cannot establish approval sufficiency for this head.

  • Root cause: Automated approval is only valid when the same-head coverage-evidence job proves supported repository test suites passed and configured docstring gates passed or were advisory, or reports not applicable because no supported source files or package manifests exist. Missing, failed, skipped, unavailable, or unsupported-tooling test evidence is a blocker.

  • Fix: Install or configure the repository test/docstring evidence tooling when source files or package manifests exist, rerun the current-head coverage-evidence job, and approve only after it reports success with required evidence or explicit no-source not-applicable evidence.

  • Regression test: Keep the approval branch checking needs.coverage-evidence.result == success before posting APPROVE, and publish REQUEST_CHANGES when coverage-evidence blocker states such as cancelled, skipped, failed, unsupported-tooling, or below-100 evidence are present.

  • Result: REQUEST_CHANGES

  • Reason: coverage-evidence result was failure, so required test/docstring evidence was not proven for current head c7aedc6a6a09bc91156e9c62e44f18cf8b4d3846.

  • Head SHA: c7aedc6a6a09bc91156e9c62e44f18cf8b4d3846

  • Workflow run: 32523127357

  • Workflow attempt: 1

Coverage evidence

Coverage evidence job did not run or did not publish coverage evidence.

Changed-File Evidence Map

flowchart LR
  PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
  Evidence --> S1["Backend (13 files)"]
  S1 --> I1["API and service runtime"]
  I1 --> R1["Review risk: Backend (13 files)"]
  R1 --> V1["backend tests"]
  Evidence --> S2["Docs: email-source-identity-provenance.md"]
  S2 --> I2["operator or user guidance"]
  I2 --> R2["Review risk: Docs: email-source-identity-provenance.md"]
  R2 --> V2["docs review"]
Loading

@opencode-agent
opencode-agent Bot disabled auto-merge August 21, 2026 21:40
@seonghobae
seonghobae dismissed stale reviews from opencode-agent[bot], opencode-agent[bot], opencode-agent[bot], opencode-agent[bot], opencode-agent[bot], and opencode-agent[bot] August 22, 2026 07:49

Verified: coverage-evidence and other non-metadata-gate required checks on the current head now report pass (gh pr checks). The coverage-evidence failure this review cited has since cleared on rerun. Dismissing as superseded.

@opencode-agent opencode-agent Bot added area: ci-cd CI, GitHub Actions, checks, release, or supply chain priority: medium Normal-priority or P2 work status: needs-review Open pull request requiring current-head review or checks type: feature New or expanded product capability labels Aug 22, 2026
opencode-agent[bot]
opencode-agent Bot previously approved these changes Aug 26, 2026

@opencode-agent opencode-agent Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

OpenCode reviewed the current-head bounded evidence and found no blocking issues.

Findings

No blocking findings.

Summary

Pull request overview: inspected changed-file evidence for backend/alembic/versions/0018_email_date_provenance.py, backend/db/models.py, backend/services/email_dedupe_service.py, backend/tests/test_imap_worker.py, and backend/tests/test_pop3_worker.py from the bounded current-head packet. Approval sufficiency: current-head source/diff evidence plus Coverage Decision PASS support the conservative backfill, explicit date_provenance model field, source-bound ingest handoff, and no remaining review/check blockers. Verification posture: review used bounded current-head evidence because direct reads under /home/runner/work/_temp/opencode-pr-head were blocked by external-directory policy; conclusions rely on the authoritative current-head Changed files, Focused changed hunks, CodeGraph evidence, and Coverage execution evidence. Linter/static: no completed failed GitHub Checks were present when evidence was collected, and no separate current-head lint failure evidence was supplied. TDD/regression: targeted regression surfaces are present in backend/tests/test_imap_worker.py and backend/tests/test_pop3_worker.py, and Coverage Decision PASS says supported repository test suites passed. Coverage: Coverage execution evidence reports Result: PASS and says supported repository test suites passed. Docstring coverage: Coverage execution evidence says configured repository docstring gates passed or docstring coverage was advisory. DAG: base-to-head focused flow below, derived from current-head Changed files plus CodeGraph changed-scope exploration.

flowchart LR
A["backend/services/email_parser.py"] --> B["backend/services/email_import_service.py"]
A --> C["backend/services/imap_worker.py"]
A --> D["backend/services/pop3_worker.py"]
B --> E["backend/services/email_dedupe_service.py"]
C --> E
D --> E
G["backend/alembic/versions/0018_email_date_provenance.py"] --> F["backend/db/models.py"]
E --> F
H["backend/tests/test_imap_worker.py + backend/tests/test_pop3_worker.py"] --> C
H --> D
Loading

PoC/execution: no trusted browser/E2E receipt applied; runtime evidence is bounded repository test coverage PASS plus source-trace/current-head test assertions. DDD/domain: this change preserves the email identity boundary by separating sender-authored Date provenance from collection-time observation. CDD/context: reviewed the parser/import/IMAP/POP3/dedupe/model/migration context named in current-head Changed files and CodeGraph changed-scope exploration. Similar issues: Changed file history shows earlier source-bound dedupe and canonical-value validation fixes already folded into backend/services/email_dedupe_service.py. Claim/concept check: the PR claim that synthetic collection timestamps should not become strong duplicate evidence is consistent with the conservative unknown backfill and raw-message handoff assertions in the current-head tests. Standards search: source limitation—no separate bounded RFC 5322 or Fellegi-Sunter reference excerpt was supplied, but the inspected current-head hunks did not expose new numeric thresholds or formula changes requiring external re-derivation before approval. Compatibility/convention: inspected changed names such as date_provenance, source_content, and DedupeDecision; the visible schema/code identifiers are descriptive two-word names and the PR body says the effective date contract is preserved. Breaking-change/backcompat: backcompat is preserved by adding date_provenance with non-null unknown defaults instead of reinterpreting historical rows as parsed sender dates. Implementation completeness: the inspected runtime hunks are concrete implementations, not pass/.../NotImplementedError placeholders. Performance: the added hashing/canonicalization work is linear in message/source size, and no new unbounded fan-out was evident in the inspected hunks. Developer experience: DX surface is the backend test/coverage contract; Review execution contracts list cd backend && python3 -m pytest tests and coverage commands, and Coverage Decision PASS confirms the repository-native suite passed. User experience: UX surface is duplicate disposition in backend email ingest rather than web UI; the change is conservative because ambiguous provenance is held out of strong auto-linking instead of silently manufacturing duplicates. Visual/DOM: non-web interaction surface reviewed—migration, parser/import/worker flow, test assertions, and documentation path; no changed DOM surface was in scope. Accessibility/i18n: non-web backend/docs changes only; no new UI interaction or localized string surface was exposed in the inspected hunks. Supply-chain/license: Changed files contain no dependency or lockfile edits, and no current-head failed security/check evidence was supplied. Packaging: despite the repo-wide unpackaged_source_surfaces signal, current-head Review execution contracts also list backend/pyproject.toml, frontend/package.json, repo-native test/coverage/security commands, and Coverage Decision PASS, which is sufficient evidence that the changed backend surface is under an existing package/test contract. Security/privacy: inspected evidence shows IMAP/POP3 worker tests preserve validated bounded import flow and raw-source handoff; no new client-visible sequential identifiers, secret logging, or unresolved security check failures were surfaced.

Approval sufficiency: bounded evidence supplied affirmative approval evidence for changed files, coverage/docstring posture, risk surfaces, and current-head verification; approval is not based merely on the absence of known blockers.
Verification posture: CodeGraph evidence was initialized and bounded current-head evidence reviewed for changed-file evidence including backend/alembic/versions/0018_email_date_provenance.py, backend/db/models.py, backend/services/email_dedupe_service.py, backend/services/email_import_service.py, backend/services/email_parser.py, and 9 more.
Linter/static: workflow/static review evidence is bounded by the current-head GitHub Checks gate and changed-file evidence.
TDD/regression: coverage execution evidence and focused changed hunks were reviewed from bounded-review-evidence.md.
Coverage: coverage execution evidence reports supported repository test suites passed.
Docstring coverage: coverage execution evidence reports configured repository docstring gates passed or docstring coverage was advisory.
DAG: CodeGraph/source-backed behavior map connects backend/alembic/versions/0018_email_date_provenance.py to the affected review, runtime, or workflow path and required checks.
PoC/execution: coverage-evidence job executed on the current head and reported PASS.
DDD/domain: workflow and repository-governance invariants were reviewed against changed files in bounded evidence.
CDD/context: CodeGraph evidence, changed-file history, and focused hunks were reviewed from bounded-review-evidence.md.
Similar issues: changed-file history evidence was reviewed for comparable local precedents.
Claim/concept check: bounded evidence, repository source, current-head workflow evidence, and, where numeric, scientific, statistical, or literature-backed claims are affected, original-paper/formula evidence and parameter-recovery expectations were used for claims.
Standards search: standards and external-source claims require trusted bounded source evidence prepared outside the isolated model process; no evidence-backed standards blocker is present in bounded evidence.
Compatibility/convention: changed workflow/script conventions, object naming, and reserved-word safety for schema/API/config/code surfaces were checked in bounded evidence.
Breaking-change/backcompat: deployment evidence and changed-file history were checked for backward-compatibility risk.
Performance: changed surfaces were checked for performance risk in bounded evidence.
Developer experience: changed automation, review, test, setup, and maintenance surfaces were checked for helpful or obstructive DX impact in bounded evidence.
User experience: connected user, operator, API, CLI, documentation, review-comment, status-check, rendering, and workflow-reader behavior was checked for contradictions against code, docs, and tests in bounded evidence.
Visual/DOM: deterministic repair does not infer browser runtime execution; source-backed DOM/UI evidence and trusted workflow receipts were reviewed when present, and non-web surfaces used API/CLI/log/docs/workflow evidence instead.
Accessibility/i18n: accessibility, localization, and human-readable text surfaces were checked where UI, CLI, API message, docs, logs, or review text changed.
Supply-chain/license: dependency, package, model, container, and external-tool changes were checked in bounded evidence.
Packaging: package, build, test, lint, and security contracts were checked in bounded evidence.
Security/privacy: workflow-token, review-gate, and repository-automation security/privacy boundaries were checked in bounded evidence.

Adversarial validation

{"status":"passed","probes":[{"path":"backend/alembic/versions/0018_email_date_provenance.py","line":49,"hypothesis":"Historical `email_records` rows could be backfilled as if they had genuine sender `Date` metadata and begin auto-linking on synthetic timestamps.","attack_or_counterexample":"Apply the migration to a database containing legacy rows with no provenance metadata and check whether the new column silently marks them parsed.","evidence":"Trusted current-head diff at backend/alembic/versions/0018_email_date_provenance.py:49 observed the added non-null column use `server_default=\"unknown\"` after the column-presence guard, so existing rows backfill to `unknown` rather than `parsed`; Trusted current-head source binding at backend/alembic/versions/0018_email_date_provenance.py:49; source-line-sha256=d65ae56094134c58bc31960d954ee5924e99eea77eb05df2053c1c78799ecbe7","outcome":"falsified"},{"path":"backend/tests/test_imap_worker.py","line":129,"hypothesis":"The IMAP ingest path could drop immutable RFC822 bytes before handing an email to the import/dedupe pipeline, forcing fallback identity back onto collection-time fields.","attack_or_counterexample":"Challenge `_sync_tenant` with a fetched IMAP message that has explicit `raw_message` bytes and verify the downstream handoff preserves those bytes.","evidence":"Coverage execution evidence at bounded-review-evidence.md:694-698 reports `Result: PASS` with supported repository test suites passed, and trusted current-head test source at backend/tests/test_imap_worker.py:129 asserts `kwargs[\"source_content\"] == raw_message` after `await worker._sync_tenant(config)`; Trusted current-head source binding at backend/tests/test_imap_worker.py:129; source-line-sha256=73a7b47ddc06dd9d9f5feb937f5d6c82559143e3c7b347fdba88dab17c4b92bb","outcome":"falsified"},{"path":"backend/tests/test_pop3_worker.py","line":183,"hypothesis":"The POP3 ingest path could likewise discard raw transport bytes and regress fallback dedupe identity to mutable parsed fields.","attack_or_counterexample":"Challenge `_sync_tenant` with a retrieved POP3 message and verify the worker passes the exact `raw_message` bytes into `process_fetched_email`.","evidence":"Coverage execution evidence at bounded-review-evidence.md:694-698 reports `Result: PASS` with supported repository test suites passed, and trusted current-head test source at backend/tests/test_pop3_worker.py:183 asserts `imported[0][\"source_content\"] == raw_message` after `await worker._sync_tenant(config, asyncio.Semaphore(1))`; Trusted current-head source binding at backend/tests/test_pop3_worker.py:183; source-line-sha256=abf1a0751d9551cdce533f9314abe51df1494b825d698692c2607331dbc9d969","outcome":"falsified"}],"residual_risk":"Direct reads under `/home/runner/work/_temp/opencode-pr-head` were blocked by external-directory policy, so approval relies on the authoritative bounded current-head packet rather than fresh full-file reads for `backend/services/email_import_service.py`, `backend/services/email_parser.py`, and `docs/doctoring/email-source-identity-provenance.md`. Within that limit, current-head evidence still shows no unresolved review threads, no completed failed checks, and PASS coverage for the repository-native test surface."}
  • Result: APPROVE
  • Reason: Current-head evidence supports the provenance gate: the migration backfills date_provenance conservatively, dedupe code adds source-bound identity primitives, IMAP/POP3 tests preserve raw RFC822 bytes, coverage passed, and no unresolved threads or failed checks remain.
  • Head SHA: c7aedc6a6a09bc91156e9c62e44f18cf8b4d3846
  • Workflow run: 32924628799
  • Workflow attempt: 1

@opencode-agent
opencode-agent Bot enabled auto-merge (squash) August 26, 2026 07:21
@opencode-agent
opencode-agent Bot disabled auto-merge August 26, 2026 08:30
@opencode-agent
opencode-agent Bot dismissed their stale review August 26, 2026 10:00

Superseded automated OpenCode approval whose explicit review evidence does not match exact current head 0b74bef; a fresh current-head review is required.

@seonghobae seonghobae added the enhancement New feature or request label Sep 7, 2026 — with ChatGPT Codex Connector
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: ci-cd CI, GitHub Actions, checks, release, or supply chain enhancement New feature or request priority: medium Normal-priority or P2 work status: needs-review Open pull request requiring current-head review or checks type: feature New or expanded product capability

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants