diff --git a/PATCHNOTES.md b/PATCHNOTES.md index 1d85bc3..2ae6e0e 100644 --- a/PATCHNOTES.md +++ b/PATCHNOTES.md @@ -1,5 +1,19 @@ # Astra Patch Notes +## v2.2.258 (2026-06-22) +### ๐Ÿ“ `/meet` ํšŒ์˜๋ก โ€” ํ™”์ž ํŒ€/์—ญํ•  ์ •๊ทœํ™” + ์Šฌ๋ฆผ ํฌ๋งท + ํƒ€์ž„์Šคํƒฌํ”„ ๊ทผ๊ฑฐ +์‹ค์ œ ํšŒ์˜๋ก ์‚ฐ์ถœ๋ฌผ(์ž์ด์–ธ์ธ  ์ด๋จธ์‹œ๋ธŒ ์ปค๋จธ์Šค ๋ฐ๋ชจ ๋ฆฌ๋ทฐ)์„ ๋…น์ทจ ์›๋ฌธ๊ณผ ๋Œ€์กฐํ•œ ํ”ผ๋“œ๋ฐฑ์„ ๋ฐ˜์˜. *๊ทธ ํšŒ์˜๋ก ํ•œ ๊ฑด์„ ๊ณ ์น˜๋Š” ๊ฒŒ ์•„๋‹ˆ๋ผ*, ์•ž์œผ๋กœ ์ƒ์„ฑ๋  ๋ชจ๋“  ํšŒ์˜๋ก์˜ ์ƒ์„ฑ ํŒŒ์ดํ”„๋ผ์ธ(ํ”„๋กฌํ”„ํŠธ+์ฝ”๋“œ+๊ฒ€์ฆํŒจ์Šค)์„ ๊ฐœ์„ . +- **ํ™”์ž ์ •๊ทœํ™”(์ตœ์šฐ์„ )**: STT ํ™”์ž๋ฒˆํ˜ธ("์ฐธ์„์ž N")๋Š” ์‹ค๋ช…ยท์—ญํ• ์ด ์•„๋‹ˆ๊ณ  ๋ฒˆํ˜ธโ†”์ด๋ฆ„ ์—ฐ๊ฒฐ๊ณ ๋ฆฌ๊ฐ€ ๋…น์ทจ๋ก์— ์—†๋‹ค. ์ตœ์ข… ๋ฌธ์„œ์—์„œ "์ฐธ์„์ž N" ํ† ํฐ์„ **0๊ฐœ๋กœ ๋ฐ•๋ฉธ**ํ•˜๊ณ , ์œ„ํ—˜ํ•œ ๊ฐœ์ธ ์ถ”์ธก ๋Œ€์‹  **ํšŒ์‚ฌ ํ‘œ์ค€ ํŒ€/์—ญํ• **(PDยท๊ธฐํšยท์‚ฌ์—…ยทํด๋ผ์ด์–ธํŠธยท๋„ฅ์„œ์Šค๊ฐœ๋ฐœํŒ€ยทUIยท๋ฐฐ๊ฒฝํŒ€ยท์บ๋ฆญํ„ฐํŒ€ยทQAยท์‚ฌ์šด๋“œยท๊ฐœ๋ฐœPM)๋กœ ๊ท€์†. ๊ฐœ์ธ๋ช…์€ ๋ช…๋‹จ+๋ฌธ๋งฅ ํ™•์‹ค ์‹œ๋งŒ ๋ณ‘๊ธฐ, ํŒ€์กฐ์ฐจ ๋ถˆ๋ช…์ด๋ฉด ๋ฌด๊ท€์† ์ค‘๋ฆฝ ์„œ์ˆ . ์‹ ๊ทœ ์„ค์ • `g1nation.meetTeamRoster`. +- **ํšŒ์˜ ํ—ค๋” ์ „(ๅ…จ)์กฐ๊ฐ ์ฃผ์ž…**: ํŒŒ์ผ ์ƒ๋‹จ ์ฐธ์„์ž ๋ช…๋‹จยท์ผ์‹œยท์žฅ์†Œยท๋…น์ทจ ๊ธธ์ด๋ฅผ ํŒŒ์‹ฑํ•ด **๋ชจ๋“  ์ฒญํฌ ์ถ”์ถœ ํ”„๋กฌํ”„ํŠธ์— ์ฃผ์ž…**(์ž๋™ ์šฉ์–ด์ง‘๊ณผ ๋™์ผ ๋ฉ”์ปค๋‹ˆ์ฆ˜) โ€” ํ—ค๋”๊ฐ€ ์ฒซ ์กฐ๊ฐ์—๋งŒ ์žˆ์–ด ํ›„๋ฐ˜๋ถ€ ํ™”์ž๊ฐ€ ๊นจ์ง€๋˜ ๊ตฌ์กฐ์  ๊ฐญ ํ•ด์†Œ. ๊ฐœ์š”์— ์žฅ์†ŒยทํšŒ์˜์œ ํ˜•ยท๋…น์ทจ๊ธธ์ดยท์ž‘์„ฑ์ผ ์ž๋™ ๋ฐ˜์˜. ([calendarHelpers.ts](src/features/datacollect/scheduling/calendarHelpers.ts) `extractMeetingHeader`) +- **์ „์—ญ ํ—ค๋“œ๋ผ์ธ ์ถ”์ถœ**: 12K ์ฒญํฌ ๋ถ„ํ• ์˜ ์•ฝ์ (๋งˆ์ง€๋ง‰ ์ฒญํฌ์—๋งŒ ์žˆ๋Š” "๊ณ ๊ฐ ํ•ต์‹ฌ ์š”๊ตฌ 3์ข…"์ด ๋ฌปํž˜)์„ reduce ๋‹จ๊ณ„ "์ „ ์ฒญํฌ ๊ด€ํ†ต ๊ฒฐ๋ก  ์ถ”์ถœ"๋กœ ํ•ด๊ฒฐ โ€” ํ•ต์‹ฌ ์š”์•ฝ ๋งจ ์•ž์— ์„ธ์›€. +- **๊ฒฐ์ • ๊ฒŒ์ดํŠธ ๊ฐ•ํ™”**: "ํ…Œ์ŠคํŠธ ํ›„ ๊ฒฐ์ •/๋‹ค์‹œ ๋ณด๊ณ  ์–˜๊ธฐ/๊ณ ๋ฏผํ•ด๋ณด์ž"๋ฅ˜ ์กฐ๊ฑด๋ถ€ยท๋ฏธํ•ฉ์˜๋ฅผ ๊ฒฐ์ •์‚ฌํ•ญ์—์„œ ๋นผ ์˜คํ”ˆ์ด์Šˆ๋กœ. ๋‹ด๋‹น+ํ–‰๋™์ด ์žˆ๋Š” ์ผ๊ฐ์€ ์•ก์…˜์œผ๋กœ(๊ฒฐ์ •์—” ์ˆœ์ˆ˜ ๋ฐฉํ–ฅ/์ •์ฑ…๋งŒ) โ€” ๊ฒฐ์ •/์•ก์…˜ ์ค‘๋ณต ์ œ๊ฑฐ. +- **๋‹ดํ™” ์ƒํƒœ ํƒœ๊น…**: ์ถ”์ถœ ๋‹จ๊ณ„๊ฐ€ ๊ฐ ์ œ์•ˆ์„ `(ํ•ฉ์˜)`/`(๋ฏธํ•ฉ์˜)`/`(๋ฐ˜๋ฐ•๋จ)`/`(์ฒ ํšŒ๋จ)`์œผ๋กœ ํ‘œ์‹œ โ†’ ์ฆ‰์‹œ ์ผ์ถ•๋œ ๊ฐ€์„ค(์˜ˆ: "ํ‘์ธ ์˜ˆ์‹œ")์ด ์ •์‹ ์ด์Šˆ๋กœ ๊ฒฉ์ƒ๋˜๋Š” ๊ฒƒ ์ฐจ๋‹จ. ํ™”์ž๊ฐ„ ์ˆ˜์น˜ ์ถฉ๋Œ(6 vs 8)์€ ๋‹จ์ผ๊ฐ’ ํ™•์ • ๋ง๊ณ  ๊ทธ๋Œ€๋กœ ๋ช…์‹œ. +- **์Šฌ๋ฆผ ํฌ๋งท**: 7โ†’6 ์„น์…˜, ํ•œ ์‚ฌ์‹ค์€ ํ•œ ์„น์…˜์—๋งŒ(์ค‘๋ณต ์ œ๊ฑฐ), **๋นˆ ์นธ์€ "โ€”"**(๋นˆ ํ…œํ”Œ๋ฆฟ์ด ํ™˜๊ฐ ์œ ๋ฐœ), ๋ฆฌ์Šคํฌ๋Š” ์‹ค์ œ ๋…ผ์˜๋์„ ๋•Œ๋งŒ ํ‘œ ๋„์›€. ์•ก์…˜ ํ‘œ 6โ†’5์ปฌ๋Ÿผ(`๋‹ด๋‹น|์•ก์…˜|๊ธฐํ•œ|์ƒํƒœ|์ถœ์ฒ˜`), ์ž‘์—…๋‚ด์šฉ+์ƒ์„ธ ๋ณ‘ํ•ฉ. +- **๊ทผ๊ฑฐ = ํƒ€์ž„์Šคํƒฌํ”„**: STT ์›๋ฌธ ํ†ต์งธ ์ธ์šฉ ๋Œ€์‹  `[mm:ss]`๋กœ ์ •์ œ(๊ฒ€์ฆ ์ ํ”„ ๊ฐ€๋Šฅ). ์ถ”์ถœ ๋…ธํŠธ์—” verbatim ๋ณด์กด(๊ฒ€์ฆ์šฉ). +- **ํŒŒ์„œ ์•ˆ์ „ํ™”**: `parseActionItems`๋ฅผ **ํ—ค๋”๋ช… ๊ธฐ๋ฐ˜ ๋งคํ•‘**์œผ๋กœ ์žฌ์ž‘์„ฑ โ€” ์ปฌ๋Ÿผ ์ˆœ์„œยท๊ฐœ์ˆ˜๊ฐ€ ๋ฐ”๋€Œ์–ด๋„(์‹ /๊ตฌ ํ˜•์‹ ๋ชจ๋‘) ์บ˜๋ฆฐ๋” ํ™•์‹  ๊ฒŒ์ดํŠธ๊ฐ€ ์–ด๊ธ‹๋‚˜์ง€ ์•Š์Œ. ์ƒํƒœ taxonomy(ํ™•์ •/์ง„ํ–‰๋ฏธ์ •/๊ธฐํ•œ๋ฏธ์ •/์กฐ๊ฑด๋ถ€/๋ฐ˜๋ณต)ยท๊ฒŒ์ดํŠธ๋Š” ๋ถˆ๋ณ€. +- **๊ฒ€์ฆ ํŒจ์Šค ๊ธฐ๋ณธ ON**: ๋‹จ์ˆœ ๊ทผ๊ฑฐ ์กด์žฌ ํ™•์ธ โ†’ โ‘ ๊ทผ๊ฑฐ๋ฏธํ™•์ธ โ‘ก"์ฐธ์„์ž N" ์ž”์กด โ‘ข๊ฒฐ์ • ๊ณผํ™•์ • โ‘ฃํ๊ธฐ ๊ฐ€์„ค ๊ฒฉ์ƒ โ‘ค์•ก์…˜ ์ค‘๋ณต **5์ข… ์ ๊ฒ€**์œผ๋กœ ํ™•์žฅ(`g1nation.meetVerifyPass` ๊ธฐ๋ณธ true). +- ํšŒ๊ท€ ๊ฐ€๋“œ ๊ฐฑ์‹ ยท์‹ ๊ทœ([meetPrompt.test.ts](tests/meetPrompt.test.ts) ยท [meetRegistration.test.ts](tests/meetRegistration.test.ts)), ์ „์ฒด 698 ํ†ต๊ณผ. ์ฝ”์–ด ์ฑ„ํŒ… ๊ฒฝ๋กœ ๋ถˆ๋ณ€. + ## v2.2.257 (2026-06-19) ### ๐Ÿ“ `/meet` ํšŒ์˜๋ก โ€” ์ฑ…์ž„ ์†Œ์žฌยท๊ทผ๊ฑฐ ์ •์ฑ… 4์ข… (์ต๋ช… ๋‹ด๋‹นยท๋นˆ ์ธ์šฉยท๊ธฐํ•œยท๋ช…๋‹จ ์ •ํ•ฉ) ์‹ค์ œ ํšŒ์˜๋ก ์‚ฐ์ถœ๋ฌผ ๋ถ„์„์—์„œ ๋“œ๋Ÿฌ๋‚œ 4๊ฐœ ๊ฒฐํ•จ์„ ํ”„๋กฌํ”„ํŠธ ์ •์ฑ…์œผ๋กœ ์ฐจ๋‹จ. ๊ณต์œ  ์ถœ๋ ฅ ํ˜•์‹(๋‹จ์ผ์ƒท+reduce)๊ณผ ์ถ”์ถœ(map) ๋‹จ๊ณ„ ๋ชจ๋‘์— ์ ์šฉ. diff --git a/package.json b/package.json index 9174a6b..5df2772 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "astra", "displayName": "Astra", "description": "The personal intelligence layer for Antigravity and VS Code. A private cognitive partner for deep project context, memory, and proactive strategic decision-making.", - "version": "2.2.257", + "version": "2.2.258", "publisher": "g1nation", "license": "MIT", "icon": "assets/icon.png", @@ -313,8 +313,13 @@ }, "g1nation.meetVerifyPass": { "type": "boolean", - "default": false, - "markdownDescription": "`/meet` ํšŒ์˜๋ก ์ƒ์„ฑ ํ›„ **๊ฒ€์ฆ ํŒจ์Šค** ์‹คํ–‰ ์—ฌ๋ถ€. ๊ฒฐ์ • ์‚ฌํ•ญยท์•ก์…˜ ์•„์ดํ…œ์„ ๋…น์ทจ๋ก(๋˜๋Š” ์ถ”์ถœ ๋…ธํŠธ)๊ณผ LLM ์œผ๋กœ ๋Œ€์กฐํ•ด, ๊ทผ๊ฑฐ๋ฅผ ๋ชป ์ฐพ๋Š” ํ•ญ๋ชฉ์„ `โš ๏ธ ๊ฒ€์ฆ ๊ฒฐ๊ณผ` ์„น์…˜์œผ๋กœ ํ‘œ์‹œํ•œ๋‹ค (๋‚ ์กฐ ๊ฒ€์ถœ). LLM ํ˜ธ์ถœ์ด 1ํšŒ ์ถ”๊ฐ€๋˜์–ด ๊ทธ๋งŒํผ ๋А๋ ค์ง โ€” ์ค‘์š”ํ•œ ํšŒ์˜์—๋งŒ ์ผœ๋Š” ๊ฒƒ์„ ๊ถŒ์žฅ." + "default": true, + "markdownDescription": "`/meet` ํšŒ์˜๋ก ์ƒ์„ฑ ํ›„ **๊ฒ€์ฆ ํŒจ์Šค** ์‹คํ–‰ ์—ฌ๋ถ€(๊ธฐ๋ณธ ON). ์™„์„ฑ๋œ ํšŒ์˜๋ก์„ ๋…น์ทจ๋ก(๋˜๋Š” ์ถ”์ถœ ๋…ธํŠธ)๊ณผ LLM ์œผ๋กœ ๋Œ€์กฐํ•ด โ‘ ๊ทผ๊ฑฐ ๋ฏธํ™•์ธ โ‘ก\"์ฐธ์„์ž N\" ํ™”์ž๋ฒˆํ˜ธ ์ž”์กด โ‘ข๊ฒฐ์ • ๊ณผํ™•์ •(ํ…Œ์ŠคํŠธํ›„๊ฒฐ์ •ยท๊ฒ€ํ† ํ•„์š”) โ‘ฃํ๊ธฐ ๊ฐ€์„ค ๊ฒฉ์ƒ โ‘ค์•ก์…˜ ์ค‘๋ณต ์„ ์ ๊ฒ€ํ•˜๊ณ  `โš ๏ธ ๊ฒ€์ฆ ๊ฒฐ๊ณผ` ์„น์…˜์œผ๋กœ ํ‘œ์‹œํ•œ๋‹ค. LLM ํ˜ธ์ถœ์ด 1ํšŒ ์ถ”๊ฐ€๋˜์–ด ๊ทธ๋งŒํผ ๋А๋ ค์ง โ€” ๋„๋ ค๋ฉด false." + }, + "g1nation.meetTeamRoster": { + "type": "string", + "default": "", + "markdownDescription": "`/meet` ํ™”์ž ์ •๊ทœํ™”์šฉ **ํšŒ์‚ฌ ํ‘œ์ค€ ํŒ€/์—ญํ•  ๋ถ„๋ฅ˜**(์‰ผํ‘œ ๊ตฌ๋ถ„). STT ํ™”์ž๋ฒˆํ˜ธ(\"์ฐธ์„์ž N\")๋ฅผ ์‹ค๋ช… ์ถ”์ธก ๋Œ€์‹  ์ด ํŒ€๋“ค ์ค‘ ํ•˜๋‚˜๋กœ ๊ท€์†ํ•ด ์˜ค๊ท€์†์„ ๋ง‰๋Š”๋‹ค. ๋น„์›Œ๋‘๋ฉด ๊ธฐ๋ณธ๊ฐ’(`PD, ๊ธฐํš, ์‚ฌ์—…, ํด๋ผ์ด์–ธํŠธ, ๋„ฅ์„œ์Šค๊ฐœ๋ฐœํŒ€(์„œ๋ฒ„), UI, ๋ฐฐ๊ฒฝํŒ€, ์บ๋ฆญํ„ฐํŒ€, QA, ์‚ฌ์šด๋“œ, ๊ฐœ๋ฐœPM`) ์‚ฌ์šฉ. ํšŒ์‚ฌ ๊ตฌ์กฐ์— ๋งž๊ฒŒ ์ˆ˜์ •ํ•˜์„ธ์š”." }, "g1nation.dailyBriefing.enabled": { "type": "boolean", diff --git a/src/features/datacollect/handlers.ts b/src/features/datacollect/handlers.ts index afadf9c..40dd069 100644 --- a/src/features/datacollect/handlers.ts +++ b/src/features/datacollect/handlers.ts @@ -33,13 +33,14 @@ import { transcriptHash, taskKey, loadRegisteredKeys, markRegistered, savePending, loadPending, classifyAction, registerAction, buildNotes, renderPendingQuestion, processConfirmDecisions, - loadGlossaryTerms, updateGlossary, extractGlossaryCandidates, + loadGlossaryTerms, updateGlossary, extractGlossaryCandidates, loadTeamRoster, type PendingItem, type PendingFile, } from './scheduling/meetRegistration'; import { addBusinessDays, toYmd, extractMeetingDate, + extractMeetingHeader, resolveTaskDate, parseActionItems, } from './scheduling/calendarHelpers'; @@ -579,12 +580,23 @@ async function runMeet(arg: string, view: Webview | undefined, context?: vscode. // ์ค‘๋ณต ๋ฐฉ์ง€ ํ‚ค โ€” ๋™์ผ ๋…น์ทจ ์žฌ์‹คํ–‰ ์‹œ ์ด๋ฏธ ๋“ฑ๋ก๋œ ์•ก์…˜์„ ๊ฑด๋„ˆ๋›ฐ๊ธฐ ์œ„ํ•œ ํ•ด์‹œ (์›๋ณธ ์ „์ฒด ๊ธฐ์ค€). const tHash = transcriptHash(transcript); const userMetadata = metadata; // ์šฉ์–ด์ง‘ ํ›„๋ณด ์ถ”์ถœ์šฉ โ€” ์ž๋™ ๋ณด๊ฐ• ์ „ ์›๋ณธ ๋ณด์กด + // [ํšŒ์˜ ํ—ค๋” ํŒŒ์‹ฑ] STT ๋ณธ๋ฌธ(์ฒซ "์ฐธ์„์ž N mm:ss" ์ค„) ์•ž์˜ ํ—ค๋” ๋ธ”๋ก(์ฐธ์„์ž ๋ช…๋‹จยท + // ์ผ์‹œยท์žฅ์†Œยท๋…น์ทจ ๊ธธ์ด)์„ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ์— ๋Œ์–ด์˜ฌ๋ฆฐ๋‹ค. ํ—ค๋”๋Š” ์ฒซ ์กฐ๊ฐ์—๋งŒ ์žˆ์–ด ํ›„๋ฐ˜ + // ์กฐ๊ฐ์ด ๋ช…๋‹จ์„ ๋ชป ๋ณด๋˜ ๋ฌธ์ œ๋ฅผ, ๋ชจ๋“  ์กฐ๊ฐ ํ”„๋กฌํ”„ํŠธ์— ์ฃผ์ž…ํ•ด ํ•ด์†Œํ•œ๋‹ค(ํ™”์ž ์ •๊ทœํ™”ยท๋ฉ”ํƒ€ ์ถ”์ถœ). + const headerBlock = extractMeetingHeader(transcript); + if (headerBlock) { + metadata = `${headerBlock}\n${metadata ? '\n' + metadata : ''}`.trim(); + } + // [ํšŒ์‚ฌ ํ‘œ์ค€ ํŒ€ ๋ถ„๋ฅ˜] ํ™”์ž๋ฒˆํ˜ธ โ†’ ํŒ€/์—ญํ•  ๊ท€์†์˜ ํ†ต์ œ ์–ดํœ˜์ง‘. ๋ชจ๋“  ์กฐ๊ฐยท๋ณ‘ํ•ฉ์— ์ฃผ์ž…. + metadata = `${metadata ? metadata + '\n' : ''}[ํšŒ์‚ฌ ํ‘œ์ค€ ํŒ€/์—ญํ•  ๋ถ„๋ฅ˜ โ€” ํ™”์ž๋ฅผ ์ด ํŒ€๋“ค ์ค‘ ํ•˜๋‚˜๋กœ ๊ท€์†ํ•  ๊ฒƒ] ${loadTeamRoster()}`; + // [์ž‘์„ฑ์ผ] ํšŒ์˜ ๊ฐœ์š”์˜ '์ž‘์„ฑ์ผ' ์ฑ„์›€์šฉ (๋ชจ๋ธ์€ ์˜ค๋Š˜ ๋‚ ์งœ๋ฅผ ๋ชจ๋ฆ„). + metadata = `${metadata}\n[์ž‘์„ฑ์ผ] ${toYmd(new Date())}`; // [์ž๋™ ์šฉ์–ด์ง‘] ์ด์ „ /meet ๋“ค์—์„œ ๋ˆ„์ ๋œ ์ธ๋ช…ยท์šฉ์–ด๋ฅผ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ์— ๋ณด๊ฐ• โ€” // meetPrompt ๊ฐ€ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ STT ๋ณด์ • ์šฉ์–ด์ง‘์œผ๋กœ ์“ฐ๋ฏ€๋กœ ๋ฐ˜๋ณต ํšŒ์˜์˜ ํ‘œ๊ธฐ // ์ผ๊ด€์„ฑ์ด ์ž๋™์œผ๋กœ ์ข‹์•„์ง„๋‹ค. ์‚ฌ์šฉ์ž ์ž…๋ ฅ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๊ฐ€ ํ•ญ์ƒ ์šฐ์„ (์•ž์— ๋ฐฐ์น˜). const glossaryTerms = loadGlossaryTerms(); if (glossaryTerms.length) { - metadata = `${metadata ? metadata + '\n' : ''}[์ž๋™ ์šฉ์–ด์ง‘ โ€” ์ด์ „ ํšŒ์˜์—์„œ ๋ˆ„์ ๋œ ์ธ๋ช…ยท์šฉ์–ด ํ‘œ๊ธฐ] ${glossaryTerms.join(', ')}`; + metadata = `${metadata}\n[์ž๋™ ์šฉ์–ด์ง‘ โ€” ์ด์ „ ํšŒ์˜์—์„œ ๋ˆ„์ ๋œ ์ธ๋ช…ยท์šฉ์–ด ํ‘œ๊ธฐ] ${glossaryTerms.join(', ')}`; chunk(view, `๐Ÿ“š ์ž๋™ ์šฉ์–ด์ง‘ ${glossaryTerms.length}๊ฐœ ์šฉ์–ด ์ฃผ์ž…\n`); } // v2.2.211: 60K ํ•˜๋“œ ์ž๋ฅด๊ธฐ ํ์ง€ โ†’ ์„ธ๊ทธ๋จผํŠธ ์ถ”์ถœ(Map) + ๋ณ‘ํ•ฉ(Reduce). @@ -696,8 +708,8 @@ async function runMeet(arg: string, view: Webview | undefined, context?: vscode. return true; } - // โ”€โ”€ ๊ฒ€์ฆ ํŒจ์Šค (์˜ต์…˜, g1nation.meetVerifyPass) โ€” ๊ฒฐ์ •ยท์•ก์…˜์„ ๊ทผ๊ฑฐ ์†Œ์Šค์™€ ๋Œ€์กฐ โ”€โ”€ - if (cfg.get('meetVerifyPass', false)) { + // โ”€โ”€ ๊ฒ€์ฆ ํŒจ์Šค (g1nation.meetVerifyPass, ๊ธฐ๋ณธ ON) โ€” ๊ฒฐ์ •ยท์•ก์…˜ยทํ™”์ž๋ฒˆํ˜ธยท๊ณผํ™•์ •ยท์ค‘๋ณต ์ ๊ฒ€ โ”€โ”€ + if (cfg.get('meetVerifyPass', true)) { try { chunk(view, `๐Ÿ” **๊ฒ€์ฆ ํŒจ์Šค** โ€” ๊ฒฐ์ •ยท์•ก์…˜ ๊ทผ๊ฑฐ ๋Œ€์กฐ ์ค‘โ€ฆ`); const t2 = Date.now(); @@ -782,7 +794,7 @@ async function runMeet(arg: string, view: Webview | undefined, context?: vscode. if (cls.route === 'hold') { holds.push({ idx: holds.length + 1, - owner: task.owner, work: task.work, detail: task.detail, deliverable: task.deliverable, due: task.due, + owner: task.owner, work: task.work, detail: task.detail, deliverable: task.deliverable, due: task.due, source: task.source, kind: cls.kind, condition: cls.condition, suggestedDate: cls.suggestedDate, }); continue; @@ -796,7 +808,7 @@ async function runMeet(arg: string, view: Webview | undefined, context?: vscode. if (cls.recurNote) extra.push(`โ†ป ๋ฐ˜๋ณต ์—…๋ฌด ์–ธ๊ธ‰(${cls.recurNote}) โ€” ์ •์ฑ…์ƒ ์ฒซ 1ํšŒ๋งŒ ๋“ฑ๋กํ•ฉ๋‹ˆ๋‹ค.`); const notes = buildNotes({ detail: task.detail, meetTitle, owner: task.owner, deliverable: task.deliverable, - dueRaw: task.due, dateLabel: cls.date, extra, + dueRaw: task.due, dateLabel: cls.date, source: task.source, extra, }); const r = await registerAction(context, { title: evTitle, date: cls.date, notes, diff --git a/src/features/datacollect/prompts/meetPrompt.ts b/src/features/datacollect/prompts/meetPrompt.ts index d71b5c2..6bf7e80 100644 --- a/src/features/datacollect/prompts/meetPrompt.ts +++ b/src/features/datacollect/prompts/meetPrompt.ts @@ -1,6 +1,17 @@ /** * ํšŒ์˜ ๋…น์ทจ ํ…์ŠคํŠธ โ†’ ์‚ฌ์‹ค ๊ธฐ๋ฐ˜ ๊ตฌ์กฐํ™” ํšŒ์˜๋ก(Actionable Minutes) LLM ํ”„๋กฌํ”„ํŠธ. * ์‚ฌ์šฉ์ž ์ •์˜ ๊ทœ์น™: Fact/Discussion/Decision/Risk/Action ๋ถ„๋ฅ˜, ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ์šฐ์„ . + * + * v2.2.258 ๊ฐœ์„ (์‚ฌ์šฉ์ž ํ”ผ๋“œ๋ฐฑ ๋ฐ˜์˜): + * - ํ™”์ž: STT ํ™”์ž๋ฒˆํ˜ธ("์ฐธ์„์ž N")๋ฅผ **ํŒ€/์—ญํ• **๋กœ ์ •๊ทœํ™”(๊ฐœ์ธ๋ช…์€ ํ™•์‹คํ•  ๋•Œ๋งŒ ๋ณ‘๊ธฐ). + * ์ตœ์ข… ๋ฌธ์„œ์— "์ฐธ์„์ž N" ํ† ํฐ์„ ์ ˆ๋Œ€ ๋…ธ์ถœํ•˜์ง€ ์•Š๋Š”๋‹ค. + * - ์ „์—ญ ํ—ค๋“œ๋ผ์ธ: ์ฒญํฌ ์ „์ฒด๋ฅผ ๊ด€ํ†ตํ•˜๋Š” ๊ฒฐ๋ก /ํ•ต์‹ฌ ์š”๊ตฌ๋ฅผ ๋ณ„๋„ ์ถ”์ถœํ•ด ๋งจ ์•ž์— ์„ธ์šด๋‹ค. + * - ๊ฒฐ์ •/์•ก์…˜ ๊ฒฝ๊ณ„: ์ผ๊ฐ(๋‹ด๋‹น ์žˆ๋Š” ๊ฒƒ)์€ ์•ก์…˜์œผ๋กœ, ๊ฒฐ์ •์‚ฌํ•ญ์—” ์ˆœ์ˆ˜ ๋ฐฉํ–ฅ/์ •์ฑ…๋งŒ. + * - ์กฐ๊ฑด๋ถ€ ๊ฒฐ์ •: "ํ…Œ์ŠคํŠธ ํ›„ ๊ฒฐ์ •" ๋ฅ˜๋Š” ๊ฒฐ์ •์ด ์•„๋‹ˆ๋ผ ์˜คํ”ˆ ์ด์Šˆ๋กœ. + * - ํ๊ธฐ ๊ฐ€์„ค/์ถฉ๋Œ: ์ฆ‰์‹œ ๋ฐ˜๋ฐ•ยท์ฒ ํšŒ๋œ ์ œ์•ˆ์€ ์ด์Šˆ๋กœ ๊ฒฉ์ƒ ๊ธˆ์ง€, ํ™”์ž๊ฐ„ ์ˆ˜์น˜์ถฉ๋Œ์€ ๊ทธ๋Œ€๋กœ ๋ช…์‹œ. + * - ์Šฌ๋ฆผ ํฌ๋งท: 7โ†’6 ์„น์…˜, ํ•œ ์‚ฌ์‹ค์€ ํ•œ ์„น์…˜์—๋งŒ(์ค‘๋ณต ์ œ๊ฑฐ), ๋นˆ ์นธ์€ "โ€”". + * - ๊ทผ๊ฑฐ: STT ์›๋ฌธ ํ†ต์งธ ์ธ์šฉ ๋Œ€์‹  ํƒ€์ž„์Šคํƒฌํ”„ [mm:ss]๋กœ ์ •์ œ(๊ฒ€์ฆ ๊ฐ€๋Šฅ ๊ธฐ๋ก). + * - ๋ฆฌ์Šคํฌ ํ‘œ๋Š” ์‹ค์ œ๋กœ ๋ฆฌ์Šคํฌ+์™„ํ™”์ฑ…์ด ๋…ผ์˜๋์„ ๋•Œ๋งŒ ๋„์šด๋‹ค(๋นˆ ํ…œํ”Œ๋ฆฟ = ํ™˜๊ฐ ์œ ๋ฐœ). */ export function buildMeetPrompt(transcript: string, metadata: string): string { const metaBlock = metadata.trim() @@ -12,45 +23,53 @@ export function buildMeetPrompt(transcript: string, metadata: string): string { # ์—ญํ•  (Role) - Fact Extractor: ๋…น์ทจ๋ก์— ๋ช…์‹œ์ ์œผ๋กœ ์กด์žฌํ•˜๋Š” ์‚ฌ์‹ค๋งŒ ์ถ”์ถœ -- Attribution Tracker: ๋ˆ„๊ฐ€ ๋ฌด์—‡์„ ๋งํ–ˆ๋Š”์ง€ ๋ฐœ์–ธ ์ฃผ์ฒด๋ฅผ ๋๊นŒ์ง€ ์ถ”์ ํ•ด ์˜ค๊ท€์†์„ ๋ฐฉ์ง€ -- Decision Tracker: ๊ฒฐ์ • ์—ฌ๋ถ€ ๊ตฌ๋ถ„ +- Attribution Tracker: ๋ˆ„๊ฐ€ ๋ฌด์—‡์„ ๋งํ–ˆ๋Š”์ง€ ์ถ”์ ํ•˜๋˜, ํ™”์ž๋ฅผ **ํŒ€/์—ญํ• **๋กœ ๊ท€์†ํ•œ๋‹ค(์•„๋ž˜ 'ํ™”์ž ์ •๊ทœํ™”' ์ฐธ์กฐ) +- Decision Tracker: ๊ฒฐ์ • ์—ฌ๋ถ€ ๊ตฌ๋ถ„ (๋ช…์‹œ์  ํ•ฉ์˜๋งŒ ๊ฒฐ์ •) - Action Organizer: ์‹คํ–‰ ํ•ญ๋ชฉ ๊ตฌ์กฐํ™” - Context Filter: ๋ถˆํ•„์š”ํ•œ ๋ฐœ์–ธ(์žก๋‹ด) ์ œ๊ฑฐ # ๋ฐ์ดํ„ฐ ์šฐ์„ ์ˆœ์œ„ (Data Priority) -1์ˆœ์œ„: ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ / 2์ˆœ์œ„: ๋…น์ทจ๋ก ๋‚ด์šฉ. ์ถฉ๋Œ ์‹œ ๋ฐ˜๋“œ์‹œ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. +1์ˆœ์œ„: ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ(ํšŒ์˜ ํ—ค๋”ยท์ฐธ์„์ž ๋ช…๋‹จยทํšŒ์‚ฌ ํ‘œ์ค€ ํŒ€ ๋ถ„๋ฅ˜) / 2์ˆœ์œ„: ๋…น์ทจ๋ก ๋‚ด์šฉ. ์ถฉ๋Œ ์‹œ ๋ฐ˜๋“œ์‹œ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. -# STT ์˜คํƒ€ ๋ณด์ • (Transcription Noise Handling โ€” ์ด ๋…น์ทจ๋ก์€ ์Œ์„ฑโ†’ํ…์ŠคํŠธ ๋ณ€ํ™˜๋ฌผ์ด๋ผ ์˜คํƒ€๊ฐ€ ๋งŽ๋‹ค) -- ๋ฐœ์Œ์ด ์œ ์‚ฌํ•œ ๋‹จ์–ด๊ฐ€ ์ž˜๋ชป ํ‘œ๊ธฐ๋ผ ์žˆ๋‹ค(์˜ˆ: "Dovrunner"โ†’"Doverunner", "ํŽ˜์–ดํ”Œ๋ ˆ์ด"โ†’"ํŽ˜์–ดํ”Œ๋ž˜์ด"). **ํ•œ ๋‹จ์–ด์˜ ์ฒ ์ž์— ์ง‘์ฐฉํ•˜์ง€ ๋ง๊ณ  ์ฃผ๋ณ€ ๋ฌธ๋งฅ(์•ž๋’ค ํ‚ค์›Œ๋“œ)์œผ๋กœ ์˜๋ฏธ๋ฅผ ๋ณต์›ํ•˜๋ผ.** -- ๋ฐœ์Œ์ด ์œ ์‚ฌํ•œ ๋ช…๋ฐฑํ•œ ์˜คํƒ€๋Š” ๋ฌธ๋งฅ์ƒ ๋งž๋Š” ๊ธฐ์ˆ  ์šฉ์–ดยท๊ณ ์œ ๋ช…์‚ฌ๋กœ **์ •๊ทœํ™”**ํ•˜๋ผ. ํ”ํ•œ ๊ธฐ์ˆ  ์šฉ์–ด(DRM, SDK, ๋”ฅ๋งํฌ, API, ๋ Œ๋”๋ง, ํŽ˜์–ดํ”Œ๋ ˆ์ด, ์•”ํ˜ธํ™” ๋“ฑ)๋Š” ๋„๋ฉ”์ธ ์ง€์‹์œผ๋กœ ๋ณด์ •ํ•ด๋„ ๋œ๋‹ค. -- ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ์— ์ธ๋ช…ยท๊ธฐ์—…๋ช…ยท์ œํ’ˆ๋ช…ยท์šฉ์–ด๊ฐ€ ์ฃผ์–ด์กŒ์œผ๋ฉด ๊ทธ๊ฒƒ์„ **์ •๋‹ต ํ‘œ๊ธฐ**๋กœ ๋ณด๊ณ , ๋…น์ทจ๋ก์˜ ์œ ์‚ฌ ์˜คํƒ€๋ฅผ ๊ทธ ํ‘œ๊ธฐ๋กœ ๋งž์ถ˜๋‹ค(๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋Š” ์‚ฌ์‹ค์ƒ ์šฉ์–ด์ง‘ ์—ญํ• ). -- **ํ•ต์‹ฌ ๊ตฌ๋ถ„ (์ ˆ๋Œ€ ํ˜ผ๋™ ๊ธˆ์ง€)**: '๋…น์ทจ๋ก์— *์žˆ๋Š”* ๋‹จ์–ด์˜ ์ฒ ์ž๋ฅผ ๋ฌธ๋งฅ์œผ๋กœ ๋ฐ”๋กœ์žก๋Š” ๊ฒƒ'์€ ํ—ˆ์šฉยท๊ถŒ์žฅ๋œ๋‹ค. '๋…น์ทจ๋ก์— *์—†๋Š”* ์‚ฌ์‹ค(์ˆ˜์น˜ยท๊ฒฐ์ •ยท์—†๋˜ ํ•ญ๋ชฉ)์„ ์ง€์–ด๋‚ด๋Š” ๊ฒƒ'์€ ๊ธˆ์ง€๋‹ค. **์ฒ ์ž ๋ณด์ • โ‰  ์‚ฌ์‹ค ๋‚ ์กฐ.** -- ์ฒ ์ž๊ฐ€ ํ‹€๋ ค๋„ ๋ฌธ๋งฅ์ƒ ์˜๋ฏธ๊ฐ€ ๋ถ„๋ช…ํ•˜๋ฉด ๊ทธ ์˜๋ฏธ๋ฅผ ํ™•์ •๋œ ๊ฒƒ์œผ๋กœ ๋‹ค๋ค„๋ผ โ€” **์˜คํƒ€ ํ•˜๋‚˜ ๋•Œ๋ฌธ์— ๋ฉ€์ฉกํ•œ ๋‚ด์šฉ ์ „์ฒด๋ฅผ "ํ™•์ธ ๋ถˆ๊ฐ€"๋กœ ๋ง‰์ง€ ๋ง ๊ฒƒ.** -- ์ •๊ทœํ™”๋Š” ํ–ˆ์ง€๋งŒ ๋ฌธ๋งฅ์œผ๋กœ๋„ ์ •์ฒด๊ฐ€ ๋๋‚ด ๋ชจํ˜ธํ•œ ์šฉ์–ด์— ํ•œํ•ด, ์ •๊ทœํ™” ํ‘œ๊ธฐ ์˜†์— ์›๋ฌธ์„ ํ•จ๊ป˜ ๋‚จ๊ธด๋‹ค: ์˜ˆ) \`Doverunner(์›๋ฌธ: "Dovrunner", ํ‘œ๊ธฐ ๋ถˆํ™•์‹ค)\`. +# ํ™”์ž ์ •๊ทœํ™” (Speaker Normalization โ€” ์ตœ์šฐ์„ , ํ™˜๊ฐยท์˜ค๊ท€์† ๋ฐฉ์ง€) +์ด ๋…น์ทจ๋ก์˜ "์ฐธ์„์ž 1", "์ฐธ์„์ž 2" โ€ฆ ๋Š” STT๊ฐ€ ์ž„์˜๋กœ ๋ถ™์ธ **ํ™”์ž๋ฒˆํ˜ธ**์ผ ๋ฟ ์‹ค๋ช…ยท์—ญํ• ์ด ์•„๋‹ˆ๋‹ค. ๋ฒˆํ˜ธโ†”์ด๋ฆ„ ์—ฐ๊ฒฐ๊ณ ๋ฆฌ๋Š” ๋…น์ทจ๋ก์— ์—†๋‹ค. +- **์ตœ์ข… ๋ฌธ์„œ์— "์ฐธ์„์ž N"(๋˜๋Š” "ํ™”์ž N", "๋ฐœ์–ธ์ž A") ํ† ํฐ์„ ์ ˆ๋Œ€ ์“ฐ์ง€ ๋ง ๊ฒƒ.** 0๊ฐœ์—ฌ์•ผ ํ•œ๋‹ค. +- ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ์˜ **ํšŒ์˜ ์ฐธ์„์ž ๋ช…๋‹จ(์—ญํ• :์ด๋ฆ„)**๊ณผ **ํšŒ์‚ฌ ํ‘œ์ค€ ํŒ€ ๋ถ„๋ฅ˜**๋ฅผ ํ†ต์ œ ์–ดํœ˜์ง‘์œผ๋กœ ์‚ผ์•„, ๊ฐ ํ™”์ž๋ฒˆํ˜ธ๋ฅผ *๋ฐœ์–ธ ๋‚ด์šฉ ๋‹จ์„œ*๋กœ **ํŒ€/์—ญํ• **์— ๋งคํ•‘ํ•œ๋‹ค. (์˜ˆ: ๋ผ์ด์„ ์ŠคยทAI์ž‘์—…ยทํด๋ฆฌ์‹ฑ์„ ๋งํ•˜๋Š” ํ™”์ž โ†’ [๋„ฅ์„œ์Šค๊ฐœ๋ฐœํŒ€], ๋ชจ๋“  ์˜์‚ฌ๊ฒฐ์ •์„ ๋‚ด๋ฆฌ๊ณ  ๋‹ค๋ฅธ ์‚ฌ๋žŒ์ด "์ƒ๋ฌด๋‹˜"์œผ๋กœ ๋ถ€๋ฅด๋Š” ํ™”์ž โ†’ [ํด๋ผ์ด์–ธํŠธ]) +- **๊ฐ™์€ ํ™”์ž๋ฒˆํ˜ธ๋Š” ํšŒ์˜ ๋‚ด๋‚ด ๊ฐ™์€ ํŒ€/์—ญํ• ๋กœ ๊ณ ์ •**ํ•œ๋‹ค(์ค‘๊ฐ„์— ๋ฐ”๊พธ์ง€ ๋ง ๊ฒƒ). +- ๊ฐœ์ธ ์‹ค๋ช…์€ ๋ช…๋‹จ+๋ฌธ๋งฅ์œผ๋กœ **ํ™•์‹คํ•  ๋•Œ๋งŒ** ๊ด„ํ˜ธ๋กœ ๋ณ‘๊ธฐํ•œ๋‹ค(์˜ˆ: [๋„ฅ์„œ์Šค๊ฐœ๋ฐœํŒ€ยท๊น€์ƒ์—ฝ]). ํ™•์‹  ์—†์œผ๋ฉด ํŒ€/์—ญํ• ๊นŒ์ง€๋งŒ. +- ํŒ€/์—ญํ• ์กฐ์ฐจ ๋‹จ์„œ๊ฐ€ ๋ถ€์กฑํ•˜๋ฉด **๊ท€์†์„ ์ƒ๋žต**ํ•˜๊ณ  "~๋ผ๋Š” ์˜๊ฒฌ์ด ์ œ์‹œ๋จ"์ฒ˜๋Ÿผ ์ฃผ์ฒด ์—†์ด ์ค‘๋ฆฝ ์„œ์ˆ ํ•œ๋‹ค. ๋ฒˆํ˜ธ๋ฅผ ๋‚จ๊ธฐ๋А๋‹ˆ ์ฃผ์ฒด๋ฅผ ๋น„์šฐ๋Š” ๊ฒŒ ๋‚ซ๋‹ค. +- ๋ฌด๋ฆฌํ•œ ๋งคํ•‘(ํŠนํžˆ ๊ฐœ์ธ ์‹ค๋ช… ์ถ”์ธก)์€ ์˜ค๊ท€์†์„ ๋‚ณ์•„ ์‹ ๋ขฐ๋„๋ฅผ ๊ฐ€์žฅ ํฌ๊ฒŒ ํ•ด์นœ๋‹ค โ€” **๋ถˆํ™•์‹คํ•˜๋ฉด ํ•œ ๋‹จ๊ณ„ ์œ„(๊ฐœ์ธโ†’ํŒ€, ํŒ€โ†’๋ฌด๊ท€์†)๋กœ ๋ฌผ๋Ÿฌ์„œ๋ผ.** + +# STT ์˜คํƒ€ ๋ณด์ • (Transcription Noise Handling โ€” ์Œ์„ฑโ†’ํ…์ŠคํŠธ ๋ณ€ํ™˜๋ฌผ์ด๋ผ ์˜คํƒ€๊ฐ€ ๋งŽ๋‹ค) +- ๋ฐœ์Œ์ด ์œ ์‚ฌํ•œ ๋‹จ์–ด๊ฐ€ ์ž˜๋ชป ํ‘œ๊ธฐ๋ผ ์žˆ๋‹ค. **ํ•œ ๋‹จ์–ด์˜ ์ฒ ์ž์— ์ง‘์ฐฉํ•˜์ง€ ๋ง๊ณ  ์ฃผ๋ณ€ ๋ฌธ๋งฅ์œผ๋กœ ์˜๋ฏธ๋ฅผ ๋ณต์›ํ•˜๋ผ.** +- ํ”ํ•œ ๊ธฐ์ˆ  ์šฉ์–ด(DRM, SDK, ๋”ฅ๋งํฌ, API, ๋ Œ๋”๋ง, ์ž์ด๋กœ์„ผ์„œ ๋“ฑ)ยท๊ณ ์œ ๋ช…์‚ฌ๋Š” ๋„๋ฉ”์ธ ์ง€์‹์œผ๋กœ **์ •๊ทœํ™”**ํ•˜๋ผ. +- ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ์— ์ธ๋ช…ยท๊ธฐ์—…๋ช…ยท์ œํ’ˆ๋ช…ยท์šฉ์–ด๊ฐ€ ์žˆ์œผ๋ฉด ๊ทธ๊ฒƒ์„ **์ •๋‹ต ํ‘œ๊ธฐ**๋กœ ๋ณธ๋‹ค(๋ฉ”ํƒ€๋ฐ์ดํ„ฐ = ์šฉ์–ด์ง‘). +- **ํ•ต์‹ฌ ๊ตฌ๋ถ„ (์ ˆ๋Œ€ ํ˜ผ๋™ ๊ธˆ์ง€)**: '๋…น์ทจ๋ก์— *์žˆ๋Š”* ๋‹จ์–ด์˜ ์ฒ ์ž๋ฅผ ๋ฌธ๋งฅ์œผ๋กœ ๋ฐ”๋กœ์žก๋Š” ๊ฒƒ'์€ ํ—ˆ์šฉยท๊ถŒ์žฅ. '๋…น์ทจ๋ก์— *์—†๋Š”* ์‚ฌ์‹ค(์ˆ˜์น˜ยท๊ฒฐ์ •ยท์—†๋˜ ํ•ญ๋ชฉ)์„ ์ง€์–ด๋‚ด๋Š” ๊ฒƒ'์€ ๊ธˆ์ง€. **์ฒ ์ž ๋ณด์ • โ‰  ์‚ฌ์‹ค ๋‚ ์กฐ.** +- ์˜คํƒ€ ํ•˜๋‚˜ ๋•Œ๋ฌธ์— ๋ฉ€์ฉกํ•œ ๋‚ด์šฉ ์ „์ฒด๋ฅผ "ํ™•์ธ ๋ถˆ๊ฐ€"๋กœ ๋ง‰์ง€ ๋ง ๊ฒƒ. # ์ฒ˜๋ฆฌ ์ ˆ์ฐจ (Processing Flow) -1. Speaker Tracking โ€” ๋ฐœ์–ธ์ž ID/์ด๋ฆ„์„ ๋๊นŒ์ง€ ์œ ์ง€ํ•œ๋‹ค. **๋ˆ„๊ฐ€ ํ•œ ๋ง์ธ์ง€๋ฅผ ์ ˆ๋Œ€ ์ž„์˜๋กœ ๋ฐ”๊พธ๊ฑฐ๋‚˜ ํ•ฉ์น˜์ง€ ๋ง ๊ฒƒ.** -2. Topic Reclustering โ€” ์ด ๋…น์ทจ๋ก์€ ๋น„์„ ํ˜•์ด๋‹ค(Aโ†’Bโ†’Zโ†’๋‹ค์‹œ A ์‹์œผ๋กœ ์ฃผ์ œ๊ฐ€ ํŠ„๋‹ค). ๋…น์ทจ๋ก ์ „์ฒด๋ฅผ ํ›‘์–ด **ํฉ์–ด์ง„ ๋ฐœ์–ธ์„ ์ฃผ์ œ๋ณ„๋กœ ๋‹ค์‹œ ๋ฌถ์€ ๋’ค** ์ •๋ฆฌํ•œ๋‹ค. ๋…น์ทจ๋ก์ƒ ์•ž๋’ค๋กœ ๋ถ™์–ด ์žˆ๋‹ค๋Š” ์ด์œ ๋งŒ์œผ๋กœ ๋‘ ๋ฐœ์–ธ์„ ์ธ๊ณผยท์—ฐ๊ฒฐ ๊ด€๊ณ„๋กœ ์—ฎ์ง€ ๋ง ๊ฒƒ(**์ธ์ ‘ โ‰  ์—ฐ๊ฒฐ**). -3. Deconstruction โ€” ์žก๋‹ด์„ ์ œ๊ฑฐํ•˜๊ณ  ์˜๋ฏธ ๋‹จ์œ„๋กœ ๋ถ„ํ•ดํ•˜๋˜, ๊ฐ ๋‹จ์œ„์— ๋ฐœ์–ธ ์ฃผ์ฒด๋ฅผ ๋ณด์กดํ•œ๋‹ค. -4. Classification โ€” ๋ชจ๋“  ๋‚ด์šฉ์„ Fact / Discussion / Decision / Risk / Action ์œผ๋กœ ๋ถ„๋ฅ˜ํ•œ๋‹ค. -5. Decision Logic - - ๋ช…ํ™•ํ•œ ํ•ฉ์˜ ํ‘œํ˜„ โ†’ Decision +1. Speaker Normalization โ€” ์œ„ ๊ทœ์น™๋Œ€๋กœ ํ™”์ž๋ฒˆํ˜ธ๋ฅผ ํŒ€/์—ญํ• ๋กœ ๋งคํ•‘(๋ฒˆํ˜ธ ๋ฐ•๋ฉธ). +2. Topic Reclustering โ€” ๋…น์ทจ๋ก์€ ๋น„์„ ํ˜•์ด๋‹ค(์ฃผ์ œ๊ฐ€ ํŠ„๋‹ค). ์ „์ฒด๋ฅผ ํ›‘์–ด **ํฉ์–ด์ง„ ๋ฐœ์–ธ์„ ์ฃผ์ œ๋ณ„๋กœ ๋‹ค์‹œ ๋ฌถ๋Š”๋‹ค.** ์•ž๋’ค๋กœ ๋ถ™์–ด ์žˆ๋‹ค๋Š” ์ด์œ ๋งŒ์œผ๋กœ ๋‘ ๋ฐœ์–ธ์„ ์ธ๊ณผ๋กœ ์—ฎ์ง€ ๋ง ๊ฒƒ(**์ธ์ ‘ โ‰  ์—ฐ๊ฒฐ**). +3. Global Headline โ€” ํšŒ์˜ ์ „์ฒด๋ฅผ ๊ด€ํ†ตํ•˜๋Š” **๊ฒฐ๋ก /ํ•ต์‹ฌ ์š”๊ตฌ**(ํŠนํžˆ ํ›„๋ฐ˜๋ถ€์— ์ •๋ฆฌ๋œ ๊ฒƒ)๋ฅผ ๋ณ„๋„๋กœ ์‹๋ณ„ํ•ด 'ํ•ต์‹ฌ ์š”์•ฝ'์— ์„ธ์šด๋‹ค. +4. Dialectic Check โ€” ๊ฐ ์ œ์•ˆ์ด **ํ•ฉ์˜๋๋Š”์ง€ / ๋ฐ˜๋ฐ•ยท์ฒ ํšŒ๋๋Š”์ง€ / ๋ฏธ๊ฒฐ์ธ์ง€**๋ฅผ ๋Œ€ํ™” ํ๋ฆ„ ๋๊นŒ์ง€ ๋ณด๊ณ  ํŒ์ •ํ•œ๋‹ค. ์ฆ‰์‹œ ์ผ์ถ•ยท๋ฐ˜๋ฐ•๋œ ๊ฐ€์„ค์„ ์ •์‹ ์ด์Šˆ๋กœ ๊ฒฉ์ƒํ•˜์ง€ ๋ง ๊ฒƒ. ํ™”์ž๊ฐ„ ์ˆ˜์น˜ยท์˜๊ฒฌ์ด ๊ฐˆ๋ฆฌ๋ฉด ๋‹จ์ผ๊ฐ’์œผ๋กœ ํ™•์ •ํ•˜์ง€ ๋ง๊ณ  ์ถฉ๋Œ์„ ๊ทธ๋Œ€๋กœ ์ ๋Š”๋‹ค(์˜ˆ: "6 vs 8, ๊ธฐ์ค€ ๋ฏธ์ •"). +5. Classification โ€” Fact / Discussion / Decision / Risk / Action ๋ถ„๋ฅ˜. +6. Decision Logic + - ๋ช…์‹œ์  ํ•ฉ์˜ ํ‘œํ˜„ โ†’ Decision (๋‹จ, ๋‹ด๋‹น+ํ–‰๋™์ด ์žˆ๋Š” ์ผ๊ฐ์€ Action์œผ๋กœ ๋ณด๋‚ด๊ณ  ๊ฒฐ์ •์—” ์ˆœ์ˆ˜ ๋ฐฉํ–ฅ/์ •์ฑ…๋งŒ) + - "ํ…Œ์ŠคํŠธํ•ด๋ณด๊ณ  ๊ฒฐ์ • / ๋‹ค์‹œ ๋ณด๊ณ  ์–˜๊ธฐ / ๊ณ ๋ฏผํ•ด๋ณด์ž" โ†’ Decision ์•„๋‹˜ โ†’ Open Issue - ์‹คํ–‰ ์ฃผ์ฒด + ํ–‰๋™ โ†’ Action - ์ œ์•ˆ/์˜๊ฒฌ โ†’ Discussion - - ์กฐ๊ฑด ๋ถ€์กฑ / ํ•ฉ์˜ ๋ถˆ๋ช…ํ™• โ†’ Open Issue -6. Structuring โ€” ์ค‘๋ณต ์ œ๊ฑฐ, ํ•ต์‹ฌ๋งŒ ์œ ์ง€, ์งง๊ณ  ๋ช…ํ™•ํ•œ ๋ฌธ์žฅ์„ ์‚ฌ์šฉํ•œ๋‹ค. +7. Dedup & Structuring โ€” ํ‘œํ˜„์ด ๋‹ฌ๋ผ๋„ ์˜๋ฏธ๊ฐ€ ๊ฐ™์€ ํ•ญ๋ชฉ์€ ํ•˜๋‚˜๋กœ ๋ณ‘ํ•ฉ. **ํ•œ ์‚ฌ์‹ค์€ ํ•œ ์„น์…˜์—๋งŒ** ๋‘”๋‹ค(์š”์•ฝยท๊ฒฐ์ •ยท์•ก์…˜์— ๊ฐ™์€ ๋‚ด์šฉ ์ค‘๋ณต ๊ธˆ์ง€). # ๊ทผ๊ฑฐยท์ •ํ™•์„ฑ ๊ทœ์น™ (Grounding Rules โ€” ๋ฐ˜๋“œ์‹œ ์ค€์ˆ˜, ํ• ๋ฃจ์‹œ๋„ค์ด์…˜ ๋ฐฉ์ง€) -- **๋…น์ทจ๋ก์— ๋ช…์‹œ๋œ ๋‚ด์šฉ๋งŒ ์ ๋Š”๋‹ค.** ์ถ”๋ก ์œผ๋กœ ๋นˆ์นธ์„ ๋ฉ”์šฐ๊ฑฐ๋‚˜, ๋ณ„๊ฐœ์˜ ๋ฐœ์–ธ์„ ํ•˜๋‚˜์˜ ์ธ๊ณผ ์‚ฌ์Šฌ๋กœ ํ•ฉ์„ฑํ•˜์ง€ ๋ง ๊ฒƒ. -- **๊ทผ๊ฑฐ ์ธ์šฉ ์˜๋ฌด**: ๋ชจ๋“  '๊ฒฐ์ • ์‚ฌํ•ญ'๊ณผ '์•ก์…˜ ์•„์ดํ…œ'์—๋Š” ๊ทผ๊ฑฐ๊ฐ€ ๋œ ๋ฐœ์–ธ ์›๋ฌธ ์ผ๋ถ€(20์ž ๋‚ด์™ธ)๋ฅผ ๋”ฐ์˜ดํ‘œ๋กœ ํ•จ๊ป˜ ์ ๋Š”๋‹ค(์˜คํƒ€๋Š” ๋ณด์ • ํ‘œ๊ธฐ๋กœ ์ธ์šฉ ๊ฐ€๋Šฅ). **์ธ์šฉํ•  ์›๋ฌธ ๋ฐœ์–ธ์„ ๋…น์ทจ๋ก์—์„œ ์ฐพ์„ ์ˆ˜ ์—†๋Š” ํ•ญ๋ชฉ์€ ๊ฒฐ์ •ยท์•ก์…˜์ด ์•„๋‹ˆ๋‹ค** โ€” ๊ทธ๋Ÿฐ ํ•ญ๋ชฉ์€ ๋งŒ๋“ค์ง€ ๋ง๊ฑฐ๋‚˜ ์˜คํ”ˆ ์ด์Šˆ๋กœ ๋‚ด๋ ค๋ผ. ์ด ์ธ์šฉ์€ ๋‚ ์กฐ ๋ฐฉ์ง€ ์žฅ์น˜๋‹ค. -- **๋ฐœ์–ธ ์ฃผ์ฒด๊ฐ€ ๋ถˆ๋ช…ํ™•ํ•˜๋ฉด ์ถ”์ธกํ•˜์ง€ ๋ง ๊ฒƒ.** ๋ˆ„๊ฐ€ ๋งํ–ˆ๋Š”์ง€ ํ™•์‹คํ•˜์ง€ ์•Š์œผ๋ฉด ์ด๋ฆ„์„ ๋ถ™์ด์ง€ ๋ง๊ณ  "(๋ฐœ์–ธ ์ฃผ์ฒด ๋ถˆ๋ช…ํ™•)"์œผ๋กœ ํ‘œ๊ธฐํ•˜๊ฑฐ๋‚˜ "~๋ผ๋Š” ์˜๊ฒฌ์ด ์ œ์‹œ๋จ"์ฒ˜๋Ÿผ ์ฃผ์ฒด ์—†์ด ์ค‘๋ฆฝ์ ์œผ๋กœ ์„œ์ˆ ํ•œ๋‹ค. ์–ด๋–ค ๋ฐœ์–ธ์ž์˜ ๋ง์„ ๋‹ค๋ฅธ ๋ฐœ์–ธ์ž์˜ ๊ฒฐ๋ก ์œผ๋กœ ์˜ฎ๊ธฐ๋Š” ๊ฒƒ์€ ๊ฐ€์žฅ ์‹ฌ๊ฐํ•œ ์˜ค๋ฅ˜๋‹ค. -- **๋…น์ทจ๋ก์— ์—†๋Š” ์ˆซ์žยท๋‚ ์งœยท๊ธˆ์•กยท๊ฒฐ์ •ยท์—†๋˜ ํ•ญ๋ชฉ์„ ๋งŒ๋“ค์–ด๋‚ด์ง€ ๋ง ๊ฒƒ.** (๋‹จ, ๋…น์ทจ๋ก์— *์žˆ๋Š”๋ฐ ์ฒ ์ž๋งŒ ํ‹€๋ฆฐ* ์šฉ์–ดยท๊ณ ์œ ๋ช…์‚ฌ๋ฅผ ๋ฌธ๋งฅ์œผ๋กœ ์ •๊ทœํ™”ํ•˜๋Š” ๊ฒƒ์€ ํ—ˆ์šฉ โ€” ์œ„ 'STT ์˜คํƒ€ ๋ณด์ •' ์ฐธ์กฐ.) ์ •๋ง ๊ทผ๊ฑฐ ์—†๋Š” *์‚ฌ์‹ค*๋งŒ "ํ™•์ธ ํ•„์š”"๋กœ ๋‘”๋‹ค. -- ์–ด๋–ค ํ•ญ๋ชฉ์˜ *๋‚ด์šฉ ์ž์ฒด*๊ฐ€ ๋…น์ทจ๋ก์—์„œ ์•ฝํ•˜๊ฑฐ๋‚˜ ๋ชจํ˜ธํ•˜๋ฉด(=์ฒ ์ž ๋ฌธ์ œ๊ฐ€ ์•„๋‹ˆ๋ผ ์‚ฌ์‹ค์ด ๋ถˆํ™•์‹ค) ์ง€์–ด๋‚ด์ง€ ๋ง๊ณ  ํ•ด๋‹น ํ•ญ๋ชฉ ๋์— "(ํ™•์ธ ํ•„์š”)"๋ฅผ ๋ถ™์ธ๋‹ค. ๋‹จ์ˆœ ํ‘œ๊ธฐ ์˜คํƒ€๋Š” ์—ฌ๊ธฐ ํ•ด๋‹นํ•˜์ง€ ์•Š๋Š”๋‹ค. -- Decision์€ ๋ช…์‹œ์  ํ•ฉ์˜ ํ‘œํ˜„์ด ์žˆ์„ ๋•Œ๋งŒ '๊ฒฐ์ •๋จ'์ด๋‹ค. ํ•ฉ์˜๊ฐ€ ๋ถˆ๋ช…ํ™•ํ•˜๋ฉด '๋…ผ์˜ ์ค‘' ๋˜๋Š” ์˜คํ”ˆ ์ด์Šˆ๋กœ ๋‘”๋‹ค. +- **๋…น์ทจ๋ก์— ๋ช…์‹œ๋œ ๋‚ด์šฉ๋งŒ ์ ๋Š”๋‹ค.** ์ถ”๋ก ์œผ๋กœ ๋นˆ์นธ์„ ๋ฉ”์šฐ๊ฑฐ๋‚˜, ๋ณ„๊ฐœ ๋ฐœ์–ธ์„ ํ•˜๋‚˜์˜ ์ธ๊ณผ ์‚ฌ์Šฌ๋กœ ํ•ฉ์„ฑํ•˜์ง€ ๋ง ๊ฒƒ. +- **๊ทผ๊ฑฐ = ํƒ€์ž„์Šคํƒฌํ”„**: ๋ชจ๋“  '๊ฒฐ์ • ์‚ฌํ•ญ'ยท'์•ก์…˜ ์•„์ดํ…œ'ยท๋ฆฌ์Šคํฌ ํ•ญ๋ชฉ ๋์—, ๊ทผ๊ฑฐ๊ฐ€ ๋œ ๋ฐœ์–ธ์˜ **ํƒ€์ž„์Šคํƒฌํ”„ [mm:ss]**๋ฅผ ๋ถ™์ธ๋‹ค(๋…น์ทจ๋ก์˜ "์ฐธ์„์ž N mm:ss" ํ‘œ์‹œ์—์„œ ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ์‹œ๊ฐ). ํƒ€์ž„์Šคํƒฌํ”„๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†๋Š” ํ•ญ๋ชฉ์€ ๊ฒฐ์ •ยท์•ก์…˜์ด ์•„๋‹ˆ๋‹ค โ€” ๋งŒ๋“ค์ง€ ๋ง๊ฑฐ๋‚˜ ์˜คํ”ˆ ์ด์Šˆ๋กœ ๋‚ด๋ ค๋ผ. ์ด ํƒ€์ž„์Šคํƒฌํ”„๋Š” ๋‚ ์กฐ ๋ฐฉ์ง€ + ๊ฒ€์ฆ ์ ํ”„ ์žฅ์น˜๋‹ค. STT ์›๋ฌธ์„ ํ†ต์งธ๋กœ ์ธ์šฉํ•˜์ง€ ๋ง ๊ฒƒ(๊ธธ๊ณ  ๋“ค์ญ‰๋‚ ์ญ‰ํ•ด์ง„๋‹ค). +- **๋…น์ทจ๋ก์— ์—†๋Š” ์ˆซ์žยท๋‚ ์งœยท๊ธˆ์•กยท๊ฒฐ์ •์„ ๋งŒ๋“ค์–ด๋‚ด์ง€ ๋ง ๊ฒƒ.** (์ฒ ์ž๋งŒ ํ‹€๋ฆฐ ์šฉ์–ด ์ •๊ทœํ™”๋Š” ํ—ˆ์šฉ.) +- ๋‚ด์šฉ ์ž์ฒด๊ฐ€ ๋ชจํ˜ธํ•˜๋ฉด(=์ฒ ์ž ๋ฌธ์ œ๊ฐ€ ์•„๋‹ˆ๋ผ ์‚ฌ์‹ค ๋ถˆํ™•์‹ค) ์ง€์–ด๋‚ด์ง€ ๋ง๊ณ  "(ํ™•์ธ ํ•„์š”)"๋ฅผ ๋ถ™์ธ๋‹ค. +- Decision์€ ๋ช…์‹œ์  ํ•ฉ์˜ ํ‘œํ˜„์ด ์žˆ์„ ๋•Œ๋งŒ '๊ฒฐ์ •๋จ'. ๋ถˆ๋ช…ํ™•ํ•˜๋ฉด ์˜คํ”ˆ ์ด์Šˆ. +- **๋นˆ ์นธ์€ ์ฑ„์šฐ์ง€ ๋ง ๊ฒƒ**: ํ‘œ์—์„œ ๊ฐ’์„ ๋ชจ๋ฅด๋ฉด "โ€”"๋กœ ๋‘”๋‹ค. placeholder๋ฅผ ๊ทธ๋Ÿด๋“ฏํ•œ ์ถ”์ธก์œผ๋กœ ๋ฉ”์šฐ์ง€ ๋ง ๊ฒƒ. ๋ชจ๋“  ์นธ์ด ๋ฏธ์ •์ธ ํ•ญ๋ชฉ์€ ์•ก์…˜์ด ์•„๋‹ˆ๋ผ ์˜คํ”ˆ ์ด์Šˆ๋‹ค. -# ์ถœ๋ ฅ ๊ฒ€์ฆ (Validation) -์ถœ๋ ฅ ์ „ ๋‚ด๋ถ€์ ์œผ๋กœ ์ ๊ฒ€ํ•œ๋‹ค: โ‘  ๊ฐ ๋ฐœ์–ธ์ด ์˜ฌ๋ฐ”๋ฅธ ์ฃผ์ฒด์—๊ฒŒ ๊ท€์†๋๋Š”๊ฐ€ โ‘ก ์ธ์ ‘ ๋ฐœ์–ธ์„ ์ž„์˜๋กœ ์—ฐ๊ฒฐํ•˜์ง€ ์•Š์•˜๋Š”๊ฐ€ โ‘ข Decision์€ ์‹ค์ œ ํ•ฉ์˜์ธ๊ฐ€ โ‘ฃ ๋…น์ทจ๋ก์— ์—†๋Š” ์ •๋ณด๋ฅผ ์ถ”๊ฐ€ํ•˜์ง€ ์•Š์•˜๋Š”๊ฐ€ โ‘ค Action์€ ์‹คํ–‰ ๊ฐ€๋Šฅํ•œ๊ฐ€. -๋‹จ, ๊ฒ€์ฆ ๊ณผ์ •ยท์ฒดํฌ ๋กœ๊ทธ๋Š” ์ถœ๋ ฅํ•˜์ง€ ๋ง ๊ฒƒ. ์ตœ์ข… ํšŒ์˜๋ก๋งŒ ์ถœ๋ ฅํ•œ๋‹ค. +# ์ถœ๋ ฅ ๊ฒ€์ฆ (Validation โ€” ์ถœ๋ ฅ ์ „ ๋‚ด๋ถ€ ์ ๊ฒ€, ๋กœ๊ทธ๋Š” ์ถœ๋ ฅ ๊ธˆ์ง€) +โ‘  "์ฐธ์„์ž N" ํ† ํฐ์ด 0๊ฐœ์ธ๊ฐ€ โ‘ก ํ™”์ž๊ฐ€ ํŒ€/์—ญํ• ๋กœ ๊ท€์†๋๊ณ  ๊ฐœ์ธ ์ถ”์ธก์ด ์—†๋Š”๊ฐ€ โ‘ข ์ธ์ ‘ ๋ฐœ์–ธ์„ ์ž„์˜ ์—ฐ๊ฒฐํ•˜์ง€ ์•Š์•˜๋Š”๊ฐ€ โ‘ฃ Decision์ด ์‹ค์ œ ํ•ฉ์˜์ธ๊ฐ€(ํ…Œ์ŠคํŠธํ›„๊ฒฐ์ •ยท๊ฒ€ํ† ํ•„์š”๊ฐ€ ์„ž์ด์ง€ ์•Š์•˜๋‚˜) โ‘ค ์ฆ‰์‹œ ๋ฐ˜๋ฐ•๋œ ๊ฐ€์„ค์„ ์ด์Šˆ๋กœ ๊ฒฉ์ƒํ•˜์ง€ ์•Š์•˜๋Š”๊ฐ€ โ‘ฅ ๊ฐ™์€ ์‚ฌ์‹ค์ด ์—ฌ๋Ÿฌ ์„น์…˜์— ์ค‘๋ณต๋˜์ง€ ์•Š์•˜๋Š”๊ฐ€ โ‘ฆ ๋นˆ ์นธ์„ ์ถ”์ธก์œผ๋กœ ์ฑ„์šฐ์ง€ ์•Š์•˜๋Š”๊ฐ€ โ‘ง ๊ฐ ํ•ญ๋ชฉ์— [mm:ss]๊ฐ€ ์žˆ๋Š”๊ฐ€. [๋ฉ”ํƒ€๋ฐ์ดํ„ฐ] ${metaBlock} @@ -65,71 +84,68 @@ ${OUTPUT_FORMAT}`; /** ์ตœ์ข… ํšŒ์˜๋ก ์ถœ๋ ฅ ํ˜•์‹ โ€” ๋‹จ์ผ์ƒท(buildMeetPrompt)๊ณผ ๋ณ‘ํ•ฉ ๋‹จ๊ณ„(buildMeetReducePrompt)๊ฐ€ ๊ณต์œ . */ const OUTPUT_FORMAT = `# ์ž‘์„ฑ ์›์น™ (ํšŒ์˜๋ก ํ’ˆ์งˆ โ€” ์ถœ๋ ฅ ์ „ ๋ฐ˜๋“œ์‹œ ๋‚ด์žฌํ™”) -ํšŒ์˜๋ก์€ *๋Œ€ํ™” ์š”์•ฝ ๋ฌธ์„œ*๊ฐ€ ์•„๋‹ˆ๋ผ **ํ”„๋กœ์ ํŠธ ๊ด€๋ฆฌ ๋ฌธ์„œ**๋‹ค. ํšŒ์˜ ๋‚ด์šฉ ์ž์ฒด๋ณด๋‹ค "๋ฌด์—‡์ด ๊ฒฐ์ •๋๋Š”๊ฐ€ / ๋ˆ„๊ฐ€ ๋ฌด์—‡์„ ํ•ด์•ผ ํ•˜๋Š”๊ฐ€ / ๋ฌด์—‡์ด ์•„์ง ๊ฒฐ์ • ์•ˆ ๋๋Š”๊ฐ€"๋ฅผ ์šฐ์„ ํ•œ๋‹ค. -- **์ •๋ณด ์šฐ์„ ์ˆœ์œ„**: โ‘ ๊ฒฐ์ •์‚ฌํ•ญ โ‘ก์•ก์…˜์•„์ดํ…œ โ‘ข์˜คํ”ˆ ์ด์Šˆ โ‘ฃ๋ฆฌ์Šคํฌ โ‘ค๋…ผ์˜์‚ฌํ•ญ ์ˆœ์œผ๋กœ ์ค‘์š”ํ•˜๋‹ค. ๋ถ„๋Ÿ‰ยท์ •์„ฑ๋„ ์ด ์ˆœ์„œ๋กœ ๋ฐฐ๋ถ„ํ•œ๋‹ค. -- **์‚ฌ์‹ค ์ค‘์‹ฌ**: ์ถ”์ •ยทํ•ด์„ยทํ‰๊ฐ€๊ฐ€ ์•„๋‹ˆ๋ผ ํšŒ์˜์—์„œ ์‹ค์ œ ๋…ผ์˜ยทํ™•์ •๋œ ๊ฒƒ๋งŒ ์ ๋Š”๋‹ค. (์˜ˆ: "API ์—ฐ๋™์ด ๊ฐ€๋Šฅํ•  ๊ฒƒ์œผ๋กœ ํŒ๋‹จ๋จ"โŒ โ†’ "API ์—ฐ๋™ ๊ฐ€๋Šฅ ์—ฌ๋ถ€ ๊ฒ€ํ†  ํ•„์š”"โœ…) -- **๊ฒฐ์ •์‚ฌํ•ญ โ†” ๋…ผ์˜์‚ฌํ•ญ ๊ตฌ๋ถ„(์ตœ์šฐ์„ )**: ๋ช…์‹œ์ ์œผ๋กœ ํ•ฉ์˜ยทํ™•์ •๋œ ๊ฒƒ๋งŒ '๊ฒฐ์ • ์‚ฌํ•ญ'์— ๋‘”๋‹ค. "๊ฒ€ํ†  ํ•„์š”/์ •์˜ ํ•„์š”/ํ™œ์šฉ ๊ฒ€ํ† "์ฒ˜๋Ÿผ *ํ™•์ •๋˜์ง€ ์•Š์€ ๊ฒƒ*์€ ๊ฒฐ์ •์‚ฌํ•ญ์ด ์•„๋‹ˆ๋‹ค โ€” ๋…ผ์˜ ์‚ฌํ•ญยท์˜คํ”ˆ ์ด์Šˆ๋กœ ๋‚ด๋ฆฐ๋‹ค. ๋ฐ˜๋Œ€๋กœ ์‹ค์ œ ํ™•์ •๋œ ๊ฒƒ์„ ๊ฒฐ์ •์‚ฌํ•ญ์—์„œ ๋ˆ„๋ฝํ•˜์ง€๋„ ๋ง ๊ฒƒ. -- **๊ฒฐ๊ณผ ์ค‘์‹ฌ**: ๋ฐœ์–ธ ์ˆœ์„œยทํ† ๋ก  ๊ณผ์ •ยท"๋ˆ„๊ฐ€ ๋ฌด์Šจ ๋ง์„ ํ–ˆ๋Š”์ง€"๋ฅผ ๋‚˜์—ดํ•˜์ง€ ๋ง๊ณ  *๊ฒฐ๊ณผ*๋ฅผ ์ ๋Š”๋‹ค. (์˜ˆ: "PlayCanvas๋ฅผ ๋…ผ์˜ํ•จ"โŒ โ†’ "PlayCanvas/Babylon.js ๋น„๊ต ๊ฒ€ํ†  ์ง„ํ–‰ ์˜ˆ์ •"โœ…) ์ฑ…์ž„ ์†Œ์žฌ๋‚˜ ์ž…์žฅ ์ฐจ์ด๊ฐ€ ํ•ต์‹ฌ์ผ ๋•Œ๋งŒ ๋ฐœ์–ธ์ž๋ฅผ ๋ฐํžŒ๋‹ค. -- **๋‹ด๋‹น์ž๋Š” ๊ฐœ์ธ ์šฐ์„ **: "๊ฐœ๋ฐœํŒ€/QAํŒ€" ๊ฐ™์€ ์กฐ์ง ๋‹จ์œ„๊ฐ€ ์•„๋‹ˆ๋ผ ๊ฐœ์ธ ์ด๋ฆ„(์˜ˆ: ์†ก๋ณ‘์ค€, ๊น€์›์ผ PD)์œผ๋กœ ์ ๋Š”๋‹ค. ์‹ค์ œ๋กœ ๊ฐœ์ธ์ด ์•ˆ ์ •ํ•ด์กŒ์œผ๋ฉด "๊ฐœ๋ฐœํŒ€ (๋‹ด๋‹น์ž ์ง€์ • ํ•„์š”)" ํ˜•ํƒœ๋กœ ํ‘œ๊ธฐ. -- **์ฆ๋น™ ๋ณด์กด**: ๊ฒฐ์ •๋˜์ง€ ์•Š์€ ์‚ฌํ•ญ์ด๋ผ๋„ ์ค‘์š”ํ•œ ๋…ผ์˜ยท๋ฆฌ์Šคํฌ๋Š” ๋น ์ง์—†์ด ๊ธฐ๋กํ•œ๋‹ค(ํ–ฅํ›„ ์ด๋ ฅยท๋ถ„์Ÿ ๊ทผ๊ฑฐ). -- **์ต๋ช…ยท๋ฒˆํ˜ธ ํ™”์ž์— ์ฑ…์ž„ ๋ฐฐ์ • ๊ธˆ์ง€(์ตœ์šฐ์„ )**: "์ฐธ์„์ž 1", "๋ฐœ์–ธ์ž A", "(์ฃผ์ฒด ๋ถˆ๋ช…ํ™•)"์ฒ˜๋Ÿผ *์‹ค๋ช…์ด ํ™•์ธ ์•ˆ ๋œ ํ™”์ž*๋ฅผ ์•ก์…˜ ์•„์ดํ…œ ๋‹ด๋‹น์œผ๋กœ ํ™•์ •ํ•˜์ง€ ๋ง ๊ฒƒ. ๋‹ด๋‹น ์นธ์€ \`[๋ฏธ์ง€์ •-ํ™•์ธํ•„์š”]\`๋กœ ๋‘๊ณ  ๊ทผ๊ฑฐ ๋ฐœ์–ธ๋งŒ ๋‚จ๊ธด๋‹ค โ€” ์ต๋ช…์—๊ฒŒ ๊ฐ€์งœ ์ฑ…์ž„์„ ๋ถ™์ด๋Š” ๊ฒƒ์ด ํšŒ์˜๋ก ์‹ ๋ขฐ๋„๋ฅผ ๊ฐ€์žฅ ํฌ๊ฒŒ ํ•ด์นœ๋‹ค. ๋˜ํ•œ **ํ•œ ์ต๋ช… ํ™”์ž์—๊ฒŒ ์•ก์…˜์ด ์—ฌ๋Ÿฌ ๊ฑด ๋ชฐ๋ฆฌ๋ฉด** ํ™”์ž๋ถ„๋ฆฌ ์˜ค๋ฅ˜์ผ ์ˆ˜ ์žˆ์œผ๋‹ˆ ๊ทธ ํ•ญ๋ชฉ๋“ค ์ž‘์—… ์ƒ์„ธ ๋์— "(๋™์ผ ํ™”์ž ์—ฌ๋ถ€ ํ™•์ธ)"์„ ๋ง๋ถ™์ธ๋‹ค. -- **๋‚ด์šฉ ์—†๋Š” ์ธ์šฉ ๊ธˆ์ง€**: "์ด๋ ‡๊ฒŒ ์ด๋ ‡๊ฒŒ", "๊ทธ๊ฑฐ", "์ด๊ฑฐ", "์ €๋ ‡๊ฒŒ" ์ฒ˜๋Ÿผ ์ง€์‹œ๋Œ€๋ช…์‚ฌ๋ฟ์ด๋ผ *๋‚ด์šฉ์ด ๋น„์–ด ์žˆ๋Š”* ๋ฐœํ™”๋Š” ๊ฒฐ์ •ยท์•ก์…˜์˜ ๊ทผ๊ฑฐ๋กœ ์ธ์šฉํ•˜์ง€ ๋ง ๊ฒƒ. ๊ทธ๋Ÿฐ ๋ฐœํ™”๋งŒ ๊ทผ๊ฑฐ์ธ ํ•ญ๋ชฉ์€ ํ•ต์‹ฌ ๋‚ด์šฉ์„ \`[๋‚ด์šฉ ํ™•์ธํ•„์š”]\`๋กœ ํ‘œ๊ธฐํ•œ๋‹ค(๋นˆ ์ธ์šฉ์„ ๊ทผ๊ฑฐ์ธ ์ฒ™ ๋‹ฌ์ง€ ๋ง ๊ฒƒ). ํ‘œ๊ธฐ ์˜คํƒ€์™€๋Š” ๋‹ค๋ฅธ, *๋‚ด์šฉ ๊ณต๋ฐฑ* ๋ฌธ์ œ๋‹ค. -- **๊ธฐํ•œ ์—ญ์ฐธ์กฐ**: ๋ฆฌ์Šคํฌยท๋…ผ์˜ยท๋…น์ทจ ์–ด๋””๋“  ๋“ฑ์žฅํ•œ ๋‚ ์งœยท๋งˆ๊ฐ("๋‹ค์Œ ์ฃผ ์ˆ˜์š”์ผ", "์ด๋‹ฌ ๋ง" ๋“ฑ)์€ *์ง์ ‘ ๊ฒฐ๋ถ€๋œ ๊ฒŒ ๋ถ„๋ช…ํ•œ* ์•ก์…˜์˜ ๊ธฐํ•œ ์นธ์— ์—ฐ๊ฒฐํ•œ๋‹ค. ๊ฒฐ๋ถ€๊ฐ€ ๋ถˆํ™•์‹คํ•˜๋ฉด ๊ธฐํ•œ ์นธ์— "(๊ธฐํ•œ ํ›„๋ณด: โ€ฆ)"๋กœ ๋ณด์ˆ˜์ ์œผ๋กœ ํ‘œ๊ธฐํ•œ๋‹ค โ€” ์•ก์…˜ ๊ธฐํ•œ์„ ์ „๋ถ€ "๋ฏธ์ •"์œผ๋กœ ๋น„์šฐ๋ฉด์„œ ๋ณธ๋ฌธ์—” ๋งˆ๊ฐ์ด ๋–  ์žˆ๋Š” ๋ชจ์ˆœ์„ ๋ง‰๋Š”๋‹ค. -- **์ฐธ์„์ž ๋ช…๋‹จ ์ •ํ•ฉ์„ฑ**: ๋ณธ๋ฌธ(์•ก์…˜ยท๊ฒฐ์ •ยท๋…ผ์˜)์— ๋“ฑ์žฅํ•œ ๋ฐœ์–ธ์ž๊ฐ€ ํšŒ์˜ ๊ฐœ์š” '์ฐธ์„์ž'์— ์—†์œผ๋ฉด ๊ทธ ํ•ญ๋ชฉ ์˜†์— "(๋ช…๋‹จ ์™ธ ํ™”์ž โ€” ํ™•์ธํ•„์š”)"๋ฅผ ๋ถ™์ธ๋‹ค. +ํšŒ์˜๋ก์€ *๋Œ€ํ™” ์š”์•ฝ ๋ฌธ์„œ*๊ฐ€ ์•„๋‹ˆ๋ผ **ํ”„๋กœ์ ํŠธ ๊ด€๋ฆฌ ๋ฌธ์„œ**๋‹ค. "๋ฌด์—‡์ด ๊ฒฐ์ •๋๋Š”๊ฐ€ / ๋ˆ„๊ฐ€(์–ด๋А ํŒ€์ด) ๋ฌด์—‡์„ ํ•ด์•ผ ํ•˜๋Š”๊ฐ€ / ๋ฌด์—‡์ด ์•„์ง ๋ฏธ๊ฒฐ์ธ๊ฐ€"๋ฅผ ์šฐ์„ ํ•œ๋‹ค. +- **ํ•œ ์‚ฌ์‹ค์€ ํ•œ ์„น์…˜์—๋งŒ**: ๊ฐ™์€ ํ•ญ๋ชฉ์„ ์š”์•ฝยท๊ฒฐ์ •ยท์•ก์…˜์— ์ค‘๋ณต ๊ธฐ์žฌํ•˜์ง€ ๋ง ๊ฒƒ. ํ•ต์‹ฌ ์š”์•ฝ์€ ๋ฏธ๋ฆฌ๋ณด๊ธฐ๊ฐ€ ์•„๋‹ˆ๋ผ ๋‹ค์ด์ œ์ŠคํŠธ๋‹ค. +- **๊ฒฐ์ • โ†” ์•ก์…˜ ๊ฒฝ๊ณ„**: ๋‹ด๋‹น+ํ–‰๋™์ด ์žˆ๋Š” *์ผ๊ฐ*์€ '์•ก์…˜ ์•„์ดํ…œ' ํ‘œ๋กœ ๋ณด๋‚ธ๋‹ค. '๊ฒฐ์ • ์‚ฌํ•ญ'์—๋Š” **๋‹ด๋‹น์ž ์—†๋Š” ์ˆœ์ˆ˜ ๋ฐฉํ–ฅ/์ •์ฑ… ๊ฒฐ์ •๋งŒ** ๋‚จ๊ธด๋‹ค(์˜ˆ: "์ œํ’ˆ ๋ฆฌ์ŠคํŠธ ํด๋ฆญ ์ด๋ฒคํŠธ ์ œ๊ฑฐํ•˜๊ธฐ๋กœ ํ•จ"). "๊ตฌํ˜„ํ•˜๊ธฐ๋กœ ํ•จ"์ฒ˜๋Ÿผ ๋ˆ„๊ฐ€ ํ•  ์ผ์ด๋ฉด ์•ก์…˜์ด๋‹ค. +- **๊ฒฐ์ • โ‰  ๊ฒ€ํ† ์š”์ฒญ**: "ํ…Œ์ŠคํŠธํ•ด๋ณด๊ณ  ๊ฒฐ์ • / ๋‹ค์‹œ ๋ณด๊ณ  ์–˜๊ธฐ / ๊ณ ๋ฏผํ•ด๋ณด์ž"๋Š” ๊ฒฐ์ •์ด ์•„๋‹ˆ๋‹ค โ†’ ์˜คํ”ˆ ์ด์Šˆ. ๋ช…์‹œ์  ํ•ฉ์˜๋งŒ ๊ฒฐ์ •. +- **๋‹ด๋‹น์€ ํŒ€/์—ญํ•  ์šฐ์„ **: STT ํ™”์ž๋ฒˆํ˜ธ ๋งคํ•‘์ด ๋ถˆํ™•์‹คํ•˜๋ฏ€๋กœ ๊ฐœ์ธ๋ช…๋ณด๋‹ค **ํŒ€/์—ญํ• **(์˜ˆ: ๋„ฅ์„œ์Šค๊ฐœ๋ฐœํŒ€, ๊ธฐํš, UI)๋กœ ์ ๋Š”๋‹ค. ๊ฐœ์ธ์ด ๋ช…๋‹จ+๋ฌธ๋งฅ์œผ๋กœ ํ™•์‹คํ•  ๋•Œ๋งŒ ๋ณ‘๊ธฐ. "์ฐธ์„์ž N" ๊ธˆ์ง€. +- **๋นˆ ์นธ์€ "โ€”"**: ๋ชจ๋ฅด๋Š” ๊ฐ’์„ ์ถ”์ธกยทplaceholder๋กœ ์ฑ„์šฐ์ง€ ๋ง ๊ฒƒ. ํ†ต์งธ๋กœ ๋ฏธ์ •์ธ ํ•ญ๋ชฉ์€ ์•ก์…˜์ด ์•„๋‹ˆ๋ผ ์˜คํ”ˆ ์ด์Šˆ๋กœ ๋‚ด๋ฆฐ๋‹ค. +- **๊ทผ๊ฑฐ = [mm:ss]**: ๊ฒฐ์ •ยท์•ก์…˜ยท๋ฆฌ์Šคํฌ์— STT ์›๋ฌธ์„ ๋ฐ•์ง€ ๋ง๊ณ  ํƒ€์ž„์Šคํƒฌํ”„๋งŒ ๋ถ™์ธ๋‹ค. +- **์‚ฌ์‹ค ์ค‘์‹ฌ**: ์ถ”์ •ยทํ‰๊ฐ€๊ฐ€ ์•„๋‹ˆ๋ผ ์‹ค์ œ ๋…ผ์˜ยทํ™•์ •๋œ ๊ฒƒ๋งŒ. ("API ์—ฐ๋™ ๊ฐ€๋Šฅ ํŒ๋‹จ๋จ"โŒ โ†’ "API ์—ฐ๋™ ๊ฐ€๋Šฅ ์—ฌ๋ถ€ ๊ฒ€ํ†  ํ•„์š”"โœ…) # ์ถœ๋ ฅ ํ˜•์‹ (Output Format โ€” ์ •ํ™•ํžˆ ์ด ๊ตฌ์กฐ๋ฅผ ์œ ์ง€) -# [ํšŒ์˜ ์ œ๋ชฉ] +# [์ œํ’ˆ/ํ”„๋กœ์ ํŠธ] ยท ํšŒ์˜์œ ํ˜• โ€” ํ•ต์‹ฌ ์•ˆ๊ฑด +(์˜ˆ: "[์ž์ด์–ธ์ธ  ์ด๋จธ์‹œ๋ธŒ ์ปค๋จธ์Šค] ๋ฐ๋ชจ ๋ฆฌ๋ทฐ โ€” ๋ชจ์ž UIยท๋ชจ๋ธ/์ฒดํ˜• ํ™•์žฅ". ํšŒ์˜์œ ํ˜•์€ ๋…น์ทจ ์„ฑ๊ฒฉ์—์„œ ํŒ๋‹จ: ๋ฐ๋ชจ ๋ฆฌ๋ทฐ / ๊ธฐํš ๋…ผ์˜ / ์ •๊ธฐ ์ ๊ฒ€ ๋“ฑ.) -## 1. ํšŒ์˜ ๊ฐœ์š” -- **์ผ์‹œ**: [YYYY๋…„ MM์›” DD์ผ | ํ™•์ธ ๋ถˆ๊ฐ€] -- **์ฐธ์„์ž**: [๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ๊ธฐ์ค€ | ์—†์„ ๊ฒฝ์šฐ: ๋…ผ์˜ ์ฐธ์—ฌ ์ฃผ์ฒด] -- **ํšŒ์˜ ๋ชฉ์ **: [์ด ํšŒ์˜๊ฐ€ ์™œ ์—ด๋ ธ๋Š”์ง€ ํ•œ ๋ฌธ์žฅ. ๋…น์ทจ๋ก์—์„œ ๋“œ๋Ÿฌ๋‚œ ๋ชฉ์ ๋งŒ ์ ๊ณ , ๋ถˆ๋ช…ํ™•ํ•˜๋ฉด "ํ™•์ธ ํ•„์š”"] +## ํšŒ์˜ ๊ฐœ์š” +- **์ผ์‹œ**: [YYYY๋…„ MM์›” DD์ผ | ํ™•์ธ ๋ถˆ๊ฐ€] โ† ๋ฐ˜๋“œ์‹œ ์ด ํ‘œ๊ธฐ(์ž๋™ ๋“ฑ๋ก์ด ๋‚ ์งœ๋ฅผ ์ฝ์Œ) +- **์žฅ์†Œ**: [๋ฉ”ํƒ€๋ฐ์ดํ„ฐ/ํ—ค๋” ๊ธฐ์ค€ | ํ™•์ธ ๋ถˆ๊ฐ€] +- **ํšŒ์˜์œ ํ˜•**: [๋ฐ๋ชจ ๋ฆฌ๋ทฐ / ๊ธฐํš ๋…ผ์˜ ๋“ฑ] +- **๋…น์ทจ ๊ธธ์ด**: [ํ—ค๋”์— ์žˆ์œผ๋ฉด | ์—†์œผ๋ฉด ์ƒ๋žต] +- **์ž‘์„ฑ์ผ**: [๋ฉ”ํƒ€๋ฐ์ดํ„ฐ์˜ ์ž‘์„ฑ์ผ | ์ƒ๋žต] +- **์ฐธ์„์ž**: ์—ญํ• (ํŒ€)๋ณ„๋กœ โ€” ๊ฐœ์ธ๋ช…์€ ๋ช…๋‹จ+๋ฌธ๋งฅ ํ™•์‹ค ์‹œ๋งŒ ๋ณ‘๊ธฐ. "์ฐธ์„์ž N" ์ ˆ๋Œ€ ๊ธˆ์ง€. -## 2. ์ฃผ์š” ๊ฒฐ๊ณผ (Executive Summary) -ํšŒ์˜ *๊ฒฐ๊ณผ*๋ฅผ 3~5์ค„ ๊ธ€๋จธ๋ฆฌํ‘œ๋กœ ์š”์•ฝํ•œ๋‹ค. ํšŒ์˜ ๋‚ด์šฉ์„ ์„ค๋ช…ํ•˜์ง€ ๋ง๊ณ (์˜ˆ: "Babylon.js๋ฅผ ๊ฒ€ํ† ํ•จ"โŒ) ๊ฒฐ๊ณผ๋ฅผ ์ ๋Š”๋‹ค(์˜ˆ: "ํ…Œ์ŠคํŠธ ์ƒ˜ํ”Œ 3์ข… ์„ ์ •", "CCOC 1์ฐจ ์ž‘์—… 6/19๊นŒ์ง€ ์ง„ํ–‰"โœ…). **์ฐธ์„ํ•˜์ง€ ์•Š์€ ์ดํ•ด๊ด€๊ณ„์ž๊ฐ€ ์ด ํ•ญ๋ชฉ๋งŒ ์ฝ์–ด๋„ ๊ฒฐ๊ณผ๋ฅผ ํŒŒ์•…ํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•œ๋‹ค.** +## ํ•ต์‹ฌ ์š”์•ฝ +ํ•œ ๋ฌธ๋‹จ(3~5์ค„)์œผ๋กœ **๋ฌด์—‡์„ ๋ฆฌ๋ทฐ/๋…ผ์˜ํ–ˆ๊ณ  / ๋ฌด์—‡์ด ์ •ํ•ด์กŒ๊ณ  / ๋‹ค์Œ ๋‹จ๊ณ„๊ฐ€ ๋ฌด์—‡์ธ์ง€**๋ฅผ ์••์ถ•ํ•œ๋‹ค. ํšŒ์˜ ์ „์ฒด๋ฅผ ๊ด€ํ†ตํ•˜๋Š” **ํ•ต์‹ฌ ์š”๊ตฌยท๊ฒฐ๋ก **(ํŠนํžˆ ํ›„๋ฐ˜๋ถ€ ์ •๋ฆฌ๋ถ„)์„ ์—ฌ๊ธฐ ๋งจ ์•ž์— ์„ธ์šด๋‹ค. ๋””ํ…Œ์ผ ๋‚˜์—ดยทํ•ญ๋ชฉ ์ค‘๋ณต ๊ธˆ์ง€. **์ฐธ์„ํ•˜์ง€ ์•Š์€ ์‚ฌ๋žŒ์ด ์ด ๋ฌธ๋‹จ๋งŒ ์ฝ์–ด๋„ ๊ฒฐ๊ณผ๋ฅผ ํŒŒ์•…**ํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•œ๋‹ค. -## 3. ๊ฒฐ์ • ์‚ฌํ•ญ -**๋ช…์‹œ์ ์œผ๋กœ ํ•ฉ์˜ยทํ™•์ •๋œ ๊ฒƒ๋งŒ** ์ ๋Š”๋‹ค (์ผ์ • ํ™•์ •ยท๊ฐœ๋ฐœ ๋ฒ”์œ„ ํ™•์ •ยท์ •์ฑ… ๋ณ€๊ฒฝยทํ›„์† ๋ฐฉํ–ฅ ํ™•์ • ๋“ฑ). ๊ฒ€ํ† ยท์ •์˜ยท๋„์ž…์—ฌ๋ถ€๊ฐ€ *ํ•„์š”*ํ•œ ๋‹จ๊ณ„์˜ ๊ฒƒ์€ ์—ฌ๊ธฐ ๋„ฃ์ง€ ๋ง๊ณ  '์˜คํ”ˆ ์ด์Šˆ'๋‚˜ '๋…ผ์˜ ์‚ฌํ•ญ'์œผ๋กœ ๋‚ด๋ฆฐ๋‹ค. -๊ฐ ๊ฒฐ์ • ๋์— ๊ทผ๊ฑฐ ๋ฐœ์–ธ์„ ์ธ์šฉํ•œ๋‹ค: \`- [๊ฒฐ์ • ๋‚ด์šฉ] โ€” ๊ทผ๊ฑฐ: "๋ฐœ์–ธ ์›๋ฌธ ์ผ๋ถ€"\` -(์ด๋ฒˆ ํšŒ์˜์—์„œ ํ™•์ •๋œ ๊ฒฐ์ •์ด ์—†์œผ๋ฉด "์ด๋ฒˆ ํšŒ์˜์—์„œ ํ™•์ •๋œ ๊ฒฐ์ •์‚ฌํ•ญ ์—†์Œ"์ด๋ผ๊ณ  ๋ช…์‹œํ•œ๋‹ค โ€” ๋นˆ์นธยท์ƒ๋žต ๊ธˆ์ง€.) +## ๊ฒฐ์ • ์‚ฌํ•ญ +**๋ช…์‹œ์ ์œผ๋กœ ํ•ฉ์˜ยทํ™•์ •๋œ ์ˆœ์ˆ˜ ๋ฐฉํ–ฅ/์ •์ฑ… ๊ฒฐ์ •๋งŒ** ์ ๋Š”๋‹ค(๋‹ด๋‹น ์žˆ๋Š” ์ผ๊ฐ์€ ์•ก์…˜์œผ๋กœ). ๊ฐ ์ค„ ๋์— ํƒ€์ž„์Šคํƒฌํ”„. +\`- [๊ฒฐ์ • ๋‚ด์šฉ] โ€” [mm:ss]\` +(ํ™•์ •๋œ ๊ฒฐ์ •์ด ์—†์œผ๋ฉด "์ด๋ฒˆ ํšŒ์˜์—์„œ ํ™•์ •๋œ ๊ฒฐ์ •์‚ฌํ•ญ ์—†์Œ"์ด๋ผ๊ณ  ๋ช…์‹œ โ€” ๋นˆ์นธยท์ƒ๋žต ๊ธˆ์ง€.) -## 4. ์•ก์…˜ ์•„์ดํ…œ -ํšŒ์˜ ํ›„ ์ˆ˜ํ–‰ํ•  ์—…๋ฌด๋ฅผ **๋‹ด๋‹นยท์ž‘์—…ยท๊ธฐํ•œยท์‚ฐ์ถœ๋ฌผ 4์š”์†Œ**๊ฐ€ ๋ชจ๋‘ ๋“œ๋Ÿฌ๋‚˜๊ฒŒ ์ •๋ฆฌํ•œ๋‹ค. ๊ฐ ํ–‰์€ ๋ฐ˜๋“œ์‹œ ๋…น์ทจ๋ก ๊ทผ๊ฑฐ๋กœ ์ž‘์„ฑํ•œ๋‹ค. ๋‹ด๋‹น์ž๋Š” ๊ฐœ์ธ ์šฐ์„ (์—†์œผ๋ฉด "OOํŒ€ (๋‹ด๋‹น์ž ์ง€์ • ํ•„์š”)"). **์‹ค๋ช…์ด ํ™•์ธ ์•ˆ ๋œ ๋ฒˆํ˜ธยท์ต๋ช… ํ™”์ž๋Š” ๋‹ด๋‹น์œผ๋กœ ํ™•์ •ํ•˜์ง€ ๋ง๊ณ  \`[๋ฏธ์ง€์ •-ํ™•์ธํ•„์š”]\`๋กœ ๋‘”๋‹ค**(์œ„ ์ž‘์„ฑ ์›์น™ ์ฐธ์กฐ). ํšŒ์˜์—์„œ ๊ธฐํ•œยท์‚ฐ์ถœ๋ฌผ์ด ์•ˆ ๋‚˜์™”์œผ๋ฉด ํ•ด๋‹น ์นธ์— "ํ™•์ธ ํ•„์š”"๋ผ๊ณ  ์ ๋˜, **๋ณธ๋ฌธ์— ๋งˆ๊ฐ ๋‚ ์งœ๊ฐ€ ์–ธ๊ธ‰๋๊ณ  ์ด ์ž‘์—…์— ๊ฒฐ๋ถ€๋˜๋ฉด ๊ทธ ๋‚ ์งœ๋ฅผ ๊ธฐํ•œ ์นธ์— ๋ฐ˜์˜**ํ•œ๋‹ค. ํ‘œ ์…€ ์•ˆ์—์„œ๋Š” ์ค„๋ฐ”๊ฟˆ๊ณผ \`|\` ๋ฌธ์ž๋ฅผ ์“ฐ์ง€ ๋ง ๊ฒƒ. -| ๋‹ด๋‹น | ์ž‘์—… ๋‚ด์šฉ | ์ž‘์—… ์ƒ์„ธ | ์‚ฐ์ถœ๋ฌผ | ๊ธฐํ•œ | ์ƒํƒœ | -| --- | --- | --- | --- | --- | --- | +## ์•ก์…˜ ์•„์ดํ…œ +ํšŒ์˜ ํ›„ ์ˆ˜ํ–‰ํ•  ์—…๋ฌด๋ฅผ ํ‘œ๋กœ ์ •๋ฆฌํ•œ๋‹ค. ๋‹ด๋‹น์€ **ํŒ€/์—ญํ•  ์šฐ์„ **(๊ฐœ์ธ ํ™•์‹ค ์‹œ ๋ณ‘๊ธฐ). ๊ฐ’์„ ๋ชจ๋ฅด๋Š” ์นธ์€ "โ€”". ๋ชจ๋“  ์นธ์ด ๋ฏธ์ •์ธ ํ•ญ๋ชฉ์€ ์—ฌ๊ธฐ ๋„ฃ์ง€ ๋ง๊ณ  '์˜คํ”ˆ ์ด์Šˆ'๋กœ. ์…€ ์•ˆ์—์„œ ์ค„๋ฐ”๊ฟˆยท\`|\` ๊ธˆ์ง€. +| ๋‹ด๋‹น | ์•ก์…˜ | ๊ธฐํ•œ | ์ƒํƒœ | ์ถœ์ฒ˜ | +| --- | --- | --- | --- | --- | -- **์ž‘์—… ๋‚ด์šฉ**: ํ•œ ์ค„์งœ๋ฆฌ ์ž‘์—…๋ช…. ์บ˜๋ฆฐ๋” ์ผ์ • ์ œ๋ชฉ์œผ๋กœ ๊ทธ๋Œ€๋กœ ์“ฐ์ด๋ฏ€๋กœ ๊ทธ ์ž์ฒด๋กœ ๋ฌด์Šจ ์ผ์ธ์ง€ ์‹๋ณ„๋˜๊ฒŒ ์ž‘์„ฑํ•œ๋‹ค. ("๊ฒ€ํ† ", "ํ™•์ธ" ๊ฐ™์€ ๋‹จ๋… ๋™์‚ฌ ๊ธˆ์ง€) -- **์ž‘์—… ์ƒ์„ธ**: ์ด ์ž‘์—…์ด **๋ฌด์—‡์ด๊ณ , ์™œ ํ•„์š”ํ•˜๋ฉฐ, ๊ตฌ์ฒด์ ์œผ๋กœ ๋ฌด์—‡์„ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•˜๋Š”์ง€**๋ฅผ 2~3๋ฌธ์žฅ์œผ๋กœ ์ ๋Š”๋‹ค(๋ฐฐ๊ฒฝยท๋ชฉ์ ยท์ˆ˜ํ–‰ ๋ฒ”์œ„). ๋…น์ทจ๋ก์—์„œ ์–ธ๊ธ‰๋œ ๋Œ€์ƒยท์ˆ˜์น˜ยท์กฐ๊ฑด์„ ๊ทธ๋Œ€๋กœ ์ธ์šฉํ•˜๊ณ , **๋งˆ์ง€๋ง‰์— ๊ทผ๊ฑฐ ๋ฐœ์–ธ ์›๋ฌธ ์ผ๋ถ€๋ฅผ \`๊ทผ๊ฑฐ: "โ€ฆ"\` ํ˜•ํƒœ๋กœ ๋ง๋ถ™์ธ๋‹ค**. ๊ทผ๊ฑฐ๊ฐ€ ๋ถ€์กฑํ•˜๋ฉด "์ถ”๊ฐ€ ํ™•์ธ ํ•„์š”: โ€ฆ" ํ˜•ํƒœ๋กœ ๋ช…์‹œ. ๋‹จ์ˆœํžˆ ์ž‘์—…๋ช…์„ ๋ฐ˜๋ณตํ•˜์ง€ ๋ง ๊ฒƒ. -- **์‚ฐ์ถœ๋ฌผ**: ์ด ์ž‘์—…์ด ๋๋‚˜๋ฉด ๋‚˜์˜ค๋Š” ๊ตฌ์ฒด์  ๊ฒฐ๊ณผ๋ฌผ(์˜ˆ: ํ…Œ์ŠคํŠธ URL ๋ชฉ๋ก, ๋น„๊ต ๋ถ„์„ ๋ฌธ์„œ, ์ผ์ •ํ‘œ). ํšŒ์˜์—์„œ ์•ˆ ๋‚˜์™”์œผ๋ฉด "ํ™•์ธ ํ•„์š”". -- **์ƒํƒœ**: ๋‹ค์Œ ์ค‘ ์ •ํ™•ํžˆ ํ•˜๋‚˜๋กœ ๋ถ„๋ฅ˜ํ•œ๋‹ค (์บ˜๋ฆฐ๋” ์ž๋™ ๋“ฑ๋ก ๊ฒŒ์ดํŠธ๊ฐ€ ์ด ๊ฐ’์œผ๋กœ ๋ถ„๊ธฐํ•˜๋ฏ€๋กœ ํ˜•์‹ ์—„์ˆ˜): +- **๋‹ด๋‹น**: ํŒ€/์—ญํ• (์˜ˆ: ๋„ฅ์„œ์Šค๊ฐœ๋ฐœํŒ€, UI, ๊ธฐํš). ๋ถˆ๋ช…ํ™•ํ•˜๋ฉด "โ€”". +- **์•ก์…˜**: ํ•œ ์ค„ ์‹คํ–‰๋ฌธ โ€” ์บ˜๋ฆฐ๋” ์ผ์ • ์ œ๋ชฉ์œผ๋กœ ๊ทธ๋Œ€๋กœ ์“ฐ์ด๋ฏ€๋กœ ๊ทธ ์ž์ฒด๋กœ ๋ฌด์Šจ ์ผ์ธ์ง€ ์‹๋ณ„๋˜๊ฒŒ(๋ฐฐ๊ฒฝยท๋Œ€์ƒยท์กฐ๊ฑด ํฌํ•จ, "๊ฒ€ํ† "ยท"ํ™•์ธ" ๋‹จ๋… ๋™์‚ฌ ๊ธˆ์ง€). ์ž‘์—… ์ƒ์„ธ๋ฅผ ๋”ฐ๋กœ ๋ฐ˜๋ณตํ•˜์ง€ ๋ง๊ณ  ์ด ํ•œ ์ค„์— ๋…น์ธ๋‹ค. +- **๊ธฐํ•œ**: ํšŒ์˜์—์„œ ๋‚˜์˜จ ๋‚ ์งœ/์‹œ์ . ์—†์œผ๋ฉด "โ€”". +- **์ƒํƒœ**: ๋‹ค์Œ ์ค‘ ์ •ํ™•ํžˆ ํ•˜๋‚˜ (์บ˜๋ฆฐ๋” ์ž๋™ ๋“ฑ๋ก ๊ฒŒ์ดํŠธ๊ฐ€ ์ด ๊ฐ’์œผ๋กœ ๋ถ„๊ธฐํ•˜๋ฏ€๋กœ ํ˜•์‹ ์—„์ˆ˜): - \`ํ™•์ •\` โ€” ์ง„ํ–‰ ํ•ฉ์˜๊ฐ€ ๋ช…์‹œ์ ์ด๊ณ  ๊ธฐํ•œ๋„ ์–ธ๊ธ‰๋จ. - - \`์ง„ํ–‰๋ฏธ์ •\` โ€” ์ž‘์—…์ด ์–ธ๊ธ‰๋์œผ๋‚˜ ์‹ค์ œ๋กœ ์ง„ํ–‰ํ• ์ง€ ํ•ฉ์˜๊ฐ€ ๋ช…ํ™•ํ•˜์ง€ ์•Š์Œ. - - \`๊ธฐํ•œ๋ฏธ์ •\` โ€” ํ•˜๊ธฐ๋กœ ํ™•์ •๋์œผ๋‚˜ ์™„๋ฃŒ์ผ/D-Day ๊ฐ€ ์ •ํ•ด์ง€์ง€ ์•Š์Œ. - - \`์กฐ๊ฑด๋ถ€: <์„ ํ–‰์ž‘์—…>\` โ€” ๋‹ค๋ฅธ ์ž‘์—…ยท์‚ฌ๊ฑด์ด ๋๋‚˜์•ผ ์ง„ํ–‰ (์„ ํ–‰์ž‘์—…์„ ์งง๊ฒŒ ๋ช…์‹œ. ์˜ˆ: \`์กฐ๊ฑด๋ถ€: ๊ณ„์•ฝ ์ฒด๊ฒฐ ํ›„\`). - - \`๋ฐ˜๋ณต: <์ฃผ๊ธฐ>\` โ€” ์ •๊ธฐ ๋ฐ˜๋ณต ์—…๋ฌด (์˜ˆ: \`๋ฐ˜๋ณต: ๋งค์ฃผ ๋ชฉ์š”์ผ\`). - ์‹ค์ œ๋กœ ํ•ฉ์˜ยท๊ธฐํ•œ์ด ๋‚˜์™”์œผ๋ฉด \`ํ™•์ •\`์œผ๋กœ ์žก๊ณ , ์ •๋ง ์•ˆ ๋‚˜์˜จ ๊ฒƒ๋งŒ ๋ณด์ˆ˜์ ์œผ๋กœ \`์ง„ํ–‰๋ฏธ์ •\`/\`๊ธฐํ•œ๋ฏธ์ •\`์œผ๋กœ ๋‘”๋‹ค. + - \`์ง„ํ–‰๋ฏธ์ •\` โ€” ์ž‘์—…์ด ์–ธ๊ธ‰๋์œผ๋‚˜ ์ง„ํ–‰ ํ•ฉ์˜๊ฐ€ ๋ถˆ๋ช…ํ™•. + - \`๊ธฐํ•œ๋ฏธ์ •\` โ€” ํ•˜๊ธฐ๋กœ ํ™•์ •๋์œผ๋‚˜ ์™„๋ฃŒ์ผ ๋ฏธ์ •. + - \`์กฐ๊ฑด๋ถ€: <์„ ํ–‰์ž‘์—…>\` โ€” ๋‹ค๋ฅธ ์ž‘์—…์ด ๋๋‚˜์•ผ ์ง„ํ–‰(์˜ˆ: \`์กฐ๊ฑด๋ถ€: ๋จธ๋ฆฌ ์ •๋ˆ ํ…Œ์ŠคํŠธ ํ›„\`). + - \`๋ฐ˜๋ณต: <์ฃผ๊ธฐ>\` โ€” ์ •๊ธฐ ๋ฐ˜๋ณต(์˜ˆ: \`๋ฐ˜๋ณต: ๋งค์ฃผ ๋ชฉ์š”์ผ\`). +- **์ถœ์ฒ˜**: ๊ทผ๊ฑฐ ๋ฐœ์–ธ์˜ ํƒ€์ž„์Šคํƒฌํ”„ \`[mm:ss]\`. -## 5. ์˜คํ”ˆ ์ด์Šˆ -ํšŒ์˜ ์ข…๋ฃŒ ์‹œ์ ์— **์•„์ง ๊ฒฐ์ •๋˜์ง€ ์•Š์€ ๋ฏธ๊ฒฐ ์‚ฌํ•ญ**์„ ํ•œ๊ณณ์— ๋ชจ์•„ ๊ธ€๋จธ๋ฆฌํ‘œ๋กœ ์ •๋ฆฌํ•œ๋‹ค (๋„์ž… ์—ฌ๋ถ€ยท์ •์˜ ํ•„์š”ยทํ™•์ • ๋Œ€๊ธฐ ๋“ฑ). ๋ถ„์‚ฐ์‹œํ‚ค์ง€ ๋ง๊ณ  ์—ฌ๊ธฐ์„œ ํ•œ๋ˆˆ์— ๋ณด์ด๊ฒŒ ํ•œ๋‹ค. -- ์˜ˆ) Babylon.js ๋„์ž… ์—ฌ๋ถ€ / ์ตœ์†Œ ์ง€์› ์‚ฌ์–‘ ์ •์˜ / ๋ฐ์ดํ„ฐ ์ž…๋ ฅ ๊ตฌ์กฐ ํ™•์ • / ๊ฐ€์šฐ์‹œ์•ˆ ์Šคํ”Œ๋ž˜ํŒ… ๋„์ž… ์—ฌ๋ถ€ +## ์˜คํ”ˆ ์ด์Šˆ / ๋‹ค์Œ ํšŒ์˜๋กœ +ํšŒ์˜ ์ข…๋ฃŒ ์‹œ์ ์— **์•„์ง ๊ฒฐ์ •๋˜์ง€ ์•Š์€ ๋ฏธ๊ฒฐ ์‚ฌํ•ญ**์„ ํ•œ๊ณณ์— ๋ชจ์€๋‹ค(๋„์ž… ์—ฌ๋ถ€ยท์ •์˜ ํ•„์š”ยทํ…Œ์ŠคํŠธ ํ›„ ๊ฒฐ์ •ยทํ™”์ž๊ฐ„ ์ถฉ๋Œ ๋“ฑ). ๊ฐ€๋Šฅํ•˜๋ฉด *๋ˆ„๊ฐ€/์–ธ์ œ ํ™•์ธ*๊นŒ์ง€. ๊ฐ ์ค„ ๋ [mm:ss]. +- ์˜ˆ) ์‚ฌ์ง„ ๋…ธ์ถœ ๊ฐœ์ˆ˜ 6 vs 8 โ€” ๊ธฐ์ค€ ๋ฏธ์ •, ํด๋ผ์ด์–ธํŠธ ํ™•์ธ ํ•„์š” โ€” [58:25] -## 6. ๋ฆฌ์Šคํฌ ๋ฐ ๊ฒ€ํ†  ์‚ฌํ•ญ -ํ”„๋กœ์ ํŠธ ์ง„ํ–‰์— ์˜ํ–ฅ์„ ์ค„ ์ˆ˜ ์žˆ๋Š” ์š”์†Œ๋ฅผ ํ‘œ๋กœ ์ •๋ฆฌํ•œ๋‹ค(์ผ์ • ์ง€์—ฐยท๊ฐœ๋ฐœ ๋‚œ์ด๋„ยท์ •์ฑ…/๋ณด์•ˆยท์™ธ๋ถ€ ์˜์กด์„ฑ ๋“ฑ). ์‹๋ณ„๋œ ๋ฆฌ์Šคํฌ๊ฐ€ ์—†์œผ๋ฉด "ํ˜„์žฌ ์‹๋ณ„๋œ ๋ฆฌ์Šคํฌ ์—†์Œ"์ด๋ผ๊ณ  ์ ๋Š”๋‹ค. ํ‘œ ์…€ ์•ˆ์—์„œ๋Š” ์ค„๋ฐ”๊ฟˆ๊ณผ \`|\` ๋ฌธ์ž๋ฅผ ์“ฐ์ง€ ๋ง ๊ฒƒ. -| ๋ฆฌ์Šคํฌ | ์˜ํ–ฅ | ๋Œ€์‘ ๋ฐฉ์•ˆ | -| --- | --- | --- | - -## 7. ๋…ผ์˜ ์‚ฌํ•ญ -๊ฒฐ์ •๋˜์ง€ ์•Š์•˜์œผ๋‚˜ ์˜ค๊ฐ„ ๋…ผ์˜๋ฅผ **์ฃผ์ œ๋ณ„ ๊ธ€๋จธ๋ฆฌํ‘œ**๋กœ ๊ฐ„๊ฒฐํ•˜๊ฒŒ ์ •๋ฆฌํ•œ๋‹ค. (ํ˜„ํ™ฉ/ํ•ต์‹ฌ ๋…ผ์˜/์ถ”๊ฐ€ ๊ฒ€ํ†  ๊ฐ™์€ ํ•˜์œ„ ๊ตฌ์กฐ๋กœ ๊ธธ๊ฒŒ ๋Š˜์ด์ง€ ๋ง ๊ฒƒ.) ๋ฐœ์–ธ ๋‚˜์—ด ๊ธˆ์ง€, ๊ฒฐ๊ณผยท์Ÿ์  ์ค‘์‹ฌ. +## ๋…ผ์˜ ๋ฉ”๋ชจ +๊ฒฐ์ •๋˜์ง€ ์•Š์•˜์œผ๋‚˜ ์˜ค๊ฐ„ ๋…ผ์˜๋ฅผ **์ฃผ์ œ๋ณ„ ๊ธ€๋จธ๋ฆฌํ‘œ**๋กœ ๊ฐ„๊ฒฐํ•˜๊ฒŒ(๋ฐœ์–ธ ๋‚˜์—ด ๊ธˆ์ง€, ๊ฒฐ๊ณผยท์Ÿ์  ์ค‘์‹ฌ). ๊ฐ ๋…ผ์  ๋ [mm:ss]. **[์ฃผ์ œ๋ช…]** -- ํ•ต์‹ฌ ๋…ผ์  ํ•œ ์ค„ -- ํ•ต์‹ฌ ๋…ผ์  ํ•œ ์ค„ +- ํ•ต์‹ฌ ๋…ผ์  ํ•œ ์ค„ โ€” [mm:ss] -**[๋‹ค๋ฅธ ์ฃผ์ œ๋ช…]** -- ํ•ต์‹ฌ ๋…ผ์  ํ•œ ์ค„ +## ๋ฆฌ์Šคํฌ (์„ ํƒ) +**์‹ค์ œ๋กœ ๋ฆฌ์Šคํฌ์™€ (๊ฐ€๋Šฅํ•˜๋ฉด) ์™„ํ™”์ฑ…์ด ๋…ผ์˜๋์„ ๋•Œ๋งŒ** ์ด ์„น์…˜๊ณผ ํ‘œ๋ฅผ ๋งŒ๋“ ๋‹ค. ํšŒ์˜์—์„œ ์•ˆ ๋‹ค๋ค„์กŒ์œผ๋ฉด ์ด ์„น์…˜์„ **ํ†ต์งธ๋กœ ์ƒ๋žต**ํ•œ๋‹ค(๋นˆ ํ…œํ”Œ๋ฆฟยท"[๋‚ด์šฉ ํ™•์ธ ํ•„์š”]" ๊ณจ๊ฒฉ๋งŒ ๋‚จ๊ธฐ์ง€ ๋ง ๊ฒƒ). '๋ฆฌ์Šคํฌ'๋Š” ์œ„ํ—˜ *์š”์ธ/์›์ธ*, '์˜ํ–ฅ'์€ ํ˜„์‹คํ™” ์‹œ์˜ *๊ฒฐ๊ณผ*๋‹ค โ€” ๋‘ ์—ด์— ๊ฐ™์€ ๋ฌธ์žฅ์„ ๋ฐ˜๋ณตํ•˜์ง€ ๋ง ๊ฒƒ. ์…€ ์•ˆ์—์„œ ์ค„๋ฐ”๊ฟˆยท\`|\` ๊ธˆ์ง€. +| ๋ฆฌ์Šคํฌ | ์˜ํ–ฅ | ๋Œ€์‘ ๋ฐฉ์•ˆ | ์ถœ์ฒ˜ | +| --- | --- | --- | --- | # ์ตœ์ข… ์ ๊ฒ€ (์ถœ๋ ฅ ์ „ ๋‚ด๋ถ€ ํ™•์ธ โ€” ์ฒดํฌ ๋กœ๊ทธ๋Š” ์ถœ๋ ฅํ•˜์ง€ ๋ง ๊ฒƒ) -โ–ก ๊ฒฐ์ •์‚ฌํ•ญ์— ํ™•์ •๋œ ๊ฒƒ๋งŒ ์žˆ๋Š”๊ฐ€(๊ฒ€ํ†  ํ•„์š” ํ•ญ๋ชฉ์ด ์„ž์ด์ง€ ์•Š์•˜๋‚˜) โ–ก ์•ก์…˜ ์•„์ดํ…œ์— ๋‹ด๋‹น(๊ฐœ์ธ)ยท์ž‘์—…ยท๊ธฐํ•œยท์‚ฐ์ถœ๋ฌผ 4์š”์†Œ๊ฐ€ ์žˆ๋Š”๊ฐ€ โ–ก ์ต๋ช…ยท๋ฒˆํ˜ธ ํ™”์ž๋ฅผ ๋‹ด๋‹น์œผ๋กœ ํ™•์ •ํ•˜์ง€ ์•Š๊ณ  [๋ฏธ์ง€์ •-ํ™•์ธํ•„์š”]๋กœ ๋’€๋Š”๊ฐ€ โ–ก "์ด๋ ‡๊ฒŒ/๊ทธ๊ฑฐ" ๊ฐ™์€ ๋นˆ ์ธ์šฉ์„ ๊ทผ๊ฑฐ๋กœ ๋‹ฌ์ง€ ์•Š์•˜๋Š”๊ฐ€([๋‚ด์šฉ ํ™•์ธํ•„์š”] ์ฒ˜๋ฆฌ) โ–ก ๋ณธ๋ฌธ์— ๋œฌ ๋งˆ๊ฐ ๋‚ ์งœ๋ฅผ ๊ฒฐ๋ถ€๋œ ์•ก์…˜ ๊ธฐํ•œ์— ๋ฐ˜์˜ํ–ˆ๋Š”๊ฐ€ โ–ก ๋ช…๋‹จ ์™ธ ํ™”์ž์— (ํ™•์ธํ•„์š”) ํ‘œ์‹œ๋ฅผ ํ–ˆ๋Š”๊ฐ€ โ–ก ์˜คํ”ˆ ์ด์Šˆ๊ฐ€ ํ•œ๊ณณ์— ๋ชจ์˜€๋Š”๊ฐ€ โ–ก ๋ฆฌ์Šคํฌ๊ฐ€ ์˜ํ–ฅยท๋Œ€์‘๋ฐฉ์•ˆ๊ณผ ํ•จ๊ป˜ ์ •๋ฆฌ๋๋Š”๊ฐ€ โ–ก ๋…ผ์˜์‚ฌํ•ญ์ด ์ฃผ์ œ๋ณ„ bullet๋กœ ๊ฐ„๊ฒฐํ•œ๊ฐ€ โ–ก ์š”์•ฝ์ด ๊ฒฐ๊ณผ ์ค‘์‹ฌ์ธ๊ฐ€ โ–ก ๊ฒฐ์ •ยท์•ก์…˜์— ๊ทผ๊ฑฐ ์ธ์šฉ์ด ๋ถ™์–ด ์žˆ๋Š”๊ฐ€ +โ–ก "์ฐธ์„์ž N" ํ† ํฐ 0๊ฐœ โ–ก ํ™”์ž๊ฐ€ ํŒ€/์—ญํ• ๋กœ ๊ท€์†(๊ฐœ์ธ ์ถ”์ธก ์—†์Œ) โ–ก ๊ฒฐ์ •์‚ฌํ•ญ์— ์ˆœ์ˆ˜ ๋ฐฉํ–ฅ/์ •์ฑ…๋งŒ(์ผ๊ฐ์€ ์•ก์…˜์œผ๋กœ) โ–ก "ํ…Œ์ŠคํŠธํ›„๊ฒฐ์ •ยท๊ฒ€ํ† ํ•„์š”"๊ฐ€ ๊ฒฐ์ •์— ์„ž์ด์ง€ ์•Š์Œ โ–ก ์ฆ‰์‹œ ๋ฐ˜๋ฐ•๋œ ๊ฐ€์„ค์„ ์ด์Šˆ๋กœ ๊ฒฉ์ƒ ์•ˆ ํ•จ โ–ก ํ™”์ž๊ฐ„ ์ถฉ๋Œ์€ ๋‹จ์ผ๊ฐ’ ํ™•์ • ๋ง๊ณ  ๊ทธ๋Œ€๋กœ ํ‘œ๊ธฐ โ–ก ๊ฐ™์€ ์‚ฌ์‹ค์ด ์—ฌ๋Ÿฌ ์„น์…˜์— ์ค‘๋ณต ์•ˆ ๋จ โ–ก ๋นˆ ์นธ์€ "โ€”"(์ถ”์ธก ์ฑ„์›€ ์—†์Œ) โ–ก ํ†ต์งธ ๋ฏธ์ • ํ•ญ๋ชฉ์€ ์˜คํ”ˆ์ด์Šˆ๋กœ โ–ก ์•ก์…˜ ์ƒํƒœ๊ฐ€ 5์ข… taxonomy ํ˜•์‹ โ–ก ๋ฆฌ์Šคํฌ๋Š” ์‹ค์ œ ๋…ผ์˜๋์„ ๋•Œ๋งŒ ํ‘œ ๋„์›€ โ–ก ๋ชจ๋“  ๊ฒฐ์ •ยท์•ก์…˜ยท๋…ผ์ ์— [mm:ss] ์œ„ ํ˜•์‹์„ ์ •ํ™•ํžˆ ๋”ฐ๋ฅด๊ณ , ๋ชจ๋“  ๋‚ด์šฉ์€ ํ•œ๊ตญ์–ด๋กœ ์ž‘์„ฑํ•˜์‹œ์˜ค.`; @@ -137,6 +153,9 @@ const OUTPUT_FORMAT = `# ์ž‘์„ฑ ์›์น™ (ํšŒ์˜๋ก ํ’ˆ์งˆ โ€” ์ถœ๋ ฅ ์ „ ๋ฐ˜๋“œ * [์„ธ๊ทธ๋จผํŠธ ์ถ”์ถœ ๋‹จ๊ณ„ โ€” Map] ๊ธด ๋…น์ทจ๋ก(๋‹จ์ผ ์ปจํ…์ŠคํŠธ ์ดˆ๊ณผ)์„ ์กฐ๊ฐ์œผ๋กœ ๋‚˜๋ˆ  * ๊ฐ ์กฐ๊ฐ์—์„œ ์‚ฌ์‹ค๋งŒ ์ถ”์ถœํ•œ๋‹ค. ์ž…๋ ฅ์ด ์งง์•„ ๋ชจ๋ธ์ด ์ถฉ์‹คํ•ด์ง€๊ณ (lost-in-the-middle * ๋ฐฉ์ง€), 60K ์ž๋ฅด๊ธฐ๋กœ ํ›„๋ฐ˜๋ถ€๊ฐ€ ํ†ต์งธ๋กœ ์‚ฌ๋ผ์ง€๋˜ ๋ฌธ์ œ๋ฅผ ์—†์•ค๋‹ค. + * + * ์ด ๋‹จ๊ณ„๋Š” ์ตœ์ข… ์ถœ๋ ฅ์ด ์•„๋‹ˆ๋ผ *๊ฒ€์ฆ ๊ฐ€๋Šฅํ•œ ๋…ธํŠธ*๋‹ค โ€” ๋”ฐ๋ผ์„œ ๊ทผ๊ฑฐ๋Š” ํƒ€์ž„์Šคํƒฌํ”„ + * **์™€** ์›๋ฌธ ์ผ๋ถ€๋ฅผ ํ•จ๊ป˜ ๋‚จ๊ฒจ ๋ณ‘ํ•ฉยท๊ฒ€์ฆ ๋‹จ๊ณ„๊ฐ€ ๋Œ€์กฐํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•œ๋‹ค(์ตœ์ข… ์ถœ๋ ฅ๋งŒ ์ •์ œ). */ export function buildMeetExtractPrompt(segment: string, metadata: string, segIndex: number, segTotal: number): string { const metaBlock = metadata.trim() || '(๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ์—†์Œ)'; @@ -145,11 +164,12 @@ export function buildMeetExtractPrompt(segment: string, metadata: string, segInd ์ตœ์ข… ํšŒ์˜๋ก์€ ๋‚˜์ค‘์— ๋ชจ๋“  ์กฐ๊ฐ์„ ํ•ฉ์ณ ์ž‘์„ฑํ•˜๋ฏ€๋กœ, ์—ฌ๊ธฐ์„œ๋Š” ์š”์•ฝยทํ•ด์„ํ•˜์ง€ ๋ง๊ณ  **๋ˆ„๋ฝ ์—†์ด ์ถ”์ถœ**ํ•˜๋Š” ๊ฒƒ์ด ์ž„๋ฌด๋‹ค. # ๊ทœ์น™ (ํ• ๋ฃจ์‹œ๋„ค์ด์…˜ ๋ฐฉ์ง€) -- ์ด ์กฐ๊ฐ์— ์—†๋Š” ์‚ฌ์‹คยท์ˆ˜์น˜ยท๊ฒฐ์ •์„ ๋งŒ๋“ค์ง€ ๋ง ๊ฒƒ. ๋ฐœ์–ธ ์ฃผ์ฒด๊ฐ€ ๋ถˆ๋ช…ํ™•ํ•˜๋ฉด "(์ฃผ์ฒด ๋ถˆ๋ช…ํ™•)"์œผ๋กœ ํ‘œ๊ธฐ. -- STT ์˜คํƒ€๋Š” ๋ฌธ๋งฅ๊ณผ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ(์šฉ์–ด์ง‘ ์—ญํ• )๋กœ ์ •๊ทœํ™”ํ•˜๋˜, ์—†๋Š” ์‚ฌ์‹ค์„ ์ง€์–ด๋‚ด๋Š” ๊ฒƒ์€ ๊ธˆ์ง€. -- ๊ฐ ํ•ญ๋ชฉ ๋์— ๊ทผ๊ฑฐ ๋ฐœ์–ธ ์›๋ฌธ ์ผ๋ถ€(20์ž ๋‚ด์™ธ)๋ฅผ \`๊ทผ๊ฑฐ: "โ€ฆ"\` ๋กœ ๋ถ™์ธ๋‹ค. ๋‹จ, "์ด๋ ‡๊ฒŒ/๊ทธ๊ฑฐ/์ด๊ฑฐ" ๊ฐ™์€ ์ง€์‹œ๋Œ€๋ช…์‚ฌ๋ฟ์ธ *๋‚ด์šฉ ๊ณต๋ฐฑ* ๋ฐœํ™”๋Š” ๊ทผ๊ฑฐ๋กœ ์“ฐ์ง€ ๋ง๊ณ  ํ•ต์‹ฌ ๋‚ด์šฉ์„ "[๋‚ด์šฉ ํ™•์ธํ•„์š”]"๋กœ ํ‘œ๊ธฐํ•œ๋‹ค. -- ์•ก์…˜ ๋‹ด๋‹น์ด ์‹ค๋ช…์œผ๋กœ ํ™•์ธ ์•ˆ ๋œ ํ™”์ž(๋ฒˆํ˜ธยท์ต๋ช…)๋ฉด \`[๋‹ด๋‹น]\`์— "[๋ฏธ์ง€์ •]"์œผ๋กœ ์ ๊ณ  ์ž„์˜ ๋ฐฐ์ •ํ•˜์ง€ ๋ง ๊ฒƒ. -- ์กฐ๊ฐ ๊ฒฝ๊ณ„์—์„œ ์ž˜๋ฆฐ ๋ฌธ์žฅ์€ ๋ฌด๋ฆฌํ•˜๊ฒŒ ํ•ด์„ํ•˜์ง€ ๋ง๊ณ  "(์กฐ๊ฐ ๊ฒฝ๊ณ„์—์„œ ์ž˜๋ฆผ)"์œผ๋กœ ํ‘œ๊ธฐ. +- ์ด ์กฐ๊ฐ์— ์—†๋Š” ์‚ฌ์‹คยท์ˆ˜์น˜ยท๊ฒฐ์ •์„ ๋งŒ๋“ค์ง€ ๋ง ๊ฒƒ. +- **ํ™”์ž ์ •๊ทœํ™”**: "์ฐธ์„์ž N"์€ STT ํ™”์ž๋ฒˆํ˜ธ์ผ ๋ฟ์ด๋‹ค. ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ์˜ ์ฐธ์„์ž ๋ช…๋‹จยทํšŒ์‚ฌ ํ‘œ์ค€ ํŒ€ ๋ถ„๋ฅ˜ + ๋ฐœ์–ธ ๋‚ด์šฉ ๋‹จ์„œ๋กœ ๊ฐ ํ™”์ž๋ฅผ **ํŒ€/์—ญํ• **๋กœ ๋งคํ•‘ํ•˜๋ผ. ๊ฐœ์ธ๋ช…์€ ํ™•์‹คํ•  ๋•Œ๋งŒ. ํŒ€/์—ญํ• ๋„ ๋ถˆ๋ช…์ด๋ฉด "[๋ฏธ์ƒ]". (๋ฒˆํ˜ธ๋Š” ์•„๋ž˜ 'ํ™”์ž ์—ญํ•  ๋งคํ•‘'์—๋งŒ ์ฐธ๊ณ ์šฉ์œผ๋กœ ๋‚จ๊ธฐ๊ณ , ๋ณธ๋ฌธ ํ•ญ๋ชฉ์—” ํŒ€/์—ญํ• ๋กœ ์ ๋Š”๋‹ค.) +- STT ์˜คํƒ€๋Š” ๋ฌธ๋งฅยท๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋กœ ์ •๊ทœํ™”ํ•˜๋˜ ์—†๋Š” ์‚ฌ์‹ค์„ ์ง€์–ด๋‚ด์ง€ ๋ง ๊ฒƒ. +- **๊ทผ๊ฑฐ**: ๊ฐ ํ•ญ๋ชฉ ๋์— \`[mm:ss] "์›๋ฌธ ์ผ๋ถ€"\` ๋ฅผ ๋ถ™์ธ๋‹ค(ํƒ€์ž„์Šคํƒฌํ”„ = ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด "์ฐธ์„์ž N mm:ss" ํ‘œ์‹œ์˜ ์‹œ๊ฐ, ์›๋ฌธ ์ผ๋ถ€ = ๊ฒ€์ฆ์šฉ ๋ฐœ์–ธ ์กฐ๊ฐ 15~20์ž). "์ด๋ ‡๊ฒŒ/๊ทธ๊ฑฐ" ๊ฐ™์€ ๋‚ด์šฉ ๊ณต๋ฐฑ ๋ฐœํ™”๋Š” ๊ทผ๊ฑฐ๋กœ ์“ฐ์ง€ ๋ง๊ณ  "[๋‚ด์šฉ ํ™•์ธํ•„์š”]". +- **๋‹ดํ™” ์ƒํƒœ**: ์ œ์•ˆ/๊ฒฐ์ • ํ•ญ๋ชฉ์—” \`(ํ•ฉ์˜)\` / \`(๋ฏธํ•ฉ์˜ยท์ œ์•ˆ)\` / \`(๋ฐ˜๋ฐ•๋จ)\` / \`(์ฒ ํšŒ๋จ)\` ์ค‘ ํ•˜๋‚˜๋ฅผ ํ‘œ์‹œ. ์ฆ‰์‹œ ๋ฐ˜๋ฐ•ยท์ผ์ถ•๋œ ๊ฐ€์„ค์€ ๊ฒฐ์ •์ด ์•„๋‹ˆ๋ผ ๊ทธ๋ ‡๊ฒŒ ํ‘œ์‹œ๋งŒ. +- ์กฐ๊ฐ ๊ฒฝ๊ณ„์—์„œ ์ž˜๋ฆฐ ๋ฌธ์žฅ์€ ๋ฌด๋ฆฌํ•˜๊ฒŒ ํ•ด์„ํ•˜์ง€ ๋ง๊ณ  "(์กฐ๊ฐ ๊ฒฝ๊ณ„์—์„œ ์ž˜๋ฆผ)". [๋ฉ”ํƒ€๋ฐ์ดํ„ฐ] ${metaBlock} @@ -160,22 +180,23 @@ ${segment} \`\`\` # ์ถœ๋ ฅ ํ˜•์‹ (์ด ์กฐ๊ฐ์— ํ•ด๋‹น ํ•ญ๋ชฉ์ด ์—†์œผ๋ฉด "์—†์Œ") -## ํšŒ์˜ ๋ชฉ์  -(์ด ์กฐ๊ฐ์—์„œ ํšŒ์˜์˜ ๋ชฉ์ ยท๋ฐฐ๊ฒฝ์ด ๋“œ๋Ÿฌ๋‚˜๋ฉด ํ•œ ์ค„๋กœ. ์•ˆ ๋“œ๋Ÿฌ๋‚˜๋ฉด "์—†์Œ") -## ๋ฐœ์–ธ์ž -(์ด ์กฐ๊ฐ์— ๋“ฑ์žฅํ•œ ๋ฐœ์–ธ์ž ์ด๋ฆ„/ID ๋ชฉ๋ก) +## ์•ˆ๊ฑด/์ฃผ์ œ (์ด ์กฐ๊ฐ์—์„œ ๋‹ค๋ค„์ง„ ์˜์ œ ๋ชฉ๋ก โ€” ๋ˆ„๋ฝ ์ ๊ฒ€์šฉ) +- ์ฃผ์ œ๋ช… โ€” [mm:ss] +## ํ™”์ž ์—ญํ•  ๋งคํ•‘ (์ด ์กฐ๊ฐ์—์„œ ํŒŒ์•…๋œ ๊ฒƒ) +- ํ™”์ž N โ†’ [ํŒ€/์—ญํ• ] (ํŒ๋‹จ ๊ทผ๊ฑฐ: ๋ฌด์Šจ ๋ฐœ์–ธ์œผ๋กœ ๊ทธ ์—ญํ• ๋กœ ๋ดค๋Š”์ง€ / ๋ถˆ๋ช…์ด๋ฉด "๋ฏธ์ƒ") +## ํšŒ์˜ ๋ชฉ์  (๋“œ๋Ÿฌ๋‚˜๋ฉด ํ•œ ์ค„, ์•„๋‹ˆ๋ฉด "์—†์Œ") ## ์‚ฌ์‹ค(Fact) -- [๋ฐœ์–ธ์ž] ๋‚ด์šฉ โ€” ๊ทผ๊ฑฐ: "โ€ฆ" +- [ํŒ€/์—ญํ• ] ๋‚ด์šฉ โ€” [mm:ss] "์›๋ฌธ ์ผ๋ถ€" ## ๋…ผ์˜(Discussion) -- [๋ฐœ์–ธ์ž] ๋‚ด์šฉ โ€” ๊ทผ๊ฑฐ: "โ€ฆ" +- [ํŒ€/์—ญํ• ] ๋‚ด์šฉ (๋‹ดํ™”์ƒํƒœ) โ€” [mm:ss] "์›๋ฌธ ์ผ๋ถ€" ## ๊ฒฐ์ •(Decision) -- ๋‚ด์šฉ โ€” ๊ทผ๊ฑฐ: "โ€ฆ" +- ๋‚ด์šฉ (ํ•ฉ์˜) โ€” [mm:ss] "์›๋ฌธ ์ผ๋ถ€" ## ๋ฆฌ์Šคํฌ/์ด์Šˆ -- ๋‚ด์šฉ โ€” ๊ทผ๊ฑฐ: "โ€ฆ" +- ๋‚ด์šฉ (+๋…ผ์˜๋œ ๋Œ€์‘์ฑ… ์žˆ์œผ๋ฉด ํ•จ๊ป˜) โ€” [mm:ss] "์›๋ฌธ ์ผ๋ถ€" ## ์•ก์…˜(Action) -- [๋‹ด๋‹น(๊ฐœ์ธ ์šฐ์„ )] ์ž‘์—… ๋‚ด์šฉ (๊ธฐํ•œ: โ€ฆ / ์‚ฐ์ถœ๋ฌผ: โ€ฆ) โ€” ๊ทผ๊ฑฐ: "โ€ฆ" -## ์–ธ๊ธ‰๋œ ์ˆ˜์น˜ยท๋‚ ์งœยท๊ธˆ์•ก -- ํ•ญ๋ชฉ: ๊ฐ’ โ€” ๊ทผ๊ฑฐ: "โ€ฆ"`; +- [๋‹ด๋‹น(ํŒ€/์—ญํ•  ์šฐ์„ )] ์•ก์…˜ ํ•œ ์ค„ (๊ธฐํ•œ: โ€ฆ / ์ƒํƒœํ›„๋ณด: ํ™•์ •ยท์ง„ํ–‰๋ฏธ์ •ยท๊ธฐํ•œ๋ฏธ์ •ยท์กฐ๊ฑด๋ถ€ยท๋ฐ˜๋ณต) โ€” [mm:ss] "์›๋ฌธ ์ผ๋ถ€" +## ์–ธ๊ธ‰๋œ ์ˆ˜์น˜ยท๋‚ ์งœยท๊ธˆ์•ก (ํ™”์ž๊ฐ„ ์ถฉ๋Œ์ด ์žˆ์œผ๋ฉด ์ถฉ๋Œ ๊ทธ๋Œ€๋กœ) +- ํ•ญ๋ชฉ: ๊ฐ’ โ€” [mm:ss]`; } /** @@ -187,12 +208,17 @@ export function buildMeetReducePrompt(notes: string, metadata: string): string { return `# ์ž„๋ฌด ๊ธด ํšŒ์˜ ๋…น์ทจ๋ก์„ ์กฐ๊ฐ๋ณ„๋กœ ์ถ”์ถœํ•œ ๋…ธํŠธ๋“ค์ด ์•„๋ž˜์— ์žˆ๋‹ค. ์ด ๋…ธํŠธ๋งŒ ๊ทผ๊ฑฐ๋กœ ์ตœ์ข… ํšŒ์˜๋ก(Actionable Minutes)์„ ์ž‘์„ฑํ•˜๋ผ. -# ๊ทœ์น™ +# ๊ทœ์น™ (๋ณ‘ํ•ฉ ์‹œ ๋ฐ˜๋“œ์‹œ ์ค€์ˆ˜) - **๋…ธํŠธ์— ์žˆ๋Š” ๋‚ด์šฉ๋งŒ** ์‚ฌ์šฉํ•œ๋‹ค. ๋…ธํŠธ์— ์—†๋Š” ์‚ฌ์‹คยท์ˆ˜์น˜ยท๊ฒฐ์ •์„ ์ถ”๊ฐ€ํ•˜์ง€ ๋ง ๊ฒƒ. -- ๊ฐ™์€ ์ฃผ์ œ๊ฐ€ ์—ฌ๋Ÿฌ ์กฐ๊ฐ์— ํฉ์–ด์ ธ ์žˆ์œผ๋ฉด ์ฃผ์ œ๋ณ„๋กœ ๋‹ค์‹œ ๋ฌถ๋Š”๋‹ค(Topic Reclustering). ๋‹จ, ์„œ๋กœ ๋‹ค๋ฅธ ๋ฐœ์–ธ์„ ํ•˜๋‚˜์˜ ์ธ๊ณผ ์‚ฌ์Šฌ๋กœ ํ•ฉ์„ฑํ•˜์ง€ ๋ง ๊ฒƒ. -- ๋ฐœ์–ธ ์ฃผ์ฒด ๊ท€์†์„ ๊ทธ๋Œ€๋กœ ์œ ์ง€ํ•œ๋‹ค. "(์ฃผ์ฒด ๋ถˆ๋ช…ํ™•)" ํ•ญ๋ชฉ์— ์ž„์˜๋กœ ์ด๋ฆ„์„ ๋ถ™์ด์ง€ ๋ง ๊ฒƒ. -- ์ค‘๋ณต ํ•ญ๋ชฉ์€ ๋ณ‘ํ•ฉํ•˜๋˜ ๊ทผ๊ฑฐ ์ธ์šฉ์€ ์œ ์ง€ํ•œ๋‹ค. ๊ฒฐ์ •(Decision)์€ ๋ช…์‹œ์  ํ•ฉ์˜๊ฐ€ ๋…ธํŠธ์— ์žˆ์„ ๋•Œ๋งŒ '๊ฒฐ์ •๋จ'. -- ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ์™€ ๋…ธํŠธ๊ฐ€ ์ถฉ๋Œํ•˜๋ฉด ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ ์šฐ์„ ํ•œ๋‹ค. +- **ํ™”์ž ์—ญํ•  ํ†ต์ผ**: ๊ฐ ์กฐ๊ฐ์˜ 'ํ™”์ž ์—ญํ•  ๋งคํ•‘'์„ ์ข…ํ•ฉํ•ด ๊ฐ™์€ ํŒ€/์—ญํ•  ๋ผ๋ฒจ๋กœ ํ†ต์ผํ•œ๋‹ค. ์ตœ์ข… ๋ฌธ์„œ์— "์ฐธ์„์ž N"์ด ๋‹จ ํ•˜๋‚˜๋„ ๋‚จ์œผ๋ฉด ์•ˆ ๋œ๋‹ค(0๊ฐœ). ์กฐ๊ฐ๋งˆ๋‹ค ๋งคํ•‘์ด ์—‡๊ฐˆ๋ฆฌ๋ฉด ๋‹ค์ˆ˜ยท๋ฌธ๋งฅ์œผ๋กœ ๊ฒฐ์ •ํ•˜๊ณ , ๋๋‚ด ๋ถˆ๋ช…์ด๋ฉด ์ฃผ์ฒด ์—†์ด ์ค‘๋ฆฝ ์„œ์ˆ . +- **์ „์—ญ ํ—ค๋“œ๋ผ์ธ ์ถ”์ถœ**: ์กฐ๊ฐ ์ „์ฒด(ํŠนํžˆ ๋งˆ์ง€๋ง‰ ์กฐ๊ฐ)๋ฅผ ๊ด€ํ†ตํ•˜๋Š” **๊ฒฐ๋ก ยทํ•ต์‹ฌ ์š”๊ตฌ**๋ฅผ ์ฐพ์•„ 'ํ•ต์‹ฌ ์š”์•ฝ' ๋งจ ์•ž์— ์„ธ์šด๋‹ค. ํ•œ ์ฒญํฌ์—๋งŒ ์žˆ๋˜ ํ•ต์‹ฌ ์š”๊ตฌ๊ฐ€ ๋ฌปํžˆ์ง€ ์•Š๊ฒŒ ํ•œ๋‹ค. +- **๋‹ดํ™” ์ƒํƒœ ๋ฐ˜์˜**: \`(๋ฐ˜๋ฐ•๋จ)\`ยท\`(์ฒ ํšŒ๋จ)\`์œผ๋กœ ํ‘œ์‹œ๋œ ๊ฐ€์„ค์€ ์˜คํ”ˆ ์ด์Šˆยท๊ฒฐ์ •์œผ๋กœ ๊ฒฉ์ƒํ•˜์ง€ ๋ง ๊ฒƒ. \`(๋ฏธํ•ฉ์˜)\`๋Š” ์˜คํ”ˆ ์ด์Šˆ/๋…ผ์˜๋กœ. \`(ํ•ฉ์˜)\`๋งŒ ๊ฒฐ์ • ํ›„๋ณด. +- **๊ฒฐ์ •/์•ก์…˜ ๊ฒฝ๊ณ„**: ๋‹ด๋‹น+ํ–‰๋™์ด ์žˆ๋Š” ์ผ๊ฐ์€ ์•ก์…˜ ํ‘œ๋กœ, ๊ฒฐ์ •์—” ์ˆœ์ˆ˜ ๋ฐฉํ–ฅ/์ •์ฑ…๋งŒ. +- **์˜๋ฏธ dedup**: ํ‘œํ˜„์ด ๋‹ฌ๋ผ๋„ ๊ฐ™์€ ์ž‘์—…ยท๋…ผ์ ์€ **ํ•˜๋‚˜๋กœ ๋ณ‘ํ•ฉ**ํ•œ๋‹ค(์—ฌ๋Ÿฌ ์กฐ๊ฐ์—์„œ ์ค‘๋ณต ์ถ”์ถœ๋œ ๊ฒƒ). ํ•œ ์‚ฌ์‹ค์€ ํ•œ ์„น์…˜์—๋งŒ. +- **์ถฉ๋Œ ๋ณด์กด**: ์ˆ˜์น˜ยท์˜๊ฒฌ์ด ํ™”์ž๊ฐ„ ๊ฐˆ๋ฆฌ๋ฉด ๋‹จ์ผ๊ฐ’์œผ๋กœ ํ™•์ •ํ•˜์ง€ ๋ง๊ณ  "A vs B, ๋ฏธ์ •"์œผ๋กœ ์˜คํ”ˆ ์ด์Šˆ์— ์ ๋Š”๋‹ค. +- **๋นˆ ์นธ์€ "โ€”"**, ๋ชจ๋“  ์นธ์ด ๋ฏธ์ •์ธ ์•ก์…˜์€ ์˜คํ”ˆ ์ด์Šˆ๋กœ. ๋ฆฌ์Šคํฌ๋Š” ์‹ค์ œ ๋…ผ์˜๋œ ๊ฒฝ์šฐ๋งŒ ํ‘œ๋ฅผ ๋งŒ๋“ ๋‹ค. +- **์•ˆ๊ฑด ๋ˆ„๋ฝ ์ ๊ฒ€**: ๋…ธํŠธ์˜ '์•ˆ๊ฑด/์ฃผ์ œ' ๋ชฉ๋ก์„ ์ฒดํฌ๋ฆฌ์ŠคํŠธ ์‚ผ์•„, ๋‹ค๋ค„์ง„ ์˜์ œ๊ฐ€ ๊ฒฐ๊ณผ ๋ฌธ์„œ์—์„œ ๋ˆ„๋ฝ๋˜์ง€ ์•Š์•˜๋Š”์ง€ ํ™•์ธํ•œ๋‹ค(ํŠนํžˆ ํšŒ์˜ ๋„์ž…๋ถ€ ์ฒซ ์•ˆ๊ฑด). +- ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ์™€ ๋…ธํŠธ๊ฐ€ ์ถฉ๋Œํ•˜๋ฉด ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ์šฐ์„ . [๋ฉ”ํƒ€๋ฐ์ดํ„ฐ] ${metaBlock} @@ -204,22 +230,28 @@ ${OUTPUT_FORMAT}`; } /** - * [๊ฒ€์ฆ ํŒจ์Šค โ€” ์˜ต์…˜] ์™„์„ฑ๋œ ํšŒ์˜๋ก์˜ ๊ฒฐ์ •ยท์•ก์…˜ยท์ˆ˜์น˜๊ฐ€ ๊ทผ๊ฑฐ ์†Œ์Šค(๋…น์ทจ๋ก ๋˜๋Š” - * ์ถ”์ถœ ๋…ธํŠธ)์— ์‹ค์ œ๋กœ ์กด์žฌํ•˜๋Š”์ง€ ๋Œ€์กฐํ•œ๋‹ค. ๋‚ ์กฐ ๊ฒ€์ถœ์šฉ 2์ฐจ ๋ฐฉ์–ด์„ . + * [๊ฒ€์ฆ ํŒจ์Šค] ์™„์„ฑ๋œ ํšŒ์˜๋ก์„ ๊ทผ๊ฑฐ ์†Œ์Šค(๋…น์ทจ๋ก ๋˜๋Š” ์ถ”์ถœ ๋…ธํŠธ)์™€ ๋Œ€์กฐํ•œ๋‹ค. + * v2.2.258: ๋‹จ์ˆœ '์กด์žฌ ํ™•์ธ'์—์„œ โ†’ โ‘ ์ฐธ์„์ž N ์ž”์กด โ‘ก๊ฒฐ์ • ๊ณผํ™•์ • โ‘ขํ๊ธฐ ๊ฐ€์„ค ๊ฒฉ์ƒ + * โ‘ฃ์•ก์…˜ ์ค‘๋ณต ๊นŒ์ง€ ์ ๊ฒ€ํ•˜๋Š” 4์ข… ๋ฐฉ์–ด์„ ์œผ๋กœ ํ™•์žฅ(์•ฝํ•œ ๋กœ์ปฌ ๋ชจ๋ธ ๋Œ€๋น„). */ export function buildMeetVerifyPrompt(report: string, source: string): string { return `# ์ž„๋ฌด -์•„๋ž˜ [ํšŒ์˜๋ก]์˜ '๊ฒฐ์ • ์‚ฌํ•ญ'๊ณผ '์•ก์…˜ ์•„์ดํ…œ'(๋ฐ ๊ทธ ์•ˆ์˜ ์ˆ˜์น˜ยท๋‚ ์งœยท๊ธˆ์•ก)์„ [๊ทผ๊ฑฐ ์†Œ์Šค]์™€ ๋Œ€์กฐํ•˜๋ผ. +์•„๋ž˜ [ํšŒ์˜๋ก]์„ [๊ทผ๊ฑฐ ์†Œ์Šค]์™€ ๋Œ€์กฐํ•ด ๊ฒฐํ•จ์„ ์ ๊ฒ€ํ•˜๋ผ. 4์ข…์„ ๋ณธ๋‹ค. + +# ์ ๊ฒ€ ํ•ญ๋ชฉ +1. **๊ทผ๊ฑฐ ๋ฏธํ™•์ธ**: '๊ฒฐ์ • ์‚ฌํ•ญ'ยท'์•ก์…˜ ์•„์ดํ…œ'์˜ ๋‚ด์šฉ(๋ฐ ์ˆ˜์น˜ยท๋‚ ์งœ)์ด ๊ทผ๊ฑฐ ์†Œ์Šค์—์„œ ํ™•์ธ๋˜๋Š”๊ฐ€? ๋ชป ์ฐพ์œผ๋ฉด FLAG. (ํ‘œ๊ธฐยท์ฒ ์ž ์ฐจ์ด๋Š” ๋ฌด์‹œ, ์˜๋ฏธ๋กœ ๋Œ€์กฐ.) +2. **ํ™”์ž๋ฒˆํ˜ธ ์ž”์กด**: ํšŒ์˜๋ก ๋ณธ๋ฌธ์— "์ฐธ์„์ž N"/"ํ™”์ž N"/"๋ฐœ์–ธ์ž A" ๊ฐ™์€ STT ํ™”์ž๋ฒˆํ˜ธ๊ฐ€ ๋‚จ์•„ ์žˆ๋Š”๊ฐ€? ์žˆ์œผ๋ฉด FLAG. +3. **๊ฒฐ์ • ๊ณผํ™•์ •**: '๊ฒฐ์ • ์‚ฌํ•ญ'์— ๋“  ํ•ญ๋ชฉ์ด ์†Œ์Šค์—์„œ๋Š” "ํ…Œ์ŠคํŠธ ํ›„ ๊ฒฐ์ • / ๋‹ค์‹œ ๋ณด๊ณ  ์–˜๊ธฐ / ๊ณ ๋ฏผํ•ด๋ณด์ž"์ฒ˜๋Ÿผ *์กฐ๊ฑด๋ถ€ยท๋ฏธํ•ฉ์˜*์ธ๊ฐ€? ๊ทธ๋ ‡๋‹ค๋ฉด FLAG(์˜คํ”ˆ ์ด์Šˆ๋กœ ๋‚ด๋ ค์•ผ ํ•จ). +4. **ํ๊ธฐ ๊ฐ€์„ค ๊ฒฉ์ƒ**: ์†Œ์Šค์—์„œ ์ฆ‰์‹œ ๋ฐ˜๋ฐ•ยท์ฒ ํšŒ๋œ ๋ฐœ์–ธ์ด ํšŒ์˜๋ก์˜ ์˜คํ”ˆ์ด์Šˆ/๋ฆฌ์Šคํฌ/๊ฒฐ์ •์œผ๋กœ ๊ฒฉ์ƒ๋ผ ์žˆ๋Š”๊ฐ€? ์žˆ์œผ๋ฉด FLAG. +5. **์•ก์…˜ ์ค‘๋ณต**: ์•ก์…˜ ์•„์ดํ…œ ์ค‘ ์˜๋ฏธ๊ฐ€ ์‚ฌ์‹ค์ƒ ๋™์ผํ•œ๋ฐ ๋ณ„๊ฐœ ํ–‰์œผ๋กœ ์ค‘๋ณต๋œ ๊ฒƒ์ด ์žˆ๋Š”๊ฐ€? ์žˆ์œผ๋ฉด FLAG(๋ณ‘ํ•ฉ ํ•„์š”). # ๊ทœ์น™ -- ๊ฐ ํ•ญ๋ชฉ์˜ ๋‚ด์šฉ์ด ๊ทผ๊ฑฐ ์†Œ์Šค์—์„œ ํ™•์ธ๋˜๋ฉด ํ†ต๊ณผ. ์ฐพ์„ ์ˆ˜ ์—†์œผ๋ฉด FLAG. -- ํ‘œ๊ธฐยท์ฒ ์ž ์ฐจ์ด๋Š” ๋ฌด์‹œํ•˜๊ณ  ์˜๋ฏธ๋กœ ๋Œ€์กฐํ•œ๋‹ค (STT ๋ณด์ • ๊ฐ์•ˆ). - ์ƒˆ ํ•ด์„ยท์ œ์•ˆ์„ ์ถ”๊ฐ€ํ•˜์ง€ ๋ง ๊ฒƒ. ํŒ์ •๋งŒ ํ•œ๋‹ค. # ์ถœ๋ ฅ ํ˜•์‹ -- ๋ชจ๋“  ํ•ญ๋ชฉ์ด ํ™•์ธ๋˜๋ฉด ์ •ํ™•ํžˆ ํ•œ ์ค„: \`๊ฒ€์ฆ ํ†ต๊ณผ\` -- FLAG ๊ฐ€ ์žˆ์œผ๋ฉด ํ•ญ๋ชฉ๋ณ„๋กœ: - - โ— [๊ฒฐ์ •|์•ก์…˜] "<ํ•ญ๋ชฉ ์š”์•ฝ>" โ€” ๊ทผ๊ฑฐ ์†Œ์Šค์—์„œ ํ™•์ธ ๋ถˆ๊ฐ€: <์งง์€ ์‚ฌ์œ > +- ๊ฒฐํ•จ์ด ์—†์œผ๋ฉด ์ •ํ™•ํžˆ ํ•œ ์ค„: \`๊ฒ€์ฆ ํ†ต๊ณผ\` +- ์žˆ์œผ๋ฉด ํ•ญ๋ชฉ๋ณ„๋กœ: + - โ— [๊ทผ๊ฑฐ|ํ™”์ž๋ฒˆํ˜ธ|๊ณผํ™•์ •|ํ๊ธฐ๊ฐ€์„ค|์ค‘๋ณต] "<ํ•ญ๋ชฉ ์š”์•ฝ>" โ€” <์งง์€ ์‚ฌ์œ > [ํšŒ์˜๋ก] ${report} diff --git a/src/features/datacollect/scheduling/calendarHelpers.ts b/src/features/datacollect/scheduling/calendarHelpers.ts index 477ee6a..a157ae0 100644 --- a/src/features/datacollect/scheduling/calendarHelpers.ts +++ b/src/features/datacollect/scheduling/calendarHelpers.ts @@ -31,6 +31,23 @@ export function toYmd(d: Date): string { return `${y}-${m}-${day}`; } +/** + * ๋…น์ทจ๋ก ๋ณธ๋ฌธ(์ฒซ ํ™”์ž ๋ฐœ์–ธ) ์•ž์˜ ํ—ค๋” ๋ธ”๋ก์„ ์ถ”์ถœํ•œ๋‹ค. + * STT ๋‹ค์ด์–ด๋ผ์ด์ œ์ด์…˜ ์ค„("์ฐธ์„์ž 3 00:46" / "ํ™”์ž 1 0:12") ์ง์ „๊นŒ์ง€๋ฅผ ํ—ค๋”๋กœ ๋ณธ๋‹ค. + * ์ฐธ์„์ž ๋ช…๋‹จยท์ผ์‹œยท์žฅ์†Œยท๋…น์ทจ ๊ธธ์ด๊ฐ€ ๋ณดํ†ต ์—ฌ๊ธฐ ์žˆ๋‹ค. ํ—ค๋”๊ฐ€ ์—†๊ฑฐ๋‚˜ ๋น„์ •์ƒ์ ์œผ๋กœ + * ๊ธธ๋ฉด(๋‹ค์ด์–ด๋ผ์ด์ œ์ด์…˜ ์—†๋Š” ์ผ๋ฐ˜ ๋ฌธ์„œ) ๋นˆ ๋ฌธ์ž์—ด์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค. + */ +export function extractMeetingHeader(transcript: string): string { + const lines = transcript.split('\n'); + let cut = -1; + for (let i = 0; i < lines.length; i++) { + if (/^\s*(?:์ฐธ์„์ž|ํ™”์ž|๋ฐœ์–ธ์ž)\s*\d+\s+\d{1,2}:\d{2}/.test(lines[i])) { cut = i; break; } + } + if (cut <= 0) return ''; + const header = lines.slice(0, cut).join('\n').trim(); + return header.length > 0 && header.length <= 1200 ? `[ํšŒ์˜ ํ—ค๋”]\n${header}` : ''; +} + /** ํšŒ์˜๋ก ๋ณธ๋ฌธ์˜ "**์ผ์‹œ**: 2026๋…„ 05์›” 08์ผ"(๊ตฌ ํ˜•์‹ "**๋‚ ์งœ**:" ๋„ ํ˜ธํ™˜)์—์„œ ํšŒ์˜ ๋‚ ์งœ ์ถ”์ถœ. ์—†์œผ๋ฉด fallback. */ export function extractMeetingDate(report: string, fallback: Date): Date { const m = report.match(/(?:์ผ์‹œ|๋‚ ์งœ)\*{0,2}\s*[:๏ผš]\s*\*{0,2}\s*(\d{4})\s*๋…„\s*(\d{1,2})\s*์›”\s*(\d{1,2})\s*์ผ/); @@ -70,34 +87,74 @@ export function resolveTaskDate(due: string, meetingDate: Date, today: Date): { return { date: toYmd(addBusinessDays(today, 5)), tentative: true }; } +export interface ParsedActionRow { owner: string; work: string; detail: string; deliverable: string; due: string; status: string; source: string } + +/** ํ‘œ ๋จธ๋ฆฌ๊ธ€ ์…€ โ†’ ํ‘œ์ค€ ํ•„๋“œ ํ‚ค. ์ปฌ๋Ÿผ ์ˆœ์„œ๊ฐ€ ๋ฐ”๋€Œ์–ด๋„ ์ด๋ฆ„์œผ๋กœ ์•ˆ์ „ํ•˜๊ฒŒ ๋งคํ•‘ํ•œ๋‹ค. */ +function headerKey(cell: string): keyof ParsedActionRow | null { + const c = cell.replace(/\s+/g, ''); + if (c === '๋‹ด๋‹น') return 'owner'; + if (c === '์•ก์…˜' || c === '์ž‘์—…๋‚ด์šฉ') return 'work'; + if (c === '์ž‘์—…์ƒ์„ธ') return 'detail'; + if (c === '์‚ฐ์ถœ๋ฌผ') return 'deliverable'; + if (c === '๊ธฐํ•œ') return 'due'; + if (c === '์ƒํƒœ') return 'status'; + if (c === '์ถœ์ฒ˜' || c === '๊ทผ๊ฑฐ') return 'source'; + return null; +} + /** - * ํšŒ์˜๋ก ๋ณธ๋ฌธ์˜ "## 5. ์•ก์…˜ ์•„์ดํ…œ" ๋งˆํฌ๋‹ค์šด ํ‘œ์—์„œ ํ–‰์„ ํŒŒ์‹ฑ. - * 5์—ด ์‹ ํ‘œ(๋‹ด๋‹น | ์ž‘์—… ๋‚ด์šฉ | ์ž‘์—… ์ƒ์„ธ | ๊ธฐํ•œ | ์ƒํƒœ) ยท 4์—ด(์ƒํƒœ ์—†์Œ) ยท - * ๊ตฌ(่ˆŠ) 3์—ด ํ‘œ(๋‹ด๋‹น | ์ž‘์—… ๋‚ด์šฉ | ๊ธฐํ•œ)๋ฅผ ๋ชจ๋‘ ์ง€์›ํ•œ๋‹ค. ๋ˆ„๋ฝ ์ปฌ๋Ÿผ์€ ๋นˆ ๋ฌธ์ž์—ด. + * ํšŒ์˜๋ก ๋ณธ๋ฌธ์˜ "## ์•ก์…˜ ์•„์ดํ…œ" ๋งˆํฌ๋‹ค์šด ํ‘œ์—์„œ ํ–‰์„ ํŒŒ์‹ฑ. + * **๋จธ๋ฆฌ๊ธ€ ์ด๋ฆ„ ๊ธฐ๋ฐ˜ ๋งคํ•‘**์ด๋ผ ์ปฌ๋Ÿผ ์ˆœ์„œยท๊ฐœ์ˆ˜๊ฐ€ ๋‹ฌ๋ผ๋„ ์•ˆ์ „ํ•˜๋‹ค: + * - ์‹  ํ˜•์‹(v2.2.258): ๋‹ด๋‹น | ์•ก์…˜ | ๊ธฐํ•œ | ์ƒํƒœ | ์ถœ์ฒ˜ + * - ๊ตฌ ํ˜•์‹: ๋‹ด๋‹น | ์ž‘์—… ๋‚ด์šฉ | ์ž‘์—… ์ƒ์„ธ | (์‚ฐ์ถœ๋ฌผ) | ๊ธฐํ•œ | ์ƒํƒœ + * ๋จธ๋ฆฌ๊ธ€์„ ๋ชป ์ฐพ์œผ๋ฉด ์œ„์น˜ ๊ธฐ๋ฐ˜์œผ๋กœ ํด๋ฐฑ(๊ตฌํ˜• ํ˜ธํ™˜). ๋ˆ„๋ฝ ์ปฌ๋Ÿผ์€ ๋นˆ ๋ฌธ์ž์—ด. */ -export function parseActionItems(report: string): { owner: string; work: string; detail: string; deliverable: string; due: string; status: string }[] { - const rows: { owner: string; work: string; detail: string; deliverable: string; due: string; status: string }[] = []; +export function parseActionItems(report: string): ParsedActionRow[] { + const rows: ParsedActionRow[] = []; + const empty = (): ParsedActionRow => ({ owner: '', work: '', detail: '', deliverable: '', due: '', status: '', source: '' }); let inSection = false; + let colMap: Partial> | null = null; for (const line of report.split('\n')) { - if (/^#{1,6}\s*(?:\d+\.\s*)?์•ก์…˜\s*์•„์ดํ…œ/.test(line)) { inSection = true; continue; } + if (/^#{1,6}\s*(?:\d+\.\s*)?์•ก์…˜\s*์•„์ดํ…œ/.test(line)) { inSection = true; colMap = null; continue; } if (!inSection) continue; if (/^#{1,6}\s/.test(line)) break; // ๋‹ค์Œ ์„น์…˜ ์‹œ์ž‘ โ†’ ์ข…๋ฃŒ if (!/^\s*\|/.test(line)) continue; const cells = line.split('|').slice(1, -1).map((c) => c.trim()); if (cells.length < 3) continue; if (/^:?-+:?$/.test(cells[0])) continue; // ํ‘œ ๊ตฌ๋ถ„์„  - if (cells[0] === '๋‹ด๋‹น' || cells[1] === '์ž‘์—… ๋‚ด์šฉ') continue; // ํ—ค๋” - if (cells.length >= 6) { - // ์‹  ํ˜•์‹: ๋‹ด๋‹น | ์ž‘์—… ๋‚ด์šฉ | ์ž‘์—… ์ƒ์„ธ | ์‚ฐ์ถœ๋ฌผ | ๊ธฐํ•œ | ์ƒํƒœ - rows.push({ owner: cells[0], work: cells[1], detail: cells[2], deliverable: cells[3], due: cells[4], status: cells[5] }); - } else if (cells.length === 5) { - // ๊ตฌ ํ˜•์‹: ๋‹ด๋‹น | ์ž‘์—… ๋‚ด์šฉ | ์ž‘์—… ์ƒ์„ธ | ๊ธฐํ•œ | ์ƒํƒœ (์‚ฐ์ถœ๋ฌผ ์ปฌ๋Ÿผ ์—†์Œ) - rows.push({ owner: cells[0], work: cells[1], detail: cells[2], deliverable: '', due: cells[3], status: cells[4] }); - } else if (cells.length === 4) { - rows.push({ owner: cells[0], work: cells[1], detail: cells[2], deliverable: '', due: cells[3], status: '' }); - } else { - rows.push({ owner: cells[0], work: cells[1], detail: '', deliverable: '', due: cells[2], status: '' }); + // ๋จธ๋ฆฌ๊ธ€ ํ–‰ ๊ฐ์ง€ โ†’ ์ปฌ๋Ÿผ ์ธ๋ฑ์Šค ๋งคํ•‘ ๊ธฐ๋ก + const isHeader = cells.some((c) => c === '๋‹ด๋‹น') && cells.some((c) => headerKey(c) === 'work'); + if (isHeader) { + colMap = {}; + cells.forEach((c, i) => { const k = headerKey(c); if (k && colMap![k] === undefined) colMap![k] = i; }); + continue; } + if (colMap) { + // 'โ€”'/๋นˆ ์นธ์€ ๋ฏธ์ • ์‹ ํ˜ธ โ†’ ๋นˆ ๋ฌธ์ž์—ด๋กœ ์ •๊ทœํ™”(๋‹ค์šด์ŠคํŠธ๋ฆผ ๊ฒŒ์ดํŠธ๊ฐ€ ๋ณด๋ฅ˜ ์ฒ˜๋ฆฌ). + const get = (k: keyof ParsedActionRow): string => { + const i = colMap![k]; + if (i === undefined) return ''; + const v = (cells[i] ?? '').trim(); + return v === 'โ€”' || v === '-' ? '' : v; + }; + const row = empty(); + row.owner = get('owner'); row.work = get('work'); row.detail = get('detail'); + row.deliverable = get('deliverable'); row.due = get('due'); row.status = get('status'); row.source = get('source'); + if (row.work) rows.push(row); + continue; + } + // ๋จธ๋ฆฌ๊ธ€ ์—†์Œ โ€” ์œ„์น˜ ๊ธฐ๋ฐ˜ ํด๋ฐฑ(๊ตฌํ˜• ํšŒ์˜๋ก ํ˜ธํ™˜) + const row = empty(); + if (cells.length >= 6) { + [row.owner, row.work, row.detail, row.deliverable, row.due, row.status] = [cells[0], cells[1], cells[2], cells[3], cells[4], cells[5]]; + } else if (cells.length === 5) { + [row.owner, row.work, row.detail, row.due, row.status] = [cells[0], cells[1], cells[2], cells[3], cells[4]]; + } else if (cells.length === 4) { + [row.owner, row.work, row.detail, row.due] = [cells[0], cells[1], cells[2], cells[3]]; + } else { + [row.owner, row.work, row.due] = [cells[0], cells[1], cells[2]]; + } + if (row.work) rows.push(row); } return rows; } diff --git a/src/features/datacollect/scheduling/meetRegistration.ts b/src/features/datacollect/scheduling/meetRegistration.ts index 7bdcacc..83c1705 100644 --- a/src/features/datacollect/scheduling/meetRegistration.ts +++ b/src/features/datacollect/scheduling/meetRegistration.ts @@ -29,7 +29,7 @@ import { resolveTaskDate, toYmd, addBusinessDays } from './calendarHelpers'; import { logInfo } from '../../../utils'; // โ”€โ”€ ํƒ€์ž… โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ -export type ActionRow = { owner: string; work: string; detail: string; deliverable: string; due: string; status: string }; +export type ActionRow = { owner: string; work: string; detail: string; deliverable: string; due: string; status: string; source?: string }; export type HoldKind = 'undecided' | 'nodate' | 'conditional'; export interface PendingItem { @@ -39,6 +39,7 @@ export interface PendingItem { detail: string; deliverable: string; // ์‚ฐ์ถœ๋ฌผ (์—†์œผ๋ฉด "ํ™•์ธ ํ•„์š”") due: string; + source?: string; // ๊ทผ๊ฑฐ ํƒ€์ž„์Šคํƒฌํ”„ [mm:ss] (์žˆ์œผ๋ฉด ๋…ธํŠธ์— ํ‘œ๊ธฐ) kind: HoldKind; condition?: string; // kind=conditional ์˜ ์„ ํ–‰์ž‘์—… suggestedDate: string; // ok ๋‹ต๋ณ€ ์‹œ ์‚ฌ์šฉํ•  ์ œ์•ˆ ๋‚ ์งœ (YYYY-MM-DD) @@ -186,9 +187,10 @@ export async function registerAction( } /** ๋“ฑ๋ก ๋…ธํŠธ ๊ณตํ†ต ๋นŒ๋”. */ -export function buildNotes(p: { detail: string; meetTitle: string; owner: string; deliverable?: string; dueRaw: string; dateLabel: string; extra?: string[] }): string { - const detailLine = p.detail?.trim() || '(๋…น์ทจ๋ก์—์„œ ์ž‘์—… ์ƒ์„ธ๊ฐ€ ์ถ”์ถœ๋˜์ง€ ์•Š์Œ โ€” ํšŒ์˜๋ก ๋ณธ๋ฌธ ์ฐธ์กฐ)'; +export function buildNotes(p: { detail: string; meetTitle: string; owner: string; deliverable?: string; dueRaw: string; dateLabel: string; source?: string; extra?: string[] }): string { + const detailLine = p.detail?.trim() || '(ํšŒ์˜๋ก ๋ณธ๋ฌธ ์ฐธ์กฐ โ€” ์•ก์…˜ ํ•œ ์ค„์— ์ƒ์„ธ๊ฐ€ ๋…น์•„ ์žˆ์Œ)'; const deliverable = p.deliverable?.trim(); + const source = p.source?.trim(); return [ 'โ–  ์ž‘์—… ์ƒ์„ธ', detailLine, '', ...(deliverable ? ['โ–  ์‚ฐ์ถœ๋ฌผ', deliverable, ''] : []), @@ -197,6 +199,7 @@ export function buildNotes(p: { detail: string; meetTitle: string; owner: string `ยท ํšŒ์˜๋ก: ${p.meetTitle}`, `ยท ๋‹ด๋‹น: ${p.owner || '(๋ฏธ์ง€์ •)'}`, `ยท ๊ธฐํ•œ: ${p.dueRaw?.trim() || '(๋ฏธํ‘œ๊ธฐ)'} โ†’ ${p.dateLabel}`, + ...(source ? [`ยท ๊ทผ๊ฑฐ: ๋…น์ทจ ${source}`] : []), '', 'โ€” Astra /meet ๋“ฑ๋ก', ].join('\n'); } @@ -329,7 +332,7 @@ export async function processConfirmDecisions( const notes = buildNotes({ detail: item.detail, meetTitle: pend.meetTitle, owner: item.owner, deliverable: item.deliverable, - dueRaw: item.due, dateLabel: date || '(๋‚ ์งœ ์—†์Œ โ€” ์กฐ๊ฑด๋ถ€)', extra, + dueRaw: item.due, dateLabel: date || '(๋‚ ์งœ ์—†์Œ โ€” ์กฐ๊ฑด๋ถ€)', source: item.source, extra, }); const r = await registerAction(context, { title, date, notes, @@ -371,6 +374,19 @@ export function loadGlossaryTerms(): string[] { return (readJson(GLOSSARY_REL)?.terms || []).filter(t => typeof t === 'string' && t.trim()); } +// โ”€โ”€ ํšŒ์‚ฌ ํ‘œ์ค€ ํŒ€/์—ญํ•  ๋ถ„๋ฅ˜ (ํ™”์ž ์ •๊ทœํ™”์šฉ ํ†ต์ œ ์–ดํœ˜์ง‘) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ +// /meet ๋Š” STT ํ™”์ž๋ฒˆํ˜ธ("์ฐธ์„์ž N")๋ฅผ ์‹ค๋ช…์ด ์•„๋‹ˆ๋ผ **ํŒ€/์—ญํ• **๋กœ ๊ท€์†ํ•œ๋‹ค. +// ํšŒ์‚ฌ์˜ ์•ˆ์ •์  ํŒ€ ๊ตฌ์กฐ๋ฅผ ํ†ต์ œ ์–ดํœ˜์ง‘์œผ๋กœ ๋ชจ๋“  ์กฐ๊ฐยท๋ณ‘ํ•ฉ ํ”„๋กฌํ”„ํŠธ์— ์ฃผ์ž…ํ•˜๋ฉด, +// ๊ฐœ์ธ ๋งคํ•‘ ์ถ”์ธก(์˜ค๊ท€์† ์œ„ํ—˜)์„ ํ”ผํ•˜๋ฉด์„œ ์ผ๊ด€๋œ ์—ญํ•  ๊ท€์†์ด ๊ฐ€๋Šฅํ•ด์ง„๋‹ค. +// ์„ค์ • `g1nation.meetTeamRoster` ๋กœ ํšŒ์‚ฌ๋ณ„ ์ปค์Šคํ„ฐ๋งˆ์ด์ฆˆ ๊ฐ€๋Šฅ. +export const DEFAULT_TEAM_ROSTER = + 'PD, ๊ธฐํš, ์‚ฌ์—…, ํด๋ผ์ด์–ธํŠธ, ๋„ฅ์„œ์Šค๊ฐœ๋ฐœํŒ€(์„œ๋ฒ„), UI, ๋ฐฐ๊ฒฝํŒ€, ์บ๋ฆญํ„ฐํŒ€, QA, ์‚ฌ์šด๋“œ, ๊ฐœ๋ฐœPM'; + +export function loadTeamRoster(): string { + const v = vscode.workspace.getConfiguration('g1nation').get('meetTeamRoster', ''); + return (v && v.trim()) ? v.trim() : DEFAULT_TEAM_ROSTER; +} + /** ๋‹ด๋‹น์ž ์ด๋ฆ„ยท๋ฉ”ํƒ€๋ฐ์ดํ„ฐ์—์„œ ๋ฝ‘์€ ์šฉ์–ด๋ฅผ ์šฉ์–ด์ง‘์— ๋ˆ„์  (์ค‘๋ณต ์ œ๊ฑฐ, ์ƒํ•œ ์œ ์ง€). */ export function updateGlossary(newTerms: string[]): void { const cleaned = newTerms diff --git a/tests/meetPrompt.test.ts b/tests/meetPrompt.test.ts index d9a748a..0ccd269 100644 --- a/tests/meetPrompt.test.ts +++ b/tests/meetPrompt.test.ts @@ -1,11 +1,13 @@ /** - * Regression guard for the /meet prompt policy. + * Regression guard for the /meet prompt policy (v2.2.258). * - * These 4 rules were added after a real meeting record showed the failure modes: - * 1) anonymous/numbered speakers assigned as action owners (fake accountability) - * 2) content-empty deictic quotes ("์ด๋ ‡๊ฒŒ ์ด๋ ‡๊ฒŒ") passed off as ๊ทผ๊ฑฐ - * 3) deadlines mentioned in risks/discussion not reflected in action ๊ธฐํ•œ - * 4) speakers in the body who aren't in the attendee list + * After a real meeting record review, the policy shifted to: + * 1) STT speaker numbers ("์ฐธ์„์ž N") must NEVER appear in output โ€” speakers are + * normalized to team/role instead (individual names only when certain). + * 2) empty cells are "โ€”", not guessed placeholders; fully-undecided โ†’ open issue. + * 3) ๊ทผ๊ฑฐ is a timestamp [mm:ss], not a raw STT quote. + * 4) decision vs action boundary: ์ผ๊ฐโ†’action table, ๊ฒฐ์ •โ†’pure direction only. + * 5) rejected/withdrawn hypotheses must not be promoted to issues/decisions. * * Prompts can't be unit-tested for model behavior, but we CAN guard that the * policy text doesn't silently get dropped in a future refactor. @@ -17,44 +19,57 @@ import { buildMeetReducePrompt, } from '../src/features/datacollect/prompts/meetPrompt'; -const transcript = '์ฐธ์„์ž 1: ์ด๊ฑฐ๋Š” ์ด๋ ‡๊ฒŒ ์ด๋ ‡๊ฒŒ ํ•ด์ฃผ์„ธ์š”. ํšจํฌ ํŒ€์žฅ: ๋„ค ์ˆ˜์ •ํ• ๊ฒŒ์š”.'; +const transcript = '์ฐธ์„์ž 1 00:01 ์ด๊ฑฐ๋Š” ์ด๋ ‡๊ฒŒ ์ด๋ ‡๊ฒŒ ํ•ด์ฃผ์„ธ์š”. ์ฐธ์„์ž 2 00:10 ๋„ค ์ˆ˜์ •ํ• ๊ฒŒ์š”.'; const metadata = 'ํšŒ์˜๋ช…: ํ…Œ์ŠคํŠธ'; -describe('/meet prompt โ€” accountability & grounding policy', () => { +describe('/meet prompt โ€” speaker normalization & slim format policy', () => { // The OUTPUT_FORMAT block is shared by the single-shot and reduce paths, so // both must carry the policy. const sharedFormatBuilders: Array<[string, string]> = [ ['buildMeetPrompt', buildMeetPrompt(transcript, metadata)], - ['buildMeetReducePrompt', buildMeetReducePrompt('## ์•ก์…˜\n- [๋ฏธ์ง€์ •] ์ž‘์—…', metadata)], + ['buildMeetReducePrompt', buildMeetReducePrompt('## ์•ก์…˜\n- [๋„ฅ์„œ์Šค๊ฐœ๋ฐœํŒ€] ์ž‘์—…', metadata)], ]; - test.each(sharedFormatBuilders)('%s forbids assigning anonymous speakers as owners', (_name, prompt) => { - expect(prompt).toContain('[๋ฏธ์ง€์ •-ํ™•์ธํ•„์š”]'); - expect(prompt).toMatch(/์ต๋ช…ยท๋ฒˆํ˜ธ ํ™”์ž/); + test.each(sharedFormatBuilders)('%s bans "์ฐธ์„์ž N" tokens in output', (_name, prompt) => { + expect(prompt).toMatch(/"์ฐธ์„์ž N"/); + expect(prompt).toMatch(/ํ† ํฐ 0๊ฐœ|์ ˆ๋Œ€ ๊ธˆ์ง€|์ ˆ๋Œ€ ์“ฐ์ง€/); }); - test.each(sharedFormatBuilders)('%s rejects content-empty deictic quotes', (_name, prompt) => { - expect(prompt).toContain('[๋‚ด์šฉ ํ™•์ธํ•„์š”]'); - expect(prompt).toMatch(/์ด๋ ‡๊ฒŒ ์ด๋ ‡๊ฒŒ/); + test.each(sharedFormatBuilders)('%s attributes speakers by team/role', (_name, prompt) => { + expect(prompt).toMatch(/ํŒ€\/์—ญํ• /); }); - test.each(sharedFormatBuilders)('%s cross-references deadlines into action ๊ธฐํ•œ', (_name, prompt) => { - expect(prompt).toMatch(/๊ธฐํ•œ ์—ญ์ฐธ์กฐ/); + test.each(sharedFormatBuilders)('%s requires timestamp ๊ทผ๊ฑฐ ([mm:ss])', (_name, prompt) => { + expect(prompt).toMatch(/\[mm:ss\]/); }); - test.each(sharedFormatBuilders)('%s flags speakers missing from the attendee list', (_name, prompt) => { - expect(prompt).toMatch(/๋ช…๋‹จ ์™ธ ํ™”์ž|์ฐธ์„์ž ๋ช…๋‹จ ์ •ํ•ฉ์„ฑ/); + test.each(sharedFormatBuilders)('%s separates decision from action', (_name, prompt) => { + expect(prompt).toMatch(/๊ฒฐ์ • โ†” ์•ก์…˜ ๊ฒฝ๊ณ„|์ˆœ์ˆ˜ ๋ฐฉํ–ฅ\/์ •์ฑ…|๊ฒฐ์ •\/์•ก์…˜ ๊ฒฝ๊ณ„/); }); - test('extract (map) stage also avoids anonymous owner assignment & empty quotes', () => { - const p = buildMeetExtractPrompt('์ฐธ์„์ž 1: ์ด๊ฑฐ ์ด๋ ‡๊ฒŒ์š”', metadata, 1, 3); - expect(p).toContain('[๋ฏธ์ง€์ •]'); - expect(p).toContain('[๋‚ด์šฉ ํ™•์ธํ•„์š”]'); + test.each(sharedFormatBuilders)('%s blanks unknown cells with "โ€”" instead of guessing', (_name, prompt) => { + expect(prompt).toMatch(/๋นˆ ์นธ์€ "โ€”"/); + }); + + test('extract (map) stage normalizes speakers to role, tags dialectic state & timestamps', () => { + const p = buildMeetExtractPrompt('์ฐธ์„์ž 1 00:01 ์ด๊ฑฐ ์ด๋ ‡๊ฒŒ์š”', metadata, 1, 3); + expect(p).toMatch(/ํŒ€\/์—ญํ• /); // role mapping + expect(p).toMatch(/\[mm:ss\]/); // timestamp grounding + expect(p).toMatch(/๋ฐ˜๋ฐ•๋จ|์ฒ ํšŒ๋จ/); // dialectic state tags + expect(p).toMatch(/์•ˆ๊ฑด\/์ฃผ์ œ/); // agenda coverage list + expect(p).toContain('[๋‚ด์šฉ ํ™•์ธํ•„์š”]'); // content-empty deictic guard retained + }); + + test('reduce stage extracts a global headline & dedups across chunks', () => { + const p = buildMeetReducePrompt('## ์•ก์…˜\n- [๊ธฐํš] ์ž‘์—…', metadata); + expect(p).toMatch(/์ „์—ญ ํ—ค๋“œ๋ผ์ธ/); + expect(p).toMatch(/dedup|๋ณ‘ํ•ฉ/); + expect(p).toMatch(/๋ฐ˜๋ฐ•๋จ|ํ๊ธฐ/); // rejected hypotheses not promoted }); test('final checklist references the new gates', () => { const prompt = buildMeetPrompt(transcript, metadata); - expect(prompt).toMatch(/์ต๋ช…ยท๋ฒˆํ˜ธ ํ™”์ž๋ฅผ ๋‹ด๋‹น์œผ๋กœ ํ™•์ •ํ•˜์ง€ ์•Š๊ณ /); - expect(prompt).toMatch(/๋นˆ ์ธ์šฉ์„ ๊ทผ๊ฑฐ๋กœ ๋‹ฌ์ง€ ์•Š์•˜๋Š”๊ฐ€/); + expect(prompt).toMatch(/"์ฐธ์„์ž N" ํ† ํฐ 0๊ฐœ/); + expect(prompt).toMatch(/๋นˆ ์นธ์€ "โ€”"/); }); }); diff --git a/tests/meetRegistration.test.ts b/tests/meetRegistration.test.ts index 69c0bb4..9de0ec6 100644 --- a/tests/meetRegistration.test.ts +++ b/tests/meetRegistration.test.ts @@ -111,8 +111,26 @@ describe('๋ณด์กฐ ์œ ํ‹ธ', () => { }); }); -describe('parseActionItems โ€” ์•ก์…˜ ํ‘œ ํŒŒ์‹ฑ (์‚ฐ์ถœ๋ฌผ ์ปฌ๋Ÿผ + ํ•˜์œ„ํ˜ธํ™˜)', () => { - test('์‹  ํ˜•์‹ 6์ปฌ๋Ÿผ: ๋‹ด๋‹น|์ž‘์—…|์ƒ์„ธ|์‚ฐ์ถœ๋ฌผ|๊ธฐํ•œ|์ƒํƒœ', () => { +describe('parseActionItems โ€” ์•ก์…˜ ํ‘œ ํŒŒ์‹ฑ (ํ—ค๋”๋ช… ๊ธฐ๋ฐ˜ ๋งคํ•‘ + ํ•˜์œ„ํ˜ธํ™˜)', () => { + test('์‹  ํ˜•์‹ 5์ปฌ๋Ÿผ(v2.2.258): ๋‹ด๋‹น|์•ก์…˜|๊ธฐํ•œ|์ƒํƒœ|์ถœ์ฒ˜ โ€” ์ปฌ๋Ÿผ ์ˆœ์„œ๊ฐ€ ๋‹ฌ๋ผ๋„ ์•ˆ์ „', () => { + const report = [ + '## ์•ก์…˜ ์•„์ดํ…œ', + '| ๋‹ด๋‹น | ์•ก์…˜ | ๊ธฐํ•œ | ์ƒํƒœ | ์ถœ์ฒ˜ |', + '| --- | --- | --- | --- | --- |', + '| ๋„ฅ์„œ์Šค๊ฐœ๋ฐœํŒ€ | ๋ชจ์ž ํ—ค์–ด์Šคํƒ€์ผ ๋‹จ์ • ๋ฒ„์ „ 3์ข… ์‹œ์•ˆ ์ œ์ž‘ | 6/18 | ํ™•์ • | [07:14] |', + '| โ€” | ๋ชจ๋ธ ๊ต์ฒด ์†Œ์š”๊ธฐ๊ฐ„ ์‚ฐ์ • | โ€” | ์ง„ํ–‰๋ฏธ์ • | [53:55] |', + '', + '## ์˜คํ”ˆ ์ด์Šˆ', + ].join('\n'); + const rows = parseActionItems(report); + expect(rows).toHaveLength(2); + // ์ถœ์ฒ˜๊ฐ€ ๊ธฐํ•œ/์ƒํƒœ ๋’ค์— ์™€๋„ ์ด๋ฆ„์œผ๋กœ ๋งคํ•‘ โ†’ ์–ด๊ธ‹๋‚˜์ง€ ์•Š๋Š”๋‹ค + expect(rows[0]).toEqual({ owner: '๋„ฅ์„œ์Šค๊ฐœ๋ฐœํŒ€', work: '๋ชจ์ž ํ—ค์–ด์Šคํƒ€์ผ ๋‹จ์ • ๋ฒ„์ „ 3์ข… ์‹œ์•ˆ ์ œ์ž‘', detail: '', deliverable: '', due: '6/18', status: 'ํ™•์ •', source: '[07:14]' }); + // 'โ€”' ๋Š” ๋ฏธ์ • ์‹ ํ˜ธ โ†’ ๋นˆ ๋ฌธ์ž์—ด๋กœ ์ •๊ทœํ™” + expect(rows[1]).toMatchObject({ owner: '', work: '๋ชจ๋ธ ๊ต์ฒด ์†Œ์š”๊ธฐ๊ฐ„ ์‚ฐ์ •', due: '', status: '์ง„ํ–‰๋ฏธ์ •', source: '[53:55]' }); + }); + + test('๊ตฌ ํ˜•์‹ 6์ปฌ๋Ÿผ: ๋‹ด๋‹น|์ž‘์—…|์ƒ์„ธ|์‚ฐ์ถœ๋ฌผ|๊ธฐํ•œ|์ƒํƒœ', () => { const report = [ '## 4. ์•ก์…˜ ์•„์ดํ…œ', '| ๋‹ด๋‹น | ์ž‘์—… ๋‚ด์šฉ | ์ž‘์—… ์ƒ์„ธ | ์‚ฐ์ถœ๋ฌผ | ๊ธฐํ•œ | ์ƒํƒœ |', @@ -123,7 +141,7 @@ describe('parseActionItems โ€” ์•ก์…˜ ํ‘œ ํŒŒ์‹ฑ (์‚ฐ์ถœ๋ฌผ ์ปฌ๋Ÿผ + ํ•˜์œ„ํ˜ธ ].join('\n'); const rows = parseActionItems(report); expect(rows).toHaveLength(1); - expect(rows[0]).toEqual({ owner: '์†ก๋ณ‘์ค€', work: 'ํ…Œ์ŠคํŠธ ์ƒ˜ํ”Œ 3์ข… ์„ ์ •', detail: 'ํ›„๋ณด ๋น„๊ต', deliverable: 'ํ…Œ์ŠคํŠธ URL ๋ชฉ๋ก', due: '6/18', status: 'ํ™•์ •' }); + expect(rows[0]).toEqual({ owner: '์†ก๋ณ‘์ค€', work: 'ํ…Œ์ŠคํŠธ ์ƒ˜ํ”Œ 3์ข… ์„ ์ •', detail: 'ํ›„๋ณด ๋น„๊ต', deliverable: 'ํ…Œ์ŠคํŠธ URL ๋ชฉ๋ก', due: '6/18', status: 'ํ™•์ •', source: '' }); }); test('๊ตฌ ํ˜•์‹ 5์ปฌ๋Ÿผ(์‚ฐ์ถœ๋ฌผ ์—†์Œ)๋„ ๊ทธ๋Œ€๋กœ ํŒŒ์‹ฑ โ€” deliverable ๋นˆ๊ฐ’', () => {