Skip to content

feat(email-writing): parse contextual review candidates - #1375

Draft
seonghobae wants to merge 5 commits into
feat/llm-email-writing-orchestrator-task5from
feat/llm-email-writing-candidate-task6
Draft

feat(email-writing): parse contextual review candidates#1375
seonghobae wants to merge 5 commits into
feat/llm-email-writing-orchestrator-task5from
feat/llm-email-writing-candidate-task6

Conversation

@seonghobae

@seonghobae seonghobae commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

Stack dependency

This Draft PR implements Task 6 of the accepted LLM email-writing guidance plan and is stacked on #1356 (feat/llm-email-writing-orchestrator-task5).

Customer next action

This PR is candidate-parse only. Customers should continue to write and send email with the current editor and send path. No user-facing writing-guidance diagnostics, language profile, or model is available in product. Writing and sending stay on the current path.

Exact-head retarget onto live #1356

Previous head (exact current PR head at launch):

a3dd2e270f7400e6c1754c437c6831241ae4aa7c

GitHub last showed base feat/llm-email-writing-orchestrator-task5 at stale:

0c0ac2b598a8338a257e69bcca4d00b6fe20daf5

Current head (normal merge commit, not squash, not rebase, not force-push):

fa844bd035ab1f188a28c58e0ed2dc45fa31d0f3

Live parent #1356 (feat/llm-email-writing-orchestrator-task5) merged as the second parent:

9cd9b953a2dd236aebe1fcdc25e59ba3e9388505

Normal merge commit parents:

  • first parent: a3dd2e270f7400e6c1754c437c6831241ae4aa7c
  • second parent: 9cd9b953a2dd236aebe1fcdc25e59ba3e9388505

Live parent #1356 already contains #1329 4570747ccebd57ccaab30ffc68239f0c9d2f1ca0 / #1328 51fb5e8543247b1e5c790f3fdf98424c8fbed669 / #1327 fb7c406ee1328a6ac42dbaf54bb6852c199d8b0a / #1322 bfc2df112136bb9fe358778d701e78bf9e78b685 / develop@dd8d15191338b841f9e6f3a06507c6a5643b95d0.

ADR numbering follows the live parent:

  • calendar ADR-0004 stays unique (0004-status-weighted-calendar-conflicts.md);
  • email-writing remains ADR-0005;
  • Task 6 candidate-review files were unchanged by the merge (no product conflict, no Task 6 semantics edit). Git auto-merged the parent stack only.

Alembic head after merge:

20260813_email_orchestrator

Parent still carries 20260812_email_writing_evidence on 0017_merge_newsdom_carddav_heads. This slice's revision did not collide and remains 20260813_email_orchestrator with down_revision = 20260812_email_writing_evidence.

Local validation counts on fa844bd035ab1f188a28c58e0ed2dc45fa31d0f3:

  • candidate-review behavior tests: 37 passed (tests/test_email_writing_candidate_review.py)
  • terminal-coverage tests: 4 passed (tests/test_email_writing_candidate_review_terminal_coverage.py)
  • combined focused Task 6 tests: 41 passed
  • Task 6 coverage: 100% (206 statements, 48 branches, fail-under=100)
  • shipped-symbol docstrings: 2 modules
  • ruff: All checks passed
  • production-module compileall for Task 6 sources: ok
  • git diff --check: ok
  • write-capable promotion/finalize workflows: absent
  • product Task 6 semantics edits: 0
  • stability scan: no Timeout / Fatal / Warn / Denied

Predecessor evidence does not transfer. Checks, reviews, and security evidence recorded for a3dd2e27, 0c0ac2b5, or any earlier head are non-passing for this head.

Test-first history

Task 6 was developed through an observable RED → GREEN sequence.

  1. 81b2929359966a5eee068dc219dbd02a0cbf8762 added the focused candidate-review contracts and fixture before the production candidate-review modules existed. Hosted run 31943760784 reached the product test step and failed there; setup and hash-locked dependency installation succeeded.
  2. 1bca07607735876ad3d166ed0301d4cb51e8d563 added only the Task 6 prompt and candidate-review implementation. The focused behavior suite passed, while the owned production coverage gate correctly remained red at 97%.
  3. 7778f76ef456bccbbd905d69855febafe61557b6 added terminal branch tests. Hosted run 31944365667 passed 41 focused tests, 100% owned statement/branch coverage, the shipped-symbol docstring gate, Ruff, and compileall.
  4. a3dd2e270f7400e6c1754c437c6831241ae4aa7c restacked the unchanged Task 6 slice on the then-current exact feat(email-writing): add hardened contextual-orchestrator boundary #1356 head 0c0ac2b598a8338a257e69bcca4d00b6fe20daf5. The parent delta and Task 6 changed-file sets are disjoint. Fresh exact-head workflow evidence is required; predecessor success is not substituted for current-head evidence.
  5. fa844bd035ab1f188a28c58e0ed2dc45fa31d0f3 restacked the unchanged Task 6 slice on the live exact feat(email-writing): add hardened contextual-orchestrator boundary #1356 head 9cd9b953a2dd236aebe1fcdc25e59ba3e9388505 with a normal two-parent merge commit. The parent delta and Task 6 changed-file sets remain disjoint. Fresh exact-head workflow evidence is required; predecessor success is not substituted for current-head evidence.

Included

  • a versioned system rubric and exact JSON candidate-response contract;
  • explicit untrusted-context boundaries and prompt-injection isolation for every authored field;
  • contextual LLM semantics with no keyword, regex, phrase-list, sender-domain, recipient-count, language-name, nearest-text, or positional semantic fallback;
  • exact JSON parsing that rejects duplicate keys, Markdown fences, surrounding prose, extra/missing fields, non-finite or invalid values, excessive nesting, and malformed Unicode;
  • bounded candidate diagnostics with rubric-owned categories, confidence, priority, evidence identifiers, and inert plain-text replacement only;
  • non-empty, in-range Unicode-code-point TextPositionSelector validation before Judge admission;
  • overlapping selector rejection and evidence IDs restricted to the server-authorized context bundle;
  • control-character and bidi-control replacement rejection while markup-looking text remains inert plain text;
  • contrast fixtures showing that the same words can have different contextual meaning and the same issue can be expressed with different words;
  • incremental → route and deep → conduct orchestration modes;
  • canonical prompt/template and candidate-payload hashes without retaining plaintext;
  • payload-redacted public errors;
  • focused Python 3.14 tests, 100% owned statement/branch coverage gate, shipped-symbol docstring gate, Ruff, and compileall.

Authority boundary

Naruon owns authorized email/thread/recipient context, prompt construction, candidate parsing, deterministic integrity validation, and candidate workflow policy. contextual-orchestrator owns provider-neutral routing and reasoning allocation.

This PR does not admit a candidate into the user-facing diagnostic response, make send decisions, call the independent fast-mlsirm Judge, publish a calibration policy, persist raw prompts or model outputs, or add deterministic semantic fallback.

Parent-authority correction inherited by the restack

The current #1356 parent removed three historical write-capable workflow identities that contradicted the dedicated single-writer boundary:

  • .github/workflows/email-writing-orchestrator-promotion.yml;
  • .github/workflows/email-writing-orchestrator-promotion-v2.yml;
  • .github/workflows/email-writing-task5-finalize.yml.

The Task 6 restack carries those removals forward. Its own dedicated workflow is read-only (contents: read) and uses persist-credentials: false.

Merge boundary

Keep this PR Draft while #1356 and its parent stack remain unmerged. Merge only after the unchanged exact head and then-live base satisfy every applicable repository/inherited ruleset, all required CI/security/coverage/dependency/package/provenance workflows are terminal-success, every actionable review thread is resolved, and a qualifying independent non-author post-last-push approval exists.

Queued, pending, skipped-required, neutral, failed, absent, stale, predecessor-head, model-only, status-only, author-only, or cancelled evidence is non-passing. This update does not approve, merge, squash, empty-requeue, force-cancel, or mark Ready.

@coderabbitai

coderabbitai Bot commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

@seonghobae, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 8 minutes

Limit details: You’ve used all 1 included review currently available under your plan.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 7333a611-af16-4d0c-8e9e-21a313c088f4

📥 Commits

Reviewing files that changed from the base of the PR and between 9cd9b95 and fa844bd.

📒 Files selected for processing (6)
  • .github/workflows/email-writing-candidate-tdd.yml
  • backend/services/email_writing_candidate_review.py
  • backend/services/email_writing_prompt.py
  • backend/tests/fixtures/email_writing/candidate_outputs.json
  • backend/tests/test_email_writing_candidate_review.py
  • backend/tests/test_email_writing_candidate_review_terminal_coverage.py

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.

@github-actions

github-actions Bot commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

PR governance metadata gate is not ready for fa844bd035ab1f188a28c58e0ed2dc45fa31d0f3:

  • Draft PR: merge automation is paused.

Bring feat/llm-email-writing-candidate-task6 onto the current
feat/llm-email-writing-orchestrator-task5 head without changing Task 6
candidate-parse semantics or restoring write-capable workflows.

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 fa844bd035ab1f188a28c58e0ed2dc45fa31d0f3 (normal merge of live parent #1356 9cd9b953). Predecessor a3dd2e27 evidence does not transfer. Local Task 6: 41 passed, 100% coverage. Write-capable promotion/finalize workflows stay absent. Keep Draft. This comment is not an approval.

@coderabbitai

coderabbitai Bot commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

@seonghobae I will review exact head fa844bd035ab1f188a28c58e0ed2dc45fa31d0f3. I will treat predecessor-head evidence as non-passing and keep the PR Draft.

⚠️ 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.

@opencode-agent opencode-agent Bot added priority: medium Normal-priority or P2 work status: draft Draft pull request type: feature New or expanded product capability labels Aug 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

priority: medium Normal-priority or P2 work status: draft Draft pull request type: feature New or expanded product capability

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants