WBS와 마일스톤
- 작성일: 2026-10-17
- 상태: 살아있는 문서. 작업 상태가 바뀔 때마다 같은 파일을 고치고 Changelog 에 남긴다.
- 기준 문서: MVP 범위와 일정 6장 (일정), 7장 (성공 기준), 시스템 구조와 데이터 모델 12장 (병렬 개발 계획)
1. 한눈에 보기
| 마일스톤 | 계획일 | 내용 | 완료 조건 | 상태 |
|---|---|---|---|---|
| M0 | 10/17 (금) | 작업 원칙, 툴체인, 스캐폴딩, 기반 문서 | mix test 통과, 문서 3종 |
완료 |
| M1 | 10/18 (토) | 데이터 기반 (스키마, 마이그레이션, 권한, engagement) 과 GL 적재 | 2만 행 적재 테스트 통과 | 완료 (1.17 통과, PR #2 병합 adf144c) |
| M2 | 10/19 (일) - 10/20 (월) | 룰 엔진, Oban 워커, 실시간 진행률 | 룰 적중과 정답 라벨 비교 테스트 통과 | 완료 (Runner 경유 정답 라벨 시험 824b89b) |
| M3 | 10/20 (월) - 10/21 (화) | AI 트리아지 (behaviour, Claude, Fake) | 키 없이 Fake 로 전체 흐름 동작 | 진행 중 (3.1-3.3 완료, S5 건별 요청 동작. S4 AI 열과 일괄 요청 3.4 남음) |
| M4 | 10/21 (화) - 10/22 (수) | 작성자 결론, 검토자 승인, SoD, 감사 로그 화면, Presence | LiveView 테스트 통과 | 진행 중 (4.1, 4.2, S5 결론과 검토 완료. Presence 와 통합 테스트 남음) |
| M5 | 10/22 (수) | 디자인 다듬기, 배포, 시드 데이터 | 외부에서 데모 URL 접속 | 완료 (10/25 Render 첫 배포, 외부 접속 확인) |
| M6 | 10/23 (목) | README, 데모 GIF, 지원서 제출 | 제출 완료 | 진행 중 (README, 문서 위키 당겨 완료) |
| M7 | 10/24 이후 | 2단계 확장 | 면접 전까지 | 대기 |
상태 값: 완료 / 진행 중 / 대기. 담당 값: 메인 (메인 세션), A/B/C/D (팀 워커, 아키텍처 문서 12장 배정. 라운드 3 은 12.1).
10/19 재조정: M2 를 계획일 10/19 에 시작하지 못해 (devlog 10/19-1) 하루씩 밀릴 상황이었다. 3.1 (AI 모듈) 은 M2 와 파일이 겹치지 않아 라운드 3 에 당겨 워커 D 에게 맡기고, M3-M4 를 반나절씩 겹쳐 M5 완충을 줄인다. M6 (10/23) 과 지원 마감 (10/25) 은 그대로다.
2. 마일스톤별 WBS
M0. 기반 (10/17, 완료)
| ID | 작업 | 담당 | 상태 | 산출물 / 근거 |
|---|---|---|---|---|
| 0.1 | 작업 원칙 (AGENTS.md, CLAUDE.md, refs/phoenix-guidelines.md) | 메인 | 완료 | PR #1 |
| 0.2 | 툴체인 (Elixir 1.20.4, OTP 29.1.2, PostgreSQL 16.4) | 메인 | 완료 | AGENTS.md 9장 |
| 0.3 | Phoenix 1.8 스캐폴딩 (--binary-id, phx.gen.auth) |
메인 | 완료 | PR #1 |
| 0.4 | GitHub 원격 연결 | 메인 | 완료 | basilry/kpmg-elixir (비공개) |
| 0.5 | 도메인 문서 (분개 테스트 룰, 감사 용어, 합성 데이터 명세) | 메인 | 완료 | domain -3 |
| 0.6 | 기획 문서 (MVP 범위와 일정) | 메인 | 완료 | planning -2 |
| 0.7 | 아키텍처 문서 (시스템 구조, 데이터 모델, 모듈 계약) | 메인 | 완료 | architecture -4 |
| 0.8 | 디자인 시스템 md, html 시안 | 메인 | 완료 | design -5, -7 |
| 0.9 | devlog (프로젝트 선정, 인증과 첫 병렬 라운드) | 메인 | 완료 | devlog -1, -6 |
완료 판정: PR #1 을 main 에 병합 (505d731).
M1. 데이터 기반과 GL 적재 (10/18 계획, 10/17 시작, 완료)
브랜치: feature/foundation (선행 작업). 병렬 라운드 2 의 워커 브랜치는 모두 92fa9e2 에서 갈라졌다.
1-A. 선행 작업 (메인, 순차)
| ID | 작업 | 담당 | 상태 | 커밋 |
|---|---|---|---|---|
| 1.1 | Oban 2.24.2, NimbleCSV 1.3.0 의존성과 큐 설정 (ingest 1, rules 4, llm 2) | 메인 | 완료 | 58e0183 |
| 1.2 | Oban, Presence 를 슈퍼비전 트리에 추가 | 메인 | 완료 | f01ecbd |
| 1.3 | 마이그레이션 8개 (oban_jobs, engagements, ledger, testing, triage, review, audit_events, append-only 트리거) | 메인 | 완료 | 3ee2579 |
| 1.4 | 도메인 스키마 13개와 DB 제약 테스트 | 메인 | 완료 | 60bc32d |
| 1.5 | AuditTrail.append/3, record, actor/1 |
메인 | 완료 | e073c9a |
| 1.6 | Engagements.Policy 역할별 권한표 |
메인 | 완료 | 54d19a8 |
| 1.7 | engagement 라우트 7개와 자리표시 LiveView 6개 | 메인 | 완료 | 9a50daa |
| 1.8 | 선행 작업 결과를 계약 문서에 반영 | 메인 | 완료 | 44dbb30 |
| 1.9 | 접근 제어 핵심 (fetch_role/2, authorize/3, topic/1, subscribe/2, broadcast/2) |
메인 | 완료 | 2f104a1 |
| 1.10 | Ledger.Generator 계약과 10/18 작업 분담 조정 |
메인 | 완료 | 92fa9e2 |
선행 작업 검증: mix precommit 통과 (테스트 145개, 실패 0).
1-B. 병렬 라운드 2 (워커, 완료)
| ID | 작업 | 담당 | 상태 | 브랜치 | 보고 문서 |
|---|---|---|---|---|---|
| 1.11 | Engagements 나머지 공개 함수와 EngagementLive (S1, S2) | A | 완료 (병합 f699d52, 메인 보정 2601443) | feature/engagements |
devlog -9 |
| 1.12 | Ledger CsvParser, Importer, ImportWorker 와 테스트 | B | 완료 (병합 ece19bd. 2만 행 적재 663-748 ms) | feature/ledger-import |
devlog -10 |
| 1.13 | Ledger.Generator 합성 GL 생성기와 Testing.Holidays |
C | 완료 (병합 56c701d. 기본 시드 8,341 전표, 19,804 행) | feature/ledger-generator |
devlog -11 |
워커별 테스트 DB 는 MIX_TEST_PARTITION (_a, _b, _c) 으로 나눴다.
1-C. 통합 (메인, 워커 병합 뒤)
| ID | 작업 | 담당 | 상태 | 선행 |
|---|---|---|---|---|
| 1.14 | 워커 브랜치 diff 와 검증 출력 확인, feature/foundation 에 하나씩 병합 (병합마다 mix precommit) |
메인 | 완료 (A f699d52, C 56c701d, B ece19bd 순. 병합 후 238 통과) | 1.11-1.13 |
| 1.15 | Ledger.generate_sample_import/3 구현 |
메인 | 완료 (cf923bb) | 1.12, 1.13 |
| 1.16 | S2 GL 적재 목록 연결 (Ledger.list_imports/2, :import_updated) |
메인 | 완료 (e2e2fd4) | 1.11, 1.12 |
| 1.17 | Generator 출력 -> CsvParser/Importer 통합 테스트 (2만 행) | 메인 | 완료 (cf923bb. CRLF 그대로 8,341 전표 / 19,804 라인 적재, 981.8 ms) | 1.15 |
| 1.18 | Testing.Holidays 를 계약 문서에 반영, 워커 계약 해석 반영 (A: add_member/4 role 문자열 허용, 비멤버 list_members/2 는 [], 스키마 @type t 부재. C: target_lines 미구현을 도메인 문서 7.1 에 표기. B: CSV 오류 코드 4종 추가) |
메인 | 완료 (8a49862, f81367d, 6ecab07. 247 통과) | 1.14 |
| 1.19 | 라운드 devlog (-12), 색인 갱신, feature/foundation -> main PR |
메인 | 완료 (PR #2 병합 adf144c) | 1.14-1.18 |
M1 완료 판정: 1.17 의 2만 행 적재 테스트 통과와 main 병합.
M2. 룰 엔진 (10/19-10/20, 완료)
| ID | 작업 | 담당 | 상태 |
|---|---|---|---|
| 2.0 | 선행 작업: Rule behaviour, RuleContext, Rules 레지스트리, 참조 룰 approval_control_gap, Testing 읽기 함수 (count_findings/2 포함), Runner/FailureHandler 골격, test config, 계약 확정 (아키텍처 문서 12.1) |
메인 | 완료 |
| 2.1 | Testing 실행 경로: start_test_run, RuleWorker, 완료 감지, FailureHandler |
A (Fable xhigh) | 완료 (병합 fadb51c, devlog 2026-10-19-2) |
| 2.2 | 나머지 룰 7개와 Rules 레지스트리 등록 | B (Astra xhigh) | 완료 (병합 ff95ad8, devlog -3) |
| 2.3 | TestRunLive (S4, 실시간 진행률) 와 ImportLive (S3) | C (Sol 6.1 max) | 완료 (병합 af65bb3, devlog -4) |
| 2.4 | 룰 적중 대 정답 라벨 비교 테스트 (도메인 7.6 기준 1, 2). 룰 직접 호출은 B, Runner 를 거친 확인은 병합 뒤 메인 | B, W5 | 완료 (B 몫 ff95ad8, Runner 경유 W5 병합 824b89b) |
| 2.5 | S1 목록에 "최근 테스트", "검토 큐" 열 추가 (1.11 에서 TestRun 부재로 보류) | 메인 | 완료 (4bac346, 1283c6d) |
| 2.6 | S2 테스트 실행 목록, "테스트 실행" 단추, stat_row 연결 (화면설계서 C-07) | 메인, W5 | 완료 (5c7e560, 단추 클릭 테스트 W5 병합 824b89b. 브라우저 확인은 라운드 4b 의 S1-S6 확인에서 메인) |
M3. AI 트리아지 (10/20-10/21, 진행 중)
| ID | 작업 | 담당 | 상태 |
|---|---|---|---|
| 3.1 | AI 모듈 (behaviour, Claude 클라이언트, Fake, input_hash/1) 과 Req.Test 테스트 |
D (Sol 6.1 max, 라운드 3) | 완료 (병합 3706032, 금지 표현 오탐 수정 90f6184 포함, devlog -5) |
| 3.2 | Triage 컨텍스트와 TriageWorker | W1 (Fable xhigh, 라운드 4) | 완료 (W1 병합 52c38c8, 518 통과) |
| 3.3 | FindingLive 상세 (S5 표시. 동작은 4.3 과 함께 라운드 4b) | W4 (Sol 6.1 max, 라운드 4) | 완료 (표시 34c247e, 동작과 반려 사유 폼 W6 2718ff9) |
| 3.4 | AI config, 키 없이 Fake 로 전체 흐름 확인 (S4 AI 열과 일괄 요청 포함) | 메인 | 진행 중 (S5 건별 AI 제안 요청 단추 0f53b7a. S4 AI 열과 일괄 요청 남음. 선행 작업 AI.model/0 fa8a3c1) |
M4. 결론, 검토, 감사 로그 (10/20-10/22, 진행 중)
| ID | 작업 | 담당 | 상태 |
|---|---|---|---|
| 4.1 | Review 컨텍스트와 SoD 테스트 | W2 (Astra xhigh, 라운드 4) | 완료 (cf88e39, 420 통과. 두 연결 실제 경합은 통합 테스트로) |
| 4.2 | AuditTrail 조회와 AuditLive (S6) | W3 (Sol 6.1 max, 라운드 4) | 완료 (80dc408). 공통 상단 바와 Presence 는 4.3 |
| 4.3 | Presence 와 FindingLive 결론/리뷰 UI | 메인 (라운드 4b), W6 (S5 동작) | 진행 중 (S5 결론 제출과 승인/반려 2718ff9, AI 요청 단추 0f53b7a, S5 상단 바 연결 f300f2f 완료. Presence 와 검토 대기열 '다음 미판단' 남음) |
| 4.4 | Presence child, router 조정, LiveView 통합 테스트 | 메인 | 대기 |
M5. 배포 (10/22, 완료 10/25)
| ID | 작업 | 담당 | 상태 |
|---|---|---|---|
| 5.1 | 배포 대상 결정 (검토: 무료 조건으로 Render + Neon 제안) | 메인 | 완료 (10/25 사용자 결정: Render Free + Neon Free) |
| 5.2 | 디자인 다듬기: layouts.ex 셸 교체와 본문 폭 확대 (디자인 문서 설치 6단계), tk-table 등 app.css 토큰, Gettext ko 로케일 (changeset 메시지 한글화), html 시안과 대조 |
F1, F2 (Sol 6.1 max, 라운드 5) | 완료 (10/20 당김. 기본 로케일 ko fbb30b8, F2 1e0574d, F1 4115351, 브라우저 확인 수정 8502ed7. devlog -12, -13, -14) |
| 5.3 | 데모용 시드 데이터 (합성 데이터만) | 메인 | 완료 (f196012. 작성자와 검토자, 누리정밀 FY2025, 적재와 룰 실행. 비밀번호는 TICKMARK_DEMO_PASSWORD 가 있을 때만) |
| 5.4 | 배포와 외부 접속 확인 (가이드) | 메인, 사용자 | 완료 (10/25. 저장소 준비와 로컬 release 확인 devlog 2026-10-25-2. 사용자 계정과 값 입력 뒤 main ce33571 첫 배포, 외부 HTTP 와 화면 확인 devlog 2026-10-25-3. https://tickmark-e0ki.onrender.com. 17:53 사용자가 플랜을 0.5c-512mb 로 바꾼 뒤 PR #4, #5 를 담은 9629df7 재배포 확인, 가이드 5.3절) |
M6. 제출 (10/23, 진행 중)
| ID | 작업 | 담당 | 상태 |
|---|---|---|---|
| 6.1 | README (아키텍처, Why Elixir, devlog 링크) | 메인 | 진행 중 (10/20 초안: 목표, 화면, 아키텍처, 스택, Why Elixir, 실행 방법. 데모 시드 기준 실행과 로그인 개정 cfbed56. M6 에 데모 GIF 와 최종 상태 반영) |
| 6.2 | 3분 데모 시나리오와 데모 GIF | 메인 | 대기 |
| 6.3 | 공개 전 점검 (시크릿, 실데이터, 절대 경로) 후 저장소 공개 전환 | 메인 | 대기 |
| 6.4 | 지원서 제출 (마감 10/25) | 사용자 | 대기 |
| 6.5 | 문서 위키 (/docs, 상단 바 링크): 저장소 문서를 배포 주소에서 읽기 |
메인 | 완료 (1a2ef4b, 584 통과, devlog -15) |
| 6.6 | 요구사항 명세서, 기능 정의서, API 연동 규격서 | D1, D2 (Astra max, 라운드 5) | 초안 완료 (D1 60781a3, D2 164788e. 기준 커밋 이후 변경은 API 연동 규격서 14장). FN 과 IF 교차 링크 남음 |
M7. 2단계 (10/24 이후, 대기)
OpenTelemetry, Terraform + Azure, ClickHouse + Benford 분석, Ash 일부 영역 실험, 두 번째 감사 절차. 순서는 M6 이후 정한다.
3. 리스크와 미결 사항
| 항목 | 영향 | 대응 | 기한 |
|---|---|---|---|
| 무료 플랜에서 막힘 (0.15 CPU, 512 MB, 메모리 지표 없음) | 데모 URL | 10/25 첫 배포 성공 (무료 Docker 허용, 시드 약 14초, 메모리 초과 이벤트 없음). Linux 메모리는 Render Metrics 에서 약 190 MB (512 MB 의 약 38%). 17:53 사용자가 0.5c-512mb (유료) 로 바꿔 잠듦과 0.15 CPU 제약이 없어짐. 막히면 Render 네이티브 Elixir 런타임 또는 Fly.io (가이드 5.3절, 6장) | 해결 |
plug_crypto 2.2.0 보안 권고 (EEF-CVE-2026-105963, MEDIUM) |
잘못된 인자로 부르면 스택 트레이스에 secret key base 가 나올 수 있음 | 2.2.1 로 올림 (PR #5, 1a3f6a3), 10/25 9629df7 재배포 확인 | 해결 |
render.yaml 의 plan: free 와 대시보드 플랜 (0.5c-512mb) 이 다름 |
render.yaml 을 바꾼 push 가 Blueprint 동기화되면 Free 로 돌아가 잠듦이 다시 생김 |
render.yaml 을 고칠 때 plan 을 맞추거나 Auto Sync 를 끈다. Free 로 돌아갈 뜻이면 그대로 둔다 (가이드 5.3절) |
render.yaml 을 고치기 전 |
| 저장소 비공개 | 제출 시 열람 불가 | 6.3 점검 뒤 공개 전환 | 10/23 |
| Generator 출력과 CsvParser 입력 형식 불일치 가능성 (B, C 가 따로 구현) | M1 완료 조건 | 해결: 1.17 통합 테스트에서 C 의 CRLF 출력을 B 의 파서가 그대로 받아 오류 없이 적재 (cf923bb) | 해결 |
| 병렬 병합 충돌, 공유 파일 변경 요청 | 통합 지연 | 공유 파일은 메인 소유 (AGENTS.md 5.3), 브랜치를 하나씩 병합 | 라운드마다 |
| 실제 Claude 호출 미검증 (기본은 Fake) | 데모 품질 | Req.Test 로 요청/응답 형태 검증, 키가 있을 때만 수동 확인 | M3 |
M1 을 계획보다 하루 일찍 시작해서 생긴 여유는 M5 (배포) 완충으로 둔다.
Changelog
- 2026-10-17: 최초 작성. M0 완료, M1 선행 작업 (1.1-1.10) 완료, 병렬 라운드 2 (1.11-1.13) 진행 중 상태 기록
- 2026-10-17: 1.11 (워커 A) 완료와 병합 반영. A 의 남은 이슈를 1.18, 2.5, 5.2 에 배정
- 2026-10-17: 1.13 (워커 C) 완료와 병합 반영.
target_lines는 1.18, CRLF 확인은 리스크 표에 추가 - 2026-10-17: 1.12 (워커 B) 병합, 1.14-1.18 완료 반영. CRLF 형식 리스크 해결. 1.19 진행 중 (devlog -12, PR 승인 대기)
- 2026-10-19: 일정 재조정 (M2 10/19-10/20, M3 10/20-10/21, M4 10/21-10/22, M5 완충 축소, M6 유지). 2.0 선행 작업 완료, 라운드 3 (A 2.1, B 2.2/2.4, C 2.3, D 3.1) 시작, 2.6 (S2 실행 목록) 추가, 3.1 을 워커 D 로 당김
- 2026-10-19: 라운드 3 B (2.2), C (2.3), D (3.1) 병합 완료 반영 (병합 뒤 347 통과). 2.5 완료, 2.6 진행 중 (351 통과). A (2.1) 는 진행 중
- 2026-10-20: 2.1 완료 (A 병합 fadb51c, 385 통과). 라운드 4 시작: 3.2 W1, 3.3 표시 W4, 4.1 W2, 4.2 W3, 2.4 Runner 경유와 2.6 단추 테스트 W5. 3.4, 4.3, 4.4 는 라운드 4b (메인). M4 를 10/20 부터 진행 중으로
- 2026-10-20: 6.1 README 초안 작성 (사용자 요청으로 M6 에서 당김)
- 2026-10-20: 4.1 완료 (W2 병합 cf88e39, 420 통과)
- 2026-10-20: 4.2 완료 (W3 병합 80dc408, 445 통과), 3.3 표시 완료 (W4 병합 34c247e, 473 통과)
- 2026-10-20: 1.19 완료 (사용자 승인으로 PR #2 병합 adf144c). 4.3 의 S5 결론 제출과 승인/반려를 W6 에 선행 배정 (W2, W4 병합으로 가능)
- 2026-10-20: 5.1 배포 대상 검토 (무료 조건, Vercel 불가 사유, Render + Neon 제안). 사용자 결정 대기
- 2026-10-20: 2.4, 2.6 완료 (W5 병합 824b89b, 484 통과), 3.2 완료 (W1 병합 52c38c8, 518 통과)
- 2026-10-20: 5.2 를 라운드 5 (F1 셸과 홈, F2 인증 화면) 로 당김. 요구사항 명세서, 기능 정의서, API 연동 규격서 작성 (D1, D2) 추가
- 2026-10-20: 4.3 의 S5 결론 제출과 승인/반려 완료 (W6 병합 2718ff9, 546 통과)
- 2026-10-20: 라운드 5 병합 (F1, F2, D1, D2). M1, M2 완료 표기. 3.3, 5.2, 5.3 완료, 3.4 와 4.3 진행 상황 (S5 AI 요청 단추 0f53b7a, 상단 바 f300f2f), 6.5 문서 위키 (1a2ef4b, 584 통과) 와 6.6 명세 문서 추가, M5 와 M6 진행 중, 배포 리스크 행 갱신
- 2026-10-25: 5.1 완료 (Render Free + Neon Free), 5.4 진행 중 (저장소 준비와 로컬 release 확인, 588 통과). 배포 리스크 행을 무료 플랜 제약으로 바꿈
- 2026-10-25: 5.4 완료 (Render 첫 배포 ce33571, 외부 HTTP 와 S1-S6 화면 확인, devlog -3). M5 완료. 무료 플랜 리스크 행 갱신,
plug_crypto보안 권고 행 추가 - 2026-10-25: 5.4 에 플랜 변경 (사용자, Free -> 0.5c-512mb) 과 9629df7 재배포 확인 추가. 무료 플랜 리스크 행에 Linux 메모리 결과 반영,
plug_crypto행 해결,render.yaml플랜 어긋남 행 추가