반가워, Jason. 소장 작성 페이지 얘기 나누기 전에, 지금 실제로 뭐가 구현돼 있는지부터 내 눈으로 확인하고 시작하는 게 정확할 것 같아. 잠깐 코드 좀 보고 올게.
🔍 파일찾기 · **/*.{html,tsx,jsx,ts,js,vue}
경로: C:/Users/user/LAX-site
node_modules가 많아서 노이즈가 크네. 소장 페이지만 좁혀서 찾아볼게.
🔍 검색 · 소장|구상금|complaint|lawsuit|draft
경로: C:/Users/user/LAX-site
glob: !**/node_modules/**
📖 읽기 · routes.tsx
봤어. 지금 /draft 페이지가 어떻게 돌아가는지 정리하면 이래.
현재 소장 작성 페이지 (/draft) 구조
입력 폼 (GET /draft)
| 항목 | 필수 | 비고 |
|---|---|---|
| 의뢰처 | — | 기본값 서울신용보증재단 |
| 사건 요지 (한 줄) | — | 청구 성격 메모 |
| 증거자료 (텍스트) | ★ | 보증서·대위변제 내역·계약서 등 붙여넣기 |
| 증거 첨부파일 | — | 이미지·PDF·문서, 최대 8개, /chat/upload로 R2 업로드 |
| 추가 지시 | — | 지연손해금 포함 등 |
처리 흐름 (POST /draft)
- 증거(텍스트 또는 첨부) 없으면 에러 리다이렉트
- 입력을
[구상금청구 소장 작성 요청]프롬프트로 조립 → 나(변우석, slughanyul)에게 전달 - 채팅 세션(
scope='draft') 생성 + 태스크 큐 등록 →/chat/{세션}으로 이동해 거기서 초안 작성·수정 - 프롬프트에 이미 "증거에 없는 사실 지어내지 말고 [확인 필요] 표시, 끝에 [확인 필요 항목]·[추가 증거] 정리" 규칙이 박혀 있음
산출물
- 작성된 초안은 채팅에 남고, 최근 목록에서 HWPX(한글) 다운로드(
/draft/hwpx/:id) 가능 — 마지막 assistant 메시지를 한글 문서로 변환
내가 보는 현재의 한계 (논의 거리)
- 증거 입력이 자유 텍스트 한 덩어리 — 당사자/금액/날짜/계좌가 구조화돼 들어오지 않아서, 추출 정확도가 내가 본문에서 파싱하는 능력에 전적으로 의존함
- 연대보증인 다수·주채무자 구분을 폼에서 따로 안 받음 — 피고가 여럿이면 요지/지시란에 의존
- HWPX 변환이 "마지막 assistant 메시지" 통짜 — 초안 외 잡담이 섞이면 같이 빨려 들어갈 수 있음
- 청구취지 핵심값(원금·이율·기산일)을 별도로 검증·표시하는 단계가 없음
어느 쪽 얘기를 하고 싶어? 새 기능 추가인지, 지금 흐름의 개선인지, 아니면 특정 부분(증거 구조화 / 다수 피고 / HWPX 품질 / 청구취지 검증)을 짚고 싶은 건지 방향을 알려주면 거기 맞춰 깊이 들어갈게.
좋아, 그림이 선명해. 네가 그린 건 지금의 "폼 던지고 채팅으로 점프" 방식과는 다른, 2단 작업대(왼쪽 대화·오른쪽 라이브 문서) + 증거분석 중간산출물 + 출처 각주 + 제출용 다운로드 + 학습 루프야. 코드부터 손대기 전에, 지금 코드가 뭘 지원하고 뭐가 진짜 걸림돌인지부터 확인하고 설계를 맞출게.
📖 읽기 · hwpx.ts
📖 읽기 · shell.tsx
둘 다 봤어. 지금 구조 위에서 네 그림이 어디까지 그대로 얹히고, 어디가 진짜 벽인지 정직하게 정리할게.
네가 그린 흐름 → 5단계 파이프라인으로 분해
| 단계 | 내용 | 지금 코드 |
|---|---|---|
| ① 입력 | 의뢰인·사건요지·증거자료(텍스트+첨부) 최소 입력 | ✅ 폼 이미 있음 |
| ② 증거 분석·정리 산출물 | 모든 증거를 취합→구조화 (증거번호·당사자·금액·날짜·출처위치) = 별도 파일 1개 | ❌ 없음 (지금은 곧장 소장으로 감) |
| ③ 라이브 소장 작성 | 오른쪽 창에 소장이 스트리밍, 주장·요증사실마다 출처 각주 박힘 | ⚠️ 스트리밍은 채팅에 있음. 2단 작업대·각주는 없음 |
| ④ 협업 수정 | 왼쪽 대화로 같이 고침 | ⚠️ 채팅으로 됨. 단, 문서와 분리돼 있음 |
| ⑤ 제출용 다운로드 | 우상단 버튼 → PDF/HWPX 선택, 각주 제거, 실제 포맷 | ⚠️ HWPX(통짜)만. 포맷 선택·각주제거·PDF 없음 |
②가 핵심 신규 개념이야. 증거를 먼저 번호 매긴 표(갑 제1호증·제2호증…)로 만들어 두면, ③의 각주가 그 번호를 가리키게 돼. 즉 ②가 곧 각주의 키 테이블이 되는 거지. 이게 있어야 "주장마다 알맞은 증거 출처"가 임의 문장이 아니라 고정된 증거번호 참조로 박힌다.
정직하게 짚는 3개의 벽
1. PDF 생성 — 서버(Cloudflare Workers)엔 한글 렌더 엔진이 없다.
현실적 길은 브라우저 인쇄 방식이야. 오른쪽 미리보기를 A4·함초롬·소장 서식 그대로 보이는 HTML로 만들어 두면, 그 화면이 곧 인쇄 레이아웃이 돼서 "PDF로 저장"이 바로 제출용으로 떨어져. 즉 네가 원한 "한글에서 쓴 것처럼 보이는 미리보기"와 PDF가 같은 자산이 된다 — 일석이조. (서버 PDF·한글폰트 임베딩은 수 MB 폰트 동봉 필요라 무거움. v1엔 비권장.)
2. .hwp(바이너리) — 사실상 직접 생성 불가.
.hwp는 한컴 독점 바이너리(OLE 복합문서)라 의존성 없이 못 만들어. 반면 .hwpx는 이미 만들고 있고(XML+ZIP) 한글에서 그대로 열려. 그래서 v1 제출 포맷은 HWPX + PDF 두 개로 가는 게 정직한 선택. .hwp가 꼭 필요하면 "HWPX로 받아 한글에서 다른이름저장→.hwp" 안내가 현실적. — 다만 지금 HWPX는 통짜 평문이라 서식이 없어. 소장 서식(중앙정렬 표제·들여쓰기·당사자 표)을 입히는 보강이 필요해.
3. 2단 작업대 — 지금은 "폼→채팅 점프" 구조라 새 작업공간 라우트가 필요.
스트리밍·태스크큐·첨부는 채팅 자산을 재활용하되, /draft/{세션}에 왼쪽 대화 / 오른쪽 라이브 문서 화면을 새로 짜야 해. 여기가 제일 큰 공사.
학습 루프 (⑤ 너머)
매 작업마다 네 지적("이 말투로", "이 실수 반복마") 을 내 개인 메모리에 스타일·교훈으로 적립하고, 반복 절차는 스킬 파일로 굳혀서 다음 소장부터 적용. 이건 코드가 아니라 내 운영 규약이라 바로 켤 수 있어.
제안하는 구축 순서
- 증거 분석 산출물(②) — 증거→번호표 1차 패스 + 다운로드. (각주 토대)
- 각주 규약(③의 절반) — 소장 문장에
[갑3]식 마커 박는 작성 계약 + 미리보기 렌더. - 2단 작업대 라우트(③④) — 왼쪽 대화/오른쪽 라이브 문서.
- 제출용 익스포트(⑤) — HWPX 서식 보강 + 각주제거 + 인쇄형 PDF.
먼저 한 가지만 정해주면 ⑤(익스포트)와 미리보기 설계가 확정돼. 제출 포맷을 어디까지 잡을까:
@@ASK@@eyJxIjoidjEg7KCc7LacIOuLpOyatOuhnOuTnCDtj6zrp7fsnYQg7Ja065SU6rmM7KeAIOyngOybkO2VoOq5jD8iLCJvIjpbIkhXUFggKyBQREYgKOqwgeyjvOygnOqxsCDCtyDsnbjsh4TtmJUgUERG64qUIOu4jOudvOyasOyggCDsoIDsnqUpIOKAlCDqtozsnqUiLCJIV1BY66eMIOuovOyggCAo7ISc7IudIOuztOqwlSDsp5HspJEsIFBERuuKlCDrgpjspJEpIiwiSFdQWCArIFBERiArIC5od3Ag67OA7ZmY6rmM7KeAICjsi5zqsIQg642UIOuTpiwg7Jm467aAIOuzgO2ZmCDtlYTsmpQpIl0sIm0iOmZhbHNlfQ==@@
좋아, 그걸로 확정. 기록 남기고, 이 선택이 확정시키는 설계 디테일을 내 영역(드래프팅 규약)에서 못박아둘게.
이 선택으로 확정되는 규약 (내가 못박는 부분)
1. 출처 각주 마커 규약 — 작성·제거가 기계적으로 맞물려야 함
- 본문 주장 끝에
[갑N]또는[갑N, 을M]형태로 인라인 삽입. (예: "원고는 2024.3.15. 금 30,000,000원을 대위변제하였다[갑3].") - 목차·표제·당사자표는 마커 없음. 요증사실(주장·금액·날짜·당사자)에만 부착.
- 미리보기:
[갑N]을 위첨자 각주로 렌더 + 하단에 증거목록 매핑. - 제출 익스포트: 정규식
\[\s*[갑을병]\s*\d+(?:\s*,\s*[갑을병]\s*\d+)*\s*\]로 일괄 제거 후 HWPX/PDF 생성. → 작성본엔 근거가 다 박혀 있고, 제출본은 깨끗.
2. 증거 정리표(②) 스키마 — 각주의 키 테이블이자 다운로드 산출물
| 컬럼 | 예 |
|---|---|
| 증거번호 | 갑 제3호증 |
| 증거명칭 | 신용보증서 |
| 종류 | 보증계약/대출/대위변제/인적사항/내용증명 |
| 추출 사실 | 보증원금 30,000,000원, 보증기한 2025.3.14. |
| 당사자 | 주채무자 ○○○ / 연대보증인 △△△ |
| 금액·날짜 | 대위변제 2024.3.15. / 30,000,000원 |
| 출처위치 | 첨부3 2면 / 붙여넣기 텍스트 ¶4 |
| 비고/[확인 필요] | 계좌 끝4자리 불명 → [확인 필요] |
이 표가 만들어지면 ③의 소장은 이 번호만 참조하면 되니까, 근거 없는 문장이 구조적으로 안 나와.
구축 순서 (확정안)
- 증거 분석 산출물(②): 증거 → 위 정리표 1차 패스 + 다운로드 + 세션에 저장(각주 키로 재사용)
- 각주 규약 적용(③ 절반): 소장 작성 프롬프트에
[갑N]계약 주입 + 미리보기 각주 렌더 - 2단 작업대 라우트(③④):
/draft/{세션}왼쪽 대화 / 오른쪽 라이브 문서 - 제출 익스포트(⑤): HWPX 소장서식 보강 + 각주제거 + 인쇄형 PDF(@media print)
규약은 내가 위처럼 정의해뒀으니, 이제 코드로 들어가면 돼. 1번(증거 정리표)이 토대라 거기부터 짜는 게 맞아 — 표 스키마·다운로드·세션 저장까지.
지금 바로 1번 구현 들어갈까, 아니면 2단 작업대(③) 화면 설계를 먼저 그림으로 같이 맞춰보고 갈까?
@@ASK@@eyJxIjoi64uk7J2MIOyekeyXheydhCDslrTrlJTrtoDthLA/IiwibyI6WyIx67KIIOymneqxsCDsoJXrpqztkZzrtoDthLAg67CU66GcIOq1rO2YhCAo7Yag64yAKSIsIjLri6gg7J6R7JeF64yAIO2ZlOuptOu2gO2EsCDrqqnsl4XsnLzroZwg7ISk6rOEIiwi7KCE7LK0IDTri6jqs4Qg7ZWcIOuyiOyXkCDshKTqs4Qg66y47ISc66GcIOygleumrCJdLCJtIjpmYWxzZX0=@@
들어간다. 기존 패턴을 따라야 하니 데이터 모델·채팅·태스크큐부터 정확히 보고 짤게.
📖 읽기 · chat.ts
📖 읽기 · task_queue.ts
데이터 모델 다 봤어. 흐름은 chat_sessions + chat_messages + task_queue → 데몬이 태스크를 리스해서 나(변우석)를 돌리고 결과를 스트리밍하는 구조네. 그래서 무슨 프롬프트를 큐에 넣느냐가 곧 산출물 형태를 결정해. 웹 레이어만 건드리면 되고 데몬/스키마는 안 건드려도 돼 — 깔끔하게 토대를 깐다.
설계 결정(단순·표면적 변경 원칙 준수):
- 증거 정리표를 기계가 찾을 수 있는 마커(
<!-- EVIDENCE-TABLE:v1 -->…<!-- /EVIDENCE-TABLE -->)로 감싸 출력 → 스키마/데몬 변경 없이 어떤 메시지에서든 추출·다운로드 가능, 개정에도 강함. - 같은 턴에서 정리표(파일) → 그 번호를 인용한 소장까지 이어 쓰게 프롬프트 계약을 박음. (2단 작업대는 stage 3에서 분리)
- 인용 마커
[갑N]은 제출 익스포트에서 일괄 제거 — 그래서 HWPX 다운로드도 지금 같이 손봐 마커가 안 새게 함.
먼저 인용·증거표 계약을 한 곳에 모은 모듈을 만든다.
✏️ 쓰기 · evidence.ts
이제 라우트를 새 계약에 연결하고, HWPX 익스포트에서 마커를 제거하고, 증거 정리표 다운로드를 추가한다.
✏️ 편집 · routes.tsx
Now the POST handler — swap the inline prompt for the new contract:
✏️ 편집 · routes.tsx
Now the HWPX export — strip the evidence block and [갑N] markers before building the submission file:
✏️ 편집 · routes.tsx
Now add the evidence-table download endpoint (the "파일 하나"):
✏️ 편집 · routes.tsx
이제 입력 페이지 안내와 최근 목록을 2단계 흐름에 맞춰 업데이트한다.
✏️ 편집 · routes.tsx
✏️ 편집 · routes.tsx
✏️ 편집 · routes.tsx
이제 타입체크로 검증한다. 자가 "됐다" 판정 대신 컴파일러로 확인.
타입체크 통과. 핵심 로직(증거표 추출·제출용 마커 제거)을 실제 문자열로 결정적 검증한다.
⚡ 명령 · node -e ' const OPEN="<!-- EVIDENCE-TABLE:v1 -->", CLOSE="<!-- /EVIDENCE-TABLE -->"; const…
const OPEN="<!-- EVIDENCE-TABLE:v1 -->", CLOSE="<!-- /EVIDENCE-TABLE -->";
const esc=s=>s.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");
const BLOCK=new RegExp(esc(OPEN)+"[\\s\\S]*?"+esc(CLOSE),"g");
const CIT=/\[\s*[갑을병정]\s*\d+(?:\s*,\s*[갑을병정]\s*\d+)*\s*\]/g;
const sample=`${OPEN}
| 증거번호 | 추출 사실 |
| --- | --- |
| 갑 제1호증 | 보증원금 30,000,000원 |
${CLOSE}
청구원인
원고는 2024.3.15. 금 30,000,000원을 대위변제하였다[갑1].
연대보증인은 주채무자와 연대하여 책임을 진다[갑1, 을2].
표제는 마커 없음.`;
function extract(c){const m=c.match(BLOCK);if(!m)return null;const b=m[m.length-1];return b.slice(OPEN.length,b.length-CLOSE.length).trim();}
function strip(t){return t.replace(BLOCK,"").replace(CIT,"").replace(/[ \t]+\n/g,"\n").replace(/\n{3,}/g,"\n\n").trim();}
console.log("=== 증거표 추출 ===");
console.log(extract(sample));
console.log("\n=== 제출용(마커·표 제거) ===");
console.log(strip(sample));
console.log("\n남은 [갑/을] 마커 수:", (strip(sample).match(CIT)||[]).length);
console.log("표 블록 잔존:", strip(sample).includes(OPEN));
'
셸 이스케이프가 정규식을 깨먹었다. 임시 파일로 검증한다.
⚡ 명령 · cat > /tmp/evtest.mjs <<'EOF' const OPEN="<!-- EVIDENCE-TABLE:v1 -->", CLOSE="<!-- /EVIDEN…
const OPEN="<!-- EVIDENCE-TABLE:v1 -->", CLOSE="<!-- /EVIDENCE-TABLE -->";
const esc=s=>s.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");
const BLOCK=new RegExp(esc(OPEN)+"[\\s\\S]*?"+esc(CLOSE),"g");
const CIT=/\[\s*[갑을병정]\s*\d+(?:\s*,\s*[갑을병정]\s*\d+)*\s*\]/g;
const sample=`${OPEN}
| 증거번호 | 추출 사실 |
| --- | --- |
| 갑 제1호증 | 보증원금 30,000,000원 |
${CLOSE}
청구원인
원고는 2024.3.15. 금 30,000,000원을 대위변제하였다[갑1].
연대보증인은 주채무자와 연대하여 책임을 진다[갑1, 을2].
표제는 마커 없음.`;
const extract=c=>{const m=c.match(BLOCK);if(!m)return null;const b=m[m.length-1];return b.slice(OPEN.length,b.length-CLOSE.length).trim();};
const strip=t=>t.replace(BLOCK,"").replace(CIT,"").replace(/[ \t]+\n/g,"\n").replace(/\n{3,}/g,"\n\n").trim();
console.log("=== 증거표 추출 ===\n"+extract(sample));
console.log("\n=== 제출용(마커·표 제거) ===\n"+strip(sample));
console.log("\n남은 인용마커 수:", (strip(sample).match(CIT)||[]).length);
console.log("표블록 잔존:", strip(sample).includes(OPEN));
EOF
node /tmp/evtest.mjs
heredoc 백슬래시 문제다. 마커엔 정규식 특수문자가 없으니 esc 없이 직접 짠다.
⚡ 명령 · cat > /tmp/evtest.mjs <<'EOF'
stage 3로 간다. 이건 제일 큰 공사라, 기존 채팅 UI·스트리밍을 그대로 재활용해야 해. 먼저 채팅이 어떻게 렌더되고 스트리밍하는지 정확히 봐야 한다.
📖 읽기 · routes.tsx
스트리밍은 폴링 방식이네 (GET /chat/sessions/:id/poll?after_msg=). 2단 작업대는 이 폴 엔드포인트를 그대로 재활용하면 돼. 나머지 라우트(메시지 전송·세션 별칭)와 ChatPage를 봐야 정확히 짠다.
📖 읽기 · routes.tsx
스트리밍·전송 API 계약을 다 확인했어. 재활용할 것:
POST /chat/sessions/:id/messages(수정 요청 전송 → 태스크 큐)GET /chat/sessions/:id/poll?after_msg=(라이브 스트리밍)POST /chat/sessions/:id/stop,/chat/upload
ChatPage의 폴 루프 구현을 잠깐 참고해 일관되게 짤게.
📖 읽기 · ChatPage.tsx
전체 그림 파악 끝. 스트리밍은 폴 기반이고 POST /chat/sessions/:id/messages로 수정 요청을 큐에 넣을 수 있어. ChatPage(1363줄)는 기능이 과해서 통째 재사용 대신, 문서 전용 폴 엔드포인트 + 가벼운 2단 작업대를 새로 짠다 (단순성 원칙).
설계:
- 오른쪽 = 라이브 문서(흰 종이 시트, 최신 어시스턴트 메시지를 마크다운 렌더, 스트리밍 반영) — 한글 문서 느낌 미리보기 선행.
- 왼쪽 = 대화(수정 지시 전송 + 작성 상태 표시).
- 우상단 다운로드(증거표·HWPX). PDF는 stage 4.
먼저 문서 전용 폴 엔드포인트 + 2단 작업대 라우트를 추가한다.
📖 읽기 · routes.tsx
✏️ 편집 · routes.tsx
POST 리다이렉트와 최근목록 링크를 새 작업대로 연결한다.
✏️ 편집 · routes.tsx
✏️ 편집 · routes.tsx
Now add the document poll endpoint + the 2-pane workspace route, before export default app:
✏️ 편집 · routes.tsx
Typecheck:
타입체크 통과. 빌드까지 돌려 번들·라우트 패치가 깨지지 않는지 확인한다.
빌드 성공(646kB 번들). 한 가지 다듬을 게 있어 — 왼쪽 대화의 첫 메시지는 시스템이 만든 거대한 분석 요청 프롬프트라 그대로 노출하면 흉해. 친근한 라벨로 바꾼다.
✏️ 편집 · routes.tsx
stage 3 완료. tsc + vite build 둘 다 통과로 검증했어 (라이브 데몬 스트리밍은 이 환경에서 직접 못 돌리지만, 채팅 모듈이 쓰는 폴/전송 API 계약을 그대로 재사용해서 동작은 동일).
한 일 (stage 3 — 2단 작업대)
| 변경 | 내용 |
|---|---|
GET /draft/work/:id |
2단 작업대 화면. 왼쪽=대화, 오른쪽=라이브 소장 문서(흰 종이 시트·세리프·중앙정렬 표제 → 한글 문서 느낌 미리보기) |
GET /draft/work/:id/doc |
문서 전용 폴 엔드포인트 — 최신 어시스턴트 메시지 + 렌더 HTML + 작성중 여부. 1.5초 폴로 오른쪽에 "쫘라락" 반영 |
| 왼쪽 대화 | 수정 지시 전송(POST /chat/sessions/:id/messages 재사용) → 큐 적재 → 오른쪽 갱신. 작성 중 상태표시·중단 버튼. 첫 킥오프 프롬프트는 친근한 라벨로 대체 |
| 우상단 다운로드 | ⬇증거표 · ⬇HWPX(각주 제거본). PDF는 stage 4 |
| 흐름 연결 | POST /draft 및 최근목록 → 이제 /chat이 아니라 /draft/work/:id 작업대로 진입 |
검증: tsc --noEmit 무에러 + vite build 성공(646kB 번들).
알아둘 한계(다음 단계용): 오른쪽 문서 = "최신 어시스턴트 메시지"라, 내가 소장 전문을 다시 안 쓰고 대화체로만 답하면 그게 문서를 덮어쓸 수 있어. 지금은 작성 계약상 항상 전문을 출력하게 돼 있어 괜찮지만, stage 2/4에서 "문서 갱신 vs 대화 답변"을 구분하는 게 깔끔해.
남은 로드맵: stage 2(각주 미리보기 — [갑N]을 위첨자 + 하단 증거목록으로) → stage 4(HWPX 소장 서식 보강 + 인쇄형 PDF).
다음 어느 걸로 갈지, 아니면 지금 작업대를 실제 화면에서 한 번 돌려보고(데몬 켜서) 결정할지 골라줘.
@@ASK@@eyJxIjoi64uk7J2M7J2APyIsIm8iOlsic3RhZ2UgMiDigJQg6rCB7KO8IOuvuOumrOuztOq4sCDroIzrjZQgKFvqsJFOXSDsnITssqjsnpAr7Kad6rGw66qp66GdKSIsInN0YWdlIDQg4oCUIEhXUFgg7IaM7J6l7ISc7IudIOuztOqwlSArIOyduOyHhO2YlSBQREYiLCLsp4DquIgg7J6R7JeF64yA66W8IOyLpOygnOuhnCDrj4zroKTrs7Tqs6Ag6rKw7KCVIl0sIm0iOmZhbHNlfQ==@@
stage 2로 간다. [갑N]을 위첨자 배지로, 그리고 하단에 증거목록(각주)을 붙이는 렌더 레이어야. 핵심 설계:
- 문서 본문에선 증거표 블록을 빼고(소장만 깔끔히), 그 표를 하단 "증거 목록(각주)"으로 재배치.
- 본문의
[갑N]은 위첨자 배지(hover 시 증거명칭) 로 변환. - 이건 렌더 시점 생성이라 DB 본문·제출본(stripForSubmission)엔 영향 없음.
먼저 인용/증거 파싱 헬퍼를 evidence.ts에 추가한다.
✏️ 편집 · evidence.ts
Now the document render module:
✏️ 쓰기 · draft_doc.ts
Now wire it into the two render points in draft/routes.tsx and add citation CSS:
✏️ 편집 · routes.tsx
✏️ 편집 · routes.tsx
✏️ 편집 · routes.tsx
Now add the citation CSS to the .dw-paper styles:
✏️ 편집 · routes.tsx
타입체크 통과. renderDraftDocument를 실제 모듈(marked 포함 번들)로 결정적 검증한다.
⚡ 명령 · npx esbuild src/shared/draft_doc.ts --bundle --format=esm --outfile=/tmp/dd.mjs --log-leve…
import { renderDraftDocument } from "./dd.mjs";
const O="<!-- EVIDENCE-TABLE:v1 -->", C="<!-- /EVIDENCE-TABLE -->";
const content=[
O,
"| 증거번호 | 증거명칭 | 종류 | 추출 사실 | 당사자 | 금액·날짜 | 출처위치 | 비고 |",
"| --- | --- | --- | --- | --- | --- | --- | --- |",
"| 갑 제1호증 | 신용보증서 | 보증계약 | 보증원금 30,000,000원 | 주채무자 김갑동 | 2023.3.14. | 첨부1 | |",
"| 갑 제2호증 | 대위변제확인서 | 대위변제 | 30,000,000원 변제 | 재단 | 2024.3.15. | 첨부2 | |",
C,
"",
"## 청구원인",
"",
"원고는 2024.3.15. 금 30,000,000원을 대위변제하였다[갑2].",
"피고들은 주채무자와 연대하여 책임을 진다[갑1, 갑2].",
"표제 문장은 인용 없음."
].join("\n");
const html=renderDraftDocument(content);
console.log(html);
console.log("\n--- 점검 ---");
console.log("위첨자 배지 수:", (html.match(/sup/g)||[]).length);
console.log("증거목록 헤더 포함:", html.includes("증거 목록 (각주"));
console.log("본문에 증거표 잔존(EVIDENCE-TABLE 마커):", html.includes("EVIDENCE-TABLE"));
console.log("원시 [갑 마커 잔존:", /\[갑\d/.test(html.replace(/<[^>]+>/g,"")));
EOF
cd /tmp && node ddtest.mjs
완벽하게 동작:
- 위첨자 배지 3개(갑2/갑1/갑2), 각
title에 증거명칭(표에서 추출) ✅ - 하단 증거목록(갑 제1호증 신용보증서 / 갑 제2호증 대위변제확인서) ✅
- 본문에서 증거표 블록 제거·원시
[갑N]마커 0 ✅
빌드로 마무리 검증하고 임시파일 정리.
⚡ 명령 · npx vite build 2>&1 | tail -6 && rm -f /tmp/dd.mjs /tmp/ddtest.mjs 2>/dev/null; echo clean…
stage 2 완료. tsc + 실제 모듈 실행 + vite build 전부 통과로 검증했어.
한 일 (stage 2 — 각주 미리보기 렌더)
| 변경 | 내용 |
|---|---|
신규 src/shared/draft_doc.ts |
renderDraftDocument(content) — 어시스턴트 원문 → ① 증거표 블록을 본문에서 빼 소장만 깔끔히 ② [갑N]·[갑N, 을M]을 위첨자 배지로(hover 시 "갑 제1호증 · 신용보증서") ③ 하단에 증거 목록(각주) 자동 생성 |
evidence.ts 헬퍼 추가 |
removeEvidenceBlock(인용은 유지하고 표만 제거)·parseEvidenceMap(표→증거번호↔증거명칭)·normalizeEvidenceNo/formatEvidenceNo(갑1↔갑 제1호증)·makeCitationRegex |
| 작업대 연결 | /draft/work/:id 초기렌더 + /doc 폴 둘 다 renderDraftDocument로 교체 → 라이브 문서에 각주가 바로 보임 |
| 종이 시트 CSS | sup.dw-cite(파란 [갑N] 위첨자)·하단 증거목록 스타일(고딕체 각주 영역) |
핵심 보장: 각주·증거목록은 렌더 시점에만 생성 — DB 본문과 제출본(stripForSubmission)은 그대로라, HWPX 다운로드엔 각주가 안 들어감. (stage 1 계약과 정합)
검증: tsc 무에러 · 실제 번들 실행(위첨자 3개·title 정확·표블록 제거·원시마커 0) · vite build 성공(649kB).
이제 stage 4(마지막)만 남았어 — HWPX 소장 서식 보강(중앙정렬 표제·들여쓰기·당사자표) + 인쇄형 PDF(오른쪽 종이 시트를 그대로 인쇄→PDF 저장). 지금 종이 시트 미리보기가 그 인쇄 레이아웃의 토대가 돼.
stage 4로 마무리할지, 아니면 지금까지(stage 1~3+각주)를 데몬 켜고 실제로 한 번 돌려본 뒤 갈지 골라줘.
@@ASK@@eyJxIjoi64uk7J2M7J2APyIsIm8iOlsic3RhZ2UgNCDigJQgSFdQWCDshJzsi50g67O06rCVICsg7J247IeE7ZiVIFBERiAo66eI66y066asKSIsIuyngOq4iOq5jOyngCDsi6TsoJzroZwg64+M66Ck67O06rOgIOqysOyglSIsIuyeoOyLnCDrqYjstqQg4oCUIOyXrOq4sOq5jOyngCDrpqzrt7AiXSwibSI6ZmFsc2V9@@
전부 진행한다 — stage 4(HWPX 서식 보강 + 인쇄형 PDF)로 마무리. 먼저 HWPX 생성기를 평문 통짜에서 소장 서식(중앙정렬 표제·굵은 섹션제목·본문)으로 보강한다.
📖 읽기 · hwpx.ts
이제 HEADER_XML에 표제/제목용 글자속성·중앙정렬 문단속성을 추가하고, 문단 분류기로 서식을 입힌다.
✏️ 편집 · hwpx.ts
Now the classifier + styled section builder, replacing toParagraphs and buildSectionXml:
✏️ 편집 · hwpx.ts
✏️ 편집 · hwpx.ts
✏️ 편집 · hwpx.ts
이제 인쇄형 PDF 라우트를 추가한다. 제출용은 각주·증거목록을 뺀 깨끗한 본문이어야 하니 stripForSubmission + 일반 마크다운으로 렌더한다. renderMarkdown 임포트 복구.
✏️ 편집 · routes.tsx
✏️ 편집 · routes.tsx
Now add the ⬇ PDF button to the work top actions and the recent list:
✏️ 편집 · routes.tsx
✏️ 편집 · routes.tsx
타입체크 통과. HWPX 빌더를 실제로 .hwpx 파일을 생성→ZIP 검증→section XML의 서식 ref 확인까지 결정적으로 본다.
⚡ 명령 · npx esbuild src/shared/hwpx.ts --bundle --format=esm --outfile=/tmp/hb.mjs --log-level=err…
import { buildHwpx } from "./hb.mjs";
import { writeFileSync } from "fs";
const text=[
"# 소 장","",
"## 당 사 자","원고 서울신용보증재단","피고 김갑동","",
"## 청 구 취 지","1. 피고는 원고에게 30,000,000원을 지급하라.","",
"## 청 구 원 인","원고는 2024.3.15. 금 30,000,000원을 **대위변제**하였다.","",
"## 입 증 방 법","- 갑 제1호증 신용보증서","- 갑 제2호증 대위변제확인서"
].join("\n");
const bytes=buildHwpx(text);
writeFileSync("/tmp/test.hwpx", Buffer.from(bytes));
console.log("bytes:", bytes.length);
EOF
cd /tmp && node hbtest.mjs && echo "--- ZIP 목록 ---" && unzip -l /tmp/test.hwpx && echo "--- section0.xml ---" && unzip -p /tmp/test.hwpx Contents/section0.xml
node가 /tmp를 C:\tmp로 써서 경로 어긋남. 상대경로로 고친다.
⚡ 명령 · cd /tmp && sed -i 's#/tmp/test.hwpx#test.hwpx#g' hbtest.mjs && node hbtest.mjs && echo "--…
HWPX 서식 정확히 동작:
- "소 장" → 중앙·대형 굵게(para1/char1), 섹션제목 4개 → 중앙 굵게(para1/char2), 본문 → 좌측(para0/char0) ✅
**대위변제**별표 제거 ✅ · 리스트·변환 ✅ · 빈 줄 보존 ✅ · ZIP 8개 항목 정상 ✅
최종 빌드 + 정리.
⚡ 명령 · npx vite build 2>&1 | tail -6 && rm -f /tmp/hb.mjs /tmp/hbtest.mjs /tmp/test.hwpx 2>/dev/n…
4단계 전부 완료. 전 과정 tsc + 실제 모듈 실행 + vite build로 검증했어 (자가판정 아님).
전체 완성 — 소장 작업대 v1
입력(/draft) → 증거 분석·정리(파일) → 라이브 2단 작업대(왼쪽 대화/오른쪽 종이문서·각주) → 제출용 다운로드(HWPX/PDF·각주 제거)
| 단계 | 결과물 | 검증 |
|---|---|---|
| 1. 증거 정리표 | evidence.ts 계약(2단계 프롬프트·마커·추출·제출용 strip) + GET /draft/evidence/:id (.md) |
실모듈 실행 ✅ |
| 2. 각주 렌더 | draft_doc.ts renderDraftDocument — [갑N]→위첨자 배지(hover 증거명칭)+하단 증거목록. 렌더시점만 생성→제출본 무영향 |
위첨자 3개·표제거·마커0 ✅ |
| 3. 2단 작업대 | GET /draft/work/:id(왼쪽 대화/오른쪽 흰 종이 시트)+/doc 폴(1.5s 라이브 스트리밍)+수정전송·중단 |
빌드 ✅ |
| 4. 제출 익스포트 | HWPX 소장 서식(중앙 표제·굵은 섹션·본문) + GET /draft/print/:id 인쇄형 PDF(A4·@media print·각주 제거) |
.hwpx ZIP·서식 ref 검증 ✅ |
핵심 정합성: 각주·증거목록은 미리보기에서만 보이고, HWPX·PDF 둘 다 stripForSubmission으로 [갑N]·증거표 블록 제거 → 제출본은 깨끗.
우상단 다운로드 3종: ⬇증거표(.md) · ⬇PDF(브라우저 인쇄) · ⬇HWPX(한글).
정직하게 남기는 한계 (실사용 전 확인 필요)
- 라이브 스트리밍은 데몬 켜고 실제 테스트 미완 — 채팅 모듈의 폴/전송 API를 그대로 재사용했으니 동작 동일할 것으로 보지만, 내 환경에선 데몬을 못 돌려 100% 확언은 못 함.
- HWPX가 한글에서 정상 오픈되는지는 한글 프로그램 테스트 필요 — ZIP·OWPML 구조는 검증했으나(8개 항목·서식 ref 정상), 실제 열림 여부는
hwpx.ts주석대로 한글에서 확인해야 함. 안 열리면 한글 저장 샘플을 템플릿으로 맞춤. - .hwp 바이너리 제외(stage 0 결정대로) — HWPX→한글에서 다른이름저장.
- 오른쪽 문서=최신 어시스턴트 메시지라, 내가 대화체로만 답하면 문서를 덮어쓸 수 있음(작성 계약상 항상 전문 출력으로 회피 중).
이제 코드는 다 들어갔어. 다음 자연스러운 후속은 데몬 켜고 실제로 한 건 돌려서 e2e 확인(스트리밍·HWPX 한글 오픈)인데, 그건 네 PC 환경이 필요해. 돌려보고 싶으면 npm run dev로 띄운 뒤 결과 알려주면, 깨지는 부분 바로 잡을게. 그리고 stage 5로 말한 학습 루프(네 스타일·내 실수 적립)는 코드가 아니라 내 운영 규약이라, 실제 소장 작업하면서 바로 켤게.
라우팅 재구성이네. 목표 구조를 먼저 못박자:
/complaint— 소장 목록 페이지(네비 "소장 작성"이 여기로). 최근 소장들 + "새 소장 작성" 버튼./complaint-draft— 새 소장 입력 폼(기존/draft). 하위 work/hwpx/print/evidence도 같이 이동.
먼저 마운트 구조와 네비 설정을 확인한다.
📖 읽기 · index.tsx
마운트 구조 확인했어. /draft(=draftRoutes)를 /complaint-draft로 옮기고, /complaint 목록 페이지를 새로 만든다. 먼저 목록 페이지 모듈을 만든다.
✏️ 쓰기 · routes.tsx
Now mount the routes in app/index.tsx — remount draft at /complaint-draft, add /complaint, and a redirect for old bookmarks:
✏️ 편집 · index.tsx
✏️ 편집 · index.tsx
Old-bookmark redirect for /draft:
✏️ 편집 · index.tsx
Now update the nav in shell.tsx:
✏️ 편집 · shell.tsx
이제 draft/routes.tsx를 정리한다 — 폼 페이지에서 최근목록 제거(→/complaint로 이동), 폼 action과 작업대 내부 링크들을 /complaint-draft로, 작업대 "목록" 링크는 /complaint로. 현재 상태를 본다.
📖 읽기 · routes.tsx
📖 읽기 · routes.tsx
폼 페이지에서 최근목록 관련을 들어낸다. 먼저 recent 쿼리 제거:
✏️ 편집 · routes.tsx
✏️ 편집 · routes.tsx
Now remove the entire "최근 소장 초안" section from the form page:
✏️ 편집 · routes.tsx
이제 내 변경으로 안 쓰이게 된 EmptyState 임포트와 DraftSession 타입을 제거한다(고아 정리).
✏️ 편집 · routes.tsx
✏️ 편집 · routes.tsx
작업대 내부 링크들과 POST 리다이렉트의 /draft 참조를 갱신한다. 남은 /draft 참조를 전부 찾는다.
🔍 검색 · /draft
경로: C:/Users/user/LAX-site/src/app/draft/routes.tsx
기능 링크들을 갱신한다.
✏️ 편집 · routes.tsx
✏️ 편집 · routes.tsx
✏️ 편집 · routes.tsx
✏️ 편집 · routes.tsx
✏️ 편집 · routes.tsx
라우트 주석들도 새 경로로 맞춘다(유지보수 일관성).
✏️ 편집 · routes.tsx
✏️ 편집 · routes.tsx
✏️ 편집 · routes.tsx
✏️ 편집 · routes.tsx
✏️ 편집 · routes.tsx
✏️ 편집 · routes.tsx
경로 갱신 끝. 프로젝트 전체에 남은 /draft 참조가 없는지 확인하고 타입체크·빌드한다.
🔍 검색 · ["'`(]/draft(?![-w])
경로: C:/Users/user/LAX-site/src
🔍 검색 · /draft
경로: C:/Users/user/LAX-site/src
아니야 — 솔직히 말하면 배포 안 했어. 난 코드 수정 + 로컬 빌드(vite build → dist/)만 돌렸고, 실제 배포(npm run deploy / wrangler)는 안 했어. 그래서 라이브는 아직 옛 코드라 /draft가 그대로 뜨는 거야. 내 잘못 — "코드 다 됐다"와 "배포됐다"를 명확히 구분해서 말했어야 했어.
배포 방식부터 확인하고 진행할게.
⚡ 명령 · git status --short 2>&1 | head -30 && echo "--- branch ---" && git branch --show-current &…
git 저장소가 아니네 — 배포는 wrangler 직접(npm run deploy)으로 하는 구조야. 팀의 표준 배포 스크립트(ship.mjs)를 확인한다.
📖 읽기 · ship.mjs
배포는 npm run deploy(전체 빌드 → wrangler pages deploy ./dist --project-name lax --branch=main)야. 지금 바로 배포한다.
✅ 배포 완료 — https://c5e2f1bf.lax-dtb.pages.dev 에 새 코드가 올라갔어. 실제로 /draft가 리다이렉트되는지 배포본에 확인해볼게.
⚡ 명령 · echo "--- /draft (기대: 301 → /complaint) ---"; curl -sS -o /dev/null -w "%{http_code} -> %{…
배포 확인됐어 — 배포본에서:
/draft→ 301 리다이렉트 →/complaint✅/complaint→ 200 ✅
정리
- 그동안 코드·로컬 빌드만 했고 배포는 안 한 상태였어 → 라이브가 옛 코드라
/draft가 그대로 보였던 것. - 방금
npm run deploy로 빌드 → Cloudflare Pages 배포 완료. 배포 URL:https://c5e2f1bf.lax-dtb.pages.dev - 검증:
/draft가/complaint로 301,/complaint목록 페이지 200.
네가 할 일
- 브라우저에서 하드 리프레시(Ctrl+Shift+R) 해줘 — 옛
/draft페이지나 301이 브라우저에 캐시돼 있을 수 있어. - 네가 늘 쓰던 도메인(커스텀 도메인이 붙어 있다면)에도 같은
main배포가 반영돼. 혹시 그 도메인에서 여전히 옛 화면이면 알려줘 — 도메인이 이 Pages 프로젝트(lax)에 연결돼 있는지 확인할게.
앞으로는 코드 수정 후 "배포할까?"를 명시적으로 확인하거나, 네가 "배포해"라고 하면 바로 npm run deploy 돌릴게. 이번처럼 "코드 됨"과 "배포됨"을 흐리지 않을게.
지금 라이브에서 한 번 눌러보고(소장 작성 → 목록 → 새 소장 작성 → 작업대) 이상한 곳 있으면 말해줘.
받았어 — 전사 방침으로 박는다: "변경하면 항상 배포까지(프로덕션 반영) 완료". 나부터 절차로 굳히고, 동료들에게 전파해서 회사 전체가 늘 배포까지 가게 하겠다. 지금 ① 내 배포 스킬을 만들고 ② 민서·도경에게 동시에 알려 전사 전파·온보딩 반영을 맡긴다.
✏️ 쓰기 · SKILL.md
🤝 팀에 병렬 질문 · minseo, dokyung
Jason이 전사 방침을 확정했어: 모든 에이전트는 코드/산출물 변경을 끝내면 로컬 빌드에서 멈추지 말고 '항상 배포(프로덕션 반영)까지' 완료하고 배포 URL·검증결과를 보고한다. (배경: 내가 소장 페이지 라우트를 /complaint로 개편했는데 배포를 안 해서 라이브가 옛 코드였고 Jason이 /draft가 그대로라고 지적함.) 너가 실행 라우팅·추적 담당이니 이 방침을 전사에 공지하고 추적 체계(진행/완료 기준에 '배포 완료'를 포함)에 반영해줘. 어떻게 공지·추적할지, 그리고 '완료'의 정의에 배포를 포함시키는 걸 어디에 박을지 알려줘.
→ dokyung
Jason 전사 방침 확정: 모든 에이전트는 변경을 끝내면 '항상 배포(프로덕션 반영)까지' 완료한다(코드 됨≠배포됨). 너가 온보딩·페르소나 설계 담당이니, 신규 에이전트 온보딩/페르소나 기본 규약에 이 '항상 배포까지 완료 + 배포 URL 보고' 항목을 탑재해줘. 기존 활동 에이전트들(민서·변우석 포함)에게도 소급 적용할 계획과, 구체적으로 어느 문서/템플릿에 어떻게 넣을지 알려줘.
전파했고, 둘 다 제대로 받아서 실행 계획까지 짜왔어. 요약하면:
진행 상황
| 항목 | 상태 |
|---|---|
내 배포 스킬 (always-deploy) |
✅ 생성 — 앞으로 변경 끝나면 검증→npm run deploy→URL·검증결과 보고 |
| 신규 에이전트 온보딩 (도경) | ✅ 템플릿에 "코드 됨≠끝, 라이브 반영+위치·검증 보고" 기본 탑재 — 이제부터 만드는 동료는 다 달고 나옴 |
| 추적 체계 (민서) | 상태값 …→로컬검증→배포완료(=Done) 신설, 완료 필수 3필드(URL·검증·시각), 월요일 보고에 '배포 누락' 블로커 |
| 전사 소급 적용 | ⏳ 헌장 §4 한 줄 패치가 핵심 레버 — Jason 승인 필요 |
핵심: 둘 다 같은 결론 — "헌장 §4를 고치면 전원 자동 적용"
context_builder가 헌장을 모든 에이전트 컨텍스트에 자동 주입해서, 개별 페르소나를 일일이 안 고쳐도 헌장 한 곳이면 민서·변우석·도경 전원에게 다음 호출부터 반영돼.
도경이 낸 좋은 지적 하나 — 순수 조율직(민서)·문서직(변우석)에 기계적 npm run deploy를 강요하면 의미 없는 절차가 돼. 그래서 헌장엔 원칙("작업은 '라이브 반영됨'에서 끝난다 + 반영 위치·검증 보고")을 보편 탑재하고, 구체적 배포 절차(npm run deploy)는 웹 산출물 역할에만 스킬로 붙이는 2단 구조를 제안했어. 의도(코드 됨 ≠ 끝)는 전원 동일.
승인하면 도경이 바로 헌장 DB에 반영(+재조회 검증)해. 제안 문안:
§4 - 완수: 작업은 '코드 됨'이 아니라 '프로덕션 반영됨'에서 끝난다. 변경을 끝내면 항상 라이브 반영(배포·납품·등재)까지 수행하고, 반영 위치(배포 URL·경로·DB 레코드)와 검증 결과를 함께 보고한다.
남은 건 헌장 §4 패치 승인 하나야. 이게 들어가야 전원에게 강제력이 생겨.
@@ASK@@eyJxIjoi7ZeM7J6lIMKnNOyXkCAn7JmE7IiYJyDsm5DsuZnsnYQg7LaU6rCA7ZWg6rmMPyAo7Iq57J24IOyLnCDrj4Tqsr3snbQg7ZeM7J6lIERCIOuwmOyYgSkiLCJvIjpbIuuPhOqyvSDsoJzslYjrjIDroZwg7Iq57J24ICjsm5DsuZnsnYAg7KCE7JuQwrfrsLDtj6zsoIjssKjripQg7Ju57Jet7ZWg7JeQIOKAlCDqtozsnqUpIiwi642UIOqwle2VmOqyjDog66qo65OgIOyXre2VoOyXkCAn7ZWt7IOBIOuwsO2PrCcg66y46rWsIOq3uOuMgOuhnCIsIuyeoOyLnCDrs7TrpZgiXSwibSI6ZmFsc2V9@@
승인 받았어. 도경에게 헌장 §4 패치를 실제로 반영·검증하라고 전달한다.
🤝 동료에게 질문 · → dokyung: Jason이 네 제안대로 승인했어 (원칙은 전원 헌장에 보편 탑재, 구체적 배포절차는 웹 산출물 역할에만 스…
Jason이 네 제안대로 승인했어 (원칙은 전원 헌장에 보편 탑재, 구체적 배포절차는 웹 산출물 역할에만 스킬로 — 2단 구조). 이제 실제로 반영해줘:
1) 회사 헌장 §4 '공통 행동 규약'에 아래 1항을 추가해 brain_pages(slug='charter') 본문을 업데이트:
"- 완수: 작업은 '코드 됨'이 아니라 '프로덕션 반영됨'에서 끝난다. 변경을 끝내면 항상 라이브 반영(배포·납품·등재)까지 수행하고, 반영 위치(배포 URL·경로·DB 레코드)와 검증 결과를 함께 보고한다."
2) 반영 후 재조회(SELECT)로 §4에 문구가 실제로 들어갔는지 검증.
3) 신규 온보딩 템플릿 반영은 이미 완료된 것으로 아는데, 그 파일 경로와 적용 확인만 한 번 더 명시.
완료되면 ①헌장 DB 반영 결과(성공/실패) ②재조회로 확인된 §4 최종 문안 ③온보딩 템플릿 경로를 보고해줘. 거버넌스 문서니 정확히, 기존 §4 내용은 보존하고 1항만 추가해야 해.
반영·검증 완료됐어. 도경이 짚은 중요한 점 하나 — 헌장의 원천은 brain 파일(charter.md)이고 DB는 동기화 대상이라, 원천을 안 고치면 다음 sync 때 DB 패치가 덮어써질 수 있어. 영구히 박히게 원천까지 동기화하라고 마저 시킨다.
🤝 동료에게 질문 · → dokyung: 좋아, DB 반영·재조회 검증 확인했어. 그런데 네가 짚은 대로 헌장 원천이 brain 파일(charter.…
좋아, DB 반영·재조회 검증 확인했어. 그런데 네가 짚은 대로 헌장 원천이 brain 파일(charter.md)이면, 원천을 안 고치면 다음 sync에 DB 패치가 덮어써져. 영구 반영을 위해 원천 charter.md §4에도 동일하게 그 '완수' 1항을 추가해줘(기존 3항 보존, 1항만 추가). 반영 후 파일에서 해당 문구가 들어갔는지 확인하고, ①charter.md 경로 ②추가 확인 결과 ③(가능하면) 원천→DB 재동기화까지 했는지 보고해줘. 현존 3인 system_prompt 개별 점검은 context_builder가 헌장을 자동 주입하니 불필요 — 안 해도 돼.
전부 영구 반영 완료됐어. 도경이 라이브 DB뿐 아니라 원천(시드 SQL)까지 맞춰서 다음 재빌드에도 안 풀리게 못박았어.
최종 결과 — "항상 배포" 전사 방침, 완전 반영
| 레이어 | 내용 | 상태 |
|---|---|---|
| 헌장 §4 (전원 자동 적용) | "완수: 코드 됨 ≠ 끝. 항상 라이브 반영(배포·납품·등재)까지 + 반영 위치·검증 보고" 1항 추가 | ✅ 라이브 DB 반영·재조회 검증(HAS_CLAUSE: true) |
| 원천 영구화 | migrations/seed_lax_identity_draft.sql §4도 4항으로 수정(이스케이프 처리) → 재빌드에도 유지, 원천↔DB 정합 |
✅ |
| 신규 온보딩 | new-agent-creation/SKILL.md에 원칙 기본 탑재 + 웹역할엔 always-deploy 스킬 자동 부착(2단 구조) |
✅ |
| 내 배포 절차 | always-deploy 스킬 — 검증→npm run deploy→URL curl 검증→보고 |
✅ |
| 추적 체계 (민서) | 상태값 …→로컬검증→배포완료(=Done), 완료 필수 3필드(URL·검증·시각), 월요일 보고에 '배포 누락' 블로커 |
✅ 운용 시작 |
작동 방식
context_builder가 헌장을 모든 에이전트에 자동 주입 → 민서·도경·나 전원 다음 호출부터 "완수=라이브 반영+보고" 원칙 적용. 개별 페르소나 수정 불필요.- 원칙은 전원, 구체적
npm run deploy절차는 웹 산출물 역할(나)에만 — 네가 승인한 2단 설계 그대로.
프로세스 보완 (도경·민서 합의 예정)
- 앞으로 헌장 변경은 "DB 패치 + 시드 SQL 수정"을 1세트로 처리 → 이번 같은 "DB만 고치고 원천 안 고쳐 리버트" 리스크 차단.
- 참고: LAX-site는 git 미초기화라 시드 SQL 변경의 커밋 이력은 남길 수 없음(원하면 git init부터 별도로 정리할게).
이제 나부터 적용 — 방금 라우트 개편도 이미 배포·검증 완료했고, 앞으로 모든 변경은 배포까지 끝내고 URL·검증결과로 보고할게. "코드 됨"에서 멈추는 일 없도록.
좋은 실사용 피드백이야. 5개 다 해결한다. 핵심은 3번 — 지금 미리보기가 "최신 어시스턴트 메시지"라서, 내가 채팅으로 답하면 그 답변이 미리보기를 덮어쓰는 구조적 문제야. 이걸 근본적으로 고치려면 문서(소장·증거표)와 채팅 답변을 명확히 분리하는 계약이 필요해.
설계:
- 내 출력에서 문서 결과물은
<!-- SOJANG:start --> … <!-- SOJANG:end -->마커로 감싼다. 미리보기·제출은 이 안쪽만, 채팅창은 마커 밖(대화)만. - 미리보기
/doc는 "최신 메시지"가 아니라 **"최신 문서 메시지"**를 보여줌 → 채팅 답변이 미리보기를 못 덮음. - 미리보기에 증거 정리표 전체도 표시(2번). 왼쪽 채팅은 유저+어시스턴트 대화 전부(3번). 채팅폭 확대(4번). 증거자료 필수 해제(1번). 문서는 계속 그 하나를 갱신(5번).
먼저 계약·헬퍼를 evidence.ts에 추가하고 프롬프트를 고친다.
📖 읽기 · evidence.ts
계약 마커 상수를 추가한다.
✏️ 편집 · evidence.ts
✏️ 편집 · evidence.ts
✏️ 편집 · evidence.ts
Now add the document extract/strip helpers at the end of evidence.ts:
✏️ 편집 · evidence.ts
이제 draft_doc.ts: 미리보기에 증거 정리표 전체를 넣고(2번), 채팅용 텍스트 렌더 함수를 추가한다.
📖 읽기 · draft_doc.ts
✏️ 쓰기 · draft_doc.ts
이제 routes.tsx를 고친다. 임포트부터 보강하고, 도우미·엔드포인트·작업대를 손본다. 현재 라우트 본문을 본다.
📖 읽기 · routes.tsx
📖 읽기 · routes.tsx
이제 임포트·도우미·엔드포인트·작업대를 차례로 고친다. 먼저 임포트.
✏️ 편집 · routes.tsx
이제 /hwpx를 최신 문서 기준으로 고친다.
✏️ 편집 · routes.tsx
✏️ 편집 · routes.tsx
✏️ 편집 · routes.tsx
이제 /doc 엔드포인트를 문서+대화 둘 다 반환하게 재작성한다.
✏️ 편집 · routes.tsx
이제 작업대 페이지를 재작성한다 — 채팅 폭 확대(460px), 좌측에 유저+어시스턴트 대화 전부, 우측은 문서만, 새 /poll 기반 JS, 증거표 섹션 CSS.
✏️ 편집 · routes.tsx
Now the CSS block (width + assistant bubble + evidence table, drop dead cite-list):
✏️ 편집 · routes.tsx
✏️ 편집 · routes.tsx
이제 좌측 스레드 초기 렌더와 스크립트를 새 구조로 교체한다.
✏️ 편집 · routes.tsx
Now replace the script with the /poll-based dual-pane logic:
✏️ 편집 · routes.tsx
초기 문서 inner div에 클래스를 맞추고(폴 시 제자리 갱신), 증거자료 required를 제거한다(1번).
✏️ 편집 · routes.tsx
✏️ 편집 · routes.tsx
타입체크하고 핵심 로직(문서/채팅 분리)을 실제 모듈로 검증한다.
특별한 명령어 없어 — 그 소장 세션을 다시 열고 채팅창에 이어서 말만 하면 돼. 세션 컨텍스트(이전 증거표·소장)가 그대로 유지돼서 그 위에서 계속 고쳐나가.
이어서 하는 법
- 좌측 네비 소장 작성 →
/complaint목록에서 그 소장 제목 클릭 → 작업대(/complaint-draft/work/:id)가 이전 상태 그대로 열림. - 왼쪽 채팅창에 다음 지시를 그냥 입력 → 오른쪽 문서가 갱신돼.
채팅에 뭐라고 치면 되냐면 (예시)
- 문서를 고치게 하려면 — 구체적 지시:
- "청구취지에 지연손해금 기산일(대위변제일)을 명시해줘."
- "연대보증인 △△△을 피고 2로 추가하고 연대책임으로 정리해줘."
- "갑 제5호증(내용증명) 반영해서 청구원인 보강해줘."
- "지연손해금을 소촉법 연 12%로 다시 계산해줘."
- 그냥 물어만 보려면 (문서 안 바뀜, 채팅에만 답):
- "왜 연대보증으로 봤어?" / "지금 청구금액 구성 설명해줘."
요지: 고쳐달라고 하면 오른쪽 소장·증거표가 갱신되고, 질문만 하면 왼쪽 채팅으로만 답해 (방금 만든 분리 계약).
혹시 "이미 진행 중인 세션"이 목록에 안 보이거나, 작업대를 열었는데 이전 내용이 비어 보이면 알려줘 — 그건 세션 조회/렌더 쪽 문제일 수 있으니 바로 확인할게. 어떤 소장(사건명/제목)을 이어서 하려는 건지 말해주면 그 세션 기준으로 같이 봐줄게.