Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
8f7ff8b
fix(email-detail): make responsive evidence actions functional
seonghobae Aug 5, 2026
e907955
ci: repair PR 1245 review findings test-first
seonghobae Aug 5, 2026
43d09e7
chore(ci): remove completed PR 1245 repair workflow
seonghobae Aug 5, 2026
abd2967
test(email-detail): stage selected-source writeback regressions
seonghobae Aug 5, 2026
3819eb9
ci: verify PR 1245 selected-source repair
seonghobae Aug 5, 2026
64fd961
fix(ci): target the EmailDetail conflict panel precisely
seonghobae Aug 5, 2026
40d43bc
ci: retry PR 1245 repair with precise panel anchor
seonghobae Aug 5, 2026
400b281
ci: rerun PR 1245 selected-source repair
seonghobae Aug 5, 2026
77b9185
fix(ci): align PR 1245 regressions with explicit confirmation
seonghobae Aug 5, 2026
940cc9a
ci: rerun PR 1245 explicit-confirmation repair
seonghobae Aug 5, 2026
8df011f
fix(ci): repair PR 1245 transformer quoting
seonghobae Aug 5, 2026
4b17725
ci: rerun verified PR 1245 repair
seonghobae Aug 5, 2026
a80c2b5
fix(ci): avoid synchronous effect state resets
seonghobae Aug 5, 2026
7802b51
ci: finalize PR 1245 selected-source repair
seonghobae Aug 5, 2026
a1a6460
chore(pr1245): remove obsolete repair workflow
seonghobae Aug 5, 2026
d750465
chore(pr1245): remove obsolete repair workflow v2
seonghobae Aug 5, 2026
2d15ea4
chore(pr1245): remove obsolete repair workflow v3
seonghobae Aug 5, 2026
b51999d
chore(pr1245): remove obsolete repair workflow v4
seonghobae Aug 5, 2026
7717cec
chore(pr1245): remove completed repair workflow v5
seonghobae Aug 5, 2026
592d91e
chore(pr1245): remove temporary patch transformer
seonghobae Aug 5, 2026
b042b21
chore(pr1245): remove temporary effect lint
seonghobae Aug 5, 2026
d1fa097
chore(pr1245): remove temporary repair patcher
seonghobae Aug 5, 2026
55e4573
chore(pr1245): remove completed repair script
seonghobae Aug 5, 2026
4d5f4e3
test(email-detail): stage selected-source calendar contract
seonghobae Aug 5, 2026
354f6c3
ci(email-detail): verify selected-source repair
seonghobae Aug 5, 2026
15137eb
ci(email-detail): repair deterministic helper state
seonghobae Aug 5, 2026
60e1afc
chore(ci): finalize verified EmailDetail review repair
seonghobae Aug 5, 2026
e48581f
chore(pr): remove completed PR 1245 finalizer
seonghobae Aug 5, 2026
cb5f3e9
chore(pr): remove completed PR 1245 repair workflow
seonghobae Aug 5, 2026
d83a175
chore(pr): remove completed PR 1245 repair helper
seonghobae Aug 5, 2026
e086f75
test(email-detail): require explicit calendar source writeback
seonghobae Aug 6, 2026
70959ee
test(ci): stage bounded PR 1245 calendar source repair
seonghobae Aug 6, 2026
05b9122
ci: verify PR 1245 explicit calendar source boundary
seonghobae Aug 6, 2026
281ef2e
ci: finalize PR 1245 calendar source on reopen
seonghobae Aug 6, 2026
3b21327
fix(ci): enable pnpm after Node setup
seonghobae Aug 6, 2026
4ef7082
fix(ci): make PR 1245 repair indentation-safe
seonghobae Aug 6, 2026
1dcd1b8
ci: bind PR 1245 repair to corrected transformer
seonghobae Aug 6, 2026
c6cb203
fix(ci): target the unique rendered action-item block
seonghobae Aug 6, 2026
8499f3f
fix(ci): normalize PR 1245 render anchors
seonghobae Aug 6, 2026
3fec4e9
ci: repair exact calendar-source panel transform
seonghobae Aug 6, 2026
41e1f92
fix(ci): remove malformed PR 1245 reopen workflow
seonghobae Aug 6, 2026
482725e
fix(ci): retrigger bounded calendar-source repair
seonghobae Aug 6, 2026
f9e7a02
fix(ci): make PR 1245 repair workflow valid YAML
seonghobae Aug 6, 2026
71a96ea
ci: activate pinned pnpm before setup-node caching
seonghobae Aug 6, 2026
67be57e
ci(pr1245): finalize explicit calendar source repair
seonghobae Aug 6, 2026
38d5e77
ci(pr1245): finalize calendar source repair v3
seonghobae Aug 6, 2026
a4f02a9
chore(ci): add fail-closed PR 1245 finalizer
seonghobae Aug 6, 2026
bb8caf6
fix(ci): finalize PR 1245 with fail-closed exact-head verification
seonghobae Aug 6, 2026
f40b377
ci(email-detail): execute fail-closed PR 1245 finalizer
seonghobae Aug 6, 2026
886220d
fix(ci): allow exact-head checkout in PR 1245 finalizer
seonghobae Aug 6, 2026
f430376
fix(ci): enable pnpm before cache initialization
seonghobae Aug 6, 2026
aa5c4b3
fix(ci): make PR 1245 status repair multiplicity explicit
seonghobae Aug 6, 2026
f76e1b2
test(email-detail): require explicit source after shell command
seonghobae Aug 6, 2026
d4574ba
fix(ci): remove invalid superseded PR 1245 workflow
seonghobae Aug 6, 2026
5aae303
test(email-detail): select the rendered writeback action
seonghobae Aug 6, 2026
6b4f2ba
fix(email-detail): key calendar sources to active context
seonghobae Aug 6, 2026
9aaea8e
fix(ci): preserve generated TypeScript indentation
seonghobae Aug 6, 2026
5bf17ff
fix(email-detail): require explicit calendar source
github-actions[bot] Aug 6, 2026
e45fc3b
docs(email-detail): record fail-closed source lifecycle
seonghobae Aug 6, 2026
4a6f339
test(email-detail): cover calendar action disabled states
seonghobae Aug 20, 2026
af81b67
Merge remote-tracking branch 'origin/develop' into HEAD
seonghobae Aug 20, 2026
796b34c
Merge remote-tracking branch 'origin/develop' into fix/pr1245-current
seonghobae Aug 21, 2026
885ee0c
fix: await EmailDetail input updates and retain callback dependencies
seonghobae Sep 6, 2026
38c375e
merge(ui): inherit complete dependency security prerequisite
seonghobae Sep 6, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -477,6 +477,10 @@ in this repo.
the visible app language; do not rely on the SVG icon alone for Calendar,
Tasks, drawer, modal, or toolbar actions.
- Execution steps resulting in `Timeout`, `Fatal`, `Warn`, or `Denied` outputs are considered hard failures. Tests must run without these warnings to be considered passing.
- React 테스트의 상태 갱신 입력은 나중의 버튼 클릭뿐 아니라 native value
setter와 `dispatchEvent`도 `await act` 안에서 실행한다. 진단 spy는 원래
출력을 유지하고 `act` 경고가 없는지 단언한다. 테스트를 통과시키려고
`console.error`를 끄지 않는다.
- Strix success artifacts must also be scanned for `Timeout`, `Fatal`, `Warn`,
or `Denied` output before accepting clean evidence. Filter only narrowly known
third-party Strix internal warnings, such as the
Expand Down
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
## [Unreleased]
### EmailDetail 반응형 실행 표면

- 참여자와 첨부파일 증거를 모바일·데스크톱에서 동일하게 확인할 수 있도록 반응형 스크롤 레일과 명시적 접근성 이름을 추가했습니다.
- 일정 충돌 패널의 `일정 조율` 버튼을 기존 calendar writeback intent에 연결하고, 서명된 서버 목록에서 사용자가 명시적으로 선택한 opaque `target_source_id`만 전송하며, source conflict 재확인·부분 실패·loading·disabled·live-status 상태를 검증합니다.
- UI PR에 섞인 thread ID, SMTP allowlist, `.msg` import, tenant scope backend 변경은 정확한 `develop` 기준으로 제거했습니다.

### 의미 단위 임베딩

- 긴 이메일·첨부 본문을 의미 단위 청크로 임베딩한 뒤 기존 email/attachment 벡터 계약으로 평균화하고, 청크 요청·벡터 누적을 제한된 창으로 처리합니다. OpenAI `text-embedding-3-*`에는 저장 차원(`1536`)을 직접 요청하도록 보강했습니다. 합성 메일 fixture 5건(70청크)과 provider 요청 계약으로 1,536차원 벡터 경로를 검증했으며, 실행 시 선택한 임베딩 제공자에 본문·파싱된 첨부 텍스트를 전송할 수 있습니다. 회사 기밀 데이터는 fixture·commit·PR·log에 포함하지 않습니다.
- EmailDetail 테스트가 지원하지 않는 스레드 병합/분리 버튼을 `textContent`뿐 아니라 `aria-label`과 `title` 접근 가능 이름으로도 검출하도록 바꿔, 아이콘 전용 버튼 회귀를 놓치지 않습니다.

Expand Down
114 changes: 114 additions & 0 deletions docs/doctoring/email-detail-responsive-action-surface.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
# EmailDetail responsive action surface doctoring

## Decision

The email detail view exposes participants and attachment names at every viewport
size. Attachments use a horizontally scrollable, explicitly named region so a
small viewport does not silently remove source evidence. The meeting-conflict
panel reuses the existing calendar writeback-intent handler rather than rendering
an inert call-to-action. The user must select an opaque source returned by the
signed server registry before the action is enabled; every intent carries that
exact `target_source_id`, and a source conflict clears the selection so the user
must confirm the current source again. Mixed batch outcomes preserve successful
intents, report the failed count, and never relabel a source identifier as a
provider calendar-event identifier. Loading, disabled, and polite live-status
states remain in the same product surface.

Calendar-source state is keyed to the active email and actionable summary
context. A navigation or summary-context change therefore derives an empty,
non-confirmed loading or idle view immediately instead of reusing a source from a
previous email. Registry success or failure publishes state only from the still
mounted request for that exact context; stale requests cannot reactivate an old
selection. This fail-closed lifecycle also avoids synchronous state resets inside
the React effect while preserving explicit confirmation.

Unrelated backend changes are excluded from this UI slice. Thread identifier,
SMTP destination, import-format, and tenant-scope policy changes require their
own security rationale and regression contracts rather than hitchhiking on a
presentation PR.

## Accessibility boundary

The implementation preserves native button semantics and the repository's
keyboard-visible focus system, gives the attachment evidence region an
accessible name, and exposes asynchronous status through `role=status` and
`aria-live=polite`. WCAG 2.2 is used as the current normative target. The focused
regression proves discoverability and activation in the DOM, but this record does
not claim full WCAG conformance without contrast, zoom, assistive-technology, and
manual usability evidence.

## Verification contract

- The participant list renders without an unsafe type assertion.
- The attachment rail is present and not hidden on small viewports.
- The meeting action is disabled when no extracted action item exists, while the
request is pending, or until one current server-authorized source is confirmed.
- Activating the meeting action sends the exact opaque `target_source_id` with
every writeback-intent request.
- A `409` source conflict clears confirmation and requires explicit reselection.
- Source state is never reused across email or actionable-summary context keys,
and an unmounted registry request cannot publish stale state.
- Complete and partial batches produce distinct polite status evidence, and
analytics never treat `target_source_id` as a provider event identifier.
- The three unrelated backend files are byte-identical to the exact PR base.
- Frontend focused tests, full tests, lint, type checking, coverage collection,
and production build run before the verified commit is published.

## 입력 이벤트와 Hook 의존성 경고 수리

PR #1245의 `796b34c5a1322f09c6f00b8cf24591ae04b89b6b`에서 EmailDetail
테스트 26개는 React `act` 경고 4개를 출력하고도 exit 0으로 끝났다.
초안 지시 입력, 초안 지우기, 전송 성공·실패 테스트가 native value setter와
입력 이벤트를 `act` 밖에서 실행했고, 이후 버튼 클릭만 감쌌다. 입력 자체가
React 상태 갱신을 예약하므로 나중의 클릭을 감싸는 것으로는 해결되지 않는다.
이전 커밋의 재현 근거는 다음 기록에 남아 있다.
https://github.com/ContextualWisdomLab/naruon/pull/1244#issuecomment-5559885208

원래 출력을 유지하는 `console.error` spy로 각 테스트의 정리 단계까지
`not wrapped in act` 발생 여부를 검사하고, 단언 전에 console을 복원한다.
검사만 추가했을 때 4개 실패·22개 통과로 재현됐다. 기존 setter/event 쌍
4개를 `await act(async () => ...)`로 감싼 뒤에는 EmailDetail과
calendar-writeback 테스트 30개가 해당 경고 없이 통과했다. 실패 경로의
API 오류 로그는 그대로 출력하며, 경고를 숨겨 통과시키지 않는다.

이후 lint에서 같은 컴포넌트의 `setSelectedWritebackSourceId` 의존성 누락을
발견했다. 일반 lint는 경고 1개와 exit 0을 반환했지만 `--max-warnings 0`은
exit 1로 실패했다. 이 함수는 안정적인 React state setter가 아니라
`sourceContextKey`와 `sourceContextIsActionable`에 따라 바뀌는 콜백이다.
일정 반영 콜백이 현재 선택 문맥을 사용하도록 의존성 목록에 추가한다.
공급자 호출 계약이나 CalendarPage 테스트는 바꾸지 않는다.

이미 사용하는 React 도구로 해결하므로 새 상호작용 라이브러리나 공통
래퍼는 추가하지 않는다. 이 수리는 실제 브라우저 동작, 전체 테스트의 모든
경고 제거, 최신 Visual Inspection 또는 보호 병합 완료를 뜻하지 않는다.
Context7은 사용량 한도로 조회에 실패해 아래 React 공식 문서의 비동기
이벤트 처리 지침을 확인했다.

`frontend`에서 실행할 검증 명령:

```sh
corepack pnpm exec vitest run src/components/EmailDetail.test.tsx src/components/EmailDetail.calendar-writeback.test.tsx
corepack pnpm exec eslint src/components/EmailDetail.tsx src/components/EmailDetail.test.tsx --max-warnings 0
```

수리 후 위 테스트 30개와 전체 `eslint . --max-warnings 0`, 타입 검사,
프로덕션 빌드는 exit 0이다. 전체 커버리지 실행은 52파일·442테스트가
통과했지만 별도 CalendarLayout `act` 경고 3개는 남았다. 커버리지는
lines 86.76%, statements 84.06%, functions 85.67%, branches 75.18%로
100% 목표를 충족하지 못한다. 측정 대상을 줄이거나 남은 경고를 숨기지
않으며, 이 결과를 전체 제품의 검증 완료로 표시하지 않는다.

## References

React. (n.d.). *act*. https://react.dev/reference/react/act

World Wide Web Consortium. (2023). *Web Content Accessibility Guidelines
(WCAG) 2.2*. https://www.w3.org/TR/WCAG22/

World Wide Web Consortium. (n.d.). *Understanding success criterion 2.4.7:
Focus visible*. Retrieved August 5, 2026, from
https://www.w3.org/WAI/WCAG22/Understanding/focus-visible.html

World Wide Web Consortium. (n.d.). *Understanding success criterion 4.1.3:
Status messages*. Retrieved August 5, 2026, from
https://www.w3.org/WAI/WCAG22/Understanding/status-messages.html
Loading
Loading