v2.2.323: /naver-trend contains 모드 — "분야 + 포함단어 + 기간"으로 검색어 뽑기

`/naver-trend 경제 방법 8월1일부터 오늘까지` → 경제 분야 인기 검색어 중
"방법"이 들어간 것을 검색량 상위 10개로.

- contains 모드(intentParser): topic/containsWord/limit 추출 + 포함 단어를
  가진 후보 최대 30개 제안. 포함 여부는 LLM을 믿지 않고 keywordContains()로
  코드에서 재검사(공백 무시, 단어 자체만인 후보 제외). 후보가 얇으면
  generateContainingKeywords()로 보충. containsWord가 비면 discover로 강등.
- rankKeywordsAnchored: 검색어트렌드 ratio는 "요청 하나 안에서" 최댓값=100인
  상대값이라 5개씩 끊어 호출하면 6위 이하 순위가 무의미했다. 첫 배치 최댓값을
  앵커로 잡아 모든 배치에 끼워 넣고 되돌린 뒤 1위=100으로 재정규화. 정렬은
  하루치 최신값 대신 구간 평균(avgRatio).
- dateRange.ts 신설: 기간을 LLM에 맡기지 않고 규칙으로 확정 —
  "8월1일부터 오늘까지", "8/1~8/10", "최근 일주일", "지난 30일", "최근 한 달".
  연도 생략 시 미래면 작년. 범위 연결어 없는 날짜 나열/버전 문자열은 미인식.
- 날짜 UTC 밀림 수정: toISOString() → ymdLocal() (KST 새벽에 "오늘"이 하루 전으로
  밀리던 문제). 긴 구간은 timeUnit을 week/month로 자동 하향.

검증: tsc 무오류 + jest 1044 통과(신규 24) + esbuild 정상.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-11 21:43:08 +09:00
co-authored by Claude Opus 5
parent b61e06ef41
commit 0b315b9c6a
16 changed files with 767 additions and 45 deletions
@@ -1,5 +1,5 @@
{
"result": "직답 결과 — single-pass mock 응답입니다.",
"createdAt": 1786009859146,
"createdAt": 1786452145565,
"modelVersion": "unknown"
}
@@ -1,5 +1,5 @@
{
"result": "---\nid: wiki_on\ndate: 2026-08-06T09:50:59.150Z\ntype: knowledge_artifact\nstandard: P-Reinforce v3.0\ntags: [automated, connect_ai, brain_sync]\n---\n\n## 📌 Brief Summary\n직답 결과 — single-pass mock 응답입니다.\n\n직답 결과 — single-pass mock 응답입니다.\n---\n## 🛡️ Reliability & Audit Summary\n> [!NOTE]\n> 이 문서는 ConnectAI의 **Intelligent Resilience** 엔진에 의해 검증 및 정제되었습니다.\n\n| Metric | Value | Status |\n| :--- | :--- | :--- |\n| **Conflict Risk** | `0/100` | ✅ Low |\n| **Fallbacks Used** | `0` | ✅ None |\n| **Auto Retries** | `0` | ✅ Stable |\n| **Deduplication** | `0` | Standard |\n| **Processing Time** | `0.0s` | ✅ Fast |\n\n### 🔍 Decision Audit Trail\n- **[DIRECT]** 답변 작성 중... (단일 호출 fast-path) (23ms)\n",
"createdAt": 1786009859151,
"result": "---\nid: wiki_on\ndate: 2026-08-11T12:42:25.565Z\ntype: knowledge_artifact\nstandard: P-Reinforce v3.0\ntags: [automated, connect_ai, brain_sync]\n---\n\n## 📌 Brief Summary\n직답 결과 — single-pass mock 응답입니다.\n\n직답 결과 — single-pass mock 응답입니다.\n---\n## 🛡️ Reliability & Audit Summary\n> [!NOTE]\n> 이 문서는 ConnectAI의 **Intelligent Resilience** 엔진에 의해 검증 및 정제되었습니다.\n\n| Metric | Value | Status |\n| :--- | :--- | :--- |\n| **Conflict Risk** | `0/100` | ✅ Low |\n| **Fallbacks Used** | `0` | ✅ None |\n| **Auto Retries** | `0` | ✅ Stable |\n| **Deduplication** | `0` | Standard |\n| **Processing Time** | `0.0s` | ✅ Fast |\n\n### 🔍 Decision Audit Trail\n- **[DIRECT]** 답변 작성 중... (단일 호출 fast-path) (18ms)\n",
"createdAt": 1786452145565,
"modelVersion": "unknown"
}
@@ -1,8 +1,8 @@
{
"missionId": "wiki_on",
"status": "completed",
"startTime": "2026-08-06T09:50:59.117Z",
"totalElapsedMs": 40,
"startTime": "2026-08-11T12:42:25.546Z",
"totalElapsedMs": 19,
"results": {
"direct": "직답 결과 — single-pass mock 응답입니다."
},
@@ -12,16 +12,16 @@
{
"from": "idle",
"to": "direct",
"durationMs": 23,
"durationMs": 18,
"message": "답변 작성 중... (단일 호출 fast-path)",
"ts": "2026-08-06T09:50:59.140Z"
"ts": "2026-08-11T12:42:25.564Z"
},
{
"from": "direct",
"to": "completed",
"durationMs": 14,
"durationMs": 1,
"message": "미션 완료",
"ts": "2026-08-06T09:50:59.154Z"
"ts": "2026-08-11T12:42:25.565Z"
}
],
"resilienceMetrics": {
@@ -1,5 +1,5 @@
{
"result": "Final report with inconsistencies. This should be long enough to pass validation.",
"createdAt": 1786009865515,
"createdAt": 1786452152471,
"modelVersion": "unknown"
}
@@ -1,5 +1,5 @@
{
"result": "Final report with inconsistencies. This should be long enough to pass validation.",
"createdAt": 1786009865514,
"createdAt": 1786452152471,
"modelVersion": "unknown"
}
@@ -1,5 +1,5 @@
{
"result": "[{\"heading\":\"본문\",\"scope\":\"전체 답변\"}]",
"createdAt": 1786009865510,
"createdAt": 1786452152459,
"modelVersion": "unknown"
}
@@ -1,5 +1,5 @@
{
"result": "[CONFLICT WARNING] 성능이 200% 증가했습니다. vs 그러나 동시에 50% 감소했습니다. 최적화와 성능 저하가 동시에 발견됨.",
"createdAt": 1786009865512,
"createdAt": 1786452152465,
"modelVersion": "unknown"
}
@@ -1,7 +1,7 @@
{
"missionId": "stress_conflict_1786009865491",
"missionId": "stress_conflict_1786452152446",
"status": "completed",
"startTime": "2026-08-06T09:51:05.491Z",
"startTime": "2026-08-11T12:42:32.446Z",
"totalElapsedMs": 25,
"results": {
"outline": "[{\"heading\":\"본문\",\"scope\":\"전체 답변\"}]",
@@ -14,30 +14,30 @@
{
"from": "idle",
"to": "outline",
"durationMs": 18,
"durationMs": 12,
"message": "답변 구조 잡는 중...",
"ts": "2026-08-06T09:51:05.509Z"
"ts": "2026-08-11T12:42:32.458Z"
},
{
"from": "outline",
"to": "section",
"durationMs": 2,
"durationMs": 1,
"message": "본문 작성 중...",
"ts": "2026-08-06T09:51:05.511Z"
"ts": "2026-08-11T12:42:32.459Z"
},
{
"from": "section",
"to": "polish",
"durationMs": 2,
"durationMs": 6,
"message": "최종 다듬기 중...",
"ts": "2026-08-06T09:51:05.513Z"
"ts": "2026-08-11T12:42:32.465Z"
},
{
"from": "polish",
"to": "completed",
"durationMs": 3,
"durationMs": 6,
"message": "미션 완료",
"ts": "2026-08-06T09:51:05.516Z"
"ts": "2026-08-11T12:42:32.471Z"
}
],
"resilienceMetrics": {